summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Fuhrmannek2014-09-25 18:07:55 +0200
committerBen Fuhrmannek2014-09-25 18:07:55 +0200
commit49a4321cec080d61ff112aaf27f55257e62402f9 (patch)
treec3500f64ef6cc5d45d70296339827857de1bf889
parent594c8df58c6f7f9b9610c7f0fd11da08a532de98 (diff)
array index whitelist/blacklist for multipart formdata
-rw-r--r--ifilter.c8
-rw-r--r--php_suhosin.h2
-rw-r--r--tests/filter/post_fileupload_array_index_blacklist.phpt41
-rw-r--r--tests/filter/post_fileupload_array_index_whitelist.phpt41
-rw-r--r--ufilter.c18
5 files changed, 106 insertions, 4 deletions
diff --git a/ifilter.c b/ifilter.c
index 4ea846f..47ab6f2 100644
--- a/ifilter.c
+++ b/ifilter.c
@@ -41,7 +41,7 @@ static size_t strnlen(const char *s, size_t maxlen) {
41} 41}
42#endif 42#endif
43 43
44static size_t strnspn(const char *input, size_t n, const char *accept) 44size_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
54static size_t strncspn(const char *input, size_t n, const char *reject) 54size_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
446void normalize_varname(char *varname); 446void normalize_varname(char *varname);
447int suhosin_rfc1867_filter(unsigned int event, void *event_data, void **extra TSRMLS_DC); 447int suhosin_rfc1867_filter(unsigned int event, void *event_data, void **extra TSRMLS_DC);
448void suhosin_bailout(TSRMLS_D); 448void suhosin_bailout(TSRMLS_D);
449size_t suhosin_strnspn(const char *input, size_t n, const char *accept);
450size_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--
2suhosin file upload filter (array index whitelist)
3--INI--
4suhosin.log.syslog=0
5suhosin.log.sapi=0
6suhosin.log.stdout=255
7suhosin.log.script=0
8file_uploads=1
9suhosin.request.array_index_blacklist=ABC
10--SKIPIF--
11<?php include('skipif.inc'); ?>
12--COOKIE--
13--GET--
14--POST_RAW--
15Content-Type: multipart/form-data; boundary=---------------------------20896060251896012921717172737
16-----------------------------20896060251896012921717172737
17Content-Disposition: form-data; name="fn[foo][bar]"
18
19ok
20-----------------------------20896060251896012921717172737
21Content-Disposition: form-data; name="fn[foo][BAR]"
22
23bad
24-----------------------------20896060251896012921717172737--
25--FILE--
26<?php
27var_dump($_POST);
28?>
29--EXPECTF--
30array(1) {
31 ["fn"]=>
32 array(1) {
33 ["foo"]=>
34 array(1) {
35 ["bar"]=>
36 string(2) "ok"
37 }
38 }
39}
40ALERT - array index contains blacklisted characters - dropped variable 'fn[foo][BAR]' (attacker 'REMOTE_ADDR not set', file '%s')
41ALERT - 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--
2suhosin file upload filter (array index whitelist)
3--INI--
4suhosin.log.syslog=0
5suhosin.log.sapi=0
6suhosin.log.stdout=255
7suhosin.log.script=0
8file_uploads=1
9suhosin.request.array_index_whitelist=abcdefghijklmnopqrstuvwxyz
10--SKIPIF--
11<?php include('skipif.inc'); ?>
12--COOKIE--
13--GET--
14--POST_RAW--
15Content-Type: multipart/form-data; boundary=---------------------------20896060251896012921717172737
16-----------------------------20896060251896012921717172737
17Content-Disposition: form-data; name="fn[foo][bar]"
18
19ok
20-----------------------------20896060251896012921717172737
21Content-Disposition: form-data; name="fn[foo][BAR]"
22
23bad
24-----------------------------20896060251896012921717172737--
25--FILE--
26<?php
27var_dump($_POST);
28?>
29--EXPECTF--
30array(1) {
31 ["fn"]=>
32 array(1) {
33 ["foo"]=>
34 array(1) {
35 ["bar"]=>
36 string(2) "ok"
37 }
38 }
39}
40ALERT - array index contains not whitelisted characters - dropped variable 'fn[foo][BAR]' (attacker 'REMOTE_ADDR not set', file '%s')
41ALERT - dropped 1 request variables - (0 in GET, 1 in POST, 0 in COOKIE) (attacker 'REMOTE_ADDR not set', file '%s')
diff --git a/ufilter.c b/ufilter.c
index 1669e88..28b61e1 100644
--- a/ufilter.c
+++ b/ufilter.c
@@ -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