Welcome!

Linux Authors: Lavenya Dilip, Ian Thain, Bruce Armstrong, Michael Sheehan, Ellen Rubin

Related Topics: Linux, Open Source

Linux: Article

"Secure Coding in C and C++" A Linux.SYS-CON.com Interview With Robert Seacord

An interview with Robert Seacord, senior vulnerability analyst at CERT

Robert C. Seacord, a senior vulnerability analyst at the CERT/Coordination Center at Carnegie Mellon University, has just published the book Secure Coding in C and C++ (Addison-Wesley, 2005). I sat down with him to discuss software security in the Linux environment and elsewhere.

LWM: There's an ongoing debate over whether Linux is more secure than Windows. Some people argue that since Linux's source code is freely available, it makes it easy for hackers to implement hacks and break into Linux systems, whereas this becomes more difficult with proprietary operating systems. What's your take on this topic?

RCS: I agree there's no real security through obscurity, but obscurity does provide an impediment. Attackers can "reuse" sections of code to develop exploits that have the same properties as the code they're attacking - an unintended but unfortunate consequence of reuse.

A number of security experts have argued that Open Source software is more secure because it's open to review by a broad range of individuals. However, Open Source software provides no guarantee that the software is reviewed or that those reviewing it understand the program's context in a larger system or the program's external interactions. In other words, just being able to read the code doesn't mean you have the wherewithal to do anything with it or about it.

On the other hand, attackers have also become adept at reverse-engineering executables so not releasing the source only slows attackers down. An analysis of CERT/CC vulnerability reports conducted by Omar Alhazmi at Colorado State University shows vulnerabilities accruing in both Windows and Linux operating systems at similar rates.

LWM: In your experience, which programming languages (e.g., C, C++, Java) provide the most secure programming safeguards and the most tools to ensure the code doesn't contain vulnerabilities?

RCS: While languages like Java that have automatic garbage collection, lack pointers, and have strict type checking can limit or prevent vulnerabilities resulting from buffer overflows and common dynamic memory management errors, programming errors that result in security vulnerabilities can happen in any language. There are tradeoffs that have to be considered in language and application development platforms that can't always be objectively reduced to "Which is more secure?"

Java programs can be vulnerable to SQL injection and cross-site scripting (XSS) vulnerabilities. Integer errors can also occur undetected, although the consequence of these errors is typically not as severe as they may be in C and C++ language programs.

Interestingly, Java language security may be due more to the reasons given above and less to Java bytecodes than typically understood. C++ programs compiled to MSIL in the Microsoft .NET environment are as susceptible to buffer overflows and other common vulnerabilities as their compiled counterparts, although additional security can be gained by using the new system-level data structures for arrays, strings, and other data types.

Because of the history of security vulnerabilities in C and C++, a number of tools and products have been developed to make these languages more secure. So, ironically, these languages generally have the best tool support.

LWM: What's the most important coding practice that we can implement to develop more secure software? Can you also provide us your Top 5 best practices for writing secure C/C++ code?

RCS: The most important coding practice is to be extremely paranoid in handling any data that originated with the user, either directly or indirectly.

As for the remaining four:

  1. Many vulnerabilities in C/C++ result from the incautious manipulation of strings. Your entire development team should select a clear and unambiguous approach to dealing with strings in your application and apply it consistently. C++ programmers have the option of using the standard std::string class, which is generally less error prone than standard C-style strings. C language programmers may want to consider using or building a string library so that all string operations (and potential vulnerabilities) can be isolated to a single module. CERT has begun developing a managed string library that could be used as the basis of such an effort and submitted it as a paper to the J11 WG14 C standard working group. Eventually we hope to release the source code for this library on the Secure Coding web site at www.cert.org/.
  2. Your entire development team should select a clear and unambiguous approach to dealing with integers and apply it consistently. Operations on integers can result in overflow, truncation, sign errors, and other related issues that can lead to exploitable vulnerabilities. Having a plan to deal with integers up-front is critical because almost every integer operation can result in an exceptional condition, particularly when the inputs can be controlled by an attacker. Generally speaking, you should limit all integer inputs to acceptable values and use safe integer operations that detect and report error conditions when dealing with "tainted" inputs.
  3. Sit down together as a development team and do code inspections. Maintain a list of common programming defects you find and make sure you check for these until they cease to be found. The inspections serve several purposes. First, they can be effective in identifying and removing defects in the code that can lead to vulnerabilities. Second, and potentially more importantly, it lets more experienced coders mentor less experienced team members about what to look for and how to correct problems. Third, inspections provide a mechanism for fostering a consistent approach to applying security-coding practices throughout the project.
  4. Use the defense-in-depth approach of applying multiple strategies so that a single error isn't necessarily fatal. Start with secure coding practices and then evaluate your code using a variety of manual processes and automated tools. Use a secure runtime environment as a final line of defense.
