tags:

views:

227

answers:

4

Hello all,

I am starting to learn everything about security and secure programming.

I have always heard about things like buffer overflow vulnerability.

But I don't know yet how such vulnerabilities are exploited. And how can we program securely enough to make sure that our code is robust.

When I say all this, my programming languages of interest are c and c++.

  1. I am looking for free tutorials, and resources on internet where I can learn every ins-n-out of secure programming.

  2. Platform specific tips are also welcome. For example, I know that in Windows programming we can use functions like "memmove_s" to have secure code. But what are the equivalents in Linux/Unix? Or is it the same there?

  3. Should a c/c++ programmer worry about specially crafted formatted stings (like the very popular old PHP formatted strings vulverability)?

A lot of questions here, but general idea is that I mean to learn Secure Programming.

Thanks for every bit of help.

+3  A: 

I'll throw a couple out there and make this community wiki:

  1. Never, ever, ever use gets.

  2. Don't assume a string is null terminated unless you really really know that it is.

  3. Never just declare a large fixed-size buffer and just assume it'll be "big enough" for what you are doing.

Eric Petroelje
Can you also share what is wrong with using "gets"?
bits
@bits: If you don't know what is wrong with `gets()`, I would strongly suggest that you obtain one of the introductory books listed on [The Definitive C++ Book Guide and List](http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list) and learn C++ before you concern yourself with writing programs with critical security requirements.
James McNellis
@James, I have owned and read some of the books mentioned there. For some reason, and yes, I don't know what is wrong with "gets" from security standpoint. It would be nicer if you would just explain.
bits
@bits - the problem with `gets` is that it doesn't do any bounds checking. If the amount of data is greater than the size of the buffer you provide, they will simply overflow the buffer.
Eric Petroelje
+2  A: 
  1. Assertions, assertions, assertions. If there's even the theoretical possibility that something might not be correct, go ahead and assert that it is. If something is not quite how you expected it, you want your program to die immediately and spectacularly. Make sure your assertions will not be optimized away.

  2. Be very careful with buffers. There are some functions (e.g. gets) that write into a buffer without knowing how big it is. Do not use these functions. Always check your buffer sizes right where you need them rather than relying on precomputed values.

  3. Always check return codes. If you cannot do anything meaningful on an error (e.g. malloc), then assert success, or better, write a wrapper function that asserts success so that it cannot possibly return an error value and never use the original. To be extra-paranoid, have your compiler emit a warning if you implicitly ignore a return value.

  4. Treat any data entering the program as a possible malicious attack, because it is. This includes configuration files as well as user input.

  5. "Premature optimization is the root of all evil". First make it right. Don't even think about making it faster unless a) you absolutely have to and b) you have profiled the code and know precisely what your bottlenecks are.

  6. Have someone else check your code.

These are only a handful of starting points. Writing secure code is hard.

Thom Smith
1. and 3.: Don't use assert for runtime checks. Use it to check the correctness of the program, e.g. if a function expects a pointer to not be NULL, assert is perfect for this, because it is a precondition for the function and it is the programmer's responsibility to fulfill the preconditions. OTOH malloc returning NULL is a runtime error that can occur anytime without your control, so it should be checked by regular code. If you use an always succeeding wrapper without caring for unsaved user data anyway, then if and exit is just as good.
Secure
Well, if you're already wrapping malloc with an if/exit, you might as well factor that out into a function. If malloc fails on a modern system, there's generally not a lot you can do to recover, and you shouldn't wait until there's an error to save user data in the first place.
Thom Smith
I was already talking about your "wrapper function that asserts success". ;) What you can do with a failing malloc surely depends on your error handling structure and recovery strategy -- if there is any at all, of course. How about trying to rescue unsaved data into a temporary disaster recovery file? If it works, it can be restored at the next program start. If it fails, no harm's done to the existing data. Depends on the application, for sure, and how important you regard the user's data.
Secure
You could certainly replace the exit in your malloc wrapper with a call to a save-and-exit function. My point is that you should have the user's data saved anyway, because a) your error-handling code should be itself error-proof, and b) your program could be forced to exit without having a chance to call your recovery code (for example, if you *really* run out of memory and the OS kills the process to reclaim some). Essentially, by the time things go wrong, it might well be too late to save the user's data, so you should try to keep your program in a state where you can exit safely.
Thom Smith
+2  A: 

Secure programming encompasses practices that reduce the chance of misuse by code maintainers themselves.

Here's my two cents -- Avoid using pointers where you can. In my opinion, a pointer should be used only when a NULL value has a special meaning. This principle carries over to several coding idioms

  • Use STL vectors instead of arrays
  • Use pass-by-reference/pass-by-value when passing basic types to a function
  • Use pass-by-const-reference when passing user-defined types to a function. This is as efficient as passing a pointer.

The bottomline is, if there's pointers involved, there's a good chance it will be misused by someone who will eventually inherit the code.

f64 rainbow