diff options
| author | Ben Fuhrmannek | 2014-10-11 10:25:59 +0200 |
|---|---|---|
| committer | Ben Fuhrmannek | 2014-10-11 10:25:59 +0200 |
| commit | c8724cde260e6c8bab4aefffffa1aa46f92a57ee (patch) | |
| tree | fa71c2fd8f6c1e84ea2b23e5040253bf1ce93825 | |
| parent | 3159694378333c08c73d4fcd4b73725c02249750 (diff) | |
fixed utf8 detection + made feature experimental
| -rw-r--r-- | php_suhosin.h | 2 | ||||
| -rw-r--r-- | suhosin.c | 4 | ||||
| -rw-r--r-- | suhosin.ini | 10 | ||||
| -rw-r--r-- | tests/filter/suhosin_upload_disallow_binary_utf8.phpt | 4 | ||||
| -rw-r--r-- | tests/filter/suhosin_upload_disallow_binary_utf8fail.phpt | 4 | ||||
| -rw-r--r-- | tests/filter/suhosin_upload_remove_binary_utf8.phpt | 4 | ||||
| -rw-r--r-- | tests/filter/suhosin_upload_remove_binary_utf8fail.phpt | 4 | ||||
| -rw-r--r-- | ufilter.c | 22 |
8 files changed, 34 insertions, 20 deletions
diff --git a/php_suhosin.h b/php_suhosin.h index d567877..df7c877 100644 --- a/php_suhosin.h +++ b/php_suhosin.h | |||
| @@ -250,7 +250,9 @@ ZEND_BEGIN_MODULE_GLOBALS(suhosin) | |||
| 250 | zend_bool upload_disallow_elf; | 250 | zend_bool upload_disallow_elf; |
| 251 | zend_bool upload_disallow_binary; | 251 | zend_bool upload_disallow_binary; |
| 252 | zend_bool upload_remove_binary; | 252 | zend_bool upload_remove_binary; |
| 253 | #ifdef SUHOSIN_EXPERIMENTAL | ||
| 253 | zend_bool upload_allow_utf8; | 254 | zend_bool upload_allow_utf8; |
| 255 | #endif | ||
| 254 | char *upload_verification_script; | 256 | char *upload_verification_script; |
| 255 | 257 | ||
| 256 | zend_bool no_more_variables; | 258 | zend_bool no_more_variables; |
| @@ -824,7 +824,9 @@ PHP_INI_BEGIN() | |||
| 824 | STD_PHP_INI_ENTRY("suhosin.upload.disallow_elf", "1", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateUploadBool, upload_disallow_elf, zend_suhosin_globals, suhosin_globals) | 824 | STD_PHP_INI_ENTRY("suhosin.upload.disallow_elf", "1", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateUploadBool, upload_disallow_elf, zend_suhosin_globals, suhosin_globals) |
| 825 | STD_PHP_INI_ENTRY("suhosin.upload.disallow_binary", "0", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateUploadBool, upload_disallow_binary, zend_suhosin_globals, suhosin_globals) | 825 | STD_PHP_INI_ENTRY("suhosin.upload.disallow_binary", "0", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateUploadBool, upload_disallow_binary, zend_suhosin_globals, suhosin_globals) |
| 826 | STD_PHP_INI_ENTRY("suhosin.upload.remove_binary", "0", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateUploadBool, upload_remove_binary, zend_suhosin_globals, suhosin_globals) | 826 | STD_PHP_INI_ENTRY("suhosin.upload.remove_binary", "0", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateUploadBool, upload_remove_binary, zend_suhosin_globals, suhosin_globals) |
| 827 | STD_PHP_INI_ENTRY("suhosin.upload.allow_utf8", "0", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateUploadBool, upload_allow_utf8, zend_suhosin_globals, suhosin_globals) | 827 | #ifdef SUHOSIN_EXPERIMENTAL |
| 828 | STD_PHP_INI_BOOLEAN("suhosin.upload.allow_utf8", "0", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateUploadBool, upload_allow_utf8, zend_suhosin_globals, suhosin_globals) | ||
| 829 | #endif | ||
| 828 | STD_PHP_INI_ENTRY("suhosin.upload.verification_script", NULL, PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateUploadString, upload_verification_script, zend_suhosin_globals, suhosin_globals) | 830 | STD_PHP_INI_ENTRY("suhosin.upload.verification_script", NULL, PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateUploadString, upload_verification_script, zend_suhosin_globals, suhosin_globals) |
| 829 | 831 | ||
| 830 | 832 | ||
diff --git a/suhosin.ini b/suhosin.ini index 3ae8ff5..311bca7 100644 --- a/suhosin.ini +++ b/suhosin.ini | |||
| @@ -105,9 +105,6 @@ | |||
| 105 | ; | LOG_LOCAL7 | 31 | | 105 | ; | LOG_LOCAL7 | 31 | |
| 106 | ; +--------------+-------+ | 106 | ; +--------------+-------+ |
| 107 | ; | 107 | ; |
| 108 | ; Using constant names is only supported with the Suhosin-Patch. If in doubt, use | ||
| 109 | ; the numeric value. | ||
| 110 | ; | ||
| 111 | ;suhosin.log.syslog.facility = LOG_USER | 108 | ;suhosin.log.syslog.facility = LOG_USER |
| 112 | ; | 109 | ; |
| 113 | 110 | ||
| @@ -141,9 +138,6 @@ | |||
| 141 | ; |LOG_ERR | 7 | | 138 | ; |LOG_ERR | 7 | |
| 142 | ; +------------+-------+ | 139 | ; +------------+-------+ |
| 143 | ; | 140 | ; |
| 144 | ; Using constant names is only supported with the Suhosin-Patch. If in doubt, use | ||
| 145 | ; the numeric value. | ||
| 146 | ; | ||
| 147 | ;suhosin.log.syslog.priority = LOG_ALERT | 141 | ;suhosin.log.syslog.priority = LOG_ALERT |
| 148 | ; | 142 | ; |
| 149 | 143 | ||
| @@ -1325,8 +1319,8 @@ | |||
| 1325 | ; * Type: Boolean | 1319 | ; * Type: Boolean |
| 1326 | ; * Default: Off | 1320 | ; * Default: Off |
| 1327 | ; | 1321 | ; |
| 1328 | ; This option allows UTF-8 along with ASCII when using | 1322 | ; This is an experimental feature. This option allows UTF-8 along with ASCII when |
| 1329 | ; `suhosin.upload.disallow_binary` or `suhosin.upload.remove_binary`. | 1323 | ; using `suhosin.upload.disallow_binary` or `suhosin.upload.remove_binary`. |
| 1330 | ; | 1324 | ; |
| 1331 | ;suhosin.upload.allow_utf8 = Off | 1325 | ;suhosin.upload.allow_utf8 = Off |
| 1332 | ; | 1326 | ; |
diff --git a/tests/filter/suhosin_upload_disallow_binary_utf8.phpt b/tests/filter/suhosin_upload_disallow_binary_utf8.phpt index 557a8d5..b4627c7 100644 --- a/tests/filter/suhosin_upload_disallow_binary_utf8.phpt +++ b/tests/filter/suhosin_upload_disallow_binary_utf8.phpt | |||
| @@ -11,7 +11,9 @@ suhosin.upload.allow_utf8=On | |||
| 11 | max_file_uploads=40 | 11 | max_file_uploads=40 |
| 12 | suhosin.upload.max_uploads=40 | 12 | suhosin.upload.max_uploads=40 |
| 13 | --SKIPIF-- | 13 | --SKIPIF-- |
| 14 | <?php include('skipif.inc'); ?> | 14 | <?php include('skipif.inc'); |
| 15 | if (ini_get('suhosin.upload.allow_utf8') === FALSE) { die("skip feature not compiled in"); } | ||
| 16 | ?> | ||
| 15 | --COOKIE-- | 17 | --COOKIE-- |
| 16 | --GET-- | 18 | --GET-- |
| 17 | --POST_RAW-- | 19 | --POST_RAW-- |
diff --git a/tests/filter/suhosin_upload_disallow_binary_utf8fail.phpt b/tests/filter/suhosin_upload_disallow_binary_utf8fail.phpt index 413d25a..0bf122b 100644 --- a/tests/filter/suhosin_upload_disallow_binary_utf8fail.phpt +++ b/tests/filter/suhosin_upload_disallow_binary_utf8fail.phpt | |||
| @@ -11,7 +11,9 @@ suhosin.upload.allow_utf8=Off | |||
| 11 | max_file_uploads=40 | 11 | max_file_uploads=40 |
| 12 | suhosin.upload.max_uploads=40 | 12 | suhosin.upload.max_uploads=40 |
| 13 | --SKIPIF-- | 13 | --SKIPIF-- |
| 14 | <?php include('skipif.inc'); ?> | 14 | <?php include('skipif.inc'); |
| 15 | if (ini_get('suhosin.upload.allow_utf8') === FALSE) { die("skip feature not compiled in"); } | ||
| 16 | ?> | ||
| 15 | --COOKIE-- | 17 | --COOKIE-- |
| 16 | --GET-- | 18 | --GET-- |
| 17 | --POST_RAW-- | 19 | --POST_RAW-- |
diff --git a/tests/filter/suhosin_upload_remove_binary_utf8.phpt b/tests/filter/suhosin_upload_remove_binary_utf8.phpt index 6fbd240..1920dc5 100644 --- a/tests/filter/suhosin_upload_remove_binary_utf8.phpt +++ b/tests/filter/suhosin_upload_remove_binary_utf8.phpt | |||
| @@ -12,7 +12,9 @@ suhosin.upload.allow_utf8=On | |||
| 12 | max_file_uploads=40 | 12 | max_file_uploads=40 |
| 13 | suhosin.upload.max_uploads=40 | 13 | suhosin.upload.max_uploads=40 |
| 14 | --SKIPIF-- | 14 | --SKIPIF-- |
| 15 | <?php include('skipif.inc'); ?> | 15 | <?php include('skipif.inc'); |
| 16 | if (ini_get('suhosin.upload.allow_utf8') === FALSE) { die("skip feature not compiled in"); } | ||
| 17 | ?> | ||
| 16 | --COOKIE-- | 18 | --COOKIE-- |
| 17 | --GET-- | 19 | --GET-- |
| 18 | --POST_RAW-- | 20 | --POST_RAW-- |
diff --git a/tests/filter/suhosin_upload_remove_binary_utf8fail.phpt b/tests/filter/suhosin_upload_remove_binary_utf8fail.phpt index 5c31115..56de404 100644 --- a/tests/filter/suhosin_upload_remove_binary_utf8fail.phpt +++ b/tests/filter/suhosin_upload_remove_binary_utf8fail.phpt | |||
| @@ -12,7 +12,9 @@ suhosin.upload.allow_utf8=Off | |||
| 12 | max_file_uploads=40 | 12 | max_file_uploads=40 |
| 13 | suhosin.upload.max_uploads=40 | 13 | suhosin.upload.max_uploads=40 |
| 14 | --SKIPIF-- | 14 | --SKIPIF-- |
| 15 | <?php include('skipif.inc'); ?> | 15 | <?php include('skipif.inc'); |
| 16 | if (ini_get('suhosin.upload.allow_utf8') === FALSE) { die("skip feature not compiled in"); } | ||
| 17 | ?> | ||
| 16 | --COOKIE-- | 18 | --COOKIE-- |
| 17 | --GET-- | 19 | --GET-- |
| 18 | --POST_RAW-- | 20 | --POST_RAW-- |
| @@ -149,19 +149,23 @@ return_failure: | |||
| 149 | } | 149 | } |
| 150 | /* }}} */ | 150 | /* }}} */ |
| 151 | 151 | ||
| 152 | static inline int suhosin_validate_utf8_multibyte(const char* cp) | 152 | #ifdef SUHOSIN_EXPERIMENTAL |
| 153 | static inline int suhosin_validate_utf8_multibyte(const char* cp, size_t maxlen) | ||
| 153 | { | 154 | { |
| 155 | if (maxlen < 2 || !(*cp & 0x80)) { return 0; } | ||
| 154 | if ((*cp & 0xe0) == 0xc0 && // 1st byte is 110xxxxx | 156 | if ((*cp & 0xe0) == 0xc0 && // 1st byte is 110xxxxx |
| 155 | (*(cp+1) & 0xc0) == 0x80 && // 2nd byte is 10xxxxxx | 157 | (*(cp+1) & 0xc0) == 0x80 && // 2nd byte is 10xxxxxx |
| 156 | (*cp & 0x1e)) { // overlong check 110[xxxx]x 10xxxxxx | 158 | (*cp & 0x1e)) { // overlong check 110[xxxx]x 10xxxxxx |
| 157 | return 2; | 159 | return 2; |
| 158 | } | 160 | } |
| 161 | if (maxlen < 3) { return 0; } | ||
| 159 | if ((*cp & 0xf0) == 0xe0 && // 1st byte is 1110xxxx | 162 | if ((*cp & 0xf0) == 0xe0 && // 1st byte is 1110xxxx |
| 160 | (*(cp+1) & 0xc0) == 0x80 && // 2nd byte is 10xxxxxx | 163 | (*(cp+1) & 0xc0) == 0x80 && // 2nd byte is 10xxxxxx |
| 161 | (*(cp+2) & 0xc0) == 0x80 && // 3rd byte is 10xxxxxx | 164 | (*(cp+2) & 0xc0) == 0x80 && // 3rd byte is 10xxxxxx |
| 162 | ((*cp & 0x0f) | (*(cp+1) & 0x20))) { // 1110[xxxx] 10[x]xxxxx 10xxxxxx | 165 | ((*cp & 0x0f) | (*(cp+1) & 0x20))) { // 1110[xxxx] 10[x]xxxxx 10xxxxxx |
| 163 | return 3; | 166 | return 3; |
| 164 | } | 167 | } |
| 168 | if (maxlen < 4) { return 0; } | ||
| 165 | if ((*cp & 0xf8) == 0xf0 && // 1st byte is 11110xxx | 169 | if ((*cp & 0xf8) == 0xf0 && // 1st byte is 11110xxx |
| 166 | (*(cp+1) & 0xc0) == 0x80 && // 2nd byte is 10xxxxxx | 170 | (*(cp+1) & 0xc0) == 0x80 && // 2nd byte is 10xxxxxx |
| 167 | (*(cp+2) & 0xc0) == 0x80 && // 3rd byte is 10xxxxxx | 171 | (*(cp+2) & 0xc0) == 0x80 && // 3rd byte is 10xxxxxx |
| @@ -171,6 +175,7 @@ static inline int suhosin_validate_utf8_multibyte(const char* cp) | |||
| 171 | } | 175 | } |
| 172 | return 0; | 176 | return 0; |
| 173 | } | 177 | } |
| 178 | #endif | ||
| 174 | 179 | ||
| 175 | int suhosin_rfc1867_filter(unsigned int event, void *event_data, void **extra TSRMLS_DC) | 180 | int suhosin_rfc1867_filter(unsigned int event, void *event_data, void **extra TSRMLS_DC) |
| 176 | { | 181 | { |
| @@ -236,14 +241,15 @@ int suhosin_rfc1867_filter(unsigned int event, void *event_data, void **extra TS | |||
| 236 | if (*cp >= 32 || isspace(*cp)) { | 241 | if (*cp >= 32 || isspace(*cp)) { |
| 237 | continue; | 242 | continue; |
| 238 | } | 243 | } |
| 244 | #ifdef SUHOSIN_EXPERIMENTAL | ||
| 239 | if ((*cp & 0x80) && SUHOSIN_G(upload_allow_utf8)) { | 245 | if ((*cp & 0x80) && SUHOSIN_G(upload_allow_utf8)) { |
| 240 | SDEBUG("checking char %x", *cp); | 246 | SDEBUG("checking char %x", *cp); |
| 241 | if ((n = suhosin_validate_utf8_multibyte(cp))) { // valid UTF8 multibyte character | 247 | if ((n = suhosin_validate_utf8_multibyte(cp, cpend-cp))) { // valid UTF8 multibyte character |
| 242 | cp += n - 1; | 248 | cp += n - 1; |
| 243 | continue; | 249 | continue; |
| 244 | } | 250 | } |
| 245 | } | 251 | } |
| 246 | 252 | #endif | |
| 247 | suhosin_log(S_FILES, "uploaded file contains binary data - file dropped"); | 253 | suhosin_log(S_FILES, "uploaded file contains binary data - file dropped"); |
| 248 | if (!SUHOSIN_G(simulation)) { | 254 | if (!SUHOSIN_G(simulation)) { |
| 249 | goto continue_with_failure; | 255 | goto continue_with_failure; |
| @@ -261,15 +267,17 @@ int suhosin_rfc1867_filter(unsigned int event, void *event_data, void **extra TS | |||
| 261 | for (i=0, j=0; i<mefd->length; i++) { | 267 | for (i=0, j=0; i<mefd->length; i++) { |
| 262 | if (mefd->data[i] >= 32 || isspace(mefd->data[i])) { | 268 | if (mefd->data[i] >= 32 || isspace(mefd->data[i])) { |
| 263 | mefd->data[j++] = mefd->data[i]; | 269 | mefd->data[j++] = mefd->data[i]; |
| 264 | } else if (SUHOSIN_G(upload_allow_utf8) && mefd->data[i] & 0x80) { | 270 | } |
| 265 | n = suhosin_validate_utf8_multibyte(mefd->data + i); | 271 | #ifdef SUHOSIN_EXPERIMENTAL |
| 272 | else if (SUHOSIN_G(upload_allow_utf8) && mefd->data[i] & 0x80) { | ||
| 273 | n = suhosin_validate_utf8_multibyte(mefd->data + i, mefd->length - i); | ||
| 266 | if (!n) { continue; } | 274 | if (!n) { continue; } |
| 267 | while (n) { | 275 | while (n--) { |
| 268 | mefd->data[j++] = mefd->data[i++]; | 276 | mefd->data[j++] = mefd->data[i++]; |
| 269 | n--; | ||
| 270 | } | 277 | } |
| 271 | i--; | 278 | i--; |
| 272 | } | 279 | } |
| 280 | #endif | ||
| 273 | } | 281 | } |
| 274 | mefd->data[j] = '\0'; | 282 | mefd->data[j] = '\0'; |
| 275 | 283 | ||
