Daniel is a business and technical systems analyst with a background in IT security and software development. He has four years of experience in the IT security field, including published academic research. His main areas of expertise include secure development, network security, and authentication. In addition to security, Daniel has a software development background in languages such as Java, PHP, SQL, and Perl. He also has over 12 years experience working with and administering various versions of Linux and related open-source software.
Secure Development - Buffer Overflows and Legacy Systems
Jul 20 2010
Due to vacation schedules and lots of other things going on this summer, "next week" has turned into "next month" for this final post in my top 10 series. Today's subject may be a little surprising to many developers: Aren't buffer overflows so 2003? Hasn't this been fixed in virtually all modern programming languages by preventing direct memory access? While the second statement is certainly true, it doesn't mean that today's developers don't need to be aware of buffer overflows, especially when interacting with closed-source and/or legacy software written in languages that allow arbitrary memory access (C and C++ being the most common examples).
Buffer overflows have a long and colorful history as one of the most persistent bugs to plague software developers (and IT security departments) since Robert Morris took down parts of the nascent Internet in 1988 with his infamous Morris Worm, which exploited buffer overflows in sendmail and the finger daemon. The basic problem occurs when a program allows user input to be stored in an array (buffer) without first checking that sufficient space is available. In programming languages that allow direct memory access, this can result in parts of the program itself being overwritten in memory. A skilled attacker can manipulate the input data to produce a predictable change in the program's execution flow, allowing the attacker to run any code of his choosing with the same privileges as the program being attacked.
In Java-based web applications, buffer overflows can crop up in the following areas:
- Legacy and Other Backend Systems - Legacy systems are often mission-critical, closed-source, and were usually designed and built before security was a big factor. In addition, many web applications today serve as front-ends to legacy systems and have to rely on them for a large amount of data processing. As a result, any underlying security problems affecting legacy systems (such as buffer overflows) can become exposed via its web front-end, and it becomes the job of the web application to mitigate this risk as much as possible.
- Native Code via JNI - Java Native Interface (JNI) is a powerful tool for integrating Java with native code (C, C++, assembly, etc.), especially when third-party libraries may only be available for a native language. Calling native code via JNI presents the same security issues (including buffer overflows) as running it as a separate program.
- OutOfMemoryException - This is only loosely related to buffer overflows, though it does illustrate the concept of "overflowing" the JVM with such a large amount of data that it runs out of memory and crashes the program. While this type of overflow cannot be exploited to control program execution, it can easily be used to launch a denial-of-service (DoS) attack on your application.
In general, defending against buffer overflows is fairly straightforward as long as you follow some basic guidelines:
- Input Validation - The basic defense against buffer overflows is simple: all user input must be properly length-checked before being stored. However, in many cases you may not have access to the source code, especially in the case of closed-source third-party libraries or legacy systems. In these instances, you'll have to rely on your front-end web application to perform the input validation before passing data to the backend.
- Calling Outside Programs - Use caution when calling out to executables (or JNI code) from within your web application: make sure that you use standard input validation techniques on all input before you pass it along, and don't forget to also validate the output from the outside program (which is really just another input to your application, but this is often overlooked).
- Use Standard Java Libraries - Java has standard libraries to address the vast majority of common development needs, so avoid using non-Java code when possible. For example, rather than calling out to sendmail via Runtime.exec(), use the JavaMail API. Not only does this improve your security posture, but it also gives you more flexibility and features. If you absolutely must use third-party native code, see item 2. (make sure you check both your input and program output thoroughly).
Next time, I will do a final wrap-up of the Top 10 series on web application vulnerabilities, summarizing the topics covered and linking them to OWASP's latest Top 10 list of general application security vulnerabilities. After that, the blog will continue by exploring other big-picture areas of the secure development process, such as security requirements gathering and testing.
© 2010 CapTech Ventures, Inc. All Rights Reserved. Legal Notices.