1#!/usr/local/bin/perl 2# DotDotPwn - The Directory Traversal Fuzzer 3# Copyright (C) 2012 Christian Navarrete and Alejandro Hernandez H. 4# 5# This program is free software: you can redistribute it and/or modify 6# it under the terms of the GNU General Public License as published by 7# the Free Software Foundation, either version 3 of the License, or 8# (at your option) any later version. 9# 10# This program is distributed in the hope that it will be useful, 11# but WITHOUT ANY WARRANTY; without even the implied warranty of 12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13# GNU General Public License for more details. 14# 15# You should have received a copy of the GNU General Public License 16# along with this program. If not, see <http://www.gnu.org/licenses/> 17# 18# ==================================================================== 19# 20#-=[]=--=[]=--=[]=--=[]=--=[]=--=[]=--=[]=--=[]=--=[]=--=[]=--=[]=--=[ 21# -=[ 22# DotDotPwn - The Directory Traversal Fuzzer -=[ 23# is a production of: -=[ 24# -=[ 25# CubilFelino Chatsubo -=[ 26# Security Research Lab and [(in)Security Dark] Labs -=[ 27# chr1x.sectester.net chatsubo-labs.blogspot.com -=[ 28# http://twitter.com/chr1x http://twitter.com/nitr0usmx -=[ 29# -=[ 30#-=[]=--=[]=--=[]=--=[]=--=[]=--=[]=--=[]=--=[]=--=[]=--=[]=--=[]=--=[ 31# 32# 33# Changes (Read CHANGELOG.txt for Details): 34# 35# * DotDotPwn v3.0.2: The Directory Traversal Fuzzer 36# by nitr0us & chr1x & Contributors (AUTHORS.txt) 37# 38# * DotDotPwn v2.1: The Directory Traversal Fuzzer 39# by chr1x & nitr0us 40# 41# * DotDotPwn v2.0: From checker to Fuzzer 42# by nitr0us (nitrousenador@gmail.com) 43# http://chatsubo-labs.blogspot.com 44# 45# * DotDotPwn v1.0 - Teh Directory Traversal Checker 46# by chr1x@sectester.net 47# http://chr1x.sectester.net 48# 49 50use lib qw(.); 51 52$| = 1; # forces a flush after every write or print 53$SIG{INT} = \&abort; # When ctrl + C is pressed, the abort function prints useful info 54 55## DotDotPwn Core Modules ## 56use DotDotPwn::TraversalEngine; 57 58## DotDotPwn Protocol Modules ## 59use DotDotPwn::HTTP; 60use DotDotPwn::HTTP_Url; 61use DotDotPwn::FTP; 62use DotDotPwn::TFTP; 63use DotDotPwn::Payload; 64use DotDotPwn::STDOUT; 65 66## DotDotPwn Misc Modules ## 67use DotDotPwn::Fingerprint; 68use DotDotPwn::BisectionAlgorithm; 69 70## Perl modules ## 71use Getopt::Std; 72#use Switch; 73 74my $DotDotPwn = 75'################################################################################# 76# # 77# CubilFelino Chatsubo # 78# Security Research Lab and [(in)Security Dark] Labs # 79# chr1x.sectester.net chatsubo-labs.blogspot.com # 80# # 81# pr0udly present: # 82# # 83# ________ __ ________ __ __________ # 84# \______ \ ____ _/ |_\______ \ ____ _/ |_\______ \__ _ __ ____ # 85# | | \ / _ \\\\ __\| | \ / _ \\\\ __\| ___/\ \/ \/ // \ # 86# | ` \( <_> )| | | ` \( <_> )| | | | \ /| | \ # 87# /_______ / \____/ |__| /_______ / \____/ |__| |____| \/\_/ |___| / # 88# \/ \/ \/ # 89# - DotDotPwn v3.0.2 - # 90# The Directory Traversal Fuzzer # 91# http://dotdotpwn.sectester.net # 92# dotdotpwn@sectester.net # 93# # 94# by chr1x & nitr0us # 95################################################################################# 96 97'; 98 99if(@ARGV < 2){ # -m module required 100 print $DotDotPwn; # Banner 101 102 print "Usage: $0 -m <module> -h <host> [OPTIONS]\n"; 103 print "\tAvailable options:\n"; 104 print "\t-m\tModule [http | http-url | ftp | tftp | payload | stdout]\n"; 105 print "\t-h\tHostname\n"; 106 print "\t-O\tOperating System detection for intelligent fuzzing (nmap)\n"; 107 print "\t-o\tOperating System type if known (\"windows\", \"unix\" or \"generic\")\n"; 108 print "\t-s\tService version detection (banner grabber)\n"; 109 print "\t-d\tDepth of traversals (e.g. deepness 3 equals to ../../../; default: 6)\n"; 110 print "\t-f\tSpecific filename (e.g. /etc/motd; default: according to OS detected, defaults in TraversalEngine.pm)\n"; 111 print "\t-E\tAdd \@Extra_files in TraversalEngine.pm (e.g. web.config, httpd.conf, etc.)\n"; 112 print "\t-S\tUse SSL for HTTP and Payload module (not needed for http-url, use a https:// url instead)\n"; 113 print "\t-u\tURL with the part to be fuzzed marked as TRAVERSAL (e.g. http://foo:8080/id.php?x=TRAVERSAL&y=31337)\n"; 114 print "\t-k\tText pattern to match in the response (http-url & payload modules - e.g. \"root:\" if trying /etc/passwd)\n"; 115 print "\t-p\tFilename with the payload to be sent and the part to be fuzzed marked with the TRAVERSAL keyword\n"; 116 print "\t-x\tPort to connect (default: HTTP=80; FTP=21; TFTP=69)\n"; 117 print "\t-t\tTime in milliseconds between each test (default: 300 (.3 second))\n"; 118 print "\t-X\tUse the Bisection Algorithm to detect the exact deepness once a vulnerability has been found\n"; 119 print "\t-e\tFile extension appended at the end of each fuzz string (e.g. \".php\", \".jpg\", \".inc\")\n"; 120 print "\t-U\tUsername (default: 'anonymous')\n"; 121 print "\t-P\tPassword (default: 'dot\@dot.pwn')\n"; 122 print "\t-M\tHTTP Method to use when using the 'http' module [GET | POST | HEAD | COPY | MOVE] (default: GET)\n"; 123 print "\t-r\tReport filename (default: 'HOST_MM-DD-YYYY_HOUR-MIN.txt')\n"; 124 print "\t-b\tBreak after the first vulnerability is found\n"; 125 print "\t-q\tQuiet mode (doesn't print each attempt)\n"; 126 print "\t-C\tContinue if no data was received from host\n"; 127 128 exit; 129} 130 131getopts("qXOSsCbEm:h:U:P:f:u:k:d:x:t:p:o:r:M:e:"); 132 133our $module = $opt_m || die "Module is neccesary (-m)\n"; 134our $host = $opt_h || die "Hostname is neccesary (-h)\n" unless ($module eq "http-url" || $module eq "stdout"); 135our $user = $opt_U || 'anonymous'; 136our $pass = $opt_P || 'dot@dot.pwn'; 137our $method = $opt_M || 'GET'; 138my $deep = $opt_d || 6; 139our $bisdeep = 16; # Deepness used when the Bisection Algorithm is going to be used (-X switch) 140our $quiet = $opt_q; 141our $break = $opt_b; 142our $url = $opt_u; 143my $ssl = $opt_S; 144our $pattern = $opt_k; 145my $file = $opt_f; 146our $extra_f = $opt_E; 147our $extens = $opt_e; 148my $OS = $opt_O; 149my $o_type = $opt_o; 150my $serv = $opt_s; 151my $ping = $opt_C; 152our $bisect = $opt_X; 153our $time = ($opt_t || 300) * 1000; # Time in milliseconds between each test 154our $start_time; # Will hold the time at the beginning of execution 155our $runtime; # Will hold the difference between the end time and $start_time, so, it's the runtime 156my $payload_file = $opt_p; 157our $payload; # The content of $payload_file 158my $proto_url; 159my $proto; 160our $port; 161our $dot_quiet_mode = 10; # When quiet mode is enabled, print a dot (.) each 10 attempts 162my $n_travs = 0; # Counter of Traversals found 163our @traversals; # Traversal strings generated by the Traversal Engine that will be launched against the target 164 165print $DotDotPwn if $module ne "stdout"; 166 167 168# Variable asignment and other validations per module 169#switch($module){ 170if ($module eq "ftp") { 171 $port = $opt_x || 21; 172} elsif ($module eq "http") { 173 $port = $ssl ? 443 : 80; $port = $opt_x if $opt_x; 174} elsif ($module eq "tftp") { 175 $port = $opt_x || 69; 176} elsif ($module eq "http-url") { 177 die "URL is neccesary (-u)\n" unless $url; 178 179 # URL Parsing 180 die "Invalid URL format!\n" if $url !~ m|(\w+)://([\w\.\-]+):?(\d*)?/|; 181 182 $port = 80; 183 $proto_url = $1; 184 $port = 443 if ($proto_url eq 'https'); 185 $host = $2; 186 $port = $3 if $3; 187 188 #die "'$proto_url' Protocol not supported\n" if $proto_url ne "http"; 189 die "No \"TRAVERSAL\" keyword found in the supplied URL\n" if $url !~ /TRAVERSAL/; 190 die "Pattern string to match is neccesary (-k)\n" unless $pattern; 191} elsif ($module eq "payload") { 192 $port = $opt_x || die "Port number is necessary (-x)\n"; 193 die "Payload file is necessary (-p)\n" unless $payload_file; 194 die "Pattern string to match is neccesary (-k)\n" unless $pattern; 195 196 open PAYLOAD_FD, $payload_file or die "Cannot open $payload_file: $!"; 197 198 # Undef the end of record character to read the whole file into one scalar variable 199 undef $/; 200 201 $payload = <PAYLOAD_FD>; 202 203 close PAYLOAD_FD; 204 205 $/ = "\n"; # Restore for normal behaviour 206 207 die "No \"TRAVERSAL\" keyword found in the supplied payload file\n" if $payload !~ /TRAVERSAL/; 208} elsif ($module eq "stdout") { 209 @traversals = TraversalEngine(OS_type($o_type), $deep, $file); 210 toSTDOUT(); 211 exit; 212} else { print "[-] Invalid Module ($module)!\n"; exit; } 213#} 214 215 216($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime(time); 217 218our $report; 219 220if($opt_r) { 221 $report = "Reports/" . $opt_r; 222} else { 223 $report = sprintf "Reports/%s_%02d-%02d-%d_%02d-%02d.txt", $host, $mon+1, $mday, $year+1900, $hour, $min; 224} 225 226print "[+] Report name: $report\n"; 227 228open(REPORT , ">$report"); 229 230printf REPORT "\n[+] Date and Time: %02d-%02d-%4d %02d:%02d:%02d\n",$mon+1, $mday, $year+1900, $hour, $min, $sec; 231 232# Target information 233for my $fh (STDOUT, REPORT) { 234 print $fh "\n[========== TARGET INFORMATION ==========]\n"; 235 print $fh "[+] Hostname: $host\n"; 236} 237 238if($OS){ 239 for my $fh (STDOUT, REPORT) { print $fh "[+] Detecting Operating System (nmap) ...\n"; } 240 $target_OS = OS_Detection($host); 241 for my $fh (STDOUT, REPORT) { print $fh "[+] Operating System detected: " . $target_OS . "\n"; } 242} 243 244# Manual definition of OS type if known 245if($o_type) { 246 if( ($o_type eq "unix") || ($o_type eq "windows") || ($o_type eq "generic") ) { 247 $target_OS = $o_type; # Overwrite the previously OS type detected by nmap. It has more importance! 248 for my $fh (STDOUT, REPORT) { print $fh "[+] Setting Operating System type to \"" . $target_OS . "\"\n"; } 249 } else { 250 for my $fh (STDOUT, REPORT) { print "[-] Invalid OS type \"" . $o_type . "\"... Using the previously detected by nmap (if -O enabled)\n"; } 251 } 252} 253 254$proto = $proto_url || ($module eq "payload" ? "N/A" : $module); 255 256for my $fh (STDOUT, REPORT) { print $fh "[+] Protocol: $proto\n"; } 257for my $fh (STDOUT, REPORT) { print $fh "[+] Port: $port\n"; } 258for my $fh (STDOUT, REPORT) { print $fh "[+] Service detected:\n" . Banner_Grabber($host, $port, $proto) if $serv; } 259 260 261#Traversal Engine 262for my $fh (STDOUT, REPORT) { print $fh "\n[=========== TRAVERSAL ENGINE ===========]\n"; } 263@traversals = TraversalEngine(OS_type($target_OS), $deep, $file); 264for my $fh (STDOUT, REPORT) { print $fh "[+] Traversal Engine DONE ! - Total traversal tests created: " . scalar(@traversals) . "\n"; } 265 266 267# Testing 268print "\n[=========== TESTING RESULTS ============]\n"; 269printf "[+] Ready to launch %.2f traversals per second\n", (1000000 / $time); 270print "[+] Press Enter to start the testing (You can stop it pressing Ctrl + C)\n"; 271<STDIN>; 272 273$start_time = time; 274 275# (nitr0us) 276# "use Switch" Added here again to avoid an existing bug in Switch.pm @ Perl 5.8 277# that raises an error in the next switch($module) statement 278# 279# http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=480106 280#use Switch; 281 282#switch($module){ 283if ($module eq "ftp") { $n_travs = FuzzFTP($host, $port, $user, $pass); } 284if ($module eq "http") { $n_travs = FuzzHTTP($host, $port, $ssl, $method, $ping); } 285if ($module eq "tftp") { $n_travs = FuzzTFTP($host, $port); } 286if ($module eq "payload") { $n_travs = FuzzPayload($host, $port, $ssl, $payload); } 287if ($module eq "http-url") { $n_travs = FuzzHTTP_Url($url, $ping); } 288#} 289 290$runtime = time - $start_time; 291for my $fh (STDOUT, REPORT) { 292 printf $fh "\n[+] Fuzz testing finished after %.2f minutes ($runtime seconds)\n", ($runtime / 60); 293 print $fh "[+] Total Traversals found: $n_travs\n"; 294} 295 296print "[+] Report saved: $report\n"; 297 298exit 31337; 299 300 301# Handler of Ctrl + C 302sub abort{ 303 # Don't know why, but the switch() statement never worked here =/ 304 305 if ($module eq "ftp") { $n_travs = $DotDotPwn::FTP::n_travs; } 306 elsif($module eq "http") { $n_travs = $DotDotPwn::HTTP::n_travs; } 307 elsif($module eq "http-url") { $n_travs = $DotDotPwn::HTTP_Url::n_travs; } 308 elsif($module eq "tftp") { $n_travs = $DotDotPwn::TFTP::n_travs; } 309 elsif($module eq "payload") { $n_travs = $DotDotPwn::Payload::n_travs; } 310 311 for my $fh (STDOUT, REPORT) { 312 print $fh "\n[+] Total Traversals found: $n_travs\n"; 313 print $fh "[-] Fuzz testing aborted\n"; 314 } 315 316 print "[+] Report saved: $report\n"; 317 318 exit; 319} 320