├── .gitignore ├── Project_Report.pdf ├── Readme.txt ├── System Security Project Presentation.pptx └── waf ├── Makefile ├── WAF_Page_File ├── WAF_Param_File ├── admin_config ├── anomaly_detection_phase.c ├── build.sh ├── mod_waf.c ├── mod_waf.h ├── mod_waf.la ├── mod_waf.lo ├── modules.mk ├── signatures ├── waf_detection_mode.c ├── waf_file_operations.h ├── waf_generate_profile.c ├── waf_parse_signature.c └── waf_train_mode.c /.gitignore: -------------------------------------------------------------------------------- 1 | # Object files 2 | *.o 3 | *.ko 4 | *.obj 5 | *.elf 6 | 7 | # Precompiled Headers 8 | *.gch 9 | *.pch 10 | 11 | # Libraries 12 | *.lib 13 | *.a 14 | *.la 15 | *.lo 16 | 17 | # Shared objects (inc. Windows DLLs) 18 | *.dll 19 | *.so 20 | *.so.* 21 | *.dylib 22 | 23 | # Executables 24 | *.exe 25 | *.out 26 | *.app 27 | *.i*86 28 | *.x86_64 29 | *.hex 30 | 31 | # Debug files 32 | *.dSYM/ 33 | *.su 34 | -------------------------------------------------------------------------------- /Project_Report.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sudeshnapal12/Web-Application-Firewall/9b7317592341cce6e0898a6186f023ed75cf7ad3/Project_Report.pdf -------------------------------------------------------------------------------- /Readme.txt: -------------------------------------------------------------------------------- 1 | 2 | Web Application Firewall 3 | Introduction 4 | --------------------------------------------------------------- 5 | 6 | A Web Application Firewall (WAF) is an HTTP application firewall, 7 | which sits in front of the application server and monitors all the 8 | incoming traffic. The WAF has been implemented as an Apache Module. 9 | 10 | 11 | Execution steps 12 | --------------------------------------------------------------- 13 | 14 | -Load the module in the Apache server using the command 15 | $ make all reload 16 | 17 | -Change directory path to point to the module's folder in the script build.sh 18 | 19 | -Set the module's handler in etc/apache2/apache2.conf 20 | -"waf" is the name of the module. 21 | 22 | SetHandler waf 23 | 24 | 25 | -Run the following command to build the module. 26 | $./build.sh 27 | 28 | -To test the module on the local machine, open browser and type: 29 | localhost/ 30 | 31 | Design 32 | --------------------------------------------------------------- 33 | The WAF is implemented as an Apache module for Apache HTTP server. 34 | The WAF filters out malicious requests in two phases, signature 35 | checks for known attacks and anomaly detection for unknown attacks. 36 | 37 | Signature: 38 | The known attack formats are defined in the signatures file. The WAF 39 | checks the request for malicious attacks based on the signatures and 40 | guards against them. New signatures can be added in the file. 41 | 42 | Anomaly Detection: 43 | For never seen before attacks, we first collect information about 44 | legitimate traffic and then later based on the collected information, 45 | requests which look vastly different from the legitimate requests 46 | are discarded. 47 | 48 | Implementation 49 | --------------------------------------------------------------- 50 | The signatures are defined in a file in an encoded format which are 51 | used by the WAF to check for attacks. 52 | For anomaly detection, the collected information about legitimate traffic 53 | stored in file system. The data stored in files is encrypted so as to 54 | avoid misuse of the data from the adversaries. 55 | 56 | Contributors 57 | --------------------------------------------------------------- 58 | Amogh Avadhani 59 | Ankit Agrahari 60 | Prachi Poddar 61 | Sudeshna Pal 62 | 63 | Passcode : CSE509PROJECT 64 | 65 | -------------------Copyright 2016, All rights reserved---------------------------- 66 | -------------------------------------------------------------------------------- /System Security Project Presentation.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sudeshnapal12/Web-Application-Firewall/9b7317592341cce6e0898a6186f023ed75cf7ad3/System Security Project Presentation.pptx -------------------------------------------------------------------------------- /waf/Makefile: -------------------------------------------------------------------------------- 1 | ## 2 | ## Makefile -- Build procedure for sample waf Apache module 3 | ## Autogenerated via ``apxs -n waf -g''. 4 | ## 5 | 6 | builddir=. 7 | top_srcdir=/usr/share/apache2 8 | top_builddir=/usr/share/apache2 9 | include /usr/share/apache2/build/special.mk 10 | 11 | # the used tools 12 | APACHECTL=apachectl 13 | 14 | # additional defines, includes and libraries 15 | #DEFS=-Dmy_define=my_value 16 | #INCLUDES=-Imy/include/dir 17 | #LIBS=-Lmy/lib/dir -lmylib 18 | 19 | # the default target 20 | all: local-shared-build 21 | 22 | # install the shared object file into Apache 23 | install: install-modules-yes 24 | 25 | # cleanup 26 | clean: 27 | -rm -f mod_waf.o mod_waf.lo mod_waf.slo mod_waf.la 28 | 29 | # simple test 30 | test: reload 31 | lynx -mime_header http://localhost/waf 32 | 33 | # install and activate shared object by reloading Apache to 34 | # force a reload of the shared object file 35 | reload: install restart 36 | 37 | # the general Apache start/restart/stop 38 | # procedures 39 | start: 40 | $(APACHECTL) start 41 | restart: 42 | $(APACHECTL) restart 43 | stop: 44 | $(APACHECTL) stop 45 | 46 | -------------------------------------------------------------------------------- /waf/WAF_Page_File: -------------------------------------------------------------------------------- 1 | 6&/joomla_final/index.php/rental-options8(/joomla_final/index.php/malicious-header:*/joomla_final/index.php/malicious-header-2'/joomla_final/index.php./joomla_final/index.php/survey5%/joomla_final/administrator/index.php,/joomla_final/index.php/news -------------------------------------------------------------------------------- /waf/WAF_Param_File: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sudeshnapal12/Web-Application-Firewall/9b7317592341cce6e0898a6186f023ed75cf7ad3/waf/WAF_Param_File -------------------------------------------------------------------------------- /waf/admin_config: -------------------------------------------------------------------------------- 1 | MODE_CURRENT=MODE_DETECT 2 | username=enigma 3 | password=enigma 4 | -------------------------------------------------------------------------------- /waf/anomaly_detection_phase.c: -------------------------------------------------------------------------------- 1 | #include "httpd.h" 2 | #include "http_config.h" 3 | #include "http_protocol.h" 4 | #include "ap_config.h" 5 | #include "http_core.h" 6 | #include "http_request.h" 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | #include "waf_file_operations.h" 13 | #include "waf_train_mode.c" 14 | #include "waf_generate_profile.c" 15 | #include "waf_detection_mode.c" 16 | 17 | typedef struct { 18 | const char *key; 19 | const char *value; 20 | } kvPair; 21 | 22 | kvPair *formData = NULL; 23 | int params_size_post = 0; 24 | int ap_args_to_table(request_rec *, apr_table_t **); 25 | int getCharSetDetect(int, request_rec *, char *, char *); 26 | 27 | typedef struct{ 28 | const char * param_name; 29 | const char * param_value; 30 | int length; 31 | }Params; 32 | 33 | int get_params_request(request_rec *r, apr_off_t * params_size); 34 | 35 | void getCharSet(int params_size, request_rec *r, char *name, char *value); 36 | 37 | Params * get_params_request_detect(request_rec *r, apr_off_t * params_size); 38 | Params * get_params_request_detect_post(request_rec *r, apr_off_t * postSize); 39 | 40 | void trainModule(request_rec *r) 41 | { 42 | apr_off_t params_size = 0; 43 | 44 | int params_request_size = get_params_request(r, ¶ms_size); 45 | //ap_rprintf(r, "parameter size is %d", params_request_size); 46 | 47 | if(strcmp(r->method, "POST") == 0) 48 | { 49 | update_page_file(r,params_request_size, r->uri); 50 | } else if (strcmp(r->method, "GET") == 0) 51 | { 52 | update_page_file(r,params_request_size, r->uri); 53 | } 54 | 55 | } 56 | 57 | int get_params_request(request_rec *r, apr_off_t * params_size){ 58 | Params * params; 59 | apr_table_t *table_req; 60 | ap_args_to_table(r, &table_req); 61 | int param_size =0; 62 | 63 | const apr_array_header_t *array_req_params = apr_table_elts(table_req); 64 | const apr_table_entry_t * elements_req_params = (apr_table_entry_t*)array_req_params->elts; 65 | 66 | *params_size = array_req_params->nelts; 67 | 68 | params = apr_pcalloc(r->pool, sizeof(Params) * (*params_size + 1)); 69 | int i = 0; 70 | if(strcmp(r->method, "GET")==0){ 71 | for (i = 0; i < *params_size; i++) { 72 | 73 | 74 | params[i].param_name = elements_req_params[i].key; 75 | params[i].param_value = elements_req_params[i].val; 76 | params[i].length = strlen(params[i].param_value); 77 | 78 | if(params[i].length > 0){ 79 | param_size++; 80 | // ap_rprintf(r,"This is %s : %s : %d \n", params[i].param_name, params[i].param_value, params[i].length); 81 | getCharSet(params[i].length, r, (char *) params[i].param_name, (char *) params[i].param_value); 82 | } 83 | } 84 | } else if(strcmp(r->method, "POST")==0){ 85 | for (i = 0; i < params_size_post; i++) { 86 | 87 | 88 | //params[i].param_name = elements_req_params[i].key; 89 | //params[i].param_value = elements_req_params[i].val; 90 | //params[i].length = strlen(params[i].param_value); 91 | 92 | if(strlen(formData[i].value) > 0){ 93 | param_size++; 94 | // ap_rprintf(r,"This is %s : %s\n", formData[i].key, formData[i].value); 95 | getCharSet(strlen(formData[i].value), r, (char *) formData[i].key, (char *) formData[i].value); 96 | } 97 | 98 | } 99 | // ap_rprintf(r,"This is %s : %s : %d \n", params[i].param_name, params[i].param_value, params[i].length); 100 | } 101 | return param_size; 102 | } 103 | 104 | void getCharSet(int param_length, request_rec *r, char *name, char *value) 105 | { 106 | 107 | char* char_set = NULL; 108 | int bitmap[256] = {0,0,0,0}; 109 | int count = 0, i, j = 0; 110 | while(*(value+j)!='\0') 111 | { 112 | if(bitmap[*(value+j)] == 0){ 113 | if(islower(*(value+j))){ 114 | for(i = 97; i<123;i++){ 115 | bitmap[i] = 1; 116 | count++; 117 | } 118 | }else if(isupper(*(value+j))){ 119 | for(i = 65; i<91;i++){ 120 | bitmap[i] = 1; 121 | count++; 122 | } 123 | }else if(isdigit(*(value+j))){ 124 | for(i = 48; i<58;i++){ 125 | bitmap[i] = 1; 126 | count++; 127 | } 128 | }else{ 129 | bitmap[*(value+j)] = 1; 130 | count++; 131 | } 132 | } 133 | j++; 134 | } 135 | 136 | count++; 137 | char_set = (char*) malloc(sizeof(char)*count); 138 | if(char_set == NULL){ 139 | //printf("Not enough memory available"); 140 | return; 141 | } 142 | count = 0; 143 | for(i=0;i<256;i++){ 144 | if(bitmap[i] == 1){ 145 | char_set[count] = i; 146 | count++; 147 | } 148 | } 149 | char_set[count] = '\0'; 150 | 151 | // ap_rprintf(r, "Param length is %d, name: %s, uri: %s, char set: %s\n", param_length, name, r->uri, char_set); 152 | 153 | update_param_file(r,param_length, name, r->uri, char_set); 154 | 155 | i++; 156 | } 157 | 158 | void generateNormalityProfile(request_rec *r) 159 | { 160 | // ap_rprintf(r, "calling generate profile\n"); 161 | generate_param_file(r); 162 | return; 163 | } 164 | 165 | int operation_for_post(request_rec *r){ 166 | 167 | int page_return; 168 | int param_return; 169 | int i = 0; 170 | int size =0; 171 | // ap_rprintf(r, "param size sending %d\n", params_size_post); 172 | // return MAX_PARAM_PASS; 173 | 174 | for (i = 0; i < params_size_post; i++) { 175 | 176 | if(strlen(formData[i].value) > 0){ 177 | size++; 178 | } 179 | } 180 | i=0; 181 | // ap_rprintf(r, "opearation for postsize is %d", size); 182 | page_return = detect_page_file(r, size, r->uri); 183 | 184 | if(page_return == MAX_PARAM_PASS) 185 | { 186 | for (i = 0; i < params_size_post; i++) { 187 | // ap_rprintf(r, " param length is and name is%d ,%s", params[i].length, params[i].param_name); 188 | if(strlen(formData[i].value) ==0){ 189 | // ap_rprintf(r, "continue=> name is %s", params[i].param_name); 190 | continue; 191 | } 192 | // ap_rprintf(r, "forData val %d, %s, %s", strlen(formData[i].value), (char *) formData[i].key, (char *) formData[i].value) ; 193 | param_return = getCharSetDetect(strlen(formData[i].value), r, (char *) formData[i].key, (char *) formData[i].value); 194 | 195 | if(param_return == PARAM_LEN_ILLEGAL) 196 | { 197 | break; 198 | } else if(param_return == CONTAINS_NO_SEEN_CHAR) 199 | { 200 | break; 201 | } else if(param_return == UNKNOWN_PARAM) 202 | { 203 | break; 204 | } 205 | 206 | 207 | } 208 | return param_return; 209 | 210 | } 211 | 212 | else 213 | { 214 | return page_return; 215 | } 216 | return PASS_DETECTION; 217 | 218 | } 219 | 220 | int detectAnomolies(request_rec *r) 221 | { 222 | apr_off_t params_size = 0; 223 | Params * params; 224 | // kvPair *kvp; 225 | if(strcmp(r->method, "GET") == 0) 226 | { 227 | // ap_rprintf(r, "in get\n"); 228 | params = get_params_request_detect(r, ¶ms_size); 229 | } else if (strcmp(r->method, "POST") == 0) 230 | { 231 | // ap_rprintf(r, "in post\n"); 232 | // params = get_params_request_detect_post(r, ¶ms_size); 233 | // params = readPostParamsNew(r); 234 | return operation_for_post(r); 235 | } 236 | 237 | int page_return; 238 | int param_return; 239 | int i = 0; 240 | int size =0; 241 | // ap_rprintf(r, "param size sending %d\n", params_size); 242 | 243 | for (i = 0; i < params_size; i++) { 244 | 245 | if(params[i].length > 0){ 246 | size++; 247 | } 248 | } 249 | i=0; 250 | // ap_rprintf(r, "size is %d", size); 251 | page_return = detect_page_file(r, size, r->uri); 252 | 253 | if(page_return == MAX_PARAM_PASS) 254 | { 255 | for (i = 0; i < params_size; i++) { 256 | // ap_rprintf(r, " param length is and name is%d ,%s", params[i].length, params[i].param_name); 257 | if(params[i].length ==0){ 258 | // ap_rprintf(r, "continue=> name is %s", params[i].param_name); 259 | continue; 260 | } 261 | 262 | param_return = getCharSetDetect(params[i].length, r, (char *) params[i].param_name, (char *) params[i].param_value); 263 | 264 | if(param_return == PARAM_LEN_ILLEGAL) 265 | { 266 | break; 267 | } else if(param_return == CONTAINS_NO_SEEN_CHAR) 268 | { 269 | break; 270 | } else if(param_return == UNKNOWN_PARAM) 271 | { 272 | break; 273 | } 274 | 275 | 276 | } 277 | return param_return; 278 | 279 | } 280 | 281 | else 282 | { 283 | return page_return; 284 | } 285 | return PASS_DETECTION; 286 | 287 | } 288 | 289 | int getCharSetDetect(int param_length, request_rec *r, char *name, char *value) 290 | { 291 | char* char_set = NULL; 292 | int bitmap[256] = {0,0,0,0}; 293 | int count = 0, i, j = 0; 294 | int param_return = 0; 295 | 296 | while(*(value+j)!='\0') 297 | { 298 | if(bitmap[*(value+j)] == 0){ 299 | if(islower(*(value+j))){ 300 | for(i = 97; i<123;i++){ 301 | bitmap[i] = 1; 302 | count++; 303 | } 304 | }else if(isupper(*(value+j))){ 305 | for(i = 65; i<91;i++){ 306 | bitmap[i] = 1; 307 | count++; 308 | } 309 | }else if(isdigit(*(value+j))){ 310 | for(i = 48; i<58;i++){ 311 | bitmap[i] = 1; 312 | count++; 313 | } 314 | }else{ 315 | bitmap[*(value+j)] = 1; 316 | count++; 317 | } 318 | } 319 | j++; 320 | } 321 | 322 | count++; 323 | char_set = (char*) malloc(sizeof(char)*count); 324 | if(char_set == NULL){ 325 | return param_return; 326 | } 327 | count = 0; 328 | for(i=0;i<256;i++){ 329 | if(bitmap[i] == 1){ 330 | char_set[count] = i; 331 | count++; 332 | } 333 | } 334 | char_set[count] = '\0'; 335 | 336 | param_return = detect_param_file(r, param_length, name, r->uri, char_set); 337 | //ap_rprintf(r,"charset value is %s\n", char_set); 338 | i++; 339 | return param_return; 340 | } 341 | 342 | Params * get_params_request_detect(request_rec *r, apr_off_t * params_size){ 343 | Params * params; 344 | apr_table_t *table_req; 345 | ap_args_to_table(r, &table_req); 346 | char* char_set; 347 | 348 | const apr_array_header_t *array_req_params = apr_table_elts(table_req); 349 | const apr_table_entry_t * elements_req_params = (apr_table_entry_t*)array_req_params->elts; 350 | 351 | *params_size = array_req_params->nelts; 352 | 353 | params = apr_pcalloc(r->pool, sizeof(Params) * (*params_size + 1)); 354 | int i = 0; 355 | for (i = 0; i < *params_size; i++) { 356 | params[i].param_name = elements_req_params[i].key; 357 | params[i].param_value = elements_req_params[i].val; 358 | params[i].length = strlen(params[i].param_value); 359 | } 360 | return params; 361 | } 362 | 363 | Params * get_params_request_detect_post(request_rec *r, apr_off_t * postSize) 364 | { 365 | ap_rprintf(r, "r->params %s",r->args); 366 | apr_array_header_t *pairs = NULL; 367 | apr_off_t len; 368 | apr_size_t size; 369 | int res; 370 | int i = 0; 371 | char *buffer; 372 | Params *kvp = NULL; 373 | 374 | apr_table_t *t; 375 | ap_args_to_table(r, &t); 376 | 377 | 378 | res = ap_parse_form_data(r, NULL, &pairs, -1, HUGE_STRING_LEN); 379 | if (res != OK || !pairs){ 380 | // ap_rprintf(r, "res is numm"); 381 | return NULL; 382 | } 383 | kvp = apr_pcalloc(r->pool, sizeof(Params) * (pairs->nelts + 1)); 384 | // ap_rprintf(r, "Anomaly pairs->nelts %d",pairs->nelts); 385 | 386 | while (pairs && !apr_is_empty_array(pairs)) { 387 | 388 | ap_form_pair_t *pair = (ap_form_pair_t *) apr_array_pop(pairs); 389 | apr_brigade_length(pair->value, 1, &len); 390 | size = (apr_size_t) len; 391 | buffer = apr_palloc(r->pool, size + 1); 392 | apr_brigade_flatten(pair->value, buffer, &size); 393 | buffer[len] = 0; 394 | kvp[i].param_name = (char *)pair->name; 395 | kvp[i].param_value = (char *)buffer; 396 | // ap_rprintf(r, " key is %s\n", (char *)kvp[i].param_name); 397 | // ap_rprintf(r, " val is %s\n", (char *)kvp[i].param_value); 398 | kvp[i].length = strlen(kvp[i].param_value); 399 | i++; 400 | } 401 | *postSize = i; 402 | 403 | return kvp; 404 | } 405 | -------------------------------------------------------------------------------- /waf/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | sudo apxs -a -i -c mod_waf.c 3 | sudo service apache2 restart 4 | sudo chown -R www-data.www-data /home/dexter/git_working/waf_apache_module/waf 5 | sudo chmod -R 774 /home/dexter/git_working/waf_apache_module/waf 6 | sudo chmod 777 /usr/lib/apache2/modules/mod_waf.so 7 | -------------------------------------------------------------------------------- /waf/mod_waf.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** mod_waf.c -- Apache sample waf module 3 | ** [Autogenerated via ``apxs -n waf -g''] 4 | ** 5 | ** To play with this sample module first compile it into a 6 | ** DSO file and install it into Apache's modules directory 7 | ** by running: 8 | ** 9 | ** $ apxs -c -i mod_waf.c 10 | ** 11 | ** Then activate it in Apache's apache2.conf file for instance 12 | ** for the URL /waf in as follows: 13 | ** 14 | ** # apache2.conf 15 | ** LoadModule waf_module modules/mod_waf.so 16 | ** 17 | ** SetHandler waf 18 | ** 19 | ** 20 | ** Then after restarting Apache via 21 | ** 22 | ** $ apachectl restart 23 | ** 24 | ** you immediately can request the URL /waf and watch for the 25 | ** output of this module. This can be achieved for instance via: 26 | ** 27 | ** $ lynx -mime_header http://localhost/waf 28 | ** 29 | ** The output should be similar to the following one: 30 | ** 31 | ** HTTP/1.1 200 OK 32 | ** Date: Tue, 31 Mar 1998 14:42:22 GMT 33 | ** Server: Apache/1.3.4 (Unix) 34 | ** Connection: close 35 | ** Content-Type: text/html 36 | ** 37 | ** The sample page from mod_waf.c 38 | */ 39 | 40 | #include "mod_waf.h" 41 | 42 | int examineHeaderParams(request_rec *, node *, int ); 43 | int isMalicious(request_rec *, const char *, const char *, node *, int ); 44 | const char *ADMIN_CONFIG_FILE="/home/dexter/git_working/waf_apache_module/waf/admin_config"; 45 | 46 | /* The sample content handler */ 47 | static int waf_handler(request_rec *r) 48 | { 49 | int detect_ret; 50 | MODE_CURRENT = readCurrMode(r); 51 | 52 | 53 | //Parse signature file to read all the defined signatures to detect anamolies 54 | parseConfigFile(r); 55 | // examine GET parameters to check characteristic of malliciousness 56 | if(gNum >0 && strcmp(r->method, "GET")==0){ 57 | if(examineGetParams(r, gList, gNum)==MALICIOUS){ 58 | ap_set_content_type(r, "text/html"); 59 | ap_rprintf(r,"

Request is blocked by WAF because the request contains a malicious string

%s

\n", illegalStr); 60 | return DONE; 61 | } 62 | } 63 | // examine POST parameters to check characteristic of malliciousness 64 | if(pNum > 0 && strcmp(r->method, "POST")==0){ 65 | if(examinePostParams(r, pList, pNum)==MALICIOUS){ 66 | ap_set_content_type(r, "text/html"); 67 | ap_rprintf(r,"

Request is blocked by WAF because the request contains a malicious string

%s

\n", illegalStr); 68 | return DONE; 69 | } 70 | } 71 | 72 | //examine HEADER parameters to check characteristic of malliciousness 73 | if(hNum > 0){ 74 | if(examineHeaderParams(r, hList, hNum)==MALICIOUS){ 75 | ap_set_content_type(r, "text/html"); 76 | ap_rprintf(r,"

Request is blocked by WAF because the request contains a malicious string

%s

\n", illegalStr); 77 | return DONE; 78 | } 79 | } 80 | 81 | if(MODE_CURRENT == MODE_TRAIN) 82 | { 83 | trainModule(r); 84 | } else if (MODE_CURRENT == MODE_NORMALITY_PROFILE) 85 | { 86 | generateNormalityProfile(r); 87 | ap_rprintf(r,"

Generate Profile Success

\n"); 88 | return DONE; 89 | 90 | } else if (MODE_CURRENT == MODE_DETECT) 91 | { 92 | detect_ret = detectAnomolies(r); 93 | if(detect_ret == PARAM_LEN_ILLEGAL) 94 | { 95 | ap_rprintf(r, "

Request is blocked by WAF because the request contains Illegal Parameter Length

\n"); 96 | return DONE; 97 | } else if (detect_ret == CONTAINS_NO_SEEN_CHAR) 98 | { 99 | ap_rprintf(r, "

Request is blocked by WAF because the request contains Illegal Character Set

\n"); 100 | return DONE; 101 | } else if (detect_ret == UNKNOWN_PARAM) 102 | { 103 | ap_rprintf(r, "

Request is blocked by WAF because the request contains Unknown Parameter

\n"); 104 | return DONE; 105 | } else if(detect_ret == PASS_DETECTION) 106 | { 107 | return DECLINED; 108 | } else if(detect_ret == EXCEED_ALL_MAX_PARAM) 109 | { 110 | ap_rprintf(r, "

Request is blocked by WAF because the request exceeds Global Maximum Parameters

\n"); 111 | return DONE; 112 | }else if(detect_ret == EXCEED_MAX_PARAM) 113 | { 114 | ap_rprintf(r, "

