diff options
| author | jvoisin | 2018-07-09 07:37:58 +0000 |
|---|---|---|
| committer | xXx-caillou-xXx | 2018-07-09 09:37:58 +0200 |
| commit | 5da3a92492bf169e62367d954cfa7432bee51fed (patch) | |
| tree | 2e094ed1a5a8400269c48c520539b7dac28ced27 | |
| parent | ca3be84076521c4bb053511775c94c0b195aeac8 (diff) | |
Trying to fix sloppy comparison (#186)
* Trying to fix sloppy comparison https://github.com/nbs-system/snuffleupagus/issues/10 by
modifying php's opcode
| -rw-r--r-- | doc/source/config.rst | 13 | ||||
| -rw-r--r-- | src/config.m4 | 2 | ||||
| -rw-r--r-- | src/php_snuffleupagus.h | 1 | ||||
| -rw-r--r-- | src/snuffleupagus.c | 5 | ||||
| -rw-r--r-- | src/sp_config.c | 1 | ||||
| -rw-r--r-- | src/sp_config.h | 4 | ||||
| -rw-r--r-- | src/sp_config_keywords.c | 5 | ||||
| -rw-r--r-- | src/sp_config_keywords.h | 1 | ||||
| -rw-r--r-- | src/sp_execute.c | 1 | ||||
| -rw-r--r-- | src/sp_sloppy.c | 39 | ||||
| -rw-r--r-- | src/sp_sloppy.h | 8 | ||||
| -rw-r--r-- | src/tests/config/sloppy_comparison.ini | 1 | ||||
| -rw-r--r-- | src/tests/sloppy_comparison.phpt | 30 | ||||
| -rw-r--r-- | src/tests/sloppy_comparison_disable.phpt | 14 |
14 files changed, 124 insertions, 1 deletions
diff --git a/doc/source/config.rst b/doc/source/config.rst index b5bcad4..0186b4a 100644 --- a/doc/source/config.rst +++ b/doc/source/config.rst | |||
| @@ -106,6 +106,19 @@ It can either be ``enabled`` or ``disabled``. | |||
| 106 | 106 | ||
| 107 | .. _config_global: | 107 | .. _config_global: |
| 108 | 108 | ||
| 109 | Prevent sloppy comparison | ||
| 110 | ^^^^^^^^^^^^^^^^ | ||
| 111 | |||
| 112 | sloppy_comparison, disabled by default, will prevent php `type | ||
| 113 | juggling <https://secure.php.net/manual/en/language.types.type-juggling.php>`_ (``==``) , preventing any bypass of a comparison. | ||
| 114 | |||
| 115 | It can either be ``enabled`` or ``disabled``. | ||
| 116 | |||
| 117 | :: | ||
| 118 | |||
| 119 | sp.sloppy_comparison.enable(); | ||
| 120 | sp.sloppy_comparison.disable(); | ||
| 121 | |||
| 109 | unserialize_hmac | 122 | unserialize_hmac |
| 110 | ^^^^^^^^^^^^^^^^ | 123 | ^^^^^^^^^^^^^^^^ |
| 111 | 124 | ||
diff --git a/src/config.m4 b/src/config.m4 index a4fea4d..0165f87 100644 --- a/src/config.m4 +++ b/src/config.m4 | |||
| @@ -6,7 +6,7 @@ sources="$sources sp_unserialize.c sp_utils.c sp_disable_xxe.c sp_list.c" | |||
| 6 | sources="$sources sp_disabled_functions.c sp_execute.c sp_upload_validation.c" | 6 | sources="$sources sp_disabled_functions.c sp_execute.c sp_upload_validation.c" |
| 7 | sources="$sources sp_cookie_encryption.c sp_network_utils.c tweetnacl.c" | 7 | sources="$sources sp_cookie_encryption.c sp_network_utils.c tweetnacl.c" |
| 8 | sources="$sources sp_config_keywords.c sp_var_parser.c sp_var_value.c sp_tree.c" | 8 | sources="$sources sp_config_keywords.c sp_var_parser.c sp_var_value.c sp_tree.c" |
| 9 | sources="$sources sp_pcre_compat.c sp_crypt.c sp_session.c" | 9 | sources="$sources sp_pcre_compat.c sp_crypt.c sp_session.c sp_sloppy.c" |
| 10 | 10 | ||
| 11 | PHP_ARG_ENABLE(snuffleupagus, whether to enable snuffleupagus support, | 11 | PHP_ARG_ENABLE(snuffleupagus, whether to enable snuffleupagus support, |
| 12 | [ --enable-snuffleupagus Enable snuffleupagus support]) | 12 | [ --enable-snuffleupagus Enable snuffleupagus support]) |
diff --git a/src/php_snuffleupagus.h b/src/php_snuffleupagus.h index f80ae66..008a480 100644 --- a/src/php_snuffleupagus.h +++ b/src/php_snuffleupagus.h | |||
| @@ -43,6 +43,7 @@ | |||
| 43 | #include "sp_utils.h" | 43 | #include "sp_utils.h" |
| 44 | #include "sp_crypt.h" | 44 | #include "sp_crypt.h" |
| 45 | #include "sp_session.h" | 45 | #include "sp_session.h" |
| 46 | #include "sp_sloppy.h" | ||
| 46 | 47 | ||
| 47 | 48 | ||
| 48 | extern zend_module_entry snuffleupagus_module_entry; | 49 | extern zend_module_entry snuffleupagus_module_entry; |
diff --git a/src/snuffleupagus.c b/src/snuffleupagus.c index c3fc686..08b2083 100644 --- a/src/snuffleupagus.c +++ b/src/snuffleupagus.c | |||
| @@ -72,6 +72,7 @@ PHP_GINIT_FUNCTION(snuffleupagus) { | |||
| 72 | 72 | ||
| 73 | SP_INIT(snuffleupagus_globals->config.config_unserialize); | 73 | SP_INIT(snuffleupagus_globals->config.config_unserialize); |
| 74 | SP_INIT(snuffleupagus_globals->config.config_random); | 74 | SP_INIT(snuffleupagus_globals->config.config_random); |
| 75 | SP_INIT(snuffleupagus_globals->config.config_sloppy); | ||
| 75 | SP_INIT(snuffleupagus_globals->config.config_readonly_exec); | 76 | SP_INIT(snuffleupagus_globals->config.config_readonly_exec); |
| 76 | SP_INIT(snuffleupagus_globals->config.config_global_strict); | 77 | SP_INIT(snuffleupagus_globals->config.config_global_strict); |
| 77 | SP_INIT(snuffleupagus_globals->config.config_auto_cookie_secure); | 78 | SP_INIT(snuffleupagus_globals->config.config_auto_cookie_secure); |
| @@ -212,6 +213,10 @@ static PHP_INI_MH(OnUpdateConfiguration) { | |||
| 212 | 213 | ||
| 213 | SNUFFLEUPAGUS_G(is_config_valid) = true; | 214 | SNUFFLEUPAGUS_G(is_config_valid) = true; |
| 214 | 215 | ||
| 216 | if ((SNUFFLEUPAGUS_G(config).config_sloppy->enable)) { | ||
| 217 | hook_sloppy(); | ||
| 218 | } | ||
| 219 | |||
| 215 | if (SNUFFLEUPAGUS_G(config).config_random->enable) { | 220 | if (SNUFFLEUPAGUS_G(config).config_random->enable) { |
| 216 | hook_rand(); | 221 | hook_rand(); |
| 217 | } | 222 | } |
diff --git a/src/sp_config.c b/src/sp_config.c index a89174a..eb5b324 100644 --- a/src/sp_config.c +++ b/src/sp_config.c | |||
| @@ -22,6 +22,7 @@ sp_config_tokens const sp_func[] = { | |||
| 22 | {.func = parse_eval_blacklist, .token = SP_TOKEN_EVAL_BLACKLIST}, | 22 | {.func = parse_eval_blacklist, .token = SP_TOKEN_EVAL_BLACKLIST}, |
| 23 | {.func = parse_eval_whitelist, .token = SP_TOKEN_EVAL_WHITELIST}, | 23 | {.func = parse_eval_whitelist, .token = SP_TOKEN_EVAL_WHITELIST}, |
| 24 | {.func = parse_session, .token = SP_TOKEN_SESSION_ENCRYPTION}, | 24 | {.func = parse_session, .token = SP_TOKEN_SESSION_ENCRYPTION}, |
| 25 | {.func = parse_sloppy_comparison, .token = SP_TOKEN_SLOPPY_COMPARISON}, | ||
| 25 | {NULL, NULL}}; | 26 | {NULL, NULL}}; |
| 26 | 27 | ||
| 27 | /* Top level keyword parsing */ | 28 | /* Top level keyword parsing */ |
diff --git a/src/sp_config.h b/src/sp_config.h index b44960f..979feda 100644 --- a/src/sp_config.h +++ b/src/sp_config.h | |||
| @@ -53,6 +53,8 @@ typedef struct { bool enable; } sp_config_global_strict; | |||
| 53 | 53 | ||
| 54 | typedef struct { bool enable; } sp_config_random; | 54 | typedef struct { bool enable; } sp_config_random; |
| 55 | 55 | ||
| 56 | typedef struct { bool enable; } sp_config_sloppy; | ||
| 57 | |||
| 56 | typedef struct { bool enable; } sp_config_auto_cookie_secure; | 58 | typedef struct { bool enable; } sp_config_auto_cookie_secure; |
| 57 | 59 | ||
| 58 | typedef struct { bool enable; } sp_config_disable_xxe; | 60 | typedef struct { bool enable; } sp_config_disable_xxe; |
| @@ -151,6 +153,7 @@ typedef struct { | |||
| 151 | 153 | ||
| 152 | typedef struct { | 154 | typedef struct { |
| 153 | sp_config_random *config_random; | 155 | sp_config_random *config_random; |
| 156 | sp_config_sloppy *config_sloppy; | ||
| 154 | sp_config_unserialize *config_unserialize; | 157 | sp_config_unserialize *config_unserialize; |
| 155 | sp_config_disabled_functions *config_disabled_functions; | 158 | sp_config_disabled_functions *config_disabled_functions; |
| 156 | sp_config_disabled_functions *config_disabled_functions_ret; | 159 | sp_config_disabled_functions *config_disabled_functions_ret; |
| @@ -192,6 +195,7 @@ typedef struct { | |||
| 192 | #define SP_TOKEN_DISABLE_XXE ".disable_xxe" | 195 | #define SP_TOKEN_DISABLE_XXE ".disable_xxe" |
| 193 | #define SP_TOKEN_EVAL_BLACKLIST ".eval_blacklist" | 196 | #define SP_TOKEN_EVAL_BLACKLIST ".eval_blacklist" |
| 194 | #define SP_TOKEN_EVAL_WHITELIST ".eval_whitelist" | 197 | #define SP_TOKEN_EVAL_WHITELIST ".eval_whitelist" |
| 198 | #define SP_TOKEN_SLOPPY_COMPARISON ".sloppy_comparison" | ||
| 195 | 199 | ||
| 196 | // common tokens | 200 | // common tokens |
| 197 | #define SP_TOKEN_ENABLE ".enable(" | 201 | #define SP_TOKEN_ENABLE ".enable(" |
diff --git a/src/sp_config_keywords.c b/src/sp_config_keywords.c index cc1f0f9..2a570cd 100644 --- a/src/sp_config_keywords.c +++ b/src/sp_config_keywords.c | |||
| @@ -105,6 +105,11 @@ int parse_random(char *line) { | |||
| 105 | NULL); | 105 | NULL); |
| 106 | } | 106 | } |
| 107 | 107 | ||
| 108 | int parse_sloppy_comparison(char *line) { | ||
| 109 | return parse_enable(line, &(SNUFFLEUPAGUS_G(config).config_sloppy->enable), | ||
| 110 | NULL); | ||
| 111 | } | ||
| 112 | |||
| 108 | int parse_disable_xxe(char *line) { | 113 | int parse_disable_xxe(char *line) { |
| 109 | return parse_enable( | 114 | return parse_enable( |
| 110 | line, &(SNUFFLEUPAGUS_G(config).config_disable_xxe->enable), NULL); | 115 | line, &(SNUFFLEUPAGUS_G(config).config_disable_xxe->enable), NULL); |
diff --git a/src/sp_config_keywords.h b/src/sp_config_keywords.h index f1f414a..36c66a5 100644 --- a/src/sp_config_keywords.h +++ b/src/sp_config_keywords.h | |||
| @@ -15,5 +15,6 @@ int parse_upload_validation(char *line); | |||
| 15 | int parse_eval_blacklist(char *line); | 15 | int parse_eval_blacklist(char *line); |
| 16 | int parse_eval_whitelist(char *line); | 16 | int parse_eval_whitelist(char *line); |
| 17 | int parse_session(char *line); | 17 | int parse_session(char *line); |
| 18 | int parse_sloppy_comparison(char *line); | ||
| 18 | 19 | ||
| 19 | #endif // __SP_CONFIG_KEYWORDS_H | 20 | #endif // __SP_CONFIG_KEYWORDS_H |
diff --git a/src/sp_execute.c b/src/sp_execute.c index ef71227..fb956ca 100644 --- a/src/sp_execute.c +++ b/src/sp_execute.c | |||
| @@ -1,4 +1,5 @@ | |||
| 1 | #include "php_snuffleupagus.h" | 1 | #include "php_snuffleupagus.h" |
| 2 | #include "zend_vm.h" | ||
| 2 | #include <errno.h> | 3 | #include <errno.h> |
| 3 | #include <string.h> | 4 | #include <string.h> |
| 4 | 5 | ||
diff --git a/src/sp_sloppy.c b/src/sp_sloppy.c new file mode 100644 index 0000000..05d2505 --- /dev/null +++ b/src/sp_sloppy.c | |||
| @@ -0,0 +1,39 @@ | |||
| 1 | #include "sp_sloppy.h" | ||
| 2 | |||
| 3 | ZEND_API zend_op_array* (*zend_compile_file_default)(zend_file_handle* file_handle, int type) = NULL; | ||
| 4 | ZEND_API zend_op_array* (*zend_compile_string_default)(zval* source_string, char* filename) = NULL; | ||
| 5 | |||
| 6 | static void modify_opcode(zend_op_array* opline) { | ||
| 7 | if (NULL != opline) { | ||
| 8 | zend_op* orig_opline = opline->opcodes; | ||
| 9 | for (; NULL != orig_opline->handler; orig_opline++) { | ||
| 10 | if (orig_opline->opcode == ZEND_IS_EQUAL) { | ||
| 11 | orig_opline->opcode = ZEND_IS_IDENTICAL; | ||
| 12 | zend_vm_set_opcode_handler(orig_opline); | ||
| 13 | } else if (orig_opline->opcode == ZEND_IS_NOT_EQUAL) { | ||
| 14 | orig_opline->opcode = ZEND_IS_NOT_IDENTICAL; | ||
| 15 | zend_vm_set_opcode_handler(orig_opline); | ||
| 16 | } | ||
| 17 | } | ||
| 18 | } | ||
| 19 | } | ||
| 20 | |||
| 21 | ZEND_API zend_op_array* sp_compile_string(zval* source_string, char* filename) { | ||
| 22 | zend_op_array* opline = zend_compile_string_default(source_string, filename); | ||
| 23 | modify_opcode(opline); | ||
| 24 | return opline; | ||
| 25 | } | ||
| 26 | |||
| 27 | ZEND_API zend_op_array* sp_compile_file(zend_file_handle* file_handle, int type) { | ||
| 28 | zend_op_array* opline = zend_compile_file_default(file_handle, type); | ||
| 29 | modify_opcode(opline); | ||
| 30 | return opline; | ||
| 31 | } | ||
| 32 | |||
| 33 | void hook_sloppy() { | ||
| 34 | zend_compile_file_default = zend_compile_file; | ||
| 35 | zend_compile_file = sp_compile_file; | ||
| 36 | |||
| 37 | zend_compile_string_default = zend_compile_string; | ||
| 38 | zend_compile_string = sp_compile_string; | ||
| 39 | } | ||
diff --git a/src/sp_sloppy.h b/src/sp_sloppy.h new file mode 100644 index 0000000..c01b77c --- /dev/null +++ b/src/sp_sloppy.h | |||
| @@ -0,0 +1,8 @@ | |||
| 1 | #ifndef SP_SLOPPY_H | ||
| 2 | #define SP_SLOPPY_H | ||
| 3 | #include "php_snuffleupagus.h" | ||
| 4 | #include "zend_vm.h" | ||
| 5 | |||
| 6 | void hook_sloppy(); | ||
| 7 | |||
| 8 | #endif | ||
diff --git a/src/tests/config/sloppy_comparison.ini b/src/tests/config/sloppy_comparison.ini new file mode 100644 index 0000000..ab2d32a --- /dev/null +++ b/src/tests/config/sloppy_comparison.ini | |||
| @@ -0,0 +1 @@ | |||
| sp.sloppy_comparison.enable(); | |||
diff --git a/src/tests/sloppy_comparison.phpt b/src/tests/sloppy_comparison.phpt new file mode 100644 index 0000000..da28e3d --- /dev/null +++ b/src/tests/sloppy_comparison.phpt | |||
| @@ -0,0 +1,30 @@ | |||
| 1 | --TEST-- | ||
| 2 | Sloppy comparison | ||
| 3 | --SKIPIF-- | ||
| 4 | <?php if (!extension_loaded("snuffleupagus")) print "skip"; ?> | ||
| 5 | --INI-- | ||
| 6 | sp.configuration_file={PWD}/config/sloppy_comparison.ini | ||
| 7 | --FILE-- | ||
| 8 | <?php | ||
| 9 | $qwe = "abc"; | ||
| 10 | if ($qwe == 0) { | ||
| 11 | echo "failed"; | ||
| 12 | } | ||
| 13 | $qwe = "0e123"; | ||
| 14 | if ("0e432" == $qwe) { | ||
| 15 | echo "failed"; | ||
| 16 | } | ||
| 17 | $qwe = []; | ||
| 18 | $test = false; | ||
| 19 | if ($test != $qwe) { | ||
| 20 | echo "lol"; | ||
| 21 | } | ||
| 22 | eval(" | ||
| 23 | \$asd = 'qwe'; | ||
| 24 | if (\$asd == 0) { | ||
| 25 | echo 'oops'; | ||
| 26 | } | ||
| 27 | "); | ||
| 28 | ?> | ||
| 29 | --EXPECT-- | ||
| 30 | lol | ||
diff --git a/src/tests/sloppy_comparison_disable.phpt b/src/tests/sloppy_comparison_disable.phpt new file mode 100644 index 0000000..f22804b --- /dev/null +++ b/src/tests/sloppy_comparison_disable.phpt | |||
| @@ -0,0 +1,14 @@ | |||
| 1 | --TEST-- | ||
| 2 | Sloppy comparison | ||
| 3 | --SKIPIF-- | ||
| 4 | <?php if (!extension_loaded("snuffleupagus")) print "skip"; ?> | ||
| 5 | --INI-- | ||
| 6 | --FILE-- | ||
| 7 | <?php | ||
| 8 | $qwe = "abc"; | ||
| 9 | if ($qwe == 0) { | ||
| 10 | echo "OK"; | ||
| 11 | } | ||
| 12 | ?> | ||
| 13 | --EXPECT-- | ||
| 14 | OK | ||
