diff options
| -rw-r--r-- | ifilter.c | 8 | ||||
| -rw-r--r-- | php_suhosin.h | 2 | ||||
| -rw-r--r-- | tests/filter/post_fileupload_array_index_blacklist.phpt | 41 | ||||
| -rw-r--r-- | tests/filter/post_fileupload_array_index_whitelist.phpt | 41 | ||||
| -rw-r--r-- | ufilter.c | 18 |
5 files changed, 106 insertions, 4 deletions
| @@ -41,7 +41,7 @@ static size_t strnlen(const char *s, size_t maxlen) { | |||
| 41 | } | 41 | } |
| 42 | #endif | 42 | #endif |
| 43 | 43 | ||
| 44 | static size_t strnspn(const char *input, size_t n, const char *accept) | 44 | size_t suhosin_strnspn(const char *input, size_t n, const char *accept) |
| 45 | { | 45 | { |
| 46 | size_t count = 0; | 46 | size_t count = 0; |
| 47 | for (; *input != '\0' && count < n; input++, count++) { | 47 | for (; *input != '\0' && count < n; input++, count++) { |
| @@ -51,7 +51,7 @@ static size_t strnspn(const char *input, size_t n, const char *accept) | |||
| 51 | return count; | 51 | return count; |
| 52 | } | 52 | } |
| 53 | 53 | ||
| 54 | static size_t strncspn(const char *input, size_t n, const char *reject) | 54 | size_t suhosin_strncspn(const char *input, size_t n, const char *reject) |
| 55 | { | 55 | { |
| 56 | size_t count = 0; | 56 | size_t count = 0; |
| 57 | for (; *input != '\0' && count < n; input++, count++) { | 57 | for (; *input != '\0' && count < n; input++, count++) { |
| @@ -581,14 +581,14 @@ unsigned int suhosin_input_filter(int arg, char *var, char **val, unsigned int v | |||
| 581 | 581 | ||
| 582 | /* index whitelist/blacklist */ | 582 | /* index whitelist/blacklist */ |
| 583 | if (SUHOSIN_G(array_index_whitelist) && *(SUHOSIN_G(array_index_whitelist))) { | 583 | if (SUHOSIN_G(array_index_whitelist) && *(SUHOSIN_G(array_index_whitelist))) { |
| 584 | if (strnspn(index, index_length, SUHOSIN_G(array_index_whitelist)) != index_length) { | 584 | if (suhosin_strnspn(index, index_length, SUHOSIN_G(array_index_whitelist)) != index_length) { |
| 585 | suhosin_log(S_VARS, "array index contains not whitelisted characters - dropped variable '%s'", var); | 585 | suhosin_log(S_VARS, "array index contains not whitelisted characters - dropped variable '%s'", var); |
| 586 | if (!SUHOSIN_G(simulation)) { | 586 | if (!SUHOSIN_G(simulation)) { |
| 587 | return 0; | 587 | return 0; |
| 588 | } | 588 | } |
| 589 | } | 589 | } |
| 590 | } else if (SUHOSIN_G(array_index_blacklist) && *(SUHOSIN_G(array_index_blacklist))) { | 590 | } else if (SUHOSIN_G(array_index_blacklist) && *(SUHOSIN_G(array_index_blacklist))) { |
| 591 | if (strncspn(index, index_length, SUHOSIN_G(array_index_blacklist)) != index_length) { | 591 | if (suhosin_strncspn(index, index_length, SUHOSIN_G(array_index_blacklist)) != index_length) { |
| 592 | suhosin_log(S_VARS, "array index contains blacklisted characters - dropped variable '%s'", var); | 592 | suhosin_log(S_VARS, "array index contains blacklisted characters - dropped variable '%s'", var); |
| 593 | if (!SUHOSIN_G(simulation)) { | 593 | if (!SUHOSIN_G(simulation)) { |
| 594 | return 0; | 594 | return 0; |
diff --git a/php_suhosin.h b/php_suhosin.h index 8877e53..7be628a 100644 --- a/php_suhosin.h +++ b/php_suhosin.h | |||
| @@ -446,6 +446,8 @@ extern unsigned int (*old_input_filter)(int arg, char *var, char **val, unsigned | |||
| 446 | void normalize_varname(char *varname); | 446 | void normalize_varname(char *varname); |
| 447 | int suhosin_rfc1867_filter(unsigned int event, void *event_data, void **extra TSRMLS_DC); | 447 | int suhosin_rfc1867_filter(unsigned int event, void *event_data, void **extra TSRMLS_DC); |
| 448 | void suhosin_bailout(TSRMLS_D); | 448 | void suhosin_bailout(TSRMLS_D); |
| 449 | size_t suhosin_strnspn(const char *input, size_t n, const char *accept); | ||
| 450 | size_t suhosin_strncspn(const char *input, size_t n, const char *reject); | ||
| 449 | 451 | ||
| 450 | /* Add pseudo refcount macros for PHP version < 5.3 */ | 452 | /* Add pseudo refcount macros for PHP version < 5.3 */ |
| 451 | #ifndef Z_REFCOUNT_PP | 453 | #ifndef Z_REFCOUNT_PP |
diff --git a/tests/filter/post_fileupload_array_index_blacklist.phpt b/tests/filter/post_fileupload_array_index_blacklist.phpt new file mode 100644 index 0000000..f0e003b --- /dev/null +++ b/tests/filter/post_fileupload_array_index_blacklist.phpt | |||
| @@ -0,0 +1,41 @@ | |||
| 1 | --TEST-- | ||
| 2 | suhosin file upload filter (array index whitelist) | ||
| 3 | --INI-- | ||
| 4 | suhosin.log.syslog=0 | ||
| 5 | suhosin.log.sapi=0 | ||
| 6 | suhosin.log.stdout=255 | ||
| 7 | suhosin.log.script=0 | ||
| 8 | file_uploads=1 | ||
| 9 | suhosin.request.array_index_blacklist=ABC | ||
| 10 | --SKIPIF-- | ||
| 11 | <?php include('skipif.inc'); ?> | ||
| 12 | --COOKIE-- | ||
| 13 | --GET-- | ||
| 14 | --POST_RAW-- | ||
| 15 | Content-Type: multipart/form-data; boundary=---------------------------20896060251896012921717172737 | ||
| 16 | -----------------------------20896060251896012921717172737 | ||
| 17 | Content-Disposition: form-data; name="fn[foo][bar]" | ||
| 18 | |||
| 19 | ok | ||
| 20 | -----------------------------20896060251896012921717172737 | ||
| 21 | Content-Disposition: form-data; name="fn[foo][BAR]" | ||
| 22 | |||
| 23 | bad | ||
| 24 | -----------------------------20896060251896012921717172737-- | ||
| 25 | --FILE-- | ||
| 26 | <?php | ||
| 27 | var_dump($_POST); | ||
| 28 | ?> | ||
| 29 | --EXPECTF-- | ||
| 30 | array(1) { | ||
| 31 | ["fn"]=> | ||
| 32 | array(1) { | ||
| 33 | ["foo"]=> | ||
| 34 | array(1) { | ||
| 35 | ["bar"]=> | ||
| 36 | string(2) "ok" | ||
| 37 | } | ||
| 38 | } | ||
| 39 | } | ||
| 40 | ALERT - array index contains blacklisted characters - dropped variable 'fn[foo][BAR]' (attacker 'REMOTE_ADDR not set', file '%s') | ||
| 41 | ALERT - dropped 1 request variables - (0 in GET, 1 in POST, 0 in COOKIE) (attacker 'REMOTE_ADDR not set', file '%s') | ||
diff --git a/tests/filter/post_fileupload_array_index_whitelist.phpt b/tests/filter/post_fileupload_array_index_whitelist.phpt new file mode 100644 index 0000000..f2fe8c8 --- /dev/null +++ b/tests/filter/post_fileupload_array_index_whitelist.phpt | |||
| @@ -0,0 +1,41 @@ | |||
| 1 | --TEST-- | ||
| 2 | suhosin file upload filter (array index whitelist) | ||
| 3 | --INI-- | ||
| 4 | suhosin.log.syslog=0 | ||
| 5 | suhosin.log.sapi=0 | ||
| 6 | suhosin.log.stdout=255 | ||
| 7 | suhosin.log.script=0 | ||
| 8 | file_uploads=1 | ||
| 9 | suhosin.request.array_index_whitelist=abcdefghijklmnopqrstuvwxyz | ||
| 10 | --SKIPIF-- | ||
| 11 | <?php include('skipif.inc'); ?> | ||
| 12 | --COOKIE-- | ||
| 13 | --GET-- | ||
| 14 | --POST_RAW-- | ||
| 15 | Content-Type: multipart/form-data; boundary=---------------------------20896060251896012921717172737 | ||
| 16 | -----------------------------20896060251896012921717172737 | ||
| 17 | Content-Disposition: form-data; name="fn[foo][bar]" | ||
| 18 | |||
| 19 | ok | ||
| 20 | -----------------------------20896060251896012921717172737 | ||
| 21 | Content-Disposition: form-data; name="fn[foo][BAR]" | ||
| 22 | |||
| 23 | bad | ||
| 24 | -----------------------------20896060251896012921717172737-- | ||
| 25 | --FILE-- | ||
| 26 | <?php | ||
| 27 | var_dump($_POST); | ||
| 28 | ?> | ||
| 29 | --EXPECTF-- | ||
| 30 | array(1) { | ||
| 31 | ["fn"]=> | ||
| 32 | array(1) { | ||
| 33 | ["foo"]=> | ||
| 34 | array(1) { | ||
| 35 | ["bar"]=> | ||
| 36 | string(2) "ok" | ||
| 37 | } | ||
| 38 | } | ||
| 39 | } | ||
| 40 | ALERT - array index contains not whitelisted characters - dropped variable 'fn[foo][BAR]' (attacker 'REMOTE_ADDR not set', file '%s') | ||
| 41 | ALERT - dropped 1 request variables - (0 in GET, 1 in POST, 0 in COOKIE) (attacker 'REMOTE_ADDR not set', file '%s') | ||
| @@ -113,6 +113,24 @@ static int check_fileupload_varname(char *varname) | |||
| 113 | } | 113 | } |
| 114 | } | 114 | } |
| 115 | 115 | ||
| 116 | /* index whitelist/blacklist */ | ||
| 117 | if (SUHOSIN_G(array_index_whitelist) && *(SUHOSIN_G(array_index_whitelist))) { | ||
| 118 | if (suhosin_strnspn(index, index_length, SUHOSIN_G(array_index_whitelist)) != index_length) { | ||
| 119 | suhosin_log(S_VARS, "array index contains not whitelisted characters - dropped variable '%s'", var); | ||
| 120 | if (!SUHOSIN_G(simulation)) { | ||
| 121 | goto return_failure; | ||
| 122 | } | ||
| 123 | } | ||
| 124 | } else if (SUHOSIN_G(array_index_blacklist) && *(SUHOSIN_G(array_index_blacklist))) { | ||
| 125 | if (suhosin_strncspn(index, index_length, SUHOSIN_G(array_index_blacklist)) != index_length) { | ||
| 126 | suhosin_log(S_VARS, "array index contains blacklisted characters - dropped variable '%s'", var); | ||
| 127 | if (!SUHOSIN_G(simulation)) { | ||
| 128 | goto return_failure; | ||
| 129 | } | ||
| 130 | } | ||
| 131 | } | ||
| 132 | |||
| 133 | |||
| 116 | index = strchr(index, '['); | 134 | index = strchr(index, '['); |
| 117 | } | 135 | } |
| 118 | 136 | ||
