Sign in to follow this  

Security of C++ Programs

This topic is 3729 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hello, I want to know what I have to take care off when writing C++ programs when it comes to security. So what is insecure and what not? Is it only neccessary to avoid memory leaks to make a program secure or are there other things I have to look at? thx in advance

Share this post


Link to post
Share on other sites
Memory leaks aren't security problems.

Things like buffer overflows are; if someone can overflow a buffer, they can write into memory they shouldn't be writing to, and if the buffer is on the stack, they can do things like overwrite the return address to cause your code to execute any code they want to.

Share this post


Link to post
Share on other sites
C++ is not an interpreted language; there is no way (short of writing your own interpreter) to execute C++ code read from a file. There are no security vulnerabilities in any of the standard c++ functions (except a few C functions that were carried over to c++ -- avoid those).

As such, C++ is a very secure language if written properly.

Like you said, memory leaks and other undefined behavior is possible if code is written poorly without following the standard. But the importance of doing things right is much more than a security issue; it effects portability and repeatability -- if you write undefined code, it may not always work.

Share this post


Link to post
Share on other sites
There are a lot of different aspects of software implementation and design that could be security risks. The big one that almost everyone knows about is buffer overruns, which can potentially allow an attacker to run arbitrary code on a machine. However, there are a large number of other factors to consider when trying to secure an application such as properly validating user input, installing with proper credentials, properly using cryptography, avoiding race conditions such as time of use/time of check (TOUTOC) problems, and so on.

It's really more than one can go on from just a forum post. Consider reading books on the subject like "Building Secure Software" by Viega and McGraw.

Share this post


Link to post
Share on other sites
- Never ever under any circumstances use raw pointers
- Never allocate memory manually
- Use STL containers only
- Never access raw pointers manually
- Never perform any kind of unsafe or improper typecast
- Never use anything that can, under any circumstances, be considered undefined behavior
- Never assume anything. Ever.
- RAII. RAII.

Drastic, yes. But C++ must be treated with respect.

Almost without exception, all security exploits these days come from improper memory management.

Assumptions like char[4096] should be enough for user entering "Y" or "N", or // will never be more than 17 are a very bad thing. In C++, there is no safety net.

All of the above is pretty drastic, once you get comfortable with pitfalls, you'll find that some things can be simplified, but in genereal - in C++ it's up to you to make sure things work. Nobody else will guard you.

Contrary to this, interpreted or VM-based languages offer active safe-guards against many problems during run-time.

Share this post


Link to post
Share on other sites
NEVER trust anything that comes into your application from the outside (be it a file, user input, data sent through a network, etc.). Properly validate everything and do so using a whitelist kind of system where possible.
Also, think about security regardless of what you do and use tools like Purify to detect buffer-overflow vulnerabilities.

Share this post


Link to post
Share on other sites
Quote:
Original post by Antheus
Almost without exception, all security exploits these days come from improper memory management.


That's over stating things by quite a bit. While buffer overruns, double frees and the like account for a large number of security exploits, they hardly add up to "almost without exception." A number of exploits result from bad implementation of algorithms which would result no matter what programming language was used. For example, several of the Microsoft Internet Explorer vulnerabilities resulted from IE not processing content-type MIME headers correctly. Many denial of service vulnerabilities result from bad input processing. For example, the attacker says it's going to send 1000 bytes of data and only sends 8 and the client patiently waits for the rest of the data that never comes. PHP alone has what seems like several million bugs that resulted from not properly urlencoding data. Improper creation of temporary files often result in potential privacy problems. Etc. etc. etc.

Share this post


Link to post
Share on other sites
Quote:
Original post by Antheus
Almost without exception, all security exploits these days come from improper memory management.
I strongly disagree. I concur with SiCrane though that this subject is too much can dealt in one forum post or even many. In fact, there are plenty of books regarding the subject. One can see possible security concerns from the table of context of the book SiCrane, for instance.

Concerning C++, there are books like Secure Coding in C and C++ and the like listed with this book on Amazon.

Quote:
Original post by Antheus
Contrary to this, interpreted or VM-based languages offer active safe-guards against many problems during run-time.
Well, memory will run out in managed string as well as in C++ string if stuffing data in there. [smile]

[EDIT]I concur also with the second post from SiCrance.[/EDIT]

Share this post


Link to post
Share on other sites
Quote:
That's over stating things by quite a bit. While buffer overruns, double frees and the like account for a large number of security exploits,


I made it sound too general. I was referring to language-level type of exploits, not the additional logic exploits.

Share this post


Link to post
Share on other sites
Quote:
Original post by King Mir
C++ is not an interpreted language; there is no way (short of writing your own interpreter) to execute C++ code read from a file.

I beg to differ. A common attack type is to use buffer overflows to load binary code directly. No need to interpret it, it's already in binary executable form.

Quote:

There are no security vulnerabilities in any of the standard c++ functions (except a few C functions that were carried over to c++ -- avoid those).

As a counter-example, the iostream library uses raw pointers to read/write data, which is not so secure. Sure, if you use it correctly, it's secure, but it's easy to make mistakes.

Quote:

As such, C++ is a very secure language if written properly.

It requires quite a bit of expertise on the programmer's side though.

Share this post


Link to post
Share on other sites
Quote:

I beg to differ. A common attack type is to use buffer overflows to load binary code directly. No need to interpret it, it's already in binary executable form.

