From ff165a4035d74fd281c826e34c36094967bb9ca6 Mon Sep 17 00:00:00 2001 From: Felipe Zimmerle Date: Tue, 26 Apr 2016 17:52:59 -0300 Subject: [PATCH] Adds support to the multithread example --- configure.ac | 1 + examples/Makefile.am | 3 +- examples/multithread_c/Makefile.am | 23 +++ examples/multithread_c/basic_rules.conf | 234 ++++++++++++++++++++++++ examples/multithread_c/multi.c | 141 ++++++++++++++ 5 files changed, 401 insertions(+), 1 deletion(-) create mode 100644 examples/multithread_c/Makefile.am create mode 100644 examples/multithread_c/basic_rules.conf create mode 100644 examples/multithread_c/multi.c diff --git a/configure.ac b/configure.ac index d19d3d63..9365bcc0 100644 --- a/configure.ac +++ b/configure.ac @@ -275,6 +275,7 @@ AC_CONFIG_FILES([\ test/fuzzer/Makefile \ examples/Makefile \ examples/simple_example_using_c/Makefile \ + examples/multithread_c/Makefile \ ]) AC_CONFIG_HEADERS([src/config.h]) diff --git a/examples/Makefile.am b/examples/Makefile.am index 8ebb7e3b..43a3d3d7 100644 --- a/examples/Makefile.am +++ b/examples/Makefile.am @@ -3,7 +3,8 @@ ACLOCAL_AMFLAGS = -I build SUBDIRS = \ - simple_example_using_c + simple_example_using_c \ + multithread_c # make clean CLEANFILES = diff --git a/examples/multithread_c/Makefile.am b/examples/multithread_c/Makefile.am new file mode 100644 index 00000000..b89c8405 --- /dev/null +++ b/examples/multithread_c/Makefile.am @@ -0,0 +1,23 @@ + + +noinst_PROGRAMS = multi + +multi_SOURCES = \ + multi.c + +multi_LDADD = \ + -L$(top_builddir)/src/.libs/ \ + -lmodsecurity \ + $(YAJL_LDFLAGS) \ + $(GEOIP_LDFLAGS) \ + $(GLOBAL_LDADD) + +multi_CFLAGS = \ + -I$(top_builddir)/headers \ + -I$(top_builddir) \ + $(GLOBAL_CFLAGS) + +MAINTAINERCLEANFILES = \ + Makefile.in + + diff --git a/examples/multithread_c/basic_rules.conf b/examples/multithread_c/basic_rules.conf new file mode 100644 index 00000000..be7a3373 --- /dev/null +++ b/examples/multithread_c/basic_rules.conf @@ -0,0 +1,234 @@ +# -- Rule engine initialization ---------------------------------------------- + +# Enable ModSecurity, attaching it to every transaction. Use detection +# only to start with, because that minimises the chances of post-installation +# disruption. +# +SecRuleEngine DetectionOnly + + +# -- Request body handling --------------------------------------------------- + +# Allow ModSecurity to access request bodies. If you don't, ModSecurity +# won't be able to see any POST parameters, which opens a large security +# hole for attackers to exploit. +# +SecRequestBodyAccess On + + +# Enable XML request body parser. +# Initiate XML Processor in case of xml content-type +# +SecRule REQUEST_HEADERS:Content-Type "text/xml" \ + "id:'200000',phase:1,t:none,t:lowercase,pass,nolog,ctl:requestBodyProcessor=XML" + +# Enable JSON request body parser. +# Initiate JSON Processor in case of JSON content-type; change accordingly +# if your application does not use 'application/json' +# +SecRule REQUEST_HEADERS:Content-Type "application/json" \ + "id:'200001',phase:1,t:none,t:lowercase,pass,nolog,ctl:requestBodyProcessor=JSON" + +# Maximum request body size we will accept for buffering. If you support +# file uploads then the value given on the first line has to be as large +# as the largest file you are willing to accept. The second value refers +# to the size of data, with files excluded. You want to keep that value as +# low as practical. +# +SecRequestBodyLimit 13107200 +SecRequestBodyNoFilesLimit 131072 + +# Store up to 128 KB of request body data in memory. When the multipart +# parser reachers this limit, it will start using your hard disk for +# storage. That is slow, but unavoidable. +# +SecRequestBodyInMemoryLimit 131072 + +# What do do if the request body size is above our configured limit. +# Keep in mind that this setting will automatically be set to ProcessPartial +# when SecRuleEngine is set to DetectionOnly mode in order to minimize +# disruptions when initially deploying ModSecurity. +# +SecRequestBodyLimitAction Reject + +# Verify that we've correctly processed the request body. +# As a rule of thumb, when failing to process a request body +# you should reject the request (when deployed in blocking mode) +# or log a high-severity alert (when deployed in detection-only mode). +# +SecRule REQBODY_ERROR "!@eq 0" \ +"id:'200002', phase:2,t:none,log,deny,status:400,msg:'Failed to parse request body.',logdata:'%{reqbody_error_msg}',severity:2" + +# By default be strict with what we accept in the multipart/form-data +# request body. If the rule below proves to be too strict for your +# environment consider changing it to detection-only. You are encouraged +# _not_ to remove it altogether. +# +SecRule MULTIPART_STRICT_ERROR "!@eq 0" \ +"id:'200003',phase:2,t:none,log,deny,status:400, \ +msg:'Multipart request body failed strict validation: \ +PE %{REQBODY_PROCESSOR_ERROR}, \ +BQ %{MULTIPART_BOUNDARY_QUOTED}, \ +BW %{MULTIPART_BOUNDARY_WHITESPACE}, \ +DB %{MULTIPART_DATA_BEFORE}, \ +DA %{MULTIPART_DATA_AFTER}, \ +HF %{MULTIPART_HEADER_FOLDING}, \ +LF %{MULTIPART_LF_LINE}, \ +SM %{MULTIPART_MISSING_SEMICOLON}, \ +IQ %{MULTIPART_INVALID_QUOTING}, \ +IP %{MULTIPART_INVALID_PART}, \ +IH %{MULTIPART_INVALID_HEADER_FOLDING}, \ +FL %{MULTIPART_FILE_LIMIT_EXCEEDED}'" + +# Did we see anything that might be a boundary? +# +SecRule MULTIPART_UNMATCHED_BOUNDARY "!@eq 0" \ +"id:'200004',phase:2,t:none,log,deny,msg:'Multipart parser detected a possible unmatched boundary.'" + +# PCRE Tuning +# We want to avoid a potential RegEx DoS condition +# +SecPcreMatchLimit 1000 +SecPcreMatchLimitRecursion 1000 + +# Some internal errors will set flags in TX and we will need to look for these. +# All of these are prefixed with "MSC_". The following flags currently exist: +# +# MSC_PCRE_LIMITS_EXCEEDED: PCRE match limits were exceeded. +# +SecRule TX:/^MSC_/ "!@streq 0" \ + "id:'200005',phase:2,t:none,deny,msg:'ModSecurity internal error flagged: %{MATCHED_VAR_NAME}'" + + +# -- Response body handling -------------------------------------------------- + +# Allow ModSecurity to access response bodies. +# You should have this directive enabled in order to identify errors +# and data leakage issues. +# +# Do keep in mind that enabling this directive does increases both +# memory consumption and response latency. +# +SecResponseBodyAccess On + +# Which response MIME types do you want to inspect? You should adjust the +# configuration below to catch documents but avoid static files +# (e.g., images and archives). +# +SecResponseBodyMimeType text/plain text/html text/xml + +# Buffer response bodies of up to 512 KB in length. +SecResponseBodyLimit 524288 + +# What happens when we encounter a response body larger than the configured +# limit? By default, we process what we have and let the rest through. +# That's somewhat less secure, but does not break any legitimate pages. +# +SecResponseBodyLimitAction ProcessPartial + + +# -- Filesystem configuration ------------------------------------------------ + +# The location where ModSecurity stores temporary files (for example, when +# it needs to handle a file upload that is larger than the configured limit). +# +# This default setting is chosen due to all systems have /tmp available however, +# this is less than ideal. It is recommended that you specify a location that's private. +# +SecTmpDir /tmp/ + +# The location where ModSecurity will keep its persistent data. This default setting +# is chosen due to all systems have /tmp available however, it +# too should be updated to a place that other users can't access. +# +SecDataDir /tmp/ + + +# -- File uploads handling configuration ------------------------------------- + +# The location where ModSecurity stores intercepted uploaded files. This +# location must be private to ModSecurity. You don't want other users on +# the server to access the files, do you? +# +#SecUploadDir /opt/modsecurity/var/upload/ + +# By default, only keep the files that were determined to be unusual +# in some way (by an external inspection script). For this to work you +# will also need at least one file inspection rule. +# +#SecUploadKeepFiles RelevantOnly + +# Uploaded files are by default created with permissions that do not allow +# any other user to access them. You may need to relax that if you want to +# interface ModSecurity to an external program (e.g., an anti-virus). +# +#SecUploadFileMode 0600 + + +# -- Debug log configuration ------------------------------------------------- + +# The default debug log configuration is to duplicate the error, warning +# and notice messages from the error log. +# +#SecDebugLog /opt/modsecurity/var/log/debug.log +#SecDebugLogLevel 3 + + +# -- Audit log configuration ------------------------------------------------- + +# Log the transactions that are marked by a rule, as well as those that +# trigger a server error (determined by a 5xx or 4xx, excluding 404, +# level response status codes). +# +SecAuditEngine RelevantOnly +SecAuditLogRelevantStatus "^(?:5|4(?!04))" + +# Log everything we know about a transaction. +SecAuditLogParts ABIJDEFHZ + +# Use a single file for logging. This is much easier to look at, but +# assumes that you will use the audit log only ocassionally. +# +SecAuditLogType Serial +SecAuditLog /var/log/modsec_audit.log + +# Specify the path for concurrent audit logging. +#SecAuditLogStorageDir /opt/modsecurity/var/audit/ + + +# -- Miscellaneous ----------------------------------------------------------- + +# Use the most commonly used application/x-www-form-urlencoded parameter +# separator. There's probably only one application somewhere that uses +# something else so don't expect to change this value. +# +SecArgumentSeparator & + +# Settle on version 0 (zero) cookies, as that is what most applications +# use. Using an incorrect cookie version may open your installation to +# evasion attacks (against the rules that examine named cookies). +# +SecCookieFormat 0 + +# Specify your Unicode Code Point. +# This mapping is used by the t:urlDecodeUni transformation function +# to properly map encoded data to your language. Properly setting +# these directives helps to reduce false positives and negatives. +# +SecUnicodeMapFile unicode.mapping 20127 + +# Improve the quality of ModSecurity by sharing information about your +# current ModSecurity version and dependencies versions. +# The following information will be shared: ModSecurity version, +# Web Server version, APR version, PCRE version, Lua version, Libxml2 +# version, Anonymous unique id for host. +SecStatusEngine On + +SecDebugLog /dev/stdout +SecDebugLogLevel 9 + +SecRule REQUEST_HEADERS:User-Agent "^(.*)$" "id:'900018',phase:1,t:none,t:sha1,t:hexEncode,setvar:tx.ua_hash=%{matched_var},nolog,pass" +SecRule &TX:REAL_IP "@eq 0" "id:'900021',phase:1,t:none,initcol:global=global,initcol:ip=%{remote_addr}_%{tx.ua_hash},setvar:tx.real_ip=%{remote_addr},nolog,pass" +SecRule REQUEST_HEADERS:User-Agent "^(.*)$" "id:'900019',phase:2,t:none,setvar:ip.auth_attempt=+1,nolog,pass" + + diff --git a/examples/multithread_c/multi.c b/examples/multithread_c/multi.c new file mode 100644 index 00000000..5007fd81 --- /dev/null +++ b/examples/multithread_c/multi.c @@ -0,0 +1,141 @@ +/* + * ModSecurity, http://www.modsecurity.org/ + * Copyright (c) 2015 Trustwave Holdings, Inc. (http://www.trustwave.com/) + * + * You may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * If any of the files related to licensing are missing or if you have any + * other questions related to licensing please contact Trustwave Holdings, Inc. + * directly using the email address security@modsecurity.org. + * + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#define SHM_SIZE 1024 +#define FORKS 10 +#define TRHREADS 10 + + +char main_rule_uri[] = "basic_rules.conf"; +Rules *rules = NULL; +ModSecurity *modsec = NULL; + +key_t key; + + +void process_request (void *ptr) +{ + int i; + for (i = 0; i < TRHREADS; i++) { + struct timeval tv; + + int shmid = shmget(key, SHM_SIZE, 0644 | IPC_CREAT); + char *data; + int *j; + data = shmat(shmid, (void *)0, 0); + j = (int *)data; + (*j)++; + + + Transaction *transaction = NULL; + transaction = msc_new_transaction(modsec, rules, NULL); + + msc_process_connection(transaction, "127.0.0.1", 12345, "127.0.0.1", 80); + msc_process_uri(transaction, + "http://www.modsecurity.org/test?key1=value1&key2=value2&key3=value3", + "GET", "1.1"); + msc_add_request_header(transaction, "User-Agent", + "Basic ModSecurity example"); + msc_process_request_headers(transaction); + msc_process_request_body(transaction); + msc_add_response_header(transaction, "Content-type", "text/html"); + msc_process_response_headers(transaction); + msc_process_response_body(transaction); + msc_process_logging(transaction, 200); + msc_transaction_cleanup(transaction); + tv.tv_sec = 0; + tv.tv_usec = 1000; + select(0, NULL, NULL, NULL, &tv); + } +} + + +int main (int argc, char **argv) +{ + int ret = 1; + const char *error = NULL; + pthread_t thread[TRHREADS*FORKS]; + int i = 0; + pid_t pid; + int shmid; + + modsec = msc_init(); + + key = ftok("shmdemo.c", 'R'); + + shmid = shmget(key, SHM_SIZE, 0644 | IPC_CREAT); + char *data = shmat(shmid, (void *)0, 0); + memset(data, '\0', SHM_SIZE); + int *z = (int *) data; + z = 0; + + msc_set_connector_info(modsec, "ModSecurity-test v0.0.1-alpha (Simple " \ + "example on how to use ModSecurity API"); + + rules = msc_create_rules_set(); + + ret = msc_rules_add_file(rules, main_rule_uri, &error); + if (ret < 0) { + fprintf(stderr, "Problems loading the rules --\n"); + fprintf(stderr, "%s\n", error); + goto end; + } + + msc_rules_dump(rules); + + for (int h = 0; h < FORKS; h++) { + pid = fork(); + if (pid == 0) { + pthread_create (&thread[h*TRHREADS], NULL, (void *) &process_request, (void *) NULL); + pthread_join(thread[h*TRHREADS], NULL); + goto child; + } + } + + wait(NULL); + + int *j; + data = shmat(shmid, (void *)0, 0); + j = (int *) data; + fprintf(stderr, "The final count is: %d\n", *j); + +child: + + if (pid == 0) { + return 0; + } +end: + msc_rules_cleanup(rules); + msc_cleanup(modsec); + + return 0; +} + +