#!/usr/bin/perl -w
#
# Copyright (C) 2007, Joshua D. Abraham (jabra@spl0it.org)
#
# 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
# use strict;
#
# post_fuzzer - fuzz a http login page using POST
#
# ex: $ ./post_fuzzer.pl --url http://www.DOMAIN.com/post \ 
#    --fields user,passwd --values USER,PASS 
#
# 
# ex: $ ./post_fuzzer.pl --url http://www.DOMAIN.com/post \ 
#    --fields user,passwd \
#    --userlist USER_LIST_FILE.txt --passwdlist PASSWORD_LIST_FILE.txt 
#
#
use strict;
use LWP::UserAgent;
use Getopt::Long;
use HTTP::Request::Common;
use Array::Each;
my $ua = LWP::UserAgent->new;
use vars qw( $PROG );
( $PROG = $0 ) =~ s/^.*[\/\\]//;    # Truncate calling path from the prog name

my $AUTH    = 'Joshua D. Abraham';  # author
my $EMAIL    = 'jabra@spl0it.org';  # email
my $VERSION = '1.0';                # version

my %options;
my $url;

my ( $field1, $field2, $value1, $value2 );
my ( @value1list, @value2list );

#
# help: ->
# display help information
# side effect:  exits program
#
sub help {
    print "Usage: $PROG [Options]
   -u  --url                      Post URL
       --fields  [field1,field2]  Name of the fields to test
       --values [value1,value2]   Values to test 
        
       --userlist [file]          File w/ values to test in field 1           
       --passlist [file]          File w/ values to test in field 2

   -v  --version                  Display version
   -h  --help                     Display this information

Send Comments to $AUTH ( $EMAIL )\n";
    exit;
}

#
# print_version ->
# displays version
# side effect: exits program
#
sub print_version {
    print "$PROG version $VERSION by $AUTH ( $EMAIL )\n";
    exit;
}

#
# post: value1 value2  ->
# post values to url
#
sub post {
    my ($value1, $value2) = @_;
    my $response = $ua->request(POST $url, [$field1 => $value1, $field2 => $value2]);
    # Check the outcome of the response
    if ($response->is_success) {
        print "Sucess! ( $field1 = $value1   $field2 = $value2 )\n";
        exit;
    }
    else {
        print "Failiure" . $response->status_line, "\n";
    }
}

GetOptions(
    \%options,
    'userlist=s', 'passwdlist=s','fields=s','values=s',
    'url|u=s',
    'help|h'    => sub { help(); },
    'version|v' => sub { print_version(); },
    )
    or exit 1;
if ( $options{url} ) {
    $url = $options{url};
}
if ( $options{fields} ) {
    ($field1, $field2) = split(',', $options{fields});
}
if ( $options{values} ) {
    ($value1, $value2) = split(',', $options{values});
}

if ( $options{userlist} ) {
    my $file = $options{userlist};
    open(INPUT, "<$file");
    while( <INPUT> ) {
        chomp;
        push(@value1list,$_);
    }
}
if ( $options{passwdlist} ) {
    my $file = $options{passwdlist};
    open(INPUT, "<$file");
    while( <INPUT> ) {
        chomp;
        push(@value2list,$_);
    }
}
if ( !defined($url) or !defined($field1) or !defined($field2) ) {
    help();
}
if ( scalar(@value1list) >= 1  and scalar(@value2list) >= 1 ) {
    my $set = Array::Each->new( \@value1list, \@value2list );
    while( my( $value1_list, $value2_list, ) = $set->each() ) {
        post($value1_list, $value2_list);
    }
}
elsif ( scalar(@value1list) >= 1 ) {
    if ( !defined($value2) ) {
        help();
    }
    foreach(@value1list) {
        post($_, $value2);
    }
}
elsif ( scalar(@value2list) >= 1 ) {
    if ( !defined($value1) ) {
        help();
    }
    foreach(@value2list) {
        post($value1, $_);
    }
}
else {
    if ( !defined($value1) or !defined($value2) ) {
        help();
    }
    post($value1, $value2);
}
