#!/usr/bin/env perl

#    Uniscan Web Vulnerability Scanner
#    Copyright (C) 2012  Douglas Poerschke Rocha
#
#    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 3 of the License.
#
#    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, see <http://www.gnu.org/licenses/>.
#
#    Development Team:
#
#	 Cicero Miguel Schons since version 6.1
#	 Douglas Poerschke Rocha since version 1.0

	
use lib "./Uniscan";
use Uniscan::Crawler;
use Uniscan::Functions;
use Uniscan::Scan;
use Uniscan::Bing;
use Uniscan::Google;
use Uniscan::FingerPrint;
use Uniscan::FingerPrint_Server;
use Uniscan::Configure;
use Uniscan::Http;
use Getopt::Std;

my $cfg = Uniscan::Configure->new(conffile => "uniscan.conf");
my %conf = $cfg->loadconf();
my $func = Uniscan::Functions->new();
my @urllist = ( );
my $scan;
our @urls = ();
$|++;

getopts('u:f:i:o:hbqwsdergj', \%args);
$func->createHTML();
$func->banner();
$func->CheckUpdate();

if($args{h}){
	$func->help();
}

if(!$args{u} && !$args{f} && !$args{i} && !$args{o}){
	$func->help();
}

if($args{u}){
	$args{u} = "http://" . $args{u} if($args{u} !~/^https?:\/\//);
	$args{u} .= "/" if($args{u} !~/\/$/);
	$func->check_url($args{u});
	push(@urllist, $args{u});
} 
elsif($args{f}){
	open(my $url_list, "<", "$args{f}") or die "$!\n";
	while(<$url_list>){
		my $line = $_;
		chomp $line;
		$func->check_url($line);
		push(@urllist, $line);
	}
	close($url_list);
}
elsif($args{i} && $args{o}){
	$func->writeHTMLCategory($conf{'lang2'});
	$func->write("="x99);
	$func->write("| Bing:");
	$func->writeHTMLItem("Bing:<br>");
	my $bing = Uniscan::Bing->new();
	$bing->search($args{i});
	$func->write("| " . $conf{'lang3'});
	$func->writeHTMLValue($conf{'lang3'});
	$func->write("="x99);
	$func->writeHTMLItem("Google:<br>");
	$func->write("| Google:");
	my $google = Uniscan::Google->new();
	$google->search($args{o});
	$func->writeHTMLValue($conf{'lang3'});
	$func->write("| ". $conf{'lang3'});
	$func->write("="x99);
	$func->writeHTMLCategoryEnd();
}
elsif($args{i}){
	$func->writeHTMLCategory($conf{'lang2'});
	$func->write("="x99);
	$func->write("| Bing:");
	$func->writeHTMLItem("Bing Search:<br>");
	my $bing = Uniscan::Bing->new();
	$bing->search($args{i});
	$func->writeHTMLValue($conf{'lang3'});
	$func->write("| ". $conf{'lang3'});
	$func->writeHTMLCategoryEnd();
}
elsif($args{o}){
	$func->writeHTMLCategory($conf{'lang2'});
	$func->write("="x99);
	$func->writeHTMLItem("Google Search:<br>");
	$func->write("| Google:");
	my $google = Uniscan::Google->new();
	$google->search($args{o});
	$func->writeHTMLValue($conf{'lang3'});
	$func->write("| ". $conf{'lang3'});
	$func->write("="x99);
	$func->writeHTMLCategoryEnd();
}
else{
    $func->help();
}

if($args{b}){
	&background();
	printf( $conf{'lang1'} . ": [%d]\n", $$);
}




$func->DoLogin();


foreach my $url (@urllist){
	$func->createHTML();
	$func->write($conf{'lang4'} . ": " . $func->date(0));

# check redirect and fix it
	my $crawler = Uniscan::Crawler->new();
	$func->writeHTMLCategory($conf{'lang5'});
	if($conf{'redirect'} == 1){
		$url = $func->CheckRedirect($url);
		my $url_temp = $url;
		my $proto = "";
		if($url_temp =~ /http:\/\//){
			$proto = "http://";
		}
		else{ $proto = "https://"; }
		$url_temp =~s/https?:\/\///g;
		if(rindex($url_temp, '/') != index($url_temp, '/')){
			$url_temp = $proto . substr($url_temp, 0, index($url_temp, '/')+1);
			$crawler->AddUrl($url_temp);
		}
	}

	push(@urls, $url);
	$crawler->AddUrl($url);
	$func->write("="x99);
	$func->write("| ". $conf{'lang6'} .": $url");
	$func->writeHTMLItem($conf{'lang6'});
	$func->writeHTMLValue($url);
	my $time1 = time();
	$func->GetServerInfo($url);
	my $time2 = time();
	my $total_time = $time2 - $time1;
	
	if($total_time < 30){
		$func->write("| IP: ". $func->GetServerIp($url));
		$func->writeHTMLItem($conf{'lang7'} . ":");
		$func->writeHTMLValue($func->GetServerIp($url));
		$func->writeHTMLCategoryEnd();
		$func->INotPage($url);
		$func->write("="x99);
		# web fingerprint
		if($args{g}){
			my $webf = Uniscan::FingerPrint->new();
			$func->writeHTMLCategory($conf{'lang8'});
			$webf->fingerprint($url);
			$webf->bannergrabing($url);
			$func->writeHTMLCategoryEnd();
		}

		# server fingerprint
		if($args{j}){
			my $serverf = Uniscan::FingerPrint_Server->new();
			$func->writeHTMLCategory($conf{'lang9'});
			$serverf->fingerprintServer($url);
			$func->writeHTMLCategoryEnd();
		}

		# start checks to feed the crawler
		#DIRECTORY CHECKS
		$func->writeHTMLCategory($conf{'lang10'});
		if($args{q}) {
			$func->write("|\n| ". $conf{'lang11'} .":");
			$func->writeHTMLItem($conf{'lang11'} .":<br>");
			my $http = Uniscan::Http->new();
			my $req = $url . "uniscan" . int(rand(1000)) . "/";
			my $res = $http->HEAD($req);
			if($res->code !~/404/){
				$func->write("| ". $conf{'lang12'}. " $req " . $conf{'lang13'});
				$func->writeHTMLValue($conf{'lang12'}." $req " . $conf{'lang13'});
			}
			else {
				my @dir = $func->Check($url, "Directory");
				foreach my $d (@dir){
					$crawler->AddUrl($d);
				}
				@dir   = ();
			}
			$func->write("="x99);
		}
		#FILE CHECKS
		if($args{w}) {
			$func->write("|" . " "x99);
			$func->write("| ". $conf{'lang14'} .":");
			$func->writeHTMLItem($conf{'lang14'} . ":<br>");
			my $http = Uniscan::Http->new();
			my $req = $url . "uniscan" . int(rand(1000)) . "/";
			my $res = $http->HEAD($req);
			if($res->code !~/404/){
				$func->write("| " . $conf{'lang12'} ." $req " . $conf{'lang13'});
				$func->writeHTMLValue($conf{'lang12'} ." $req " . $conf{'lang13'});
			}
			else {
				my @files = $func->Check($url, "Files");
				foreach my $f (@files){
					$crawler->AddUrl($f);
				}
				@files = ();
			}
			$func->write("="x99);
		}
		#robots check
		if($args{e}){
			$func->write("|\n| ". $conf{'lang15'} .":");
			$func->writeHTMLItem($conf{'lang15'} .":<br>");
			foreach my $f ($crawler->CheckRobots($url)){
				$crawler->AddUrl($f);
			}
			
			$func->write("|\n| ". $conf{'lang144'} .":");
			$func->writeHTMLItem($conf{'lang144'} .":<br>");
			foreach my $f ($crawler->CheckSitemap($url)){
				$crawler->AddUrl($f);
			}
			
			$func->write("="x99);
		}
		# end of checks to feed the crawler

		if($args{d}){
			# crawler start
			$func->write("|\n| ". $conf{'lang16'} .":");
			$crawler->loadPlugins();
			@urls = $crawler->start();
			our @forms = $crawler->GetForms();
			foreach (@forms){
				push(@urls, $_);
			}
			# crawler end
			$crawler->Clear();
			$crawler = undef;
		}
		$func->writeHTMLCategoryEnd();
		$scan = Uniscan::Scan->new();
		if($args{d}){
			$func->writeHTMLCategory($conf{'lang17'});
			#start dinamic and static tests
			$func->write("="x99);
			$func->write("| ". $conf{'lang18'} .":");
			$scan->loadPluginsDynamic();
			$scan->runDynamic(@urls);
			$func->writeHTMLCategoryEnd();
		}
	
		if($args{s}){
			$func->writeHTMLCategory($conf{'lang19'});
			$func->write("="x99);
			$func->write("| ". $conf{'lang20'} .":");
			$scan->loadPluginsStatic();
			$scan->runStatic($url);
			$func->writeHTMLCategoryEnd();
		}
		$scan = undef;
		if($args{r}){
			use Uniscan::Stress;
			my $stress = Uniscan::Stress->new();
			$func->write("="x99);
			$func->writeHTMLCategory($conf{'lang21'});
			$func->write("| ". $conf{'lang22'} .":");
			$stress->loadPlugins();
			$stress->run(@urls);
			$func->writeHTMLCategoryEnd();
		}
		$func->write("="x99);
		$func->write( $conf{'lang23'} .": " . $func->date(1) . "\n\n\n");
	}
	else{
		$func->write("| [-] ". $conf{'lang24'});
	}
	@urls = ();
	$func->writeHTMLEnd();
	$func->MoveReport($url);
}


##############################################
# Function background
# This function put Uniscan to background mode
#
#
# Param: nothing
# Return: nothing
##############################################


sub background{
	
	$SIG{"INT"} = "IGNORE";
	$SIG{"HUP"} = "IGNORE";
	$SIG{"TERM"} = "IGNORE";
	$SIG{"CHLD"} = "IGNORE";
	$SIG{"PS"} = "IGNORE";
	our $pid = fork;
	exit if $pid;
	die "Fork problem: $!\n" unless defined($pid);
}
