bunkerweb 1.4.0

This commit is contained in:
bunkerity
2022-06-03 17:24:14 +02:00
parent 3a078326c5
commit a9f886804a
5245 changed files with 1432051 additions and 27894 deletions

View File

@@ -0,0 +1,7 @@
The util directory contains many supporting tools/scripts that may be used with
the OWASP ModSecurity CRS files.
Docker Support
==============
A Dockerfile can be found in the docker/ directory, along with additional
notes in docker/README.md

View File

@@ -0,0 +1,652 @@
#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;
}

View 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];

View File

@@ -0,0 +1,2 @@
gcc -c -o common.o -DEXTERN= common.c
gcc -o runAV -DEXTERN=extern common.o runAV.c

View 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);
}
}
}
}

View 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);
}
}
}
}

View 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";

View File

@@ -0,0 +1,78 @@
(function() { // don't leak XSSTripwire into global ns
/*
Assumptions:
- we need to run first, before any other attacker script
- we can't prevent tripwire from being detected (e.g. by side effects)
Todo:
- a lot more in lockdown
- protect XHR
*/
var XSSTripwire = new Object();
XSSTripwire.report = function() {
// Notify server
var notify = XSSTripwire.newXHR();
// Create a results string to send back
var results;
try {
results = "HTML=" + encodeURIComponent(document.body.outerHTML);
} catch (e) {} // we don't always have document.body
notify.open("POST", XSSTripwire.ReportURL, true);
notify.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
notify.send(results);
}
XSSTripwire.lockdown = function(obj, name) {
if (Object.defineProperty) {
Object.defineProperty(obj, name, {
configurable: false
})
}
}
XSSTripwire.newXHR = function() {
var xmlreq = false;
if (window.XMLHttpRequest) {
xmlreq = new XMLHttpRequest();
} else if (window.ActiveXObject) {
// Try ActiveX
try {
xmlreq = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e1) {
// first method failed
try {
xmlreq = new ActiveXObject("Microsoft.XMLHTTP");
} catch (e2) {
// both methods failed
}
}
}
return xmlreq;
};
XSSTripwire.proxy = function(obj, name, report_function_name, exec_original) {
var proxy = obj[name];
obj[name] = function() {
// URL of the page to notify, in the event of a detected XSS event:
XSSTripwire.ReportURL = "xss-tripwire-report?function=" + encodeURIComponent(report_function_name);
XSSTripwire.report();
if (exec_original) {
return proxy.apply(this, arguments);
}
};
XSSTripwire.lockdown(obj, name);
};
XSSTripwire.proxy(window, 'alert', 'window.alert', true);
XSSTripwire.proxy(window, 'confirm', 'window.confirm', true);
XSSTripwire.proxy(window, 'prompt', 'window.prompt', true);
XSSTripwire.proxy(window, 'unescape', 'unescape', true);
XSSTripwire.proxy(document, 'write', 'document.write', true);
XSSTripwire.proxy(String, 'fromCharCode', 'String.fromCharCode', true);
})();

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,30 @@
CRS 2.x to 3.x migration utility
================================
In CRS 3.0, we have renumbered the rules to be more logical and helpful.
The new rule file names now correspond with the rule IDs in the file.
First rule of a given file is usually 9XX100, then the rules continue
in steps of ten. Related rules/siblings follow with a single digit
change (9XX101, etc.).
This utility replaces CRS 2 ruleIds with their CRS 3 counterparts.
You can use it when migrating your CRS 2 exclusion/.conf files to CRS 3.0
or higher.
Example usage:
./update.py -f your_old_modsec_conf.conf
Rules which have been removed in CRS 3 are listed with the new ID 000000 in the
CSV file. This means that the former rule is no longer part of CRS 3. If after
replacement you find a string 000000 in your config files, you can likely
remove that exclusion or special case.
If you want to create your own tooling for this migration, you can use
the file idNumbering.csv in this directory. It lists the old rule IDs of
CRS 2.2, together with the corresponding rule IDs in CRS 3.0.
A rule renumbering is painful for all existing installations. But we really
think that the rule IDs lacked sense and reason, and we are confident future
maintenance will be much easier once this is done. We do not plan to change
rule IDs after this. We appreciate your understanding in this matter.

View File