LWM: What are the three most dangerous C lib functions to use and why?

RCS: I would have to say gets(), strcpy(), and sprintf().

The gets() function is on the list because it can't be used safely. The function reads a line from standard input into the buffer until a terminating new line or EOF is found. In fact, the Linux man page for this function contains the following advice:

Because it is impossible to tell without knowing the data in advance how many characters gets() will read, and because gets() will continue to store characters past the end of the buffer, it is extremely dangerous to use.

There are two alternative functions that can be used: fgets() and gets_s(). The following example shows how these calls are used:

1.  #define BUFFSIZE 8
2.  int main(int argc, char *argv[]){
3.  char buff[BUFFSIZE]; // insecure use of gets()
4.  gets(buff);
5.  printf("gets: %s.\n", buff); // more secure use of fgets()
6.  if (fgets(buff, BUFFSIZE, stdin) == NULL) {
7.  printf("read error.\n");
8.  abort();
9.  }
10.  printf("fgets: %s.\n", buff); // more secure use of gets_s()
11.  if (gets_s(buff, BUFFSIZE) == NULL) {
12.  printf("invalid input.\n");
13.  abort();
14.  }
15.  printf("gets_s: %s.\n", buff);
16.  return 0;
17.  }

The fgets() function is defined in C99 and has similar behavior to gets().The fgets() function accepts two additional arguments: the number of characters to read and an input stream. The gets_s() function is defined in ISO/IEC TR 24731 to provide a compatible version of gets() that was less prone to buffer overflow.

The strcpy() function is on the list because, even though it can generally be used safely, it's often used in an insecure fashion, for example by dynamically allocating the required storage as shown below:

1.  int main(int argc, char *argv[]) {
2.  char *buff = (char *)malloc(strlen(argv[1])+1);
3.  if (buff != NULL) {
4.    strcpy(buff, argv[1]);
5.    printf("argv[1] = %s.\n", buff);
6.  }
7.  else {/* Couldn't get the memory - recover */
8.  }
9.  return 0;
10.  }

There are also many, many alternatives to using strcpy() that are generally less error prone, including strcpy_s(), strlcpy() (available for many flavors of Unix but not GCC/Linux), strdup(), and others.

More Stories By Ibrahim Haddad

Dr. Ibrahim Haddad is a seasoned telecommunications expert with over a decade of multinational experience in infrastructure, carrier grade, Linux mobile platforms, software development, standards, industry global initiatives, Open Source software and legal compliance. Dr. Ibrahim Haddad is currently Director of Open Source at Palm. His previous professional experiences include Ericsson, the Open Source Development Labs and Motorola. Haddad is the author of “Practical Guide to Open Source Compliance” to be published early 2010 and co-author of two books on Red Hat Linux and Fedora. Dr. Haddad is a Contributing Editor of the Linux Journal and served on numerous conference and review committees. Haddad received a B.Sc. and M.Sc. in Computer Science from the Lebanese American University (Byblos, Lebanon) and a Ph.D. in Computer Science from Concordia University (Montreal, Canada).

Comments (3) View Comments

Share your thoughts on this story.

Add your comment
You must be signed in to add a comment. Sign-in | Register

In accordance with our Comment Policy, we encourage comments that are on topic, relevant and to-the-point. We will remove comments that include profanity, personal attacks, racial slurs, threats of violence, or other inappropriate material that violates our Terms and Conditions, and will block users who make repeated violations. We ask all readers to expect diversity of opinion and to treat one another with dignity and respect.


Most Recent Comments
SYS-CON Australia News Desk 12/24/05 03:26:54 PM EST

Robert C. Seacord, a senior vulnerability analyst at the CERT/Coordination Center at Carnegie Mellon University, has just published the book Secure Coding in C and C++ (Addison-Wesley, 2005). I sat down with him to discuss software security in the Linux environment and elsewhere.

SYS-CON Canada News Desk 12/24/05 03:07:06 PM EST

Robert C. Seacord, a senior vulnerability analyst at the CERT/Coordination Center at Carnegie Mellon University, has just published the book Secure Coding in C and C++ (Addison-Wesley, 2005). I sat down with him to discuss software security in the Linux environment and elsewhere.

LinuxWorld News Desk 12/24/05 02:42:03 PM EST

"Secure Coding in C and C++" A LinuxWorld Interview With Robert Seacord. Robert C. Seacord, a senior vulnerability analyst at the CERT/Coordination Center at Carnegie Mellon University, has just published the book Secure Coding in C and C++ (Addison-Wesley, 2005). I sat down with him to discuss software security in the Linux environment and elsewhere.