Perl


Perl was a popular language for creating CGI scripts because it was well suited for rapid text-oriented Web programming. It's rarely encountered in new production systems, however; it's mostly been supplanted by PHP, Java, and Microsoft solutions. When present, it's usually confined to smaller one-off pieces of a larger Web application, and the code is often several years old.

Perl is an extremely flexible language, designed to give developers many ways to perform a task. A lot of "magic" is involved, with expressions performing nuanced behaviors behind the scenes to make things work smoothly. Needless to say, Perl has plenty of security pitfalls, too.

SQL Injection

Database access is usually done through the Perl DBI module, although other mechanisms can be used. In general, you should do a non-case-sensitive search for the strings DBI, ODBC, SQL, SELECT, EXECUTE, QUERY, and INSERT to locate database interaction code. The following is a brief example of what vulnerable SQL DBI code looks like in Perl:

use DBI; ... $dbh = DBI- >connect("DBI:mysql:test:localhost","test","tpass"); ... $sth = $dbh->prepare("select * from cars where brand='$brand'"); $sth->execute;


This code issues a simple vulnerable SQL query to a MySQL database. One interesting point is that this code first prepares and then executes the query. However, the prepared query is vulnerable because the user-supplied data is not bound.

File Access

Perl has flexible mechanisms for accessing the file system, but this flexibility makes these access mechanisms susceptible to user manipulation. The most common way to open a handle to a file is the open() function. It's dangerous to allow users to control parts of a filename string passed to this function, as the filename string can specify the access mode to the file or even tell open() it should spawn a shell and perform a command. These issues are covered at length in Chapter 8, "Strings and Metacharacters."

For example, say you have a CGI script that takes a user-supplied variable and places it in $firstname. The following code could be a security disaster:

open(MYHANDLE, "$firstname");


Users could specify a filename ending or starting in a pipe character and issue an arbitrary command with a filename such as "cat /etc/shadow|". Users could also open any file on the file system, for reading, writing, or appending.

Another important nuance to note is that Perl is susceptible to the NUL byte injection issue. It doesn't treat the NUL-terminating byte as the end of the string, but when its strings are passed to the underlying OS, the OS does honor them. So, if you had code like this:

open(MYHANDLE, "/usr/local/myapp/desc/".$firstname.".txt");


Users could specify a $firstname of ../../../../etc/passwd%00, and the code would end up opening /etc/passwd. The well-known security researcher Rain Forest Puppy (RFP) wrote an excellent article introducing the world to this problem, published in Issue 55 of Phrack magazine (www.phrack.org).

Shell Invocation

Programmers can start a command shell in numerous ways in Perl. Calling open() to open a command shell, as in the previous example, is the most devious case to look for because it usually catches developers by surprise. The system() and exec() functions are more straightforward and perform similarly to their standard library counterparts. Backticks are also an interesting built-in language construct for starting a subshell. So code similar to the following would be vulnerable:

$fileinfo= `ls l $filename`;


If users specify a filename of "/;cat /etc/passwd", the subshell would honor it as a two-command sequence.

File Inclusion

The require() function can be used to read in arbitrary code at runtime, so any situation in which users can modify the file argument to require() is dangerous. The use() function is safer because it's limited to loading Perl modules, and it works at compile time, not runtime. The do() function is used infrequently; It's roughly equivalent to require() in that it loads an external Perl file and runs it through the parser/interpreter. Here's an example of what a vulnerable use of the require statement might look like:

# assume $user_language is taken from a cookie my $module = "/usr/local/myapp/localization/conversion_"     . $user_language . "pm"; require $module;


This code attempts to load in a block of code to handle conversion of output into the correct language. It assumes the language taken from the cookie ($user_language) corresponds to a two-letter code, such as en or fr. If attackers use directory traversal and the NUL-byte injection, they can exploit the code to run any Perl file on the system.

Inline Evaluation

The eval() function evaluates Perl code dynamically, as does the /e regular expression modifier. If user-malleable data is used in the dynamically constructed code, attackers might be able to run arbitrary Perl. Razvan Dragomirescu, an independent researcher, discovered an instance of this vulnerability in the Majordomo mailing list manager (www.securityfocus.com/bid/2310). Here's the vulnerable code:

foreach $i (@array) {                       $command = "(q~$reply_addr~ =~ $i)";                       $result = 1, last if (eval $command);                    }


Attackers can exert just enough control over reply_addr to seize control of the script. Dragomirescu's exploitation technique embedded backticks in the reply address so that the Perl interpreter opened an attacker controlled subshell.

The eval() syntax is straightforward, as shown in the previous example. The /e modifier is a bit less common and might be harder to spot. Here's a basic example of how it could be used:

    s/\d+/sprintf("%5d",$&)/e;  # yields 'abc 246xyz'


If an attacker can modify the expression being executed, they can likely compromise the application causing to generate an attacker-controlled command line.

Cross-Site Scripting

Perl provides the HTML::Entities::encode() function to escape HTML metacharacters, and the URI::Escape::uri_encode() function for handling URLs. The HTML::Entities and URI::Escape modules include some additional interfaces to handle different encodings, among other things. The Apache::TaintRequest module can also be used to prevent reflected cross-site scripting through the Perl taint system. When auditing Perl code, look for the absence of any of these protection methods in code displaying user-malleable HTML.

Taint Mode

Taint mode is a novel feature of Perl that can be used in Web applications to help buttress their security and diagnose or discover security issues. It marks any external input as potentially tainted. If the program tries to do something sensitive with that input, it encounters an error and halts. Sensitive operations are tasks such as opening files, spawning subshells, dynamically evaluating code, and interacting with the file system, database, or network. The perlsec reference page in your Perl installation is a good place to start for learning more about taint mode.




The Art of Software Security Assessment. Identifying and Preventing Software Vulnerabilities
The Art of Software Security Assessment: Identifying and Preventing Software Vulnerabilities
ISBN: 0321444426
EAN: 2147483647
Year: 2004
Pages: 194

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net