Network.Security.Tools [Electronic resources] نسخه متنی

اینجــــا یک کتابخانه دیجیتالی است

با بیش از 100000 منبع الکترونیکی رایگان به زبان فارسی ، عربی و انگلیسی

Network.Security.Tools [Electronic resources] - نسخه متنی

| نمايش فراداده ، افزودن یک نقد و بررسی
افزودن به کتابخانه شخصی
ارسال به دوستان
جستجو در متن کتاب
بیشتر
تنظیمات قلم

فونت

اندازه قلم

+ - پیش فرض

حالت نمایش

روز نیمروز شب
جستجو در لغت نامه
بیشتر
لیست موضوعات
توضیحات
افزودن یادداشت جدید









8.6. Complete Source Code



The rest of this chapter contains the complete source code for the
two scripts developed and outlined in this chapter.



8.6.1. simpleScanner.pl



Example 8-8 shows the full source code for the
simpleScanner.pl script.



Example 8-8. Code for simpleScanner.pl


#!/usr/bin/perl
use LWP::UserAgent;
use strict;
use Getopt::Std;
my %args;
getopts(''c:o:v'', \%args);
printReport("\n** Simple Web Application Scanner **\n");
if ($#ARGV < 1) {
die "\n$0 [-o <file>] [-c <cookie data>] [-v] inputfile
http://hostname\n\n-c: Use HTTP Cookie\n-o: Output File\n-v: Be Verbose\n";
}
# Open input file
open(IN, "< $ARGV[0]") or die"ERROR => Can''t open file $ARGV[0].\n";
my @requestArray = <IN>;
my ($oRequest,$oResponse, $oStatus, %dirLog, %paramLog);
printReport("\n** Beginning Scan **\n\n");
# Loop through each of the input file requests
foreach $oRequest (@requestArray) {
# Remove line breaks and carriage returns
$oRequest =~ s/(\n|\r)//g;
# Only process GETs and POSTs
if ($oRequest =~ /^(GET|POST)/) {
# Check for request data
if ($oRequest =~ /\?/) {
# Issue the original request for reference purposes
($oStatus, $oResponse) = makeRequest($oRequest);
#Populate methodAndFile and reqData variables
my ($methodAndFile, $reqData) = split(/\?/, $oRequest, 2);
my @reqParams = split(/\&/, $reqData);
my $pLogEntry = $methodAndFile;
# Build parameter log entry
my $parameter;
foreach $parameter (@reqParams) {
my ($pName) = split("=", $parameter);
$pLogEntry .= "+".$pName;
}
$paramLog{$pLogEntry}++;
if ($paramLog{$pLogEntry} eq 1) {
# Loop to perform test on each parameter
for (my $i = 0; $i <= $#reqParams; $i++) {
my $testData;
# Loop to reassemble the request parameters
for (my $j = 0; $j <= $#reqParams; $j++) {
if ($j == $i) {
my ($varName, $varValue) = split("=",$reqParams[$j],2);
$testData .= $varName."="."---PLACEHOLDER---"."&";
} else {
$testData .= $reqParams[$j]."&";
}
}
chop($testData);
my $paramRequest = $methodAndFile."?".$testData;
## Perform input validation tests
my $sqlVuln = sqlTest($paramRequest);
my $xssVuln = xssTest($paramRequest);
} # End of loop for each request parameter
} # End if statement for unique parameter combos
} # Close if statement checking for request data
my $trash;
($trash, $oRequest, $trash) = split(/\ |\?/, $oRequest);
my @directories = split(/\//, $oRequest);
my @checkSlash = split(//, $oRequest);
my $totalDirs = $#directories;
# Start looping through each directory level
for (my $d = 0; $d <= $totalDirs; $d++) {
if ((($checkSlash[(-1)] ne "/") && ($d == 0)) || ($d != 0)) {
pop(@directories);
}
my $dirRequest = "GET ".join("/", @directories)."\/";
# Add directory log entry
$dirLog{$dirRequest}++;
if ($dirLog{$dirRequest} eq 1) {
my $dListVuln = dirList($dirRequest);
my $dPutVuln = dirPut($dirRequest);
} # End check for unique directory
} # End loop for each directory level
} # End check for GET or POST request
} # End loop on each input file entry
printReport("\n\n** Scan Complete **\n\n");
sub dirPut {
my ($putRequest, $putStatus, $putResults, $putVulnerable);
($putRequest) = @_;
# Format the test request to upload the file
$putRequest =~ s/^GET/PUT/;
$putRequest .= "uploadTest.txt?ThisIsATest";
# Make the request and get the response data
($putStatus, $putResults) = makeRequest($putRequest);
# Format the request to check for the new file
$putRequest =~ s/^PUT/GET/;
$putRequest =~ s/\?ThisIsATest//;
# Check for the uploaded file
($putStatus, $putResults) = makeRequest($putRequest);
if ($putResults =~ /ThisIsATest/) {
$putVulnerable = 1;
# If vulnerable, print something to the user
printReport("\n\nALERT: Writeable Directory Detected:\n=> $putRequest\n\n");
} else {
$putVulnerable = 0;
}
# Return the test results.
return $putVulnerable;
}
sub dirList {
my ($dirRequest, $dirStatus, $dirResults, $dirVulnerable);
($dirRequest) = @_;
# Make the request and get the response data
($dirStatus, $dirResults) = makeRequest($dirRequest);
# Check to see if it looks like a listing
if ($dirResults =~ /(<TITLE>Index of \/|(<h1>|<title>)
Directory Listing For|<title>Directory of|\"\?N=D\"|\"\?S=A\"|\"\?
M=A\"|\"\?D=A\"| - \/<\/title>|&lt;dir&gt;| - \/<\/H1><hr>|\[To Parent Directory\])/i) {
$dirVulnerable = 1;
# If vulnerable, print something to the user
printReport("\n\nALERT: Directory Listing Detected:\n=> $dirRequest\n\n");
} else {
$dirVulnerable = 0;
}
# Return the test results.
return $dirVulnerable;
}
sub xssTest {
my ($xssRequest, $xssStatus, $xssResults, $xssVulnerable);
($xssRequest) = @_;
# Replace the "---PLACEHOLDER---" string with our test string
$xssRequest =~ s/---PLACEHOLDER---/"><script>alert(''Vulnerable'');<\/script>/;
# Make the request and get the response data
($xssStatus, $xssResults) = makeRequest($xssRequest);
# Check to see if the output matches our vulnerability signature.
if ($xssResults =~ /"><script>alert\(''Vulnerable''\);<\/script>/i) {
$xssVulnerable = 1;
# If vulnerable, print something to the user
printReport("\n\nALERT: Cross-Site Scripting Vulnerability
Detected:\n=> $xssRequest\n\n");
} else {
$xssVulnerable = 0;
}
# Return the test results
return $xssVulnerable;
}
sub sqlTest {
my ($sqlRequest, $sqlStatus, $sqlResults, $sqlVulnerable);
($sqlRequest) = @_;
# Replace the "---PLACEHOLDER---" string with our test string
$sqlRequest =~ s/---PLACEHOLDER---/te''st/;
# Make the request and get the response data
($sqlStatus, $sqlResults) = makeRequest($sqlRequest);
# Check to see if the output matches our vulnerability signature.
my $sqlRegEx = qr /(OLE DB|SQL Server|Incorrect
Syntax|ODBC Driver|ORA-|SQL command
not|Oracle Error Code|CFQUERY|MySQL|Sybase
| DB2 |Pervasive|Microsoft Access|MySQL|
CLI Driver|The string constant beginning
with|does not have an ending string
delimiter|JET Database Engine error)/i;
if (($sqlResults =~ $sqlRegEx) && ($oResponse !~ $sqlRegEx)) {
$sqlVulnerable = 1;
printReport("\n\nALERT: Database Error Message Detected:\n=>
$sqlRequest\n\n");
} else {
$sqlVulnerable = 0;
}
# Return the test result indicator
return $sqlVulnerable;
}
sub makeRequest {
my ($request, $lwp, $method, $uri, $data, $req, $status, $content);
($request)=@_;
if ($args{v}) {
printReport("Making Request: $request\n");
} else {
print ".";
}
# Setup LWP UserAgent
$lwp = LWP::UserAgent->new(env_proxy => 1,
keep_alive => 1,
timeout => 30,
);
# Method should always precede the request with a space
($method, $uri) = split(/ /, $request);
# PUTS and POSTS should have data appended to the request
if (($method eq "POST") || ($method eq "PUT")) {
($uri, $data) = split(/\?/, $uri);
}
# Append the URI to the hostname and setup the request
$req = new HTTP::Request $method => $ARGV[1].$uri;
# Add request content for POST and PUTS
if ($data) {
$req->content_type(''application/x-www-form-urlencoded'');
$req->content($data);
}
# If cookies are defined, add a COOKIE header
if ($args{c}) {
$req->header(Cookie => $args{c});
}
my $response = $lwp->request($req);
# Extract the HTTP status code and HTML content from the response
$status = $response->status_line;
$content = $response->content;
if ($status =~ /^400/) {
die "Error: Invalid URL or HostName\n\n";
}
return ($status, $content);
}
sub printReport {
my ($printData) = @_;
if ($args{o}) {
open(REPORT, ">>$args{o}") or die "ERROR => Can''t write to file $args{o}\n";
print REPORT $printData;
close(REPORT);
}
print $printData;
}



8.6.2. parseLog.pl



Example 8-9 contains the full source for the
parseLog.pl script.



Example 8-9. Code for parseLog.pl


#!/usr/bin/perl
use strict;
if ($#ARGV < 0) {
die "Usage: $0 LogFile\n";
}
open(IN, "< $ARGV[0]") or die"ERROR: Can''t open file $ARGV[0].\n";
# Change the input record separator to select entire log entries
$/ = "=" x 54;
my @logData = <IN>;
# Loop through each request and parse it
my ($request,$logEntry, @requests);
foreach $logEntry (@logData) {
# Create an array containing each line of the raw request
my @logEntryLines = split(/\n/, $logEntry);
# Create an array containing each element of the first request line
my @requestElements = split(/ /, $logEntryLines[1]);
# Only parse GET and POST requests
if ($requestElements[0] eq "GET" || $requestElements[0] eq "POST" ) {
if ($requestElements[0] eq "GET" ) {
print $requestElements[0]." ".$requestElements[1]."\n";
}
# POST request data is appended after the question mark
if ($requestElements[0] eq "POST" ) {
print $requestElements[0]." ".$requestElements[1]."?".$logEntryLines[-2]."\n";
}
} # End check for GET or POST
} # End loop for input file entries



/ 85