1#!/usr/local/bin/perl
2#
3# Package to craft and send the HTTP requests
4# by chr1x & nitr0us
5#
6
7package DotDotPwn::HTTP;
8use Exporter 'import';
9@EXPORT = qw(FuzzHTTP);
10
11use DotDotPwn::BisectionAlgorithm;
12
13use HTTP::Request;
14use LWP::UserAgent;
15use Time::HiRes qw(usleep);
16
17sub FuzzHTTP{
18	my ($host, $port, $ssl, $method, $ping, $bisection_request) = @_;
19	our $n_travs = 0;
20	my $false_pos = 0;
21	my $foo = 0; # Used as an auxiliary variable in quiet mode (see below)
22	my $UserAgent;
23
24	open(AGENTS, "/usr/local/share/dotdotpwn/User-Agents.txt") or die "[-] Cannot open User-Agents.txt file: $!";
25	my @UserAgents = <AGENTS>;
26	close(AGENTS);
27
28	if(!$bisection_request){
29		open(REPORT , ">>$main::report");
30	}
31
32	foreach my $traversal (@main::traversals){
33		my $http = LWP::UserAgent->new();
34
35		$UserAgent = @UserAgents[int(rand(@UserAgents))];
36                my $request = new HTTP::Request $method, '' . ($ssl ? "https://" : "http://") . "$host" . ($port ? ":$port" : "") . "/" . $traversal;
37		$UserAgent =~ s/[\r\n]//g;
38                $request->header('User-Agent', $UserAgent);
39
40		# Return 1 (vulnerable) or 0 (not vulnerable) to BisectionAlgorithm()
41		if($bisection_request){
42			my $reponse = $http->request($bisection_request);
43
44			if($response->code == 200){
45				if($main::pattern){
46					if($http->content() =~ /$main::pattern/s ){
47						return 1; # Vulnerable
48					} else {
49						return 0; # Not Vulnerable
50					}
51				} else {
52					return 1; # Vulnerable
53				}
54			} else {
55				return 0; # Not Vulnerable
56			}
57		}
58
59		#my $request = new HTTP::Request $method, "http://$host" . ($port ? ":$port" : "") . "/" . $traversal;
60    #$request->header('User-Agent', $UserAgent);
61    my $response = $http->request($request);
62		if($response->message =~ /[Cc]onnect/){ # LWP reports 500 errors for Connection failed, timeout, etc :(
63			my $runtime = time - $main::start_time;
64			for my $fh (STDOUT, REPORT) {
65				print  $fh "\n[+] False positives detected: $false_pos" if $false_pos > 0;
66				printf $fh "\n[+] Fuzz testing finished after %.2f minutes ($runtime seconds)\n", ($runtime / 60);
67				print  $fh "[+] Total Traversals found (so far): $n_travs\n";
68			}
69			if(!$ping){
70				die "[-] Web server ($host) didn't respond !\n";
71			}
72		}
73
74		if($response->code == 200){
75			if($main::pattern){
76				if($response->content =~ /$main::pattern/s ){
77					for my $fh (STDOUT, REPORT) { print $fh "\n[*] Testing Path (response analysis): ".$request->uri." <- VULNERABLE!\n"; }
78					$n_travs++;
79
80					if($main::bisect){
81						print "\n[========= BISECTION ALGORITHM  =========]\n\n";
82						DotDotPwn::BisectionAlgorithm::BisectionAlgorithm(1, $main::bisdeep, $request);
83
84						return 1;
85					}
86
87					return $n_travs if $main::break;
88				} else {
89					if($main::quiet){
90						print ". " unless $foo++ % $main::dot_quiet_mode;
91					} else {
92						print "\n[*] Testing Path: ".$request->uri." <- FALSE POSITIVE!\n";
93					}
94
95					$false_pos++;
96				}
97			} else {
98				for my $fh (STDOUT, REPORT) { print $fh "\n[*] Testing Path: ".$request->uri." <- VULNERABLE!\n"; }
99				$n_travs++;
100
101				if($main::bisect){
102					print "\n[========= BISECTION ALGORITHM  =========]\n\n";
103					DotDotPwn::BisectionAlgorithm::BisectionAlgorithm(1, $main::bisdeep, $request);
104
105					return 1;
106				}
107
108				return $n_travs if $main::break;
109			}
110
111			usleep($main::time);
112			next;
113		}
114
115		if($main::quiet){
116			print ". " unless $foo++ % $main::dot_quiet_mode;
117		} else{
118			print "[*] HTTP Status: " . $response->code . " | Testing Path: ".$request->uri."\n";
119		}
120
121		usleep($main::time);
122        }
123
124	for my $fh (STDOUT, REPORT) { print $fh "\n[+] False positives detected: $false_pos" if $false_pos > 0; }
125
126	return $n_travs;
127}
128