The CERT Perl Secure Coding Standard
As security specialists, we are often asked to audit software and provide expertise on secure coding practices. Our research and efforts have produced several coding standards specifically dealing with security in popular programming languages, such as C, Java, and C++. This posting describes our work on the CERT Perl Secure Coding Standard, which provides a core of well-documented and enforceable coding rules and recommendations for Perl, which is a popular scripting language.
Perl is a relatively young language, only slightly older than Java. Perl became popular early in its lifetime because it was the first general-purpose scripting language on many Unix platforms. Perl enjoyed a second burst of popularity as the web became prominent because it was especially well-suited to writing Common Gateway Interface (CGI) scripts.
In recent years Perl's popularity has been cemented by CPAN, a public repository of free software libraries written in Perl. Any computer with Perl installed provides straightforward mechanisms to install and use any software library from CPAN. This feature enables programmers to use libraries provided by the community easily and quickly. Several new features in Perl began life as CPAN modules before being integrated into the language. As a result of its popularity, many important software systems are written in Perl, such as the Request Tracker database (RT), an open-source project for managing tickets or bugs for a help desk, which is maintained by Best Practical Solutions. Many websites, such as amazon.com, also rely on Perl code on their servers.
The CERT Perl Secure Coding standard is still young and growing. The C and Java standards have more than 200 rules in about 20 sections each. The Perl standard currently has slightly more than 30 rules in the following eight sections:
- Input Validation and Data Sanitization - issues dealing with data provided by an attacker, such as XML injection and cross-site scripting (XSS).
- Declarations and Initialization - issues dealing with securely declaring variables and functions including package versus lexical variables, name clashes, and dangers of uninitialized data.
- Expressions - issues dealing with Perl's expressions syntax including list versus scalar contexts, when to use the $_ variable, and when to use the various types of comparison operators.
- Integers - issues dealing with numbers, such as how to specify octal numbers.
- Strings - issues dealing with strings and regular expressions (regexes) including the danger of providing a string literal to a subroutine that expects a regex.
- Object-Oriented Programming (OOP) - issues dealing with OOP are covered in this section, such as recognizing the convention of private variables.
- File Input and Output - issues dealing with how to safely work with files, including safely working with Perl's filehandles.
- Miscellaneous - issues that don't fall into other sections, such as handling dead code and unused variables.
Addressing Security Vulnerabilities in Perl
The Perl community has always prioritized practicality over theoretical elegance, and so it has always been considered an easy language to write code in--although Perl code is often considered ugly due to the tendency of some Perl developers to create "write only" programs. Perl was not designed as a secure programming language. However, problems relating to security in Perl programs have been discussed in security circles, and appear in databases such as the CERT vulnerability database. Moreover, companies that request software audits are just as likely to want Perl software audited as they are to request audits for C, C++, or Java. While the Perl community is interested in improving the language, the focus on security has historically tended to take a back seat to other priorities, such as new features and improved performance.
Our work on the CERT Perl Secure Coding Standard therefore centers on addressing issues in the Perl language and libraries that deal specifically with security. The standard covers issues, such as XML injection, integer security, and proper input and output, as outlined above. By making the standard publicly accessible, we invite the Perl community to help us improve the standard.
The standard leverages several sources to provide relevant material on security. For example, it takes advantage of the US-CERT vulnerability database, which contains entries on several vulnerabilities that address the Perl language or applications written in Perl. It also leverages experience gained from the Source Code Analysis Lab (SCALe), which has been used to perform security audits on several pieces of Perl code, including the previously-mentioned RequestTracker (RT) tool created by Best Practical Solutions. Other analysis tools, such as Perl::Critic, provide an automated audit of a Perl program by examining a codebase and producing a list of diagnostics. These diagnostics can range from insecure coding practices and bugs to stylistic issues. The SCALe project uses these tools to harvest the diagnostics that address security issues, while discarding diagnostics not relevant to security.
The CERT Perl standard can leverage the other CERT standards for security issues that are not bound to any particular language. For instance, many issues about securely opening files on a Unix machine are language-independent. As a result, these portions of CERT standards for security issues can affect any software that runs on Unix systems regardless of the language in which it is written.
While Perl has many of the same security issues that plague C and Java, several issues are unique to Perl. For example, Perl's open() function can take two arguments, with the latter argument being either a file name or a shell command. The open() function either opens the file or executes the command. If the argument begins or ends with a | (pipe) character, it is interpreted as a command to execute. Consequently, if an attacker can specify a filename to Perl's open() function--and that filename begins or ends with |--the attacker can cause Perl to execute the command for which the file is named. This issue is discussed further in rule IDS31-PL in the CERT Perl Secure Coding Standard.
Perl has some technology that appears similar to other languages but presents unique problems when examined more closely. For example, C, Java, and Perl all share the concept of an array, which is a continuous vector of items that can be accessed via an index. In C and Java, arrays are fixed-size, which means they are created to hold a specific number of elements and their size remains fixed until they are destroyed. Trying to refer to an element greater than the size of the array is illegal. For example, asking for the 11th element in a 10-element array in Java will cause an exception to be thrown, which usually causes the program to crash.
In contrast, Perl's arrays can grow over their lifetime. Assigning a value to the 11th element of a 10-element Perl array causes the array to grow in memory such that the array contains 11 elements, so the request becomes valid. This quality makes Perl an especially agreeable language to work with Ibecause it never reports that an array is too small. If you were to assign a value to the 1,000,000,000th element of an array,however, Perl would attempt to grow the array enough to accommodate the request and might exhaust memory.
Exhausting system memory, whether deliberate or unintentional, can lead to security vulnerabilities because a system with limited memory will refuse to provide memory to any program that requests more. At the same time, many programs fail to check whether their memory requests succeeded. A machine with no free memory, therefore, is likely to have running programs that crash, either unintentionally or by design, using some sort of "out of memory" error. Consequently, the CERT Perl Secure Coding standard contains rule IDS32-PL, which forbids allowing untrusted users from providing an array index, lest they cause Perl to exhaust memory with an excessively large number.
What's Ahead for the CERT Perl Secure Coding Standard
We are adding several rules each week, and presumably the Perl secure coding standard can grow to about the same size as the C or Java standards since it's comparable in scope. We welcome your assistance in helping us complete the standard.
Editor's Note: In response to feedback from our readers, this post has been edited. The post originally stated "Asking for the 11th element of a 10-element Perl array causes the array to grow in memory such that the array contains 11 elements, so the request becomes valid." As our readers pointed out in the comments section, "Simple asking is not enough." The post now states that "Assigning a value to the 11th element of a 10-element Perl array causes the array to grow in memory such that the array contains 11 elements, so the request becomes valid."
The CERT Perl Secure Coding Standard may be viewed at