Thursday, 18 August 2011

More on Secure coding

I am Continuing from a previous post on teaching secure coding as I getting ready to teach introductory C programming soon.

I am picking on some of Chapter 2 of the same book which is:
Teach Yourself C in 21 days by SAMS.

AGAIN, WHY must we teach bad code practices?

I will look at exercise 2.5 today. This is another example of the types of education and training we are providing in code development.

As I stated last time… It is through bad text-books that we have bad code and clueless developers!

In the book, right from the start they make liberal use of printf(). This chapter thewy also introduce “gets()”. Exercise 2.5 on page 40 of this book is listed below:

1: /* EX2-5.c */ 2: #include
3: #include

4: int main()
5: {
6: char buffer[256];
7: printf( "Enter your name and press enter\n" );
8: gets( buffer);
9:
10: printf( "\nYour name has %d characters and spaces!",
11: strlen( buffer ));
12: return 0;
13: }
14: /* End of Program */
Again, it works, so what is the problem you ask?

We see below a strange result from this. Here, we have a buffer overflow.

Line 6 of the code above has a buffer set at 256 characters. We entered a sting longer than that and we have again crashed the program. This is the cause of buffer overflows. it comes from not considering the fundamentals right from the start.

Yes, I have entered a ridiculously long name. This is an issue as we have not though of the exceptions to our use case. What about the abuse case? Attackers do not act as we want them to, this is why they are acting maliciously. We cannot leave errors and expect people to act nicely, we need to start thinking about what can go wrong and stop it from the beginning!

What we need to do is set the size of the buffer from the start. That is, change gets() to fgets() as is noted below:
gets (name);
to
fgets (name, 10, stdin);
This is a simple change to line 8 as we have listed below:
1: /* EX2-5.c */ 2: #include
3: #include

4: int main()
5: {
6: char buffer[256];
7: printf( "Enter your name and press enter\n" );
8: fgets( buffer, 256, stdin);
9:
10: printf( "\nYour name has %d characters and spaces!",
11: strlen( buffer ));
12: return 0;
13: }
14: /* End of Program */
Here, a simple change at line 8 has limited the input we will accept to a size that fits with the buffer we have configured in line 6..

I have not fixed all of the issues here. Some of the problems that I noted in the last post remain, but the buffer overflow from the gets() function has at least been fixed.
As I stated, NEVER use gets() – always use fgets(). This is not a complex change and takes just a few seconds. This simple change to how we teach developers makes such a vast difference!

I will reiterate the lesson from the other day:
Basically, STOP using strcpy(), strcat(), sprintf(), index(), or strchr() on buffers that might not contain a trailing NUL byte, or that could ever contain embedded NUL bytes (binary data). 

Instead… Use:
  • strncpy() or memcpy() or memmove() in place of strcpy()
  • memchr() in the place of index() or strchr()
  • snprintf() and never think of using sprintf()
  • fgets() and never ever consider using gets()
  • Just forget that bzero() and bcopy() ever existed
Reference:
The C FAQ:
http://c-faq.com/ or http://www.faqs.org/faqs/C-faq/faq/

For further information on the sprintf() problem and snprintf() solution see Section 12.21 of the FAQ.

No comments: