diff options
Diffstat (limited to 'ufilter.c')
| -rw-r--r-- | ufilter.c | 252 |
1 files changed, 126 insertions, 126 deletions
| @@ -17,7 +17,7 @@ | |||
| 17 | +----------------------------------------------------------------------+ | 17 | +----------------------------------------------------------------------+ |
| 18 | */ | 18 | */ |
| 19 | /* | 19 | /* |
| 20 | $Id: ufilter.c,v 1.1.1.1 2007-11-28 01:15:35 sesser Exp $ | 20 | $Id: ufilter.c,v 1.1.1.1 2007-11-28 01:15:35 sesser Exp $ |
| 21 | */ | 21 | */ |
| 22 | 22 | ||
| 23 | #ifdef HAVE_CONFIG_H | 23 | #ifdef HAVE_CONFIG_H |
| @@ -48,12 +48,12 @@ static int check_fileupload_varname(char *varname TSRMLS_DC) | |||
| 48 | 48 | ||
| 49 | /* Normalize the variable name */ | 49 | /* Normalize the variable name */ |
| 50 | normalize_varname(var); | 50 | normalize_varname(var); |
| 51 | 51 | ||
| 52 | /* Find length of variable name */ | 52 | /* Find length of variable name */ |
| 53 | index = strchr(var, '['); | 53 | index = strchr(var, '['); |
| 54 | total_len = strlen(var); | 54 | total_len = strlen(var); |
| 55 | var_len = index ? index-var : total_len; | 55 | var_len = index ? index-var : total_len; |
| 56 | 56 | ||
| 57 | /* Drop this variable if it exceeds the varname/total length limit */ | 57 | /* Drop this variable if it exceeds the varname/total length limit */ |
| 58 | if (SUHOSIN_G(max_varname_length) && SUHOSIN_G(max_varname_length) < var_len) { | 58 | if (SUHOSIN_G(max_varname_length) && SUHOSIN_G(max_varname_length) < var_len) { |
| 59 | suhosin_log(S_FILES, "configured request variable name length limit exceeded - dropped variable '%s'", var); | 59 | suhosin_log(S_FILES, "configured request variable name length limit exceeded - dropped variable '%s'", var); |
| @@ -79,38 +79,38 @@ static int check_fileupload_varname(char *varname TSRMLS_DC) | |||
| 79 | goto return_failure; | 79 | goto return_failure; |
| 80 | } | 80 | } |
| 81 | } | 81 | } |
| 82 | 82 | ||
| 83 | /* Find out array depth */ | 83 | /* Find out array depth */ |
| 84 | while (index) { | 84 | while (index) { |
| 85 | char *index_end; | 85 | char *index_end; |
| 86 | unsigned int index_length; | 86 | unsigned int index_length; |
| 87 | 87 | ||
| 88 | /* overjump '[' */ | 88 | /* overjump '[' */ |
| 89 | index++; | 89 | index++; |
| 90 | 90 | ||
| 91 | /* increase array depth */ | 91 | /* increase array depth */ |
| 92 | depth++; | 92 | depth++; |
| 93 | 93 | ||
| 94 | index_end = strchr(index, ']'); | 94 | index_end = strchr(index, ']'); |
| 95 | if (index_end == NULL) { | 95 | if (index_end == NULL) { |
| 96 | index_end = index+strlen(index); | 96 | index_end = index+strlen(index); |
| 97 | } | 97 | } |
| 98 | 98 | ||
| 99 | index_length = index_end - index; | 99 | index_length = index_end - index; |
| 100 | 100 | ||
| 101 | if (SUHOSIN_G(max_array_index_length) && SUHOSIN_G(max_array_index_length) < index_length) { | 101 | if (SUHOSIN_G(max_array_index_length) && SUHOSIN_G(max_array_index_length) < index_length) { |
| 102 | suhosin_log(S_FILES, "configured request variable array index length limit exceeded - dropped variable '%s'", var); | 102 | suhosin_log(S_FILES, "configured request variable array index length limit exceeded - dropped variable '%s'", var); |
| 103 | if (!SUHOSIN_G(simulation)) { | 103 | if (!SUHOSIN_G(simulation)) { |
| 104 | goto return_failure; | 104 | goto return_failure; |
| 105 | } | 105 | } |
| 106 | } | 106 | } |
| 107 | if (SUHOSIN_G(max_post_array_index_length) && SUHOSIN_G(max_post_array_index_length) < index_length) { | 107 | if (SUHOSIN_G(max_post_array_index_length) && SUHOSIN_G(max_post_array_index_length) < index_length) { |
| 108 | suhosin_log(S_FILES, "configured POST variable array index length limit exceeded - dropped variable '%s'", var); | 108 | suhosin_log(S_FILES, "configured POST variable array index length limit exceeded - dropped variable '%s'", var); |
| 109 | if (!SUHOSIN_G(simulation)) { | 109 | if (!SUHOSIN_G(simulation)) { |
| 110 | goto return_failure; | 110 | goto return_failure; |
| 111 | } | 111 | } |
| 112 | } | 112 | } |
| 113 | 113 | ||
| 114 | /* index whitelist/blacklist */ | 114 | /* index whitelist/blacklist */ |
| 115 | if (SUHOSIN_G(array_index_whitelist) && *(SUHOSIN_G(array_index_whitelist))) { | 115 | if (SUHOSIN_G(array_index_whitelist) && *(SUHOSIN_G(array_index_whitelist))) { |
| 116 | if (suhosin_strnspn(index, index_length, SUHOSIN_G(array_index_whitelist)) != index_length) { | 116 | if (suhosin_strnspn(index, index_length, SUHOSIN_G(array_index_whitelist)) != index_length) { |
| @@ -127,11 +127,11 @@ static int check_fileupload_varname(char *varname TSRMLS_DC) | |||
| 127 | } | 127 | } |
| 128 | } | 128 | } |
| 129 | } | 129 | } |
| 130 | 130 | ||
| 131 | 131 | ||
| 132 | index = strchr(index, '['); | 132 | index = strchr(index, '['); |
| 133 | } | 133 | } |
| 134 | 134 | ||
| 135 | /* Drop this variable if it exceeds the array depth limit */ | 135 | /* Drop this variable if it exceeds the array depth limit */ |
| 136 | if (SUHOSIN_G(max_array_depth) && SUHOSIN_G(max_array_depth) < depth) { | 136 | if (SUHOSIN_G(max_array_depth) && SUHOSIN_G(max_array_depth) < depth) { |
| 137 | suhosin_log(S_FILES, "configured request variable array depth limit exceeded - dropped variable '%s'", var); | 137 | suhosin_log(S_FILES, "configured request variable array depth limit exceeded - dropped variable '%s'", var); |
| @@ -145,8 +145,8 @@ static int check_fileupload_varname(char *varname TSRMLS_DC) | |||
| 145 | goto return_failure; | 145 | goto return_failure; |
| 146 | } | 146 | } |
| 147 | } | 147 | } |
| 148 | 148 | ||
| 149 | 149 | ||
| 150 | /* Drop this variable if it is one of GLOBALS, _GET, _POST, ... */ | 150 | /* Drop this variable if it is one of GLOBALS, _GET, _POST, ... */ |
| 151 | /* This is to protect several silly scripts that do globalizing themself */ | 151 | /* This is to protect several silly scripts that do globalizing themself */ |
| 152 | if (php_varname_check(var, var_len, 1 TSRMLS_CC) == FAILURE || suhosin_is_protected_varname(var, var_len)) { | 152 | if (php_varname_check(var, var_len, 1 TSRMLS_CC) == FAILURE || suhosin_is_protected_varname(var, var_len)) { |
| @@ -158,10 +158,10 @@ static int check_fileupload_varname(char *varname TSRMLS_DC) | |||
| 158 | 158 | ||
| 159 | efree(var); | 159 | efree(var); |
| 160 | return SUCCESS; | 160 | return SUCCESS; |
| 161 | 161 | ||
| 162 | return_failure: | 162 | return_failure: |
| 163 | efree(var); | 163 | efree(var); |
| 164 | return FAILURE; | 164 | return FAILURE; |
| 165 | } | 165 | } |
| 166 | /* }}} */ | 166 | /* }}} */ |
| 167 | 167 | ||
| @@ -200,54 +200,54 @@ int suhosin_rfc1867_filter(unsigned int event, void *event_data, void **extra TS | |||
| 200 | SDEBUG("rfc1867_filter %u", event); | 200 | SDEBUG("rfc1867_filter %u", event); |
| 201 | 201 | ||
| 202 | switch (event) { | 202 | switch (event) { |
| 203 | case MULTIPART_EVENT_START: | 203 | case MULTIPART_EVENT_START: |
| 204 | case MULTIPART_EVENT_FORMDATA: | 204 | case MULTIPART_EVENT_FORMDATA: |
| 205 | /* nothing todo */ | 205 | /* nothing todo */ |
| 206 | break; | 206 | break; |
| 207 | 207 | ||
| 208 | case MULTIPART_EVENT_FILE_START: | 208 | case MULTIPART_EVENT_FILE_START: |
| 209 | { | 209 | { |
| 210 | multipart_event_file_start *mefs = (multipart_event_file_start *) event_data; | 210 | multipart_event_file_start *mefs = (multipart_event_file_start *) event_data; |
| 211 | 211 | ||
| 212 | /* Drop if no more variables flag is set */ | 212 | /* Drop if no more variables flag is set */ |
| 213 | if (SUHOSIN_G(no_more_uploads)) { | 213 | if (SUHOSIN_G(no_more_uploads)) { |
| 214 | goto continue_with_failure; | 214 | goto continue_with_failure; |
| 215 | } | 215 | } |
| 216 | 216 | ||
| 217 | /* Drop this fileupload if the limit is reached */ | 217 | /* Drop this fileupload if the limit is reached */ |
| 218 | if (SUHOSIN_G(upload_limit) && SUHOSIN_G(upload_limit) <= SUHOSIN_G(num_uploads)) { | 218 | if (SUHOSIN_G(upload_limit) && SUHOSIN_G(upload_limit) <= SUHOSIN_G(num_uploads)) { |
| 219 | suhosin_log(S_FILES, "configured fileupload limit exceeded - file dropped"); | 219 | suhosin_log(S_FILES, "configured fileupload limit exceeded - file dropped"); |
| 220 | if (!SUHOSIN_G(simulation)) { | 220 | if (!SUHOSIN_G(simulation)) { |
| 221 | SUHOSIN_G(no_more_uploads) = 1; | 221 | SUHOSIN_G(no_more_uploads) = 1; |
| 222 | goto continue_with_failure; | 222 | goto continue_with_failure; |
| 223 | } | 223 | } |
| 224 | } | 224 | } |
| 225 | |||
| 226 | |||
| 227 | if (check_fileupload_varname(mefs->name TSRMLS_CC) == FAILURE) { | ||
| 228 | goto continue_with_failure; | ||
| 229 | } | ||
| 230 | } | ||
| 231 | |||
| 232 | break; | ||
| 233 | 225 | ||
| 234 | case MULTIPART_EVENT_FILE_DATA: | ||
| 235 | 226 | ||
| 236 | if (SUHOSIN_G(upload_disallow_elf)) { | 227 | if (check_fileupload_varname(mefs->name TSRMLS_CC) == FAILURE) { |
| 237 | multipart_event_file_data *mefd = (multipart_event_file_data *) event_data; | 228 | goto continue_with_failure; |
| 238 | 229 | } | |
| 239 | if (mefd->offset == 0 && mefd->length > 10) { | 230 | } |
| 240 | if (mefd->data[0] == 0x7F && mefd->data[1] == 'E' && mefd->data[2] == 'L' && mefd->data[3] == 'F') { | 231 | |
| 241 | suhosin_log(S_FILES, "uploaded file is an ELF executable - file dropped"); | 232 | break; |
| 242 | if (!SUHOSIN_G(simulation)) { | 233 | |
| 243 | goto continue_with_failure; | 234 | case MULTIPART_EVENT_FILE_DATA: |
| 244 | } | 235 | |
| 245 | } | 236 | if (SUHOSIN_G(upload_disallow_elf)) { |
| 246 | } | 237 | multipart_event_file_data *mefd = (multipart_event_file_data *) event_data; |
| 247 | } | 238 | |
| 248 | 239 | if (mefd->offset == 0 && mefd->length > 10) { | |
| 240 | if (mefd->data[0] == 0x7F && mefd->data[1] == 'E' && mefd->data[2] == 'L' && mefd->data[3] == 'F') { | ||
| 241 | suhosin_log(S_FILES, "uploaded file is an ELF executable - file dropped"); | ||
| 242 | if (!SUHOSIN_G(simulation)) { | ||
| 243 | goto continue_with_failure; | ||
| 244 | } | ||
| 245 | } | ||
| 246 | } | ||
| 247 | } | ||
| 248 | |||
| 249 | if (SUHOSIN_G(upload_disallow_binary)) { | 249 | if (SUHOSIN_G(upload_disallow_binary)) { |
| 250 | 250 | ||
| 251 | multipart_event_file_data *mefd = (multipart_event_file_data *) event_data; | 251 | multipart_event_file_data *mefd = (multipart_event_file_data *) event_data; |
| 252 | 252 | ||
| 253 | char *cp, *cpend; | 253 | char *cp, *cpend; |
| @@ -275,11 +275,11 @@ int suhosin_rfc1867_filter(unsigned int event, void *event_data, void **extra TS | |||
| 275 | } | 275 | } |
| 276 | 276 | ||
| 277 | if (SUHOSIN_G(upload_remove_binary)) { | 277 | if (SUHOSIN_G(upload_remove_binary)) { |
| 278 | 278 | ||
| 279 | multipart_event_file_data *mefd = (multipart_event_file_data *) event_data; | 279 | multipart_event_file_data *mefd = (multipart_event_file_data *) event_data; |
| 280 | size_t i, j; | 280 | size_t i, j; |
| 281 | int n; | 281 | int n; |
| 282 | 282 | ||
| 283 | for (i=0, j=0; i<mefd->length; i++) { | 283 | for (i=0, j=0; i<mefd->length; i++) { |
| 284 | if (mefd->data[i] >= 32 || isspace(mefd->data[i])) { | 284 | if (mefd->data[i] >= 32 || isspace(mefd->data[i])) { |
| 285 | mefd->data[j++] = mefd->data[i]; | 285 | mefd->data[j++] = mefd->data[i]; |
| @@ -296,7 +296,7 @@ int suhosin_rfc1867_filter(unsigned int event, void *event_data, void **extra TS | |||
| 296 | #endif | 296 | #endif |
| 297 | } | 297 | } |
| 298 | mefd->data[j] = '\0'; | 298 | mefd->data[j] = '\0'; |
| 299 | 299 | ||
| 300 | SDEBUG("removing binary %zu %zu",i,j); | 300 | SDEBUG("removing binary %zu %zu",i,j); |
| 301 | /* IMPORTANT FOR DAISY CHAINING */ | 301 | /* IMPORTANT FOR DAISY CHAINING */ |
| 302 | mefd->length = j; | 302 | mefd->length = j; |
| @@ -304,31 +304,31 @@ int suhosin_rfc1867_filter(unsigned int event, void *event_data, void **extra TS | |||
| 304 | *mefd->newlength = j; | 304 | *mefd->newlength = j; |
| 305 | } | 305 | } |
| 306 | } | 306 | } |
| 307 | |||
| 308 | break; | ||
| 309 | 307 | ||
| 310 | case MULTIPART_EVENT_FILE_END: | 308 | break; |
| 311 | 309 | ||
| 312 | if (SUHOSIN_G(upload_verification_script)) { | 310 | case MULTIPART_EVENT_FILE_END: |
| 313 | multipart_event_file_end *mefe = (multipart_event_file_end *) event_data; | 311 | |
| 314 | char cmd[8192]; | 312 | if (SUHOSIN_G(upload_verification_script)) { |
| 315 | FILE *in; | 313 | multipart_event_file_end *mefe = (multipart_event_file_end *) event_data; |
| 316 | int first=1; | 314 | char cmd[8192]; |
| 315 | FILE *in; | ||
| 316 | int first=1; | ||
| 317 | struct stat st; | 317 | struct stat st; |
| 318 | char *sname = SUHOSIN_G(upload_verification_script); | 318 | char *sname = SUHOSIN_G(upload_verification_script); |
| 319 | 319 | ||
| 320 | /* ignore files that will get deleted anyway */ | 320 | /* ignore files that will get deleted anyway */ |
| 321 | if (mefe->cancel_upload) { | 321 | if (mefe->cancel_upload) { |
| 322 | break; | 322 | break; |
| 323 | } | 323 | } |
| 324 | 324 | ||
| 325 | /* ignore empty scriptnames */ | 325 | /* ignore empty scriptnames */ |
| 326 | while (isspace(*sname)) ++sname; | 326 | while (isspace(*sname)) ++sname; |
| 327 | if (*sname == 0) { | 327 | if (*sname == 0) { |
| 328 | SUHOSIN_G(num_uploads)++; | 328 | SUHOSIN_G(num_uploads)++; |
| 329 | break; | 329 | break; |
| 330 | } | 330 | } |
| 331 | 331 | ||
| 332 | if (VCWD_STAT(sname, &st) < 0) { | 332 | if (VCWD_STAT(sname, &st) < 0) { |
| 333 | suhosin_log(S_FILES, "unable to find fileupload verification script %s - file dropped", sname); | 333 | suhosin_log(S_FILES, "unable to find fileupload verification script %s - file dropped", sname); |
| 334 | if (!SUHOSIN_G(simulation)) { | 334 | if (!SUHOSIN_G(simulation)) { |
| @@ -343,29 +343,29 @@ int suhosin_rfc1867_filter(unsigned int event, void *event_data, void **extra TS | |||
| 343 | goto continue_with_failure; | 343 | goto continue_with_failure; |
| 344 | } else { | 344 | } else { |
| 345 | goto continue_with_next; | 345 | goto continue_with_next; |
| 346 | } | 346 | } |
| 347 | } | 347 | } |
| 348 | |||
| 349 | ap_php_snprintf(cmd, sizeof(cmd), "%s %s 2>&1", sname, mefe->temp_filename); | ||
| 350 | 348 | ||
| 351 | if ((in=VCWD_POPEN(cmd, "r"))==NULL) { | 349 | ap_php_snprintf(cmd, sizeof(cmd), "%s %s 2>&1", sname, mefe->temp_filename); |
| 352 | suhosin_log(S_FILES, "unable to execute fileupload verification script %s - file dropped", sname); | 350 | |
| 353 | if (!SUHOSIN_G(simulation)) { | 351 | if ((in=VCWD_POPEN(cmd, "r"))==NULL) { |
| 354 | goto continue_with_failure; | 352 | suhosin_log(S_FILES, "unable to execute fileupload verification script %s - file dropped", sname); |
| 355 | } else { | 353 | if (!SUHOSIN_G(simulation)) { |
| 356 | goto continue_with_next; | 354 | goto continue_with_failure; |
| 357 | } | 355 | } else { |
| 358 | } | 356 | goto continue_with_next; |
| 359 | 357 | } | |
| 360 | retval = FAILURE; | 358 | } |
| 361 | 359 | ||
| 362 | /* read and forget the result */ | 360 | retval = FAILURE; |
| 363 | while (1) { | 361 | |
| 364 | int readbytes = fread(cmd, 1, sizeof(cmd), in); | 362 | /* read and forget the result */ |
| 365 | if (readbytes<=0) { | 363 | while (1) { |
| 366 | break; | 364 | int readbytes = fread(cmd, 1, sizeof(cmd), in); |
| 367 | } | 365 | if (readbytes<=0) { |
| 368 | if (first) { | 366 | break; |
| 367 | } | ||
| 368 | if (first) { | ||
| 369 | if (strncmp(cmd, "sh: ", 4) == 0) { | 369 | if (strncmp(cmd, "sh: ", 4) == 0) { |
| 370 | /* assume this is an error */ | 370 | /* assume this is an error */ |
| 371 | suhosin_log(S_FILES, "error while executing fileupload verification script %s - file dropped", sname); | 371 | suhosin_log(S_FILES, "error while executing fileupload verification script %s - file dropped", sname); |
| @@ -378,30 +378,30 @@ int suhosin_rfc1867_filter(unsigned int event, void *event_data, void **extra TS | |||
| 378 | retval = atoi(cmd) == 1 ? SUCCESS : FAILURE; | 378 | retval = atoi(cmd) == 1 ? SUCCESS : FAILURE; |
| 379 | first = 0; | 379 | first = 0; |
| 380 | } | 380 | } |
| 381 | } | 381 | } |
| 382 | } | 382 | } |
| 383 | pclose(in); | 383 | pclose(in); |
| 384 | } | 384 | } |
| 385 | |||
| 386 | if (retval != SUCCESS) { | ||
| 387 | suhosin_log(S_FILES, "fileupload verification script disallows file - file dropped"); | ||
| 388 | if (!SUHOSIN_G(simulation)) { | ||
| 389 | goto continue_with_failure; | ||
| 390 | } | ||
| 391 | } | ||
| 385 | 392 | ||
| 386 | if (retval != SUCCESS) { | 393 | SUHOSIN_G(num_uploads)++; |
| 387 | suhosin_log(S_FILES, "fileupload verification script disallows file - file dropped"); | 394 | break; |
| 388 | if (!SUHOSIN_G(simulation)) { | ||
| 389 | goto continue_with_failure; | ||
| 390 | } | ||
| 391 | } | ||
| 392 | 395 | ||
| 393 | SUHOSIN_G(num_uploads)++; | 396 | case MULTIPART_EVENT_END: |
| 394 | break; | 397 | /* nothing todo */ |
| 398 | break; | ||
| 395 | 399 | ||
| 396 | case MULTIPART_EVENT_END: | 400 | default: |
| 397 | /* nothing todo */ | 401 | /* unknown: return failure */ |
| 398 | break; | 402 | goto continue_with_failure; |
| 399 | |||
| 400 | default: | ||
| 401 | /* unknown: return failure */ | ||
| 402 | goto continue_with_failure; | ||
| 403 | } | 403 | } |
| 404 | continue_with_next: | 404 | continue_with_next: |
| 405 | #if HAVE_RFC1867_CALLBACK | 405 | #if HAVE_RFC1867_CALLBACK |
| 406 | if (php_rfc1867_callback != NULL) { | 406 | if (php_rfc1867_callback != NULL) { |
| 407 | return php_rfc1867_callback(event, event_data, extra TSRMLS_CC); | 407 | return php_rfc1867_callback(event, event_data, extra TSRMLS_CC); |
| @@ -409,7 +409,7 @@ continue_with_next: | |||
| 409 | #endif | 409 | #endif |
| 410 | return SUCCESS; | 410 | return SUCCESS; |
| 411 | continue_with_failure: | 411 | continue_with_failure: |
| 412 | SUHOSIN_G(abort_request) = 1; | 412 | SUHOSIN_G(abort_request) = 1; |
| 413 | return FAILURE; | 413 | return FAILURE; |
| 414 | } | 414 | } |
| 415 | 415 | ||