Request is blocked by WAF because the request exceeds Maximum Parameter

\n"); 115 | return DONE; 116 | } 117 | } 118 | return DECLINED; 119 | } 120 | 121 | int examineGetParams(request_rec *r, node *getSigs, int getSigsCount){ 122 | //Parse get request and store in table 123 | apr_table_t *GET; 124 | ap_args_to_table(r, &GET); 125 | 126 | //Get all GET-request parameters from GET table 127 | const apr_array_header_t *getParamsArr = apr_table_elts(GET); 128 | const apr_table_entry_t *getParams = (apr_table_entry_t*)getParamsArr->elts; 129 | 130 | //For each GET-request parameter check if the request parameter is mallicious i.e. defined in SignatureList 131 | //If the parameter is mallicious return MALICIOUS else return NON_MALICIOUS. 132 | int i = 0; 133 | for(i = 0; i < getParamsArr->nelts; i++) { 134 | // ap_rprintf(r, "examineGetParams :: %s = %s\n", getParams[i].key, getParams[i].val); 135 | if(0 == isMalicious(r, getParams[i].key, getParams[i].val, getSigs, getSigsCount)){ 136 | return MALICIOUS; 137 | } 138 | } 139 | return NON_MALICIOUS; 140 | } 141 | 142 | kvPair *readPostParams(request_rec *r) { 143 | // ap_rprintf(r, "Sig r->params %s",r->args); 144 | apr_array_header_t *pairs = NULL; 145 | apr_off_t len; 146 | apr_size_t size; 147 | int res; 148 | int i = 0; 149 | char *buffer; 150 | kvPair *kvp = NULL; 151 | 152 | apr_table_t *t; 153 | ap_args_to_table(r, &t); 154 | 155 | 156 | res = ap_parse_form_data(r, NULL, &pairs, -1, HUGE_STRING_LEN); 157 | if (res != OK || !pairs) return NULL; 158 | kvp = apr_pcalloc(r->pool, sizeof(kvPair) * (pairs->nelts + 1)); 159 | params_size_post = pairs->nelts; 160 | // ap_rprintf(r, "pairs->nelts %d",pairs->nelts); 161 | 162 | while (pairs && !apr_is_empty_array(pairs)) { 163 | ap_form_pair_t *pair = (ap_form_pair_t *) apr_array_pop(pairs); 164 | apr_brigade_length(pair->value, 1, &len); 165 | size = (apr_size_t) len; 166 | buffer = apr_palloc(r->pool, size + 1); 167 | apr_brigade_flatten(pair->value, buffer, &size); 168 | buffer[len] = 0; 169 | kvp[i].key = (char *)pair->name; 170 | kvp[i].value = (char *)buffer; 171 | // ap_rprintf(r, " key is %s\n", (char *)kvp[i].key); 172 | // ap_rprintf(r, " val is %s\n", (char *)kvp[i].value); 173 | i++; 174 | } 175 | return kvp; 176 | } 177 | 178 | int examinePostParams(request_rec *r, node * postSigs, int postSigsCount){ 179 | // kvPair *formData = NULL; 180 | 181 | //Get post parameters from request received 182 | formData = readPostParams(r); 183 | if (formData) { 184 | int i; 185 | for (i = 0; &formData[i]; i++) { 186 | if (formData[i].key && formData[i].value) { 187 | // ap_rprintf(r, "FORM-DATA %s = %s\n",(char *)formData[i].key, (char *)formData[i].value); 188 | if(0 == isMalicious(r, formData[i].key, formData[i].value, postSigs, postSigsCount)){ 189 | return MALICIOUS; 190 | } 191 | }else { 192 | break; 193 | } 194 | } 195 | } 196 | return NON_MALICIOUS; 197 | } 198 | 199 | int examineHeaderParams(request_rec *r, node *headerSigs, int headerSigsCount){ 200 | const apr_array_header_t *hdrParamsArr; 201 | apr_table_entry_t *headerParams = 0; 202 | 203 | //Get Header parameters from request_received 204 | hdrParamsArr = apr_table_elts(r->headers_in); 205 | headerParams = (apr_table_entry_t *) hdrParamsArr->elts; 206 | int i = 0; 207 | for(i = 0; i < hdrParamsArr->nelts; i++) { 208 | if(0 == isMalicious(r, headerParams[i].key, headerParams[i].val, headerSigs, headerSigsCount)){ 209 | return MALICIOUS; 210 | } 211 | } 212 | return NON_MALICIOUS; 213 | } 214 | 215 | //return 1 is non-malicious and return 0 if malicious 216 | int isMalicious(request_rec *r, const char* key, const char* value, node * sigs, int sigsCount){ 217 | int i = 0; 218 | for(i = 0; i < sigsCount; i++){ 219 | // For GET requests, signatures file has key=* 220 | if(strcmp(sigs[i].key,"*")==0 || strcmp(sigs[i].key, key)==0){ 221 | 222 | //Check if any substring of GET-parameter is a malicious content 223 | if(strstr(value, sigs[i].val)!=NULL){ 224 | if(illegalStr == NULL){ 225 | illegalStr = (char *) calloc(0, BUFF_SIZE); 226 | } 227 | strcpy(illegalStr, sigs[i].val); 228 | return 0; 229 | } 230 | } 231 | } 232 | return 1; 233 | } 234 | 235 | void toLowerCase(char * str){ 236 | int len = strlen(str); 237 | int i = 0; 238 | for(i=0; i 9 | #include 10 | #include 11 | 12 | #include "anomaly_detection_phase.c" 13 | #include "waf_parse_signature.c" 14 | /*#include "waf_file_operations.h" 15 | #include "waf_train_mode.c" 16 | #include "waf_generate_profile.c" 17 | #include "waf_detection_mode.c"*/ 18 | 19 | /*typedef struct { 20 | const char *key; 21 | const char *value; 22 | } kvPair; 23 | 24 | static kvPair *formData= NULL; 25 | int param_size_post = 0;*/ 26 | 27 | static int MODE_CURRENT = 999; 28 | 29 | static int MODE_TRAIN = 998; 30 | 31 | static int MODE_NORMALITY_PROFILE = 997; 32 | 33 | static int MODE_DETECT = 999; 34 | 35 | static int FLAG_GENERATE = 0; 36 | 37 | static int NON_MALICIOUS = 11; 38 | 39 | static int MALICIOUS = 12; 40 | 41 | static char* modeSetUri ="/joomla/"; 42 | 43 | //static const char *ADMIN_CONFIG_FILE="/home/ankit/waf_git/waf_apache_module/waf/admin_config"; 44 | //static const char *SIGNITURE_CONFIG="/home/ankit/waf_git/waf_apache_module/waf/signatures"; 45 | 46 | static char * illegalStr; 47 | 48 | int readCurrMode(); 49 | 50 | void read_admin_config_file(request_rec *r, char *usr, char *pwd); 51 | 52 | int examineGetParams(request_rec *r, node * getSigs, int getSigLen); 53 | 54 | int examinePostParams(request_rec *r, node * postSigs, int postSigsCount); 55 | 56 | int isLegal(request_rec *r, const char* key, const char* value, node * list, int listSize); 57 | 58 | void toLowerCase(char * str); -------------------------------------------------------------------------------- /waf/mod_waf.la: -------------------------------------------------------------------------------- 1 | # mod_waf.la - a libtool library file 2 | # Generated by libtool (GNU libtool) 2.4.2 Debian-2.4.2-1.3ubuntu2 3 | # 4 | # Please DO NOT delete this file! 5 | # It is necessary for linking the library. 6 | 7 | # The name that we can dlopen(3). 8 | dlname='mod_waf.so' 9 | 10 | # Names of this library. 11 | library_names='mod_waf.so mod_waf.so mod_waf.so' 12 | 13 | # The name of the static archive. 14 | old_library='' 15 | 16 | # Linker flags that can not go in dependency_libs. 17 | inherited_linker_flags='' 18 | 19 | # Libraries that this one depends upon. 20 | dependency_libs='' 21 | 22 | # Names of additional weak libraries provided by this library 23 | weak_library_names='' 24 | 25 | # Version information for mod_waf. 26 | current=0 27 | age=0 28 | revision=0 29 | 30 | # Is this an already installed library? 31 | installed=no 32 | 33 | # Should we warn about portability when linking against -modules? 34 | shouldnotlink=yes 35 | 36 | # Files to dlopen/dlpreopen 37 | dlopen='' 38 | dlpreopen='' 39 | 40 | # Directory that this library needs to be installed in: 41 | libdir='/usr/lib/apache2/modules' 42 | -------------------------------------------------------------------------------- /waf/mod_waf.lo: -------------------------------------------------------------------------------- 1 | # mod_waf.lo - a libtool object file 2 | # Generated by libtool (GNU libtool) 2.4.2 Debian-2.4.2-1.3ubuntu2 3 | # 4 | # Please DO NOT delete this file! 5 | # It is necessary for linking the library. 6 | 7 | # Name of the PIC object. 8 | pic_object='.libs/mod_waf.o' 9 | 10 | # Name of the non-PIC object 11 | non_pic_object=none 12 | 13 | -------------------------------------------------------------------------------- /waf/modules.mk: -------------------------------------------------------------------------------- 1 | mod_waf.la: mod_waf.slo 2 | $(SH_LINK) -rpath $(libexecdir) -module -avoid-version mod_waf.lo 3 | DISTCLEAN_TARGETS = modules.mk 4 | shared = mod_waf.la 5 | -------------------------------------------------------------------------------- /waf/signatures: -------------------------------------------------------------------------------- 1 | REQUEST_METHOD:GET,PARAMETER:*,CONTAINS:"'" /*Detect SQL Injection*/ 2 | REQUEST_METHOD:GET,PARAMETER:*,CONTAINS:"select" /*Detect SQL Injection*/ 3 | REQUEST_METHOD:GET,PARAMETER:*,CONTAINS:"union all" /*Detect SQL Injection*/ 4 | REQUEST_METHOD:GET,PARAMETER:*,CONTAINS:"<" /*Detect XSS Attack*/ 5 | REQUEST_METHOD:GET,PARAMETER:*,CONTAINS:">" /*Detect XSS Attack*/ 6 | REQUEST_METHOD:GET,PARAMETER:*,CONTAINS:"javascript" /*Detect XSS Attack*/ 7 | REQUEST_METHOD:POST,PARAMETER:*,CONTAINS:"../" /*Search the parameter "foo" of POST Requests for possible 8 | Directory Traversal vulnerabilities*/ 9 | HEADER:User-Agent,CONTAINS:"