diff --git a/lib/Engine/Fuzzer.pm b/lib/Engine/Fuzzer.pm index f0e2eb2..d49993e 100755 --- a/lib/Engine/Fuzzer.pm +++ b/lib/Engine/Fuzzer.pm @@ -7,39 +7,41 @@ package Engine::Fuzzer { sub new { my ($self, $timeout, $headers, $skipssl, $proxy) = @_; - my $userAgent = Mojo::UserAgent -> new() -> request_timeout($timeout) -> insecure($skipssl); + my $userAgent = Mojo::UserAgent->new()->request_timeout($timeout)->insecure($skipssl); if ($proxy) { - $userAgent -> proxy -> http($proxy); - $userAgent -> proxy -> https($proxy); + $userAgent->proxy->http($proxy); + $userAgent->proxy->https($proxy); } - bless { + my $instance = bless { useragent => $userAgent, headers => $headers }, $self; + + return $instance; } sub request { my ($self, $method, $agent, $endpoint, $payload, $accept) = @_; - my $request = $self -> {useragent} -> build_tx ( + my $request = $self->{useragent}->build_tx( $method => $endpoint => { "User-Agent" => $agent, - %{$self -> {headers}} + %{$self->{headers}} } => $payload || "" ); try { - my $response = $self -> {useragent} -> start($request) -> result(); + my $response = $self->{useragent}->start($request)->result(); my $result = { "Method" => $method, "URL" => $endpoint, - "Code" => $response -> code(), - "Response" => $response -> message(), - "Content" => $response -> body(), - "Length" => $response -> headers() -> content_length() || "0" + "Code" => $response->code(), + "Response" => $response->message(), + "Content" => $response->body(), + "Length" => $response->headers()->content_length() || "0" }; return $result; @@ -47,7 +49,9 @@ package Engine::Fuzzer { catch { return 0; - } + }; + + return; } } diff --git a/lib/Engine/FuzzerThread.pm b/lib/Engine/FuzzerThread.pm index 8f10d7c..10525de 100644 --- a/lib/Engine/FuzzerThread.pm +++ b/lib/Engine/FuzzerThread.pm @@ -4,72 +4,72 @@ package Engine::FuzzerThread { use threads; use warnings; use Engine::Fuzzer; - + sub new { my ( $self, $queue, $target, $methods, $agent, $headers, $accept, $timeout, $return, $payload, $json, $delay, $exclude, $skipssl, $length, $content, $proxy ) = @_; - + my @verbs = split (/,/, $methods); my @valid_codes = split /,/, $return || ""; my @invalid_codes = split /,/, $exclude || ""; - + my $fuzzer = Engine::Fuzzer -> new($timeout, $headers, $skipssl, $proxy); my $format = JSON -> new() -> allow_nonref() -> pretty(); - + my $cmp; - + if ($length) { ($cmp, $length) = $length =~ /([>=<]{0,2})(\d+)/; - $cmp = sub { $_[0] >= $length } if ($cmp eq ">="); $cmp = sub { $_[0] <= $length } if ($cmp eq "<="); $cmp = sub { $_[0] != $length } if ($cmp eq "<>"); $cmp = sub { $_[0] > $length } if ($cmp eq ">"); $cmp = sub { $_[0] < $length } if ($cmp eq "<"); - $cmp = sub { $_[0] == $length } if (!$cmp or $cmp eq "="); + $cmp = sub { $_[0] == $length } if (defined($cmp) || $cmp eq "="); } - + async { while (defined(my $resource = $queue -> dequeue())) { - my $endpoint = $target . $resource; + my $endpoint = $target . $resource; my $found = 0; - + for my $verb (@verbs) { my $result = $fuzzer -> request($verb, $agent, $endpoint, $payload, $accept); - + unless ($result) { next; } - + my $status = $result -> {Code}; - - if (grep(/^$status$/, @invalid_codes) || ($return && !grep(/^$status$/, @valid_codes))) { + + if (scalar(grep { $_ eq $status } @invalid_codes) || ($return && !scalar(grep { $_ eq $status } @valid_codes))) { next; } - + if ($length && !($cmp -> ($result -> {Length}))) { next; } - + my $message = $json ? $format -> encode($result) : sprintf( "Code: %d | URL: %s | Method: %s | Response: %s | Length: %s", $status, $result -> {URL}, $result -> {Method}, $result -> {Response} || "?", $result -> {Length} ); - + print $message, "\n" if !$content || $result -> {Content} =~ m/$content/; - + sleep($delay); + $found = 1; } } }; - + return 1; } } -1; \ No newline at end of file +1; diff --git a/lib/Engine/Orchestrator.pm b/lib/Engine/Orchestrator.pm index 22a0ded..7ed1759 100644 --- a/lib/Engine/Orchestrator.pm +++ b/lib/Engine/Orchestrator.pm @@ -1,7 +1,8 @@ -package Engine::Orchestrator { +package Engine::Orchestrator { use strict; use threads; use warnings; + use Fcntl qw(O_RDONLY); use Engine::FuzzerThread; my $wordlist_queue; @@ -13,20 +14,22 @@ package Engine::Orchestrator { for (1 .. $number) { return unless (@{$list} > 0); - if (eof($list -> [0])) { + if (eof($list->[0])) { close shift @{$list}; - (@{$list} > 0) || $wordlist_queue -> end(); + (@{$list} > 0) || $wordlist_queue->end(); - next + next; } - my $filehandle = $list -> [0]; + my $filehandle = $list->[0]; chomp(my $line = <$filehandle>); - $wordlist_queue -> enqueue($line); + $wordlist_queue->enqueue($line); } + + return; } sub add_target { @@ -39,6 +42,8 @@ package Engine::Orchestrator { push @targets_queue, $target; } + + return; } sub run_fuzzer { @@ -51,27 +56,30 @@ package Engine::Orchestrator { $target = shift @targets_queue; } - $self -> threaded_fuzz($target, %options); + $self->threaded_fuzz($target, %options); } + + return 0; } sub threaded_fuzz { my ($self, $target, %options) = @_; my @current = map { - open(my $filehandle, "<$_") || die "$0: Can't open $_: $!"; + my $filehandle; + sysopen($filehandle, $_, O_RDONLY) || die "$0: Can't open $_: $!"; - $filehandle + $filehandle; } glob($options{wordlist}); - $wordlist_queue = Thread::Queue -> new(); + $wordlist_queue = Thread::Queue->new(); - use constant CONCURRENT_TASKS => 10; + my $CONCURRENT_TASKS = 10; - fill_queue(\@current, CONCURRENT_TASKS * $options{tasks}); + fill_queue(\@current, $CONCURRENT_TASKS * $options{tasks}); for (1 .. $options{tasks}) { - Engine::FuzzerThread -> new ( + Engine::FuzzerThread->new( $wordlist_queue, $target, $options{method}, @@ -92,11 +100,13 @@ package Engine::Orchestrator { ); } - while (threads -> list(threads::running) > 0) { + while (threads->list(threads::running) > 0) { fill_queue(\@current, $options{tasks}); } - map { $_ -> join() } threads -> list(threads::all); + map { $_->join() } threads->list(threads::all); + + close $_ for @current; return 0; }