@@ -0,0 +1,55 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""This is designed to convert 2.x CRS ID numbering to 3.x CRS numbering"""
from __future__ import print_function
import csv
import argparse
import os
import sys
def main():
"""Main function that contains all the logic to relabel CRS IDs"""
id_translation_file = os.path.join(sys.path[0], "IdNumbering.csv")
if not os.path.isfile(id_translation_file):
sys.stderr.write("We were unable to locate the ID translation CSV (idNumbering.csv) \
please place this is the same directory as this script\n")
sys.exit(1)
parser = argparse.ArgumentParser(description="A program that takes in an exceptions file \
and renumbers all the ID to match OWASP CRS 3 numbers. Output will be directed to STDOUT.")
parser.add_argument("-f", "--file", required=True, action="store", dest="fname", \
help="the file to be renumbered")
args = parser.parse_args()
if not os.path.isfile((args.fname).encode('utf8')):
sys.stderr.write("We were unable to find the file you were trying to update the ID numbers \
in, please check your path\n")
sys.exit(1)
fcontent = ""
try:
update_file = open((args.fname).encode('utf-8'), "r")
try:
fcontent = update_file.read()
finally:
update_file.close()
except IOError:
sys.stderr.write("There was an error opening the file you were trying to update")
if fcontent != "":
# CSV File
id_csv_file = open(id_translation_file, 'rt')
try:
reader = csv.reader(id_csv_file)
for row in reader:
fcontent = fcontent.replace(row[0], row[1])
finally:
id_csv_file.close()
print(fcontent)
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,5 @@
License
The GeoLite databases are distributed under the Creative Commons Attribution-ShareAlike 3.0 Unported License. The attribution requirement may be met by including the following in all advertising and documentation mentioning features of or use of this database:
This product includes GeoLite data created by MaxMind, available from
<a href="http://www.maxmind.com">http://www.maxmind.com</a>.

View 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.

View File

@@ -0,0 +1,97 @@
##########################################################################
# 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

View File

@@ -0,0 +1,30 @@
#
# 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>

View File

@@ -0,0 +1,2 @@
900000-2999999
2000000-299999

View File

@@ -0,0 +1,47 @@
#!/usr/bin/env python
#
# This script reads all the rule files passed on the command line,
# and outputs them, with each (multi-line) directive joined as a
# single line.
#
# This can be used to work around a bug in Apache < 2.4.11 in
# parsing long configuration directives.
#
# Usage:
#
# util/join-multiline-rules/join.py rules/*.conf > rules/rules.conf.joined
#
# This produces a single 'rules.conf.joined' file that can be included
# in buggy Apache versions. It is recommended to keep this file in the
# rules/ directory (because it refers to .data files in that directory)
# but give it a name not ending in .conf (so the file will not be
# included in *.conf and you can re-run the command multiple times
# without including its own output).
#
# Example:
#
# SecRule &TX:paranoia_level "@eq 0" \
# "id:901120,\
# phase:1,\
# pass,\
# nolog,\
# setvar:tx.paranoia_level=1"
#
# will be outputted as:
#
# SecRule &TX:paranoia_level "@eq 0" "id:901120,phase:1,pass,nolog,setvar:tx.paranoia_level=1"
#
import fileinput, sys
for line in fileinput.input():
line = line.strip()
if line == '':
sys.stdout.write("\n")
continue
if line[-1] == '\\':
sys.stdout.write(line[0:-1])
else:
sys.stdout.write(line)
sys.stdout.write("\n")

View File

@@ -0,0 +1,168 @@
# Word list for rule 932100 (RCE Unix command injection part 1/3)
#
# To convert to a regexp that can be pasted into the rule:
# cat regexp-932100.txt | ./regexp-cmdline.py unix | ./regexp-assemble.pl
#
# Entries starting with ' are used verbatim.
# Everything after # is a comment.
#
# To prevent some FP for a command, you can require command parameters
# after a command. Only do this if the command regularly causes FP and if
# allowing the bare command (without parameters) is not too dangerous.
# (Note: due to \b following the regexp, a word boundary is also required
# further on, so some letter/number is needed for a match). Example:
#
# diff+
# Special regexp case for the '.' (source) command to prevent FP:
'\.\s.*
7z
7za
7zr
adduser
alias+
apt-get
arch+
arp
awk+
bash
batch+
breaksw
bsdcat
bsdiff
bsdtar
builtin
bzcat
bzdiff
bzegrep
bzfgrep
bzgrep
bzip2
bzless
bzmore
cat+
cc+
chattr
chdir+
chflags
chmod
command+
compress+
coproc
cp+
crontab
csh
curl
dash
dhclient
diff+
dmesg
doas
done
dpkg
du+
echo+
egrep
endif
endsw
env
env-update
esac
eval
exec+
expand
export
expr
fc+
fetch+
fgrep
fi
file+
filetest
find+
foreach
ftp+
ftpstats
ftpwho
function
gcc+
gdb
GET+
getfacl+
git+
grep+
gunzip
gzcat
gzip
head+
history
hostid
hostname
htdigest
htpasswd
hup+
# 'id' causes way too much FP, so we require whitespace; this will allow
# injecting ';id' unfortunately.
id+
ifconfig
ip6tables
ipconfig
iptables
irb
irb1
irb18
irb19
irb20
irb21
irb22
java+
jexec
jobs+
kill+
killall
last+
lastcomm
lastlog
lastlogin
ldconfig
ldd+
less+
lessecho
lessfile
lesspipe
lftp
lftpget
ln+
local+
locate+
logname
lp+
ls
ls-F
lsb_release
lscpu
lshw
lsmod
lsof
lspci
lsusb
lwp-download
lwp-dump
lwp-mirror
lwp-request
lynx+
lzcat
lzcmp
lzdiff
lzegrep
lzfgrep
lzgrep
lzless
lzma
lzmore
mailq
mailx+
mkdir+
mlocate
more+

View File

@@ -0,0 +1,174 @@
# Word list for rule 932105 (RCE Unix command injection part 2/3)
#
# To convert to a regexp that can be pasted into the rule:
# cat regexp-932105.txt | ./regexp-cmdline.py unix | ./regexp-assemble.pl
#
# Entries starting with ' are used verbatim.
# Everything after # is a comment.
#
# To prevent some FP for a command, you can require command parameters
# after a command. Only do this if the command regularly causes FP and if
# allowing the bare command (without parameters) is not too dangerous.
# (Note: due to \b following the regexp, a word boundary is also required
# further on, so some letter/number is needed for a match). Example:
#
# diff+
mount+
mutt+
mv+
mysql
mysqladmin
mysqldump
mysqldumpslow
mysqlhotcopy
mysqlshow
nano+
nc+
nc.openbsd
nc.traditional
ncat
net+
netcat
netkit-ftp
netstat
nice+
nmap
nohup
nping
nslookup
nstat
onintr
openssl
passwd
patch+
perl
perl5
perlsh
perms
pftp
pgrep
php
php5
php7
ping
pkexec
pkg
pkg_info
pkginfo
pkill
popd
printenv
printf+
ps+
ptar
ptardiff
ptargrep
pushd
python
python2
python3
python3m
rar+
rcp+
realpath
rename+
repeat+
replace+
rm+
rmdir+
rmuser
rnano
route
rpm+
rsync
ruby
ruby1
ruby18
ruby19
ruby20
ruby21
ruby22
sched
scp+
sdiff
sed+
sendmail
set+
setenv
setfacl+
setsid
sftp
sh+
sh.distrib
shutdown
sleep
socat
sort+
source+
ssh
strings
su+
sudo
svn
sysctl
tail
tailf
tar+
tcping
tcptraceroute
tcsh
tee+
telnet
time+
timeout
top
touch+
traceroute
traceroute6
ulimit+
uname
uncompress
unlink+
unlzma
unrar
unset
unxz
unzip
useradd
userdel
usermod
vigr
vim+
vipw
w3m
wget
# 'who' causes many FP, so require whitespace.
# Unfortunately, without whitespace it may still leak some info.
who+
whoami
xargs
xterm
xxd+
xz+
xzcat
xzcmp
xzdec
xzdiff
xzegrep
xzfgrep
xzgrep
xzless
xzmore
yum
zcat
zcmp
zdiff
zegrep
zfgrep
zgrep
zip+
zless
zmore
zrun
zsh

View File

@@ -0,0 +1,26 @@
# Word list for rule 932106 (RCE Unix command injection part 3/3)
#
# To convert to a regexp that can be pasted into the rule:
# cat regexp-932106.txt | ./regexp-cmdline.py unix | ./regexp-assemble.pl
#
#
# Entries starting with ' are used verbatim.
# Everything after # is a comment.
#
# To prevent some FP for a command, you can require command parameters
# after a command. Only do this if the command regularly causes FP and if
# allowing the bare command (without parameters) is not too dangerous.
# (Note: due to \b following the regexp, a word boundary is also required
# further on, so some letter/number is needed for a match). Example:
#
# diff+
vi+
ps
pwd
who
w+
aptitude+
pacman+
dnf+
up2date+

View File

@@ -0,0 +1,164 @@
# Word list for rule 932110 (RCE Windows command injection part 1/2)
#
# To convert to a regexp that can be pasted into the rule:
# cat regexp-932110.txt | ./regexp-cmdline.py windows | ./regexp-assemble.pl
#
# Entries starting with ' are used verbatim.
# Everything after # is a comment.
#
# To prevent some FP for a command, you can require command parameters
# after a command. Only do this if the command regularly causes FP and if
# allowing the bare command (without parameters) is not too dangerous.
# (Note: due to \b following the regexp, a word boundary is also required
# further on, so some letter/number is needed for a match). Example:
#
# diff@
7z
7za
7zr
addusers
admodcmd
arp@
assoc
attrib
azman
bcdboot
bcdedit
bitsadmin
bootcfg
browstat
cacls
call@
certreq
certutil
#disabled for FP: change
chdir@
chkdsk
chkntfs
cipher
cleanmgr
clearmem
cluster
cmd
cmdkey
comexp
comp@
compact@
compmgmt
con2prt
convert
copy
csccmd
cscript
csvde
curl
date@
dcomcnfg
debug
defrag
del@
delprof
deltree
devcon
devmgmt
diff@
dir@
diruse
diskmgmt
diskpart
diskshadow
dnsstat
doskey
driverquery
dsacls
dsadd
dsget
dsmod
dsmove
dsquery
dsrm
dxdiag
echo
egrep
endlocal
erase
eventcreate
eventvwr
expand@
explorer
fc@
fgrep
find@
findstr
foreach
forfiles
format@
freedisk
fsmgmt
fsutil
ftp@
ftype
gathernetworkinfo
getmac
git@
gpedit
gpresult
gpupdate
hdwwiz
hostname
icacls
ifmember
inetcpl
ipconfig
irb
irb1
irb18
irb19
irb20
irb21
irb22
java@
label@
logevent
logman
logoff
logtime
lusrmgr
mapisend
mbsacli
md@
mdsched
measure
mkdir@
mklink
mmsys
mode@
more@
mount@
mountvol
moveuser
msconfig
msg@
msiexec
msinfo32
mstsc
mysql
mysqladmin
mysqldump
mysqldumpslow
mysqlhotcopy
mysqlshow
nbtstat
nc@
ncat
net@
netcat
netdom
netsh
netstat
netsvc
nmap
nslookup
ntbackup
ntrights

View File

@@ -0,0 +1,164 @@
# Word list for rule 932115 (RCE Windows command injection part 2/2)
#
# To convert to a regexp that can be pasted into the rule:
# cat regexp-932115.txt | ./regexp-cmdline.py windows | ./regexp-assemble.pl
#
# Entries starting with ' are used verbatim.
# Everything after # is a comment.
#
# To prevent some FP for a command, you can require command parameters
# after a command. Only do this if the command regularly causes FP and if
# allowing the bare command (without parameters) is not too dangerous.
# (Note: due to \b following the regexp, a word boundary is also required
# further on, so some letter/number is needed for a match). Example:
#
# diff@
odbcad32
odbcconf
openfiles
path@
pathping
perfmon
perl
perl5
perlsh
php
php5
php7
ping
pkgmgr
popd
portqry
powercfg
powershell
powershell_ise
print@
printbrm
prncnfg
prnmngr
prompt
psexec
psfile
psgetsid
psinfo
pskill
pslist
psloggedon
psloglist
pspasswd
psping
psservice
psshutdown
pssuspend
pushd
python
python2
python3
python3m
qgrep
qprocess
query@
qwinsta
rar@
rasdial
rasphone
rd@
recdisc
recover
reg@
regedit
regini
regsvr32
rekeywiz
ren@
rename@
replace@
reset@
rm@
rmdir@
rmtshare
robocopy
route@
rstrui
rsync
ruby1
ruby18
ruby19
ruby20
ruby21
ruby22
runas
rundll32
schtasks
sclist
secpol
select
set@
setlocal
setx@
sfc
share
shellrunas
shift
shortcut
showgrps
showmbrs
shrpubw
shutdown
sigverif
sleep
slmgr
sort
start@
subinacl
subst
svn
sysdm
syskey
systeminfo
systempropertiesadvanced
systempropertiesdataexecutionprevention
systempropertieshardware
systempropertiesperformance
takeown
taskkill
tasklist
taskmgr
taskschd
telnet
timeout
tlist
tpminit
tracert
tree
tsdiscon
tsshutdn
type@
typeperf
unrar
unzip
useraccountcontrolsettings
usrstat
verify
vol@
waitfor
wevtutil
wget
#disabled for FP: where@
whoami
windiff
winmsdp
winrm
winrs
winvar
wmic
wmimgmt
wscript
wscui
wuapp
wuauclt
wusa
xcacls
xcopy
zip@

View File

@@ -0,0 +1,5 @@
\$\(.*\)
\$\{.*\}
<\(.*\)
>\(.*\)
\$\(\(.*\)\)

View File

@@ -0,0 +1,2 @@
\bfor(?:/[dflr].*)? %+[^ ]+ in\(.*\)\s?do
\bif(?:/i)?(?: not)?(?: exist\b| defined\b| errorlevel\b| cmdextversion\b|(?: |\().*(?:\bgeq\b|\bequ\b|\bneq\b|\bleq\b|\bgtr\b|\blss\b|==))

View File

@@ -0,0 +1,203 @@
# Word list for rule 932150 (RCE Unix command injection)
# To lower FP, this rule requires whitespace after a command.
#
# To convert to a regexp that can be pasted into the rule:
# cat regexp-932150.txt | ./regexp-cmdline.py unix | ./regexp-assemble.pl
#
# Entries starting with ' are used verbatim.
# Everything after # is a comment.
#
bash
bsdcat
bsdiff
bsdtar
builtin
bzcat
bzdiff
bzegrep
bzfgrep
bzgrep
bzless
bzmore
cc
command
coproc
csh
curl
dash
diff
dmesg
doas
echo
egrep
env
eval
exec
fetch
fgrep
filetest
ftpstats
ftpwho
gcc
GET
grep
gzcat
gzip
head
hup
irb
irb1
irb18
irb19
irb20
irb21
irb22
java
jobs -x
lastcomm
lastlog
lastlogin
lessecho
lessfile
lesspipe
lftp
lftpget
ls
ls-F
lsb_release
lscpu
lsmod
lsof
lspci
lsusb
lwp
lwp-download
lynx
lzcat
lzcmp
lzdiff
lzegrep
lzfgrep
lzgrep
lzless
lzma
lzmore
mailq
mlocate
mysqladmin
mysqldump
mysqldumpslow
mysqlhotcopy
mysqlshow
nc
nc.openbsd
nc.traditional
ncat
netcat
netkit-ftp
netstat
nohup
nping
nstat
onintr
perl
perl5
pftp
pgrep
php
php5
php7
ping
pkexec
pkill
popd
printenv
ptar
ptardiff
ptargrep
python
python2
python3
python3m
rcp
realpath
rename
repeat
replace
rmdir
rmuser
rnano
rsync
ruby
ruby1
ruby18
ruby19
ruby20
ruby21
ruby22
sched
scp
sdiff
sed
sendmail
setenv
setsid
sftp
sh
sh.distrib
socat
source
ssh
strings
sudo
svn
sysctl
tail
tailf
tar
tcping
tcptraceroute
tcsh
telnet
time
timeout
traceroute
traceroute6
uname
uncompress
unlzma
unrar
unset
unxz
unzip
useradd
userdel
usermod
vigr
vipw
w3m
wget
whoami
xargs
xz
xzcat
xzcmp
xzdec
xzdiff
xzegrep
xzfgrep
xzgrep
xzless
xzmore
zcat
zcmp
zdiff
zegrep
zfgrep
zgrep
zip
zless
zmore
zrun
zsh

View File

@@ -0,0 +1,16 @@
AUTH_TYPE
HTTP_ACCEPT
HTTP_ACCEPT_CHARSET
HTTP_ACCEPT_ENCODING
HTTP_ACCEPT_LANGUAGE
HTTP_CONNECTION
HTTP_HOST
HTTP_KEEP_ALIVE
HTTP_REFERER
HTTP_USER_AGENT
HTTP_X_FORWARDED_FOR
ORIG_PATH_INFO
PATH_INFO
PATH_TRANSLATED
QUERY_STRING
REQUEST_URI

View File

@@ -0,0 +1,226 @@
array_diff_uassoc
array_diff_ukey
array_filter
array_intersect_uassoc
array_intersect_ukey
array_map
array_reduce
array_udiff
array_udiff_assoc
array_udiff_uassoc
array_uintersect
array_uintersect_assoc
array_uintersect_uassoc
assert
assert_options
base64_encode
bson_decode
bson_encode
bzopen
chr
convert_uuencode
create_function
curl_exec
curl_file_create
curl_init
debug_backtrace
error_reporting
escapeshellarg
escapeshellcmd
eval
exec
exif_imagetype
exif_read_data
exif_tagname
exif_thumbnail
file
file_exists
fileatime
filectime
filegroup
fileinode
filemtime
fileperms
finfo_open
fopen
fputs
ftp_connect
ftp_get
ftp_nb_get
ftp_nb_put
ftp_put
function_exists
fwrite
get_cfg_var
get_current_user
get_meta_tags
getcwd
getenv
getimagesize
getlastmod
getmygid
getmyinode
getmypid
getmyuid
glob
gzcompress
gzdeflate
gzencode
gzfile
gzopen
gzread
gzwrite
hash_file
hash_hmac_file
hash_update_file
header_register_callback
hex2bin
highlight_file
html_entity_decode
htmlentities
htmlspecialchars
htmlspecialchars_decode
image2wbmp
imagecreatefromgif
imagecreatefromjpeg
imagecreatefrompng
imagecreatefromwbmp
imagecreatefromxbm
imagecreatefromxpm
imagegd
imagegd2
imagegif
imagejpeg
imagepng
imagewbmp
imagexbm
ini_get
ini_get_all
ini_set
iptcembed
is_dir
is_executable
is_file
is_readable
is_writable
is_writeable
iterator_apply
json_decode
json_encode
mb_ereg
mb_ereg_match
mb_ereg_replace
mb_ereg_replace_callback
mb_eregi
mb_eregi_replace
mb_parse_str
md5_file
method_exists
mkdir
move_uploaded_file
mysql_query
ob_clean
ob_end_clean
ob_end_flush
ob_flush
ob_get_clean
ob_get_contents
ob_get_flush
ob_start
odbc_connect
odbc_exec
odbc_execute
odbc_result
odbc_result_all
opendir
parse_ini_file
parse_str
passthru
pg_connect
pg_execute
pg_prepare
pg_query
php_strip_whitespace
php_uname
phpinfo
phpversion
popen
posix_getegid
posix_geteuid
posix_getgid
posix_getlogin
posix_getpwnam
posix_kill
posix_mkfifo
posix_mknod
posix_ttyname
preg_match
preg_match_all
preg_replace
preg_replace_callback
preg_replace_callback_array
preg_split
print_r
proc_close
proc_get_status
proc_nice
proc_open
proc_terminate
putenv
rawurldecode
rawurlencode
read_exif_data
readdir
readfile
readgzfile
register_shutdown_function
register_tick_function
rename_function
runkit_constant_add
runkit_constant_redefine
runkit_function_add
runkit_function_copy
runkit_function_redefine
runkit_function_rename
runkit_method_add
runkit_method_copy
runkit_method_redefine
runkit_method_rename
session_set_save_handler
session_start
set_error_handler
set_exception_handler
set_include_path
set_magic_quotes_runtime
setdefaultstub
sha1_file
show_source
simplexml_load_file
simplexml_load_string
socket_connect
socket_create
spl_autoload_register
sqlite_array_query
sqlite_create_aggregate
sqlite_create_function
sqlite_exec
sqlite_open
sqlite_popen
sqlite_query
sqlite_single_query
sqlite_unbuffered_query
stream_context_create
stream_socket_client
stripcslashes
stripslashes
strrev
system
tmpfile
uasort
uksort
unpack
unserialize
urldecode
urlencode
usort
var_dump

View File

@@ -0,0 +1,202 @@
abs
acos
acosh
array
arsort
asin
asinh
asort
assert
atan
atan2
atanh
basename
bindec
ceil
chdir
checkdate
chmod
chop
chown
chroot
closedir
closelog
compact
constant
copy
cos
cosh
count
crypt
current
date
decoct
define
defined
die
dir
dirname
diskfreespace
dl
doubleval
each
easter_date
easter_days
echo
empty
end
ereg
eregi
error_log
exit
exp
explode
extract
fclose
feof
fgets
fileowner
filepro
filesize
filetype
floatval
flock
floor
flush
fmod
fread
fstat
ftell
ftok
function
getdate
gettext
gettype
gmdate
hash
header
headers_list
headers_sent
hebrev
hypot
iconv
idate
implode
include
intdiv
intval
invoke
is_a
is_array
is_bool
is_callable
is_double
is_finite
is_float
is_infinite
is_int
is_integer
is_link
is_long
is_nan
is_null
is_numeric
is_object
is_real
is_resource
is_scalar
is_string
isset
join
key
ksort
lcfirst
levenshtein
link
linkinfo
list
localtime
log
log10
log1p
lstat
ltrim
mail
main
max
mbereg
mbsplit
metaphone
mhash
microtime
min
msql
mysql
natsort
next
octdec
openlog
ord
pack
pathinfo
pclose
pi
pos
pow
prev
print
printf
quotemeta
rand
range
readline
readlink
recode
rename
require
reset
rewind
round
rsort
rtrim
scandir
serialize
settype
shuffle
similar_text
sin
sinh
sizeof
sleep
sort
soundex
split
spliti
sprintf
sqrt
srand
stat
strcoll
strlen
strspn
substr
symlink
syslog
taint
tan
tanh
tempnam
textdomain
time
touch
trim
ucfirst
umask
uniqid
unlink
unset
untaint
usleep
usort
virtual
wordwrap

View File

@@ -0,0 +1,8 @@
_\$\$ND_FUNC\$\$_
__js_function
\beval\s*\(
String\s*\.\s*fromCharCode
function\s*\(\s*\)\s*{
new\s+Function\s*\(
this\.constructor
module\.exports\s*=

View File

@@ -0,0 +1,10 @@
(?i)[\s\S]xlink:href\b
(?i)[\s\S]xhtml\b
(?i)[\s\S]xmlns\b
(?i)[\s\S]!ENTITY\s+(?:\S+|%\s+\S+)\s+SYSTEM\b
(?i)[\s\S]!ENTITY\s+(?:\S+|%\s+\S+)\s+PUBLIC\b
(?i)[\s\S]data:text/html\b
(?i)[\s\S]formaction\b
(?i)[\s\S]@import\b
(?i)[\s\S];base64\b
(?i)[\s\S]pattern\b.*?=\b

View File

@@ -0,0 +1,308 @@
<[^\w<>]*(?:[^<>\"'\s]*:)?[^\w<>]*\W*?s\W*?c\W*?r\W*?i\W*?p\W*?t
<[^\w<>]*(?:[^<>\"'\s]*:)?[^\w<>]*\W*?f\W*?o\W*?r\W*?m
<[^\w<>]*(?:[^<>\"'\s]*:)?[^\w<>]*\W*?s\W*?t\W*?y\W*?l\W*?e
<[^\w<>]*(?:[^<>\"'\s]*:)?[^\w<>]*\W*?s\W*?v\W*?g
<[^\w<>]*(?:[^<>\"'\s]*:)?[^\w<>]*\W*?m\W*?a\W*?r\W*?q\W*?u\W*?e\W*?e
<[^\w<>]*(?:[^<>\"'\s]*:)?[^\w<>]*\W*?l\W*?i\W*?n\W*?k[^>\w]
<[^\w<>]*(?:[^<>\"'\s]*:)?[^\w<>]*\W*?o\W*?b\W*?j\W*?e\W*?c\W*?t[^>\w]
<[^\w<>]*(?:[^<>\"'\s]*:)?[^\w<>]*\W*?e\W*?m\W*?b\W*?e\W*?d[^>\w]
<[^\w<>]*(?:[^<>\"'\s]*:)?[^\w<>]*\W*?a\W*?p\W*?p\W*?l\W*?e\W*?t[^>\w]
<[^\w<>]*(?:[^<>\"'\s]*:)?[^\w<>]*\W*?p\W*?a\W*?r\W*?a\W*?m[^>\w]
<[^\w<>]*(?:[^<>\"'\s]*:)?[^\w<>]*\W*?i?\W*?f\W*?r\W*?a\W*?m\W*?e[^>\w]
<[^\w<>]*(?:[^<>\"'\s]*:)?[^\w<>]*\W*?b\W*?a\W*?s\W*?e[^>\w]
<[^\w<>]*(?:[^<>\"'\s]*:)?[^\w<>]*\W*?b\W*?o\W*?d\W*?y[^>\w]
<[^\w<>]*(?:[^<>\"'\s]*:)?[^\w<>]*\W*?m\W*?e\W*?t\W*?a[^>\w]
<[^\w<>]*(?:[^<>\"'\s]*:)?[^\w<>]*\W*?i\W*?m\W*?a?\W*?g\W*?e?[^>\w]
<[^\w<>]*(?:[^<>\"'\s]*:)?[^\w<>]*\W*?v\W*?i\W*?d\W*?e\W*?o[^>\w]
<[^\w<>]*(?:[^<>\"'\s]*:)?[^\w<>]*\W*?a\W*?u\W*?d\W*?i\W*?o[^>\w]
<[^\w<>]*(?:[^<>\"'\s]*:)?[^\w<>]*\W*?b\W*?i\W*?n\W*?d\W*?i\W*?n\W*?g\W*?s[^>\w]
<[^\w<>]*(?:[^<>\"'\s]*:)?[^\w<>]*\W*?s\W*?e\W*?t[^>\w]
<[^\w<>]*(?:[^<>\"'\s]*:)?[^\w<>]*\W*?a\W*?n\W*?i\W*?m\W*?a\W*?t\W*?e[^>\w]
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)background[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)formaction[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)lowsrc[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onAppCommand[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onDOMActivate[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onDOMAttrModified[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onDOMCharacterDataModified[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onDOMFocusIn[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onDOMFocusOut[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onDOMMouseScroll[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onDOMNodeInsertedIntoDocument[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onDOMNodeInserted[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onDOMNodeRemovedFromDocument[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onDOMNodeRemoved[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onDOMSubtreeModified[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onLoad[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onMozAfterPaint[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onMozAudioAvailable[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onMozBeforeResize[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onMozEdgeUICanceled[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onMozEdgeUICompleted[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onMozEdgeUIStarted[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onMozMagnifyGestureStart[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onMozMagnifyGestureUpdate[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onMozMagnifyGesture[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onMozMouseHittest[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onMozMousePixelScroll[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onMozPressTapGesture[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onMozRotateGestureStart[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onMozRotateGestureUpdate[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onMozRotateGesture[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onMozScrolledAreaChanged[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onMozSwipeGestureEnd[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onMozSwipeGestureStart[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onMozSwipeGestureUpdate[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onMozSwipeGesture[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onMozTapGesture[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onRequest[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onSVGAbort[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onSVGError[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onSVGLoad[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onSVGResize[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onSVGScroll[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onSVGUnload[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onSVGZoom[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onabort[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onactivate[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onadapteradded[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onaddtrack[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onafterprint[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onafterscriptexecute[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onafterupdate[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onalerting[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onanimationend[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onanimationiteration[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onanimationstart[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onantennastatechange[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onaudioend[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onaudioprocess[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onaudiostart[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onbeforeactivate[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onbeforedeactivate[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onbeforecopy[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onbeforecut[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onbeforeeditfocus[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onbeforepaste[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onbeforeprint[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onbeforescriptexecute[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onbeforeunload[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onbeforeupdate[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onbeginEvent[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onbegin[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onblocked[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onblur[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onbounce[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onboundary[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onbroadcast[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onbusy[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)oncached[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)oncallschanged[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)oncanplay[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)oncanplaythrough[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)oncardstatechange[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)oncellchange[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)oncfstatechange[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onchange[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onchargingchange[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onchargingtimechange[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onchecking[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onclick[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onclose[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)oncommand[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)oncommandupdate[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)oncomplete[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)oncompositionend[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)oncompositionstart[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)oncompositionupdate[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onconnected[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onconnecting[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)oncontextmenu[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)oncontrolselect[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)oncopy[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)oncuechange[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)oncut[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)ondataavailable[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)ondatachange[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)ondataerror[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)ondatasetchanged[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)ondatasetcomplete[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)ondblclick[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)ondeactivate[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)ondeliveryerror[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)ondeliverysuccess[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)ondevicefound[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)ondevicelight[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)ondevicemotion[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)ondeviceorientation[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)ondeviceproximity[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)ondialing[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)ondisabled[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)ondischargingtimechange[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)ondisconnected[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)ondisconnecting[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)ondownloading[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)ondragdrop[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)ondragend[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)ondragenter[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)ondragexit[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)ondraggesture[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)ondragleave[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)ondragover[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)ondragstart[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)ondrop[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)ondurationchange[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onemptied[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onenabled[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onendEvent[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onend[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onended[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onenter[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onerror[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onerrorupdate[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onexit[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onfailed[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onfilterchange[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onfinish[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onfocus[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onfocusin[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onfocusout[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onformchange[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onforminput[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)ongamepadaxismove[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)ongamepadbuttondown[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)ongamepadbuttonup[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)ongamepadconnected[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)ongamepaddisconnected[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onget[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onhashchange[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onheadphoneschange[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onheld[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onhelp[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onholding[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onicccardlockerror[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)oniccinfochange[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onincoming[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)oninput[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)oninvalid[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onkeydown[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onkeypress[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onkeyup[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onlevelchange[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onloadeddata[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onloadedmetadata[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onloadend[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onloadstart[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onlosecapture[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)only[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onmark[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onmessage[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onmousedown[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onmouseenter[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onmouseleave[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onmousemove[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onmouseout[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onmouseover[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onmouseup[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onmousewheel[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onmove[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onmoveend[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onmovestart[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onmozfullscreenchange[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onmozfullscreenerror[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onmoznetworkdownload[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onmoznetworkupload[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onmozorientationchange[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onmozpointerlockchange[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onmozpointerlockerror[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onmoztimechange[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onnomatch[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onnoupdate[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onobsolete[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onoffline[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)ononline[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onopen[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onoverflow[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onoverflowchanged[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onpagehide[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onpageshow[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onpaint[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onpaste[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onpause[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onplay[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onplaying[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onpopstate[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onpopuphidden[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onpopuphiding[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onpopupshowing[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onpopupshown[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onprogress[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onpropertychange[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onratechange[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onreadystatechange[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onreceived[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onremovetrack[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onrepeatEvent[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onrepeat[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onreset[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onresize[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onresult[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onresume[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onresuming[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onretrieving[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onrowenter[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onrowexit[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onrowsdelete[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onrowsinserted[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onscroll[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onseekcomplete[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onseeked[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onseeking[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onselect[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onselectstart[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onsending[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onsent[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onset[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onshow[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onsoundend[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onsoundstart[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onspeechend[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onspeechstart[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onstalled[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onstart[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onstatechange[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onstatuschanged[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onstkcommand[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onstksessionend[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onstop[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onsubmit[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onsuccess[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onsuspend[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)ontext[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)ontimeout[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)ontimeupdate[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)ontouchcancel[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)ontouchend[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)ontouchenter[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)ontouchleave[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)ontouchmove[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)ontouchstart[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)ontransitioncancel[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)ontransitionend[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)ontransitionrun[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onunderflow[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onunload[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onupdateready[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onupgradeneeded[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onuserproximity[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onussdreceived[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onversionchange[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onvoicechange[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onvolumechange[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onwaiting[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onwarning[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onwheel[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)onzoom[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)ping[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)src[\s\x08]*?=
(?:<\w[\s\S]*[\s\/]|['\"](?:[\s\S]*[\s\/])?)style[\s\x08]*?=

View File

@@ -0,0 +1,21 @@
\!\=
\&\&
\|\|
>>
<<
>=
<=
<>
<=>
\bxor\b
\bregexp\b
regexp\s+binary
\bisnull\b
\brlike\b
rlike\s+binary
not\s+between\s+0\s+and
is\s+null
like\s+null
^in[+\s]*\([\s\d\"]+[^()]*\)
\Win[+\s]*\([\s\d\"]+[^()]*\)
<>\s+binary

View File

@@ -0,0 +1,16 @@
[\s'\"`()]*?\b([\d\w]+)\b[\s'\"`()]*?=[\s'\"`()]*?(?:\b\1\b)
[\s'\"`()]*?\b([\d\w]+)\b[\s'\"`()]*?<=>[\s'\"`()]*?(?:\b\1\b)
[\s'\"`()]*?\b([\d\w]+)\b[\s'\"`()]*?like[\s'\"`()]*?(?:\b\1\b)
[\s'\"`()]*?\b([\d\w]+)\b[\s'\"`()]*?rlike[\s'\"`()]*?(?:\b\1\b)
[\s'\"`()]*?\b([\d\w]+)\b[\s'\"`()]*?sounds\s+like[\s'\"`()]*?(?:\b\1\b)
[\s'\"`()]*?\b([\d\w]+)\b[\s'\"`()]*?regexp[\s'\"`()]*?(?:\b\1\b)
[\s'\"`()]*?\b([\d\w]+)\b[\s'\"`()]*?!=[\s'\"`()]*?(?!\b\1\b)[\d\w]+
[\s'\"`()]*?\b([\d\w]+)\b[\s'\"`()]*?<=[\s'\"`()]*?(?!\b\1\b)[\d\w]+
[\s'\"`()]*?\b([\d\w]+)\b[\s'\"`()]*?>=[\s'\"`()]*?(?!\b\1\b)[\d\w]+
[\s'\"`()]*?\b([\d\w]+)\b[\s'\"`()]*?<>[\s'\"`()]*?(?!\b\1\b)[\d\w]+
[\s'\"`()]*?\b([\d\w]+)\b[\s'\"`()]*?<[\s'\"`()]*?(?!\b\1\b)[\d\w]+
[\s'\"`()]*?\b([\d\w]+)\b[\s'\"`()]*?>[\s'\"`()]*?(?!\b\1\b)[\d\w]+
[\s'\"`()]*?\b([\d\w]+)\b[\s'\"`()]*?\^[\s'\"`()]*?(?!\b\1\b)[\d\w]+
[\s'\"`()]*?\b([\d\w]+)\b[\s'\"`()]*?is\s+not[\s'\"`()]*?(?!\b\1\b)[\d\w]+
[\s'\"`()]*?\b([\d\w]+)\b[\s'\"`()]*?not\s+like[\s'\"`()]*?(?!\b\1\b)[\d\w]+
[\s'\"`()]*?\b([\d\w]+)\b[\s'\"`()]*?not\s+regexp[\s'\"`()]*?(?!\b\1\b)[\d\w]+

View File

@@ -0,0 +1,25 @@
database\W*\(
db_name\W*\(
information_schema\b
master\.\.sysdatabases\b
msdb\b
msysaccessobjects\b
msysaccessstorage\b
msysaccessxml\b
msysaces\b
msysmodules2\b
msysmodules\b
msysobjects\b
msysqueries\b
msysrelationships\b
mysql\.db\b
northwind\b
pg_catalog\b
pg_toast\b
schema_name\b
schema\W*\(
sqlite_master\b
sqlite_temp_master\b
sysaux\b
sys\.database_name\b
tempdb\b

View File

@@ -0,0 +1,236 @@
abs
acos
adddate
addtime
aes_decrypt
aes_encrypt
ascii
asciistr
asin
atan
atan2
avg
benchmark
bin
bin_to_num
bit_and
bit_count
bit_length
bit_or
bit_xor
cast
ciel
cieling
char_length
char
character_length
charset
chr
coalesce
coercibility
collation
compress
concat_ws
concat
connection_id
conv
convert_tz
convert
cos
cot
count
dcount
cr32
curdate
current_date
current_time
current_timestamp
current_user
curtime
database
date
date_add
date_format
date_sub
datediff
day
dayname
dayofmonth
dayofweek
dayofyear
decode
default
degrees
des_decrypt
des_encrypt
dump
elt
encode
encrypt
exp
export_set
extract
extractvalue
field
field_in_set
find_in_set
floor
format
found_rows
from_base64
from_days
from_unixtime
get_format
get_lock
greatest
group_concat
hex
hextoraw
rawtohex
hour
if
ifnull
in
inet6_aton
inet6_ntoa
inet_aton
inet_ntoa
insert
instr
interval
isnull
is_free_lock
is_ipv4_compat
is_ipv4_mapped
is_ipv4
is_ipv6
is_not_null
is_not
is_null
is_used_lock
last
last_day
last_inser_id
lcase
least
left
length
ln
load_file
local
localtimestamp
locate
log
log2
log10
lower
lpad
ltrim
make_set
makedate
master_pos_wait
max
md5
microsecond
mid
min
minute
mod
month
monthname
name_const
not_in
now
nullif
oct
octet_length
old_password
ord
password
period_add
period_diff
pi
position
pow
power
procedure_analyse
quarter
quote
radians
rand
release_lock
repeat
replace
reverse
right
round
row_count
rpad
rtrim
schema
sec_to_time
second
session_user
sha
sha1
sha2
sign
sin
pg_sleep
sleep
soundex
space
sqrt
std
stddev_pop
stddev_samp
str_to_date
strcmp
subdate
substring
substring_index
substr
subtime
sum
sysdate
system_user
tan
time
timestamp
timestampadd
timestampdiff
timediff
time_format
time_to_sec
to_base64
todays
toseconds
tochar
tonchar
trim
truncate
ucase
uncompress
uncompressed_length
unhex
unix_timestamp
updatexml
upper
user
utc_date
utc_time
utc_timestamp
uuid
uuid_short
values
var_pop
var_samp
variance
version
week
weekday
weekofyear
weight_string
year
yearweek
xmltype

View File

@@ -0,0 +1,6 @@
select\s+benchmark\s*?\(\s*?[(]?\s*?\w+
;\s+benchmark\s*?\(\s*?[(]?\s*?\w+
select\s+if\s*?\(\s*?[(]?\s*?\w+
;\s+if\s*?\(\s*?[(]?\s*?\w+
select\s+sleep\s*?\(\s*?[(]?\s*?\w+
;\s+sleep\s*?\(\s*?[(]?\s*?\w+

View File

@@ -0,0 +1,21 @@
\d[\"'`]\s+[\"'`]\s+\d
^admin\s*?[\"'`]
(?:/\*)+[\"'`]+\s?
(?:/\*)+[\"'`]+\s?--
(?:/\*)+[\"'`]+\s?#
(?:/\*)+[\"'`]+\s?/\*
(?:/\*)+[\"'`]+\s?{
[\"'`]\s*?or[\w\s-]+\s*?[+<>=(),-]\s*?[\d\"'`]
[\"'`]\s*?xor[\w\s-]+\s*?[+<>=(),-]\s*?[\d\"'`]
[\"'`]\s*?div[\w\s-]+\s*?[+<>=(),-]\s*?[\d\"'`]
[\"'`]\s*?like[\w\s-]+\s*?[+<>=(),-]\s*?[\d\"'`]
[\"'`]\s*?between[\w\s-]+\s*?[+<>=(),-]\s*?[\d\"'`]
[\"'`]\s*?and[\w\s-]+\s*?[+<>=(),-]\s*?[\d\"'`]
[\"'`]\s*?[^\w\s]?=\s*?[\"'`]
[\"'`]\W*?[+=]+\W*?[\"'`]
[\"'`]\s*?[!=|][\d\s!=+-]+.*?[\"'`(].*?$
[\"'`]\s*?[!=|][\d\s!=]+.*?\d+$
[\"'`]\s*?like\W+[\w\"'`(]
\sis\s*?0\W
where\s[\s\w\.,-]+\s=
[\"'`][<>~]+[\"'`]

View File

@@ -0,0 +1,20 @@
[\"'`]\s*?!\s*?[\"'`\w]
[\"'`];?\s*?having\b\s*?[^\s]
[\"'`];?\s*?select\b\s*?[^\s]
[\"'`];?\s*?union\b\s*?[^\s]
\s*?exec.*?\Wxp_cmdshell
\s*?execute.*?\Wxp_cmdshell
\wiif\s*?\(
connection_id\s*?\([^\)]*?
current_user\s*?\([^\)]*?
database\s*?\([^\)]*?
exec\s+master\.
execute\s+master\.
from\W+information_schema\W
into[\s+]+dumpfile\s*?[\"'`]
into[\s+]+outfile\s*?[\"'`]
schema\s*?\([^\)]*?
select.*?\w?user\(
union select @
union[\w(\s]*?select
user\s*?\([^\)]*?

View File

@@ -0,0 +1,14 @@
,.*?[)\da-f\"'`][\"'`][\"'`].*?[\"'`]
,.*?[)\da-f\"'`][\"'`](?:\r?\n)?\z
,.*?[)\da-f\"'`][\"'`][^\"'`]+
\Wselect.+\W*?from
select\s*?\(\s*?space\s*?\(
create\s*?\(\s*?space\s*?\(
rename\s*?\(\s*?space\s*?\(
truncate\s*?\(\s*?space\s*?\(
load\s*?\(\s*?space\s*?\(
alter\s*?\(\s*?space\s*?\(
delete\s*?\(\s*?space\s*?\(
update\s*?\(\s*?space\s*?\(
insert\s*?\(\s*?space\s*?\(
desc\s*?\(\s*?space\s*?\(

View File

@@ -0,0 +1,40 @@
@.+=\s*?\(\s*?select
\d\s*?or\s*?\d+\s*?[\-+]
\d\s*?xor\s*?\d+\s*?[\-+]
\d\s*?div\s*?\d+\s*?[\-+]
\d\s*?like\s*?\d+\s*?[\-+]
\d\s*?between\s*?\d+\s*?[\-+]
\d\s*?and\s*?\d+\s*?[\-+]
\/\w+;?\s+having\W
\/\w+;?\s+and\W
\/\w+;?\s+or\W
\/\w+;?\s+xor\W
\/\w+;?\s+div\W
\/\w+;?\s+like\W
\/\w+;?\s+between\W
\/\w+;?\s+select\W
\d\s+group\s+by.+\(
;\s*?drop
#\s*?drop
--\s*?drop
;\s*?alter
#\s*?alter
--\s*?alter
;\s*?update\s*?\w{2,}
#\s*?update\s*?\w{2,}
--\s*?update\s*?\w{2,}
;\s*?insert\s*?\w{2,}
#\s*?insert\s*?\w{2,}
--\s*?insert\s*?\w{2,}
[^\w]SET\s*?@\w+
and[\s(]+\w+[\s)]*?[!=+]+[\s\d]*?[\"'`=()]
nand[\s(]+\w+[\s)]*?[!=+]+[\s\d]*?[\"'`=()]
or[\s(]+\w+[\s)]*?[!=+]+[\s\d]*?[\"'`=()]
xor[\s(]+\w+[\s)]*?[!=+]+[\s\d]*?[\"'`=()]
xxor[\s(]+\w+[\s)]*?[!=+]+[\s\d]*?[\"'`=()]
div[\s(]+\w+[\s)]*?[!=+]+[\s\d]*?[\"'`=()]
like[\s(]+\w+[\s)]*?[!=+]+[\s\d]*?[\"'`=()]
between[\s(]+\w+[\s)]*?[!=+]+[\s\d]*?[\"'`=()]
not[\s(]+\w+[\s)]*?[!=+]+[\s\d]*?[\"'`=()]
\|\|[\s(]+\w+[\s)]*?[!=+]+[\s\d]*?[\"'`=()]
\&\&[\s(]+\w+[\s)]*?[!=+]+[\s\d]*?[\"'`=()]

View File

@@ -0,0 +1,5 @@
alter\s*?\w+.*?character\s+set\s+\w+
alter\s*?\w+.*?char\s+set\s+\w+
[\"'`];*?\s*?waitfor\s+time\s+[\"'`]
[\"'`];*?\s*?waitfor\s+delay\s+[\"'`]
[\"'`];.*?:\s*?goto

View File

@@ -0,0 +1,22 @@
union\s*?\s*?[([]*?\s*?select\s+
union\s*?all\s*?[([]*?\s*?select\s+
union\s*?distinct\s*?[([]*?\s*?select\s+
union\s*?[(!@]*?\s*?[([]*?\s*?select\s+
\w\s+like\s+[\"'`]
like\s*?[\"'`]\%
[\"'`]\s*?like\W*?[\"'`\d]
[\"'`]\s*?and\s+[\s\w]+=\s*?\w+\s*?having\s+
[\"'`]\s*?nand\s+[\s\w]+=\s*?\w+\s*?having\s+
[\"'`]\s*?or\s+[\s\w]+=\s*?\w+\s*?having\s+
[\"'`]\s*?xor\s+[\s\w]+=\s*?\w+\s*?having\s+
[\"'`]\s*?xxor\s+[\s\w]+=\s*?\w+\s*?having\s+
[\"'`]\s*?div\s+[\s\w]+=\s*?\w+\s*?having\s+
[\"'`]\s*?like\s+[\s\w]+=\s*?\w+\s*?having\s+
[\"'`]\s*?between\s+[\s\w]+=\s*?\w+\s*?having\s+
[\"'`]\s*?not\s+[\s\w]+=\s*?\w+\s*?having\s+
[\"'`]\s*?\|\|\s+[\s\w]+=\s*?\w+\s*?having\s+
[\"'`]\s*?\&\&\s+[\s\w]+=\s*?\w+\s*?having\s+
[\"'`]\s*?\*\s*?\w+\W+[\"'`]
[\"'`]\s*?[^?\w\s=.,;)(]++\s*?[(@\"'`]*?\s*?\w+\W+\w
select\s+?[\[\]()\s\w\.,\"'`-]+from\s+
find_in_set\s*?\(

View File

@@ -0,0 +1,7 @@
select\s*?pg_sleep
waitfor\s*?delay\s?[\"'`]+\s?\d
;\s*?shutdown\s*?;
;\s*?shutdown\s*?--
;\s*?shutdown\s*?#
;\s*?shutdown\s*?\/\*
;\s*?shutdown\s*?{

View File

@@ -0,0 +1,18 @@
\)\s*?when\s*?\d+\s*?then
[\"'`]\s*?#
[\"'`]\s*?--
[\"'`]\s*?{
\/\*!\s?\d+
char\s*?\(\s*?\d
chr\s*?\(\s*?\d
and\s+\s*?\w+\(
nand\s+\s*?\w+\(
or\s+\s*?\w+\(
xor\s+\s*?\w+\(
xxor\s+\s*?\w+\(
div\s+\s*?\w+\(
like\s+\s*?\w+\(
between\s+\s*?\w+\(
not\s+\s*?\w+\(
\|\|\s+\s*?\w+\(
\&\&\s+\s*?\w+\(

View File

@@ -0,0 +1,15 @@
[\"'`]\s+and\s*?=\W
\(\s*?select\s*?\w+\s*?\(
\*\/from
\+\s*?\d+\s*?\+\s*?@
\w[\"'`]\s*?(?:[-+=|@]+\s+?)+[\d(]
\w[\"'`]\s*?[-+=|@]+[\d(]
coalesce\s*?\(
@@\w+\s*?[^\w\s]
\W!+[\"'`]\w
[\"'`];\s*?if
[\"'`];\s*?while
[\"'`];\s*?begin
[\"'`][\s\d]+=\s*?\d
order\s+by\s+if\w*?\s*?\(
[\s(]+case\d*?\W.+[tw]hen[\s(]

View File

@@ -0,0 +1,7 @@
create\s+function\s*?\w+\s*?\(\s*?\)\s*?-
create\s+procedure\s*?\w+\s*?\(\s*?\)\s*?-
declare[^\w]+[@#]\s*?\w+
exec\s*?\(\s*?@
procedure\s+analyse\s*?\(
;\s*?declare\s+[\w-]+
;\s*?open\s+[\w-]+

View File

@@ -0,0 +1,46 @@
[\"'`]\s*?or\s*?[\"'`]?\d
[\"'`]\s*?xor\s*?[\"'`]?\d
[\"'`]\s*?div\s*?[\"'`]?\d
[\"'`]\s*?like\s*?[\"'`]?\d
[\"'`]\s*?between\s*?[\"'`]?\d
[\"'`]\s*?and\s*?[\"'`]?\d
\\\\x(?:23|27|3d)
^.?[\"'`]$
^[\"'`\\\\]*?[\d\"'`]+\s*?and\s*?[\w\"'`][+&!@(),.-]
^[\"'`\\\\]*?[\d\"'`]+\s*?nand\s*?[\w\"'`][+&!@(),.-]
^[\"'`\\\\]*?[\d\"'`]+\s*?or\s*?[\w\"'`][+&!@(),.-]
^[\"'`\\\\]*?[\d\"'`]+\s*?xor\s*?[\w\"'`][+&!@(),.-]
^[\"'`\\\\]*?[\d\"'`]+\s*?xxor\s*?[\w\"'`][+&!@(),.-]
^[\"'`\\\\]*?[\d\"'`]+\s*?div\s*?[\w\"'`][+&!@(),.-]
^[\"'`\\\\]*?[\d\"'`]+\s*?like\s*?[\w\"'`][+&!@(),.-]
^[\"'`\\\\]*?[\d\"'`]+\s*?between\s*?[\w\"'`][+&!@(),.-]
^[\"'`\\\\]*?[\d\"'`]+\s*?not\s*?[\w\"'`][+&!@(),.-]
^[\"'`\\\\]*?[\d\"'`]+\s*?\|\|\s*?[\w\"'`][+&!@(),.-]
^[\"'`\\\\]*?[\d\"'`]+\s*?\&\&\s*?[\w\"'`][+&!@(),.-]
^[\"'`\\\\]*?[^\"'`]+[\"'`]\s*?and\s*?[\w\"'`][+&!@(),.-]
^[\"'`\\\\]*?[^\"'`]+[\"'`]\s*?nand\s*?[\w\"'`][+&!@(),.-]
^[\"'`\\\\]*?[^\"'`]+[\"'`]\s*?or\s*?[\w\"'`][+&!@(),.-]
^[\"'`\\\\]*?[^\"'`]+[\"'`]\s*?xor\s*?[\w\"'`][+&!@(),.-]
^[\"'`\\\\]*?[^\"'`]+[\"'`]\s*?xxor\s*?[\w\"'`][+&!@(),.-]
^[\"'`\\\\]*?[^\"'`]+[\"'`]\s*?div\s*?[\w\"'`][+&!@(),.-]
^[\"'`\\\\]*?[^\"'`]+[\"'`]\s*?like\s*?[\w\"'`][+&!@(),.-]
^[\"'`\\\\]*?[^\"'`]+[\"'`]\s*?between\s*?[\w\"'`][+&!@(),.-]
^[\"'`\\\\]*?[^\"'`]+[\"'`]\s*?not\s*?[\w\"'`][+&!@(),.-]
^[\"'`\\\\]*?[^\"'`]+[\"'`]\s*?\|\|\s*?[\w\"'`][+&!@(),.-]
^[\"'`\\\\]*?[^\"'`]+[\"'`]\s*?\&\&\s*?[\w\"'`][+&!@(),.-]
[^\w\s]\w+\s*?[|-]\s*?[\"'`]\s*?\w
@\w+\s+and\s*?[\"'`\d]+
@\w+\s+or\s*?[\"'`\d]+
@\w+\s+xor\s*?[\"'`\d]+
@\w+\s+div\s*?[\"'`\d]+
@\w+\s+like\s*?[\"'`\d]+
@\w+\s+between\s*?[\"'`\d]+
@[\w-]+\sand\s*?[^\w\s]
@[\w-]+\sor\s*?[^\w\s]
@[\w-]+\sxor\s*?[^\w\s]
@[\w-]+\sdiv\s*?[^\w\s]
@[\w-]+\slike\s*?[^\w\s]
@[\w-]+\sbetween\s*?[^\w\s]
[^\w\s:]\s*?\d\W+[^\w\s]\s*?[\"'`].
\Winformation_schema
table_name\W

View File

@@ -0,0 +1,17 @@
in\s*?[(]+\s*?select
(?i:n?and|x?x?or|div|like|between|not|\|\||\&\&)\s+[\s\w+]+regexp\s*?\(
(?i:n?and|x?x?or|div|like|between|not|\|\||\&\&)\s+[\s\w+]+sounds\s+like\s*?[\"'`]
(?i:n?and|x?x?or|div|like|between|not|\|\||\&\&)\s+[\s\w+]+[=\d]+x
[\"'`]\s*?\d\s*?--
[\"'`]\s*?\d\s*?#
[\"'`][\%&<>^=]+\d\s*?=
[\"'`][\%&<>^=]+\d\s*?or
[\"'`][\%&<>^=]+\d\s*?xor
[\"'`][\%&<>^=]+\d\s*?div
[\"'`][\%&<>^=]+\d\s*?like
[\"'`][\%&<>^=]+\d\s*?between
[\"'`][\%&<>^=]+\d\s*?and
[\"'`]\W+[\w+-]+\s*?=\s*?\d\W+[\"'`]
[\"'`]\s*?is\s*?\d.+[\"'`]?\w
[\"'`][|]?[\w-]{3,}[^\w\s.,]+[\"'`]
[\"'`]\s*?is\s*?[\d.]+\s*?\W.*?[\"'`]

View File

@@ -0,0 +1,11 @@
create\s+function\s+.+\s+returns
;\s*?alter\b\s*?[\[(]?\w{2,}
;\s*?create\b\s*?[\[(]?\w{2,}
;\s*?delete\b\s*?[\[(]?\w{2,}
;\s*?desc\b\s*?[\[(]?\w{2,}
;\s*?insert\b\s*?[\[(]?\w{2,}
;\s*?load\b\s*?[\[(]?\w{2,}
;\s*?rename\b\s*?[\[(]?\w{2,}
;\s*?select\b\s*?[\[(]?\w{2,}
;\s*?truncate\b\s*?[\[(]?\w{2,}
;\s*?update\b\s*?[\[(]?\w{2,}

View File

@@ -0,0 +1,134 @@
alter\s+char\s?[(]?
alter\s+group_concat\s?[(]?
alter\s+load_file\s?[(]?
create\s+char\s?[(]?
create\s+group_concat\s?[(]?
create\s+load_file\s?[(]?
delete\s+char\s?[(]?
delete\s+group_concat\s?[(]?
delete\s+load_file\s?[(]?
desc\s+char\s?[(]?
desc\s+group_concat\s?[(]?
desc\s+load_file\s?[(]?
insert\s+char\s?[(]?
insert\s+group_concat\s?[(]?
insert\s+load_file\s?[(]?
load\s+char\s?[(]?
load\s+group_concat\s?[(]?
load\s+load_file\s?[(]?
rename\s+char\s?[(]?
rename\s+group_concat\s?[(]?
rename\s+load_file\s?[(]?
select\s+char\s?[(]?
select\s+group_concat\s?[(]?
select\s+load_file\s?[(]?
truncate\s+char\s?[(]?
truncate\s+group_concat\s?[(]?
truncate\s+load_file\s?[(]?
update\s+char\s?[(]?
update\s+group_concat\s?[(]?
update\s+load_file\s?[(]?
end\s*?\);
[\s(]load_file\s*?\(
[\"'`]\s+regexp\W
[\d\W]\s+as\b\s*[\"'`\w]+\s*\bfrom
^[\W\d]+\s*?create\s+\w+
^[\W\d]+\s*?delete\b
^[\W\d]+\s*?desc\b
^[\W\d]+\s*?insert\b
^[\W\d]+\s*?load\b
^[\W\d]+\s*?rename\b
^[\W\d]+\s*?select\b
^[\W\d]+\s*?truncate\b
^[\W\d]+\s*?update\b
^[\W\d]+\s*?alter\s*aggregate\b
^[\W\d]+\s*?alter\s*application\s*role\b
^[\W\d]+\s*?alter\s*assembly\b
^[\W\d]+\s*?alter\s*asymmetric\s*key\b
^[\W\d]+\s*?alter\s*audit\b
^[\W\d]+\s*?alter\s*authorization\b
^[\W\d]+\s*?alter\s*availability\s*group\b
^[\W\d]+\s*?alter\s*broker\s*priority\b
^[\W\d]+\s*?alter\s*bufferpool\b
^[\W\d]+\s*?alter\s*certificate\b
^[\W\d]+\s*?alter\s*cluster\b
^[\W\d]+\s*?alter\s*collation\b
^[\W\d]+\s*?alter\s*column\b
^[\W\d]+\s*?alter\s*conversion\b
^[\W\d]+\s*?alter\s*credential\b
^[\W\d]+\s*?alter\s*cryptographic\s*provider\b
^[\W\d]+\s*?alter\s*database\b
^[\W\d]+\s*?alter\s*default\b
^[\W\d]+\s*?alter\s*dimension\b
^[\W\d]+\s*?alter\s*diskgroup\b
^[\W\d]+\s*?alter\s*domain\b
^[\W\d]+\s*?alter\s*endpoint\b
^[\W\d]+\s*?alter\s*extension\b
^[\W\d]+\s*?alter\s*external\b
^[\W\d]+\s*?alter\s*event\b
^[\W\d]+\s*?alter\s*flashback\b
^[\W\d]+\s*?alter\s*foreign\b
^[\W\d]+\s*?alter\s*fulltext\b
^[\W\d]+\s*?alter\s*function\b
^[\W\d]+\s*?alter\s*hierarchy\b
^[\W\d]+\s*?alter\s*group\b
^[\W\d]+\s*?alter\s*histogram\b
^[\W\d]+\s*?alter\s*index\b
^[\W\d]+\s*?alter\s*indextype\b
^[\W\d]+\s*?alter\s*inmemory\b
^[\W\d]+\s*?alter\s*instance\b
^[\W\d]+\s*?alter\s*java\b
^[\W\d]+\s*?alter\s*language\b
^[\W\d]+\s*?alter\s*large\b
^[\W\d]+\s*?alter\s*library\b
^[\W\d]+\s*?alter\s*lockdown\b
^[\W\d]+\s*?alter\s*logfile\s*group\b
^[\W\d]+\s*?alter\s*login\b
^[\W\d]+\s*?alter\s*mask\b
^[\W\d]+\s*?alter\s*master\s*key\b
^[\W\d]+\s*?alter\s*materialized\b
^[\W\d]+\s*?alter\s*message\s*type\b
^[\W\d]+\s*?alter\s*method\b
^[\W\d]+\s*?alter\s*module\b
^[\W\d]+\s*?alter\s*nickname\b
^[\W\d]+\s*?alter\s*operator\b
^[\W\d]+\s*?alter\s*outline\b
^[\W\d]+\s*?alter\s*package\b
^[\W\d]+\s*?alter\s*partition\b
^[\W\d]+\s*?alter\s*permission\b
^[\W\d]+\s*?alter\s*procedure\b
^[\W\d]+\s*?alter\s*profile\b
^[\W\d]+\s*?alter\s*queue\b
^[\W\d]+\s*?alter\s*remote\b
^[\W\d]+\s*?alter\s*resource\b
^[\W\d]+\s*?alter\s*role\b
^[\W\d]+\s*?alter\s*rollback\b
^[\W\d]+\s*?alter\s*route\b
^[\W\d]+\s*?alter\s*schema\b
^[\W\d]+\s*?alter\s*search\b
^[\W\d]+\s*?alter\s*security\b
^[\W\d]+\s*?alter\s*server\b
^[\W\d]+\s*?alter\s*service\b
^[\W\d]+\s*?alter\s*sequence\b
^[\W\d]+\s*?alter\s*session\b
^[\W\d]+\s*?alter\s*symmetric\s*key\b
^[\W\d]+\s*?alter\s*synonym\b
^[\W\d]+\s*?alter\s*stogroup\b
^[\W\d]+\s*?alter\s*table\b
^[\W\d]+\s*?alter\s*tablespace\b
^[\W\d]+\s*?alter\s*text\b
^[\W\d]+\s*?alter\s*threshold\b
^[\W\d]+\s*?alter\s*trigger\b
^[\W\d]+\s*?alter\s*trusted\b
^[\W\d]+\s*?alter\s*type\b
^[\W\d]+\s*?alter\s*usage\b
^[\W\d]+\s*?alter\s*user\b
^[\W\d]+\s*?alter\s*view\b
^[\W\d]+\s*?alter\s*work\b
^[\W\d]+\s*?alter\s*workload\b
^[\W\d]+\s*?alter\s*wrapper\b
^[\W\d]+\s*?alter\s*xml\s*schema\b
^[\W\d]+\s*?alter\s*xsrobject\b
^[\W\d]+\s*?union\s*all\b
^[\W\d]+\s*?union\s*select\b
^[\W\d]+\s*?union\s*distinct\b

View File

@@ -0,0 +1,19 @@
[\"'`]\s*?\*.+or\W*?[\"'`]\d
[\"'`]\s*?\*.+xor\W*?[\"'`]\d
[\"'`]\s*?\*.+div\W*?[\"'`]\d
[\"'`]\s*?\*.+like\W*?[\"'`]\d
[\"'`]\s*?\*.+between\W*?[\"'`]\d
[\"'`]\s*?\*.+and\W*?[\"'`]\d
[\"'`]\s*?\*.+id\W*?[\"'`]\d
\^[\"'`]
[\"'`]\s*?[^\w\s?]+\s*?[^\w\s]+\s*?[\"'`]
[\"'`]\s*?[^\w\s]+\s*?[\W\d].*?#
[\"'`]\s*?[^\w\s]+\s*?[\W\d].*?--
[\"'`].*?\*\s*?\d
[\"'`]\s*?or\s[^\d]+[\w-]+.*?\d
[\"'`]\s*?xor\s[^\d]+[\w-]+.*?\d
[\"'`]\s*?div\s[^\d]+[\w-]+.*?\d
[\"'`]\s*?like\s[^\d]+[\w-]+.*?\d
[\"'`]\s*?between\s[^\d]+[\w-]+.*?\d
[\"'`]\s*?and\s[^\d]+[\w-]+.*?\d
[()\*<>%+-][\w-]+[^\w\s]+[\"'`][^,]

View File

@@ -0,0 +1,19 @@
\b(?i:having)\b\s+\d{1,10}\s*?[=<>]
\b(?i:having)\b\s+'[^=]{1,10}'\s*?[=<>]
(?i:\bexecute\()
(?i:\bexecute\s{1,5}[\w\.$]{1,5}\s{0,3})
\bhaving\b ?\d{1,10} ?[=<>]+
\bhaving\b ?[\'\"][^=]{1,10}[\'\" ?[=<>]+
(?i:\bcreate\s+?table.{0,20}?\()
(?i:\blike\W*?char\W*?\()
(?i:select.*?case)
(?i:from.*?limit)
(?i:order\sby)
exists\s\sselect
exists\sselect\Sif\s\(
exists\sselect\Sifnull\s\(
exists\sselect\Stop
exists\sselect\Sconcat
exists\ssystem\s\(
exists\s\b(?i:having)\b\s+\d{1,10}
exists\s'[^=]{1,10}'

View File

@@ -0,0 +1,12 @@
(?i:\bor\b ?\d{1,10} ?[=<>]+)
(?i:\bor\b ?[\'\"][^=]{1,10}[\'\"] ?[=<>]+)
(?i:'\s+or\s+.{1,20}[+\-!<>=])
(?i:'\s+xor\s+.{1,20}[+\-!<>=])
\b(?i:or)\b\s+\d{1,10}
\b(?i:or)\b\s+'[^=]{1,10}'
\b(?i:xor)\b\s+\d{1,10}
\b(?i:xor)\b\s+'[^=]{1,10}'
\b(?i:or)\b\s+\d{1,10}\s*?[=<>]
\b(?i:xor)\b\s+\d{1,10}\s*?[=<>]
\b(?i:or)\b\s+'[^=]{1,10}'\s*?[=<>]
\b(?i:xor)\b\s+'[^=]{1,10}'\s*?[=<>]

View File

@@ -0,0 +1,6 @@
\band\b\s+\d{1,10}\s*?[=<>]
\band\b\s+'[^=]{1,10}'\s*?[=<>]
\band\b\s+\d{1,10}
\band\b\s+'[^=]{1,10}'
\band\b ?\d{1,10} ?[=<>]+
\band\b ?[\'\"][^=]{1,10}[\'\"] ?[=<>]+

View File

@@ -0,0 +1,239 @@
abs
acos
adddate
addtime
aes_decrypt
aes_encrypt
asin
ascii
asciistr
atan
atan2
avg
benchmark
bin
bin_to_num
bit_and
bit_count
bit_length
bit_or
bit_xor
cast
char
character_length
char_length
charset
chr
ciel
cieling
coalesce
coercibility
compress
concat
concat_ws
connection_id
conv
convert
convert_tz
cos
cot
count
cr32
curdate
current_date
current_time
current_timestamp
current_user
curtime
database
date
date_add
datediff
date_format
date_sub
day
dayname
dayofmonth
dayofweek
dayofyear
dcount
decode
default
degrees
des_decrypt
des_encrypt
dump
elt
encode
encrypt
exp
export_set
extract
extractvalue
field
field_in_set
find_in_set
floor
format
found_rows
from_base64
from_days
from_unixtime
get_format
get_lock
greatest
group_concat
hex
hextoraw
hour
if
ifnull
in
inet6_aton
inet6_ntoa
inet_aton
inet_ntoa
insert
instr
interval
is
is_free_lock
is_ipv4
is_ipv4_compat
is_ipv4_mapped
is_ipv6
is_not
is_not_null
isnull
is_null
is_used_lock
last
last_day
last_insert_id
lcase
least
left
length
ln
load_file
local
localtimestamp
locate
log
log10
log2
lower
lpad
ltrim
makedate
make_set
master_pos_wait
max
md5
microsecond
mid
min
minute
mod
month
monthname
name_const
not_in
now
nullif
oct
octet_length
old_password
ord
password
period_add
period_diff
pg_sleep
pi
position
pow
power
procedure_analyse
quarter
quote
radians
rand
rawtohex
rawtonhex
rawtonhextoraw
release_lock
repeat
replace
reverse
right
round
row_count
rpad
rtrim
schema
second
sec_to_time
session_user
sha
sha1
sha2
sign
sin
sleep
soundex
space
sqrt
std
stddev
stddev_pop
stddev_samp
strcmp
str_to_date
subdate
substr
substring
substring_index
subtime
sum
sysdate
system_user
tan
time
timediff
time_format
timestamp
timestampadd
timestampdiff
time_to_sec
to_base64
to_char
to_days
to_nchar
to_seconds
trim
truncate
ucase
uncompress
uncompressed_length
unhex
unix_timestamp
updatexml
upper
user
utc_date
utc_time
utc_timestamp
uuid
uuid_short
values
variance
var_pop
var_samp
version
week
weekday
weekofyear
weight_string
xmltype
year
yearweek

View File

@@ -0,0 +1,45 @@
autonomous_transaction
dba_users
dbms_java
nvarchar
openowa_util
openquery
openrowset
sp_addextendedproc
sp_execute
sp_executesql
sp_help
sp_is_srvrolemember
sp_makewebtask
sp_oacreate
sp_password
sp_prepare
sp_replwritetovarbin
sp_sqlexec
sql_longvarchar
sql_variant
tbcreator
utl_file
utl_http
varchar
xp_availablemedia
xp_cmdshell
xp_dirtree
xp_enumdsn
xp_execresultset
xp_filelist
xp_loginconfig
xp_makecab
xp_ntsec
xp_ntsec_enumdomains
xp_regaddmultistring
xp_regdeletekey
xp_regdeletevalue
xp_regenumkeys
xp_regenumvalues
xp_regread
xp_regremovemultistring
xp_regwrite
xp_servicecontrol
xp_terminate
xp_terminate_process

View File

@@ -0,0 +1,29 @@
\bdbms_\w+\.\b
\bdelete\b\W*?\bfrom\b
\bgroup\b.*?\bby\b.{1,100}?\bhaving\b
\binner\b\W*?\bjoin\b
\binsert\b\W*?\binto\b
\binto\b\W*?\bdumpfile\b
\binto\b\W*?\boutfile\b
\bload\b\W*?\bdata\b.*?\binfile\b
\bprint\b\W*?\@\@
\bselect\b.{1,100}?\b.*?\bdump\b.*\bfrom\b
\bselect\b.{1,100}?\bcount\b.{1,100}?\bfrom\b
\bselect\b.{1,100}?\bdata_type\b
\bselect\b.{1,100}?\bfrom\b.{1,100}?\bwhere\b
\bselect\b.{1,100}?\binstr\b
\bselect\b.{1,100}?\blength\b.{1,100}?\bfrom\b
\bselect\b.{1,100}?\bto_char\b
\bselect\b.{1,100}?\bto_number\b
\bselect\b.{1,100}?\btop\b.{1,100}?\bfrom\b
\bsys_context\b
\bunion\b.{1,100}?\bselect\b
\butl_inaddr\b
collation\W*?\(a\b
'dbo'
'msdasql'
'sa'
'sqloledb'
\@\@version\b
;\W*?\bdrop\b
;\W*?\bshutdown\b

View File

@@ -0,0 +1,29 @@
#!/usr/bin/env perl
#
# Create one regexp from a set of regexps.
# Regexps can be submitted via standard input, one per line.
#
# Requires Regexp::Assemble Perl module.
# To install: cpan install Regexp::Assemble
#
# See: https://coreruleset.org/20190826/optimizing-regular-expressions/
#
use strict;
use Regexp::Assemble;
my $ra = Regexp::Assemble->new;
while (<>)
{
# Handle possessive qualifiers
# https://rt.cpan.org/Public/Bug/Display.html?id=50228#txn-672717
my $arr = $ra->lexstr($_);
for (my $n = 0; $n < $#$arr - 1; ++$n)
{
if ($arr->[$n] =~ /\+$/ and $arr->[$n + 1] eq '+') {
$arr->[$n] .= splice(@$arr, $n + 1, 1);
}
}
$ra->insert(@$arr);
}
print $ra->as_string() . "\n";

View File

@@ -0,0 +1,20 @@
#!/usr/bin/env perl
#
# Create one regexp from a set of regexps.
# Regexps can be submitted via standard input, one per line.
#
# Requires Regexp::Assemble Perl module.
# To install: cpan install Regexp::Assemble
#
# See: https://coreruleset.org/20190826/optimizing-regular-expressions/
#
use strict;
use Regexp::Assemble;
my $ra = Regexp::Assemble->new;
while (<>)
{
$ra->add($_);
}
print $ra->as_string() . "\n";

View File

@@ -0,0 +1,64 @@
#!/usr/bin/env python
#
# Convert a word list to a list of regexps usable by Regexp::Assemble.
#
# Examples:
# cat regexp-932100.txt | ./regexp-cmdline.py unix | ./regexp-assemble.pl
# cat regexp-932110.txt | ./regexp-cmdline.py windows | ./regexp-assemble.pl
# cat regexp-932150.txt | ./regexp-cmdline.py unix | ./regexp-assemble.pl
#
# Refer to rule 932100, 932110, 932150 for documentation.
#
import fileinput, string, sys
# Convert a single line to regexp format, and insert anti-cmdline
# evasions between characters.
def regexp_str(str, evasion):
# By convention, if the line starts with ' char, copy the rest
# verbatim.
if str[0] == "'":
return str[1:]
result = ''
for i, char in enumerate(str):
if i > 0:
result += evasion
result += regexp_char(char, evasion)
return result
# Ensure that some special characters are escaped
def regexp_char(char, evasion):
char = str.replace(char, '.', '\.')
char = str.replace(char, '-', '\-')
char = str.replace(char, '+', r'''(?:\s|<|>).*''')
# Unix: "cat foo", "cat<foo", "cat>foo"
char = str.replace(char, '@', r'''(?:[\s,;]|\.|/|<|>).*''')
# Windows: "more foo", "more,foo", "more;foo", "more.com", "more/e",
# "more<foo", "more>foo"
char = str.replace(char, ' ', '\s+')
# Ensure multiple spaces are matched
return char
# Insert these sequences between characters to prevent evasion.
# This emulates the relevant parts of t:cmdLine.
evasions = {
'unix': r'''[\\\\'\"]*''',
'windows': r'''[\"\^]*''',
}
# Parse arguments
if len(sys.argv) <= 1 or not sys.argv[1] in evasions:
print(sys.argv[0] + ' unix|windows [infile]')
sys.exit(1)
evasion = evasions[sys.argv[1]]
del sys.argv[1]
# Process lines from input file, or if not specified, standard input
for line in fileinput.input():
line = line.rstrip('\n ')
line = line.split('#')[0]
if line != '':
print(regexp_str(line, evasion))

View File

@@ -0,0 +1,170 @@
#!/bin/bash
#
# Script to post a payload against a local webserver at each paranoia level.
#
# Note: Webserver has to be prepared to take desired PL as Request Header "PL".
#
# WARNING: Setting the paranoia level using a header without proper
# authentication and authorization is extremely dangerous, and is not
# recommended for production.
#
# Check how to use the Christian Folini's Apache access log format at:
# https://www.netnea.com/cms/apache-tutorial-5_extending-access-log/
#
# LogFormat "%h %{GEOIP_COUNTRY_CODE}e %u [%{%Y-%m-%d %H:%M:%S}t.%{usec_frac}t] \"%r\" %>s %b \
# \"%{Referer}i\" \"%{User-Agent}i\" \"%{Content-Type}i\" %{remote}p %v %A %p %R \
# %{BALANCER_WORKER_ROUTE}e %X \"%{cookie}n\" %{UNIQUE_ID}e %{SSL_PROTOCOL}x %{SSL_CIPHER}x \
# %I %O %{ratio}n%% %D %{ModSecTimeIn}e %{ApplicationTime}e %{ModSecTimeOut}e \
# %{ModSecAnomalyScoreInPLs}e %{ModSecAnomalyScoreOutPLs}e \
# %{ModSecAnomalyScoreIn}e %{ModSecAnomalyScoreOut}e" extended
#
# This script assumes %{ModSecAnomalyScoreIn}e is the column before to last in
# the access log, if this does not match your LogFormat the script won't work
# For better results set the SecDefaultAction to 'pass'.
#
# The anomaly score envvar can be set as follows:
# SecAction "id:90101,phase:5,pass,nolog,\
# setenv:ModSecAnomalyScoreIn=%{TX.anomaly_score}"
#
# Sample rule to setup the PL dynamically from localhost"
# SecRule REMOTE_ADDR "@ipMatch 127.0.0.1,192.168.0.128" \
# "id:90102,phase:1,pass,capture,log,auditlog,\
# msg:'Setting engine to PL%{matched_var}',chain"
# SecRule REQUEST_HEADERS:PL "@rx ([1-4])" \
# "setvar:'tx.executing_paranoia_level=%{matched_var}'"
# Path to CRS rule set and local files
CRS="/usr/share/modsecurity-crs/rules"
accesslog="/apache/logs/access.log"
errorlog="/apache/logs/error.log"
URL="localhost:40080"
protocol="http"
while [[ $# > 0 ]]
do
case "$1" in
-c|--crs)
CRS="$2"
shift
;;
-a|--access)
accesslog="$2"
shift
;;
-e|--error)
errorlog="$2"
shift
;;
-u|--url)
URL="$2"
shift
;;
-r|--resolve)
resolve="$2"
resolve="--resolve $resolve"
shift
;;
--protocol)
protocol="$2"
shift
;;
-P|--payload)
PAYLOAD="$2"
shift
;;
-h|--help)
echo "Usage:"
echo " --access \"/apache/logs/access.log\""
echo " --error \"/apache/logs/error.log\""
echo " --url \"localhost:40080\""
echo " --resolve \"someservername:40080:localhost\""
echo " --protocol \"https\""
echo " --payload \"/tmp/payload\""
echo " --help"
exit 1
;;
esac
shift
done
echo "Using CRS: $CRS"
echo "Using accesslog: $accesslog"
echo "Using errorlog: $errorlog"
echo "Using URL: $URL"
echo "Using protocol: $protocol"
if [ -z "${PAYLOAD+x}" ]; then
echo "Please submit valid payload file as parameter. This is fatal. Aborting."
$0 -h
echo "Examples:"
echo " ./send-payload-pls.sh -a /logs/test/access.log \
-e /logs/test/error.log -u test.test.test.com:6443 --protocol https \
--payload /tmp/payload --resolve test.test.test.com:6443:192.168.0.128"
echo " ./send-payload-pls.sh -a /logs/test/access.log \
-e /logs/test/error.log -u test.test.test.com:6443 --protocol https \
--payload 'or 1=1;--' --resolve test.test.test.com:6443:192.168.0.128"
exit 1
fi
# URL of web server
# Rules per Paranoia level
# Paranoia level 1 rules, rule 012 is the delimiter of the start of PL1
# Paranoia level 1 rules, rule 013 is the delimiter of the end of PL1
PL1=$(awk "/012,phase:2/,/013,phase:1/" $CRS/*.conf |egrep -v "(012|013),phase" |egrep -o "id:[0-9]+" |sed -r 's,id:([0-9]+),\1\\,' |tr -t '\n' '\|' |sed -r 's,\\\|$,,')
# Paranoia level 2 rules, rule 014 is the delimiter of the start of PL2
# Paranoia level 2 rules, rule 015 is the delimiter of the end of PL2
PL2=$(awk "/014,phase:2/,/015,phase:1/" $CRS/*.conf |egrep -v "(014|015),phase" |egrep -o "id:[0-9]+" |sed -r 's,id:([0-9]+),\1\\,' |tr -t '\n' '\|' |sed -r 's,\\\|$,,')
# Paranoia level 3 rules, rule 016 is the delimiter of the start of PL3
# Paranoia level 3 rules, rule 017 is the delimiter of the end of PL3
PL3=$(awk "/016,phase:2/,/017,phase:1/" $CRS/*.conf |egrep -v "(016|017),phase" |egrep -o "id:[0-9]+" |sed -r 's,id:([0-9]+),\1\\,' |tr -t '\n' '\|' |sed -r 's,\\\|$,,')
# Paranoia level 4 rules, rule 018 is the delimiter of the start of PL4
# Paranoia level 4 rules, "Paranoia Levels Finished" delimiter of the end of PL4
PL4=$(awk "/018,phase:2/,/Paranoia Levels Finished/" $CRS/*.conf |egrep -v "018,phase" |egrep -o "id:[0-9]+" |sed -r 's,id:([0-9]+),\1\\,' |tr -t '\n' '\|' |sed -r 's,\\\|$,,')
echo "Sending the following payload at multiple paranoia levels: $PAYLOAD"
echo
for PL in 1 2 3 4; do
echo "--- Paranoia Level $PL ---"
echo
if [ -f "$PAYLOAD" ]; then
curl $protocol://$URL $resolve -k --data-binary "@$PAYLOAD" -H "PL: $PL" -o /dev/null -s
else
curl $protocol://$URL $resolve -k -d "$PAYLOAD" -H "PL: $PL" -o /dev/null -s
fi
# Here are three ways to get the transaction unique id,
# the first one is Christian's format, second is Spartan's format,
# and the third one tries to guess which is the unique id using a
# regular expression, the first two require specific format.
# The automatic format detection may cause the script to malfunction.
# Uncomment only the required format.
# To use Christian's accesslog format uncomment the following line
uniq_id=$(tail -1 $accesslog | cut -d\" -f11 | cut -b2-26)
# To use Spartan's accesslog format (21 col) uncomment the following line
#uniq_id=$(tail -1 $accesslog | awk '{print $21}')
# To use the automatic unique_id detection uncomment the following line
#uniq_id=$(tail -1 $accesslog | egrep -o '[a-zA-Z0-9]{26,28}')
echo "Tracking unique id: $uniq_id"
grep $uniq_id $errorlog | sed -e "s/.*\[id \"//" -e "s/\(......\).*\[msg \"/\1 /" -e "s/\"\].*//" -e "s/(Total .*/(Total ...) .../" -e "s/Incoming and Outgoing Score: [0-9]* [0-9]*/Incoming and Outgoing Score: .../" | sed -e "s/$PL1/& PL1/" -e "s/$PL2/& PL2/" -e "s/$PL3/& PL3/ " -e "s/$PL4/& PL4/" | sort -k2 | sed -r "s/^([0-9]+)$/\1 FOREIGN RULE NOT IN CRS/"
echo
echo -n "Total Incoming Score: "
# Here are two ways to get the transaction anomaly score,
# the first one is Christian's format, second is Spartan's format
# To use Christian's accesslog format uncomment the following line
tail -1 $accesslog | cut -d\" -f11 | cut -d\ -f14 | tr "-" "0"
# To use Spartan's accesslog format (21 col) uncomment the following line
# To use a different column change the $NF value, e.g. $(NF-1)
#tail -1 $accesslog | awk '{print $NF}' | tr "-" "0"
echo
done

View File

@@ -0,0 +1,117 @@
#!/usr/bin/env ruby
# -*- coding: utf-8 -*-
#
# Copyright © 2012 Diego Elio Pettenò <flameeyes@flameeyes.eu>
#
# Permission to use, copy, modify, and distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
# ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
# OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
# CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
# DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
# PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
# SOFTWARE.
require 'set'
seen_ids = Set.new
res = 0
# read reserved id range from the id-range file so that it can be
# configured on a per-repository basis.
range = Range.new(*File.read('id-range').rstrip.split('-').map(&:to_i))
# open all the rule files
Dir.chdir("../")
Dir["**/*.conf"].each do |rulefile|
# read the content
content = File.read(rulefile)
lineno = 0
this_chained = next_chained = false
prevline = nil
# for each line in the rule file
content.each_line do |line|
lineno += 1
# handle continuation lines
line = (prevline + line) unless prevline.nil?
# remove comments
line.gsub!(/^([^'"]|'[^']+'|"[^"]+")#.*/) { $1 }
if line =~ /\\\n$/
prevline = line.gsub(/\\\n/, '')
next
else
prevline = nil
end
# skip if it's an empty line (this also skip comment-only lines)
next if line =~ /(?:^\s+$|^#)/
this_chained = next_chained
next_chained = false
# split the directive in its components, considering quoted strings
directive = line.scan(/([^'"\s][^\s]*[^'"\s]|'(?:[^']|\\')*[^\\]'|"(?:[^"]|\\")*[^\\]")(?:\s+|$)/).flatten
directive.map! do |piece|
# then make sure to split the quoting out of the quoted strings
(piece[0] == '"' || piece[0] == "'") ? piece[1..-2] : piece
end
# skip if it's not a SecRule or SecAction
case directive[0]
when "SecRule"
rawrule = directive[3]
when "SecAction"
rawrule = directive[1]
else
next
end
# get the rule and split in its components
rule = (rawrule || "").gsub(/(?:^"|"$)/, '').split(/\s*,\s*/)
if rule.include?("chain")
next_chained = true
end
ids = rule.find_all { |piece| piece =~ /^id:/ }
if ids.size > 1
$stderr.puts "#{rulefile}:#{lineno} rule with multiple ids"
next
elsif ids.size == 0
id = nil
else
id = ids[0].sub(/^id:/, '').gsub(/(?:^'|'$)/, '').to_i
end
if this_chained
unless id.nil?
$stderr.puts "#{rulefile}:#{lineno} chained rule with id"
res = 1
end
next
elsif id.nil?
$stderr.puts "#{rulefile}:#{lineno} rule missing id (#{rule.join(',')})"
res = 1
next
elsif ! range.include?(id)
$stderr.puts "#{rulefile}:#{lineno} rule with id #{id} outside of reserved range #{range}"
res = 1
elsif seen_ids.include?(id)
$stderr.puts "#{rulefile}:#{lineno} rule with duplicated id #{id}"
res = 1
end
seen_ids << id
end
end
exit res

View File

@@ -0,0 +1,318 @@
#!/opt/local/bin/perl -T
#############################################
# -=[ Virtual Patching Converter Script ]=- #
# Converts arachni XML Output #
# 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 separate 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.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.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.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.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.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.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;
}

View File

@@ -0,0 +1,318 @@
#!/opt/local/bin/perl -T
#############################################
# -=[ Virtual Patching Converter Script ]=- #
# Converts OWASP ZAP XML Output #
# 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 separate 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.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.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.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.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.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.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;
}