"Binary code" (machine code) isn't C++ though, and I think that's what he was specifically referring to. It's true, I guess, but a bit of false security blanket. You can't just run C++ directly... You could use that machine code to load a shim that compiled and ran some C++ I guess. But at that point you're just making more effort for yourself; you've broken down the front door just to go unlock the window, leave the house, and climb in that way. Big deal.

Share this post


Link to post
Share on other sites
Quote:
Original post by King Mir
There are no security vulnerabilities in any of the standard c++ functions.


char buffer[256];
std::cin >> buffer;


There's absolutely no sane or useful way to make the above overload safe. You could, of course, check for space characters and then unget everything, or perhaps use another stream (a known-size stringstream), but the vulnerability remains.

Share this post


Link to post
Share on other sites
Quote:
Original post by Antheus
I made it sound too general. I was referring to language-level type of exploits, not the additional logic exploits.


Even so, there are a number of non-memory management language level issues that can cause security problems. A good chunk of security problems come from simple signed/unsigned variable type mix-ups/integer overflow errors. My favorite example was from when the MSIE 5 source code was leaked a few years ago. Long story short, in the bitmap handling function, IE 5 had a signed int variable that could overflow and doing so would allow a specially crafted bitmap to run arbitrary code. IIRC, there was a similar bug in IE 6. Of course, Microsoft isn't the only one to make that kind of mistake; Opera had a similar bug in its JPEG handling code.

Of course almost any aspect of the language that can produce bugs can produce potential security exploits, such as switch case fall through, or the ability to ignore return values from functions.

And if you switch from C++ to another language you may get rid of the extra problems that C++ brings to the table, but you inherit problems that the other language has. For example, with Java you get the nice benefit of array bounds checking and don't have to worry about most memory management issues, but now have to worry about the security implications of Java's facilities for reflection, inner classes, cloning, serialization and deserialization, all of which can cause potential security issues.

Share this post


Link to post
Share on other sites
Quote:

A good chunk of security problems come from simple signed/unsigned variable type mix-ups/integer overflow errors.


No matter how good the C++ Standard library is, or how good the programmer's skill, one of the major security problems is that C++ has used the inherently unsafe type system of the C language to underpin almost all functionality (perhaps to ensure compatibility of C++ and C). I think that the starting point for any secure system is a thorough understanding of defined/undefined behaviour of primitive types, and perhaps utilizing a primitive type 'wrapper' of some sort, to offer clear conversion behaviour and bounds/exception checks under all circumstances. This is not a trivial exercise.

Quote:

char buffer[256];
std::cin >> buffer;


Are there dangers with this though?


std::string buffer;
std::cin >> buffer;


--random

[Edited by - random_thinker on October 1, 2007 5:58:15 PM]

Share this post


Link to post
Share on other sites
Following on from the previous post...imho, if a type wrapper (class) is applied as suggested previously (to which C++ has many advantages over C and other languages), and the programmer strictly applies the C++ Standard library, then the remaining risk will not be a language risk, but logic risk, which is the same risk that will occur with any programming language.

Mad...if you want to find out what safety/security risks there are, and you have the time, start out by trying to write a primitive type wrapper class for safe types; you will learn a lot about the grass-roots problems associated with primitive types, and how C++ uses them. It is also an excellent way to learn the basics of C++.

--random

Share this post


Link to post
Share on other sites
Quote:
Original post by King Mir
C++ is not an interpreted language; there is no way (short of writing your own interpreter) to execute C++ code read from a file.

This reminds me of a pretty recent exploit in what I believe was a png library (I can't find any references to the article anymore, I could be wrong and it wasn't a png lib).
The problem occurred when loading a file it used the header information to allocate a buffer, however, it read the entire file into the buffer without checking if it would actually fit in the buffer.
So, for example, it would allocate a 200 byte buffer based on the header information, but it would read 400 bytes from the file because that's how big the file was. Those last 200 bytes could contain arbitrary executable code.

I could be wrong about the details, but that was the general gist of it. And when I read that it kind of shocked me because in the past I wrote code that was vulnerable to these kind of attacks. You know... just taking the easy route, put 1024 bytes on the stack, read the entire file, because heck... the file will never be bigger than 1024 bytes... riiiiiiight.
Luckily this was just for hobby projects and I got a bit wiser over the years, but it's still pretty hard to write secure code. And probably even more so in C++ because you are working (relatively) close to the memory without any real safety net that will prevent you from making mistakes like that.

Share this post


Link to post
Share on other sites
Quote:
Original post by Antheus
Perhaps a better way of putting it would be this:

- You can exploit a program in n ways
- You can exploit a program written in C++ in n+1 ways
But a "program written in C++" is also a "program", therefore:
You can exploit a program written in C++ in (((((n+1)+1)+1)+1)+1)+1 ways etc...

In other words, you forgot to exclude C++ from the first statement, although I disagree with the idea that a particular language can somehow provide 1 additional type of exploit over every other type of language, anyway.

Share this post


Link to post
Share on other sites
Quote:
Original post by Antheus
- Never ever under any circumstances use raw pointers
- Never allocate memory manually

How am I supposed to implement my smart pointer class then? ;-P

(If the answer is "use boost's smart pointers", then I can't because they're obviously a security risk because they use raw pointers internally)

Share this post


Link to post
Share on other sites

This topic is 3729 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this