diff options
| author | Julien Voisin | 2022-12-08 20:59:29 +0100 |
|---|---|---|
| committer | GitHub | 2022-12-08 20:59:29 +0100 |
| commit | 93c2c5632e27549d95fb7d9493769f013e49a749 (patch) | |
| tree | 97dcd84aed33b1d98095d0cf3f467e9dfb975f0c | |
| parent | 3134f49d4de12d1e2507272e0e5022bdf5d60093 (diff) | |
| parent | ccfaf3e4713b1878241f1235a6fcb66ad0582d47 (diff) | |
Add an `unserialize_noclass` option
| -rw-r--r-- | doc/source/config.rst | 14 | ||||
| -rw-r--r-- | doc/source/features.rst | 2 | ||||
| -rw-r--r-- | src/php_snuffleupagus.h | 1 | ||||
| -rw-r--r-- | src/snuffleupagus.c | 8 | ||||
| -rw-r--r-- | src/sp_config.c | 1 | ||||
| -rw-r--r-- | src/sp_config.h | 6 | ||||
| -rw-r--r-- | src/sp_config_keywords.c | 18 | ||||
| -rw-r--r-- | src/sp_config_keywords.h | 1 | ||||
| -rw-r--r-- | src/sp_unserialize.c | 37 | ||||
| -rw-r--r-- | src/tests/unserialize/config/config_serialize_noclass.ini | 1 | ||||
| -rw-r--r-- | src/tests/unserialize/unserialize_noclass_forced.phpt | 21 | ||||
| -rw-r--r-- | src/tests/unserialize/unserialize_wrong_call.phpt | 2 | ||||
| -rw-r--r-- | src/tests/unserialize_php8/config/config_serialize_noclass.ini | 1 | ||||
| -rw-r--r-- | src/tests/unserialize_php8/config/config_serialize_noclass_disabled.ini | 1 | ||||
| -rw-r--r-- | src/tests/unserialize_php8/unserialize_noclass_forced.phpt | 38 | ||||
| -rw-r--r-- | src/tests/unserialize_php8/unserialize_noclass_forced_disabled.phpt | 35 |
16 files changed, 171 insertions, 16 deletions
diff --git a/doc/source/config.rst b/doc/source/config.rst index 9d2d0ed..bce4667 100644 --- a/doc/source/config.rst +++ b/doc/source/config.rst | |||
| @@ -202,6 +202,20 @@ It can either be ``enabled`` or ``disabled``. | |||
| 202 | sp.sloppy_comparison.enable(); | 202 | sp.sloppy_comparison.enable(); |
| 203 | sp.sloppy_comparison.disable(); | 203 | sp.sloppy_comparison.disable(); |
| 204 | 204 | ||
| 205 | unserialize_noclass | ||
| 206 | ^^^^^^^^^^^^^^^^^^^ | ||
| 207 | |||
| 208 | :ref:`unserialize_noclass <unserialize-feature>`, available only on PHP8+ and | ||
| 209 | disabled by default, will disable the deserialization of objects via | ||
| 210 | ``unserialize``. It's equivalent to setting the ``options`` parameter of | ||
| 211 | ``unserialize`` to ``false``, on every call. It can either be ``enabled`` or | ||
| 212 | ``disabled``. | ||
| 213 | |||
| 214 | :: | ||
| 215 | |||
| 216 | sp.unserialize_noclass.enable(); | ||
| 217 | sp.unserialize_noclass.disable(); | ||
| 218 | |||
| 205 | unserialize_hmac | 219 | unserialize_hmac |
| 206 | ^^^^^^^^^^^^^^^^ | 220 | ^^^^^^^^^^^^^^^^ |
| 207 | 221 | ||
diff --git a/doc/source/features.rst b/doc/source/features.rst index 25fd62d..60dbbef 100644 --- a/doc/source/features.rst +++ b/doc/source/features.rst | |||
| @@ -166,6 +166,8 @@ CVE-2016-9138 <https://bugs.php.net/bug.php?id=73147>`_, `2016-7124 | |||
| 166 | <https://bugs.php.net/bug.php?id=72663>`_, `CVE-2016-5771 and CVE-2016-5773 | 166 | <https://bugs.php.net/bug.php?id=72663>`_, `CVE-2016-5771 and CVE-2016-5773 |
| 167 | <https://www.evonide.com/how-we-broke-php-hacked-pornhub-and-earned-20000-dollar/>`_. | 167 | <https://www.evonide.com/how-we-broke-php-hacked-pornhub-and-earned-20000-dollar/>`_. |
| 168 | 168 | ||
| 169 | A less subtle mitigation can be used to simply prevent the deserialization of objects altogether. | ||
| 170 | |||
| 169 | 171 | ||
| 170 | Examples of related vulnerabilities | 172 | Examples of related vulnerabilities |
| 171 | """"""""""""""""""""""""""""""""""" | 173 | """"""""""""""""""""""""""""""""""" |
diff --git a/src/php_snuffleupagus.h b/src/php_snuffleupagus.h index 7c534a8..2117462 100644 --- a/src/php_snuffleupagus.h +++ b/src/php_snuffleupagus.h | |||
| @@ -119,6 +119,7 @@ ZEND_BEGIN_MODULE_GLOBALS(snuffleupagus) | |||
| 119 | sp_config_random config_random; | 119 | sp_config_random config_random; |
| 120 | sp_config_sloppy config_sloppy; | 120 | sp_config_sloppy config_sloppy; |
| 121 | sp_config_unserialize config_unserialize; | 121 | sp_config_unserialize config_unserialize; |
| 122 | sp_config_unserialize_noclass config_unserialize_noclass; | ||
| 122 | sp_config_readonly_exec config_readonly_exec; | 123 | sp_config_readonly_exec config_readonly_exec; |
| 123 | sp_config_upload_validation config_upload_validation; | 124 | sp_config_upload_validation config_upload_validation; |
| 124 | sp_config_cookie config_cookie; | 125 | sp_config_cookie config_cookie; |
diff --git a/src/snuffleupagus.c b/src/snuffleupagus.c index be6240e..8454fc1 100644 --- a/src/snuffleupagus.c +++ b/src/snuffleupagus.c | |||
| @@ -332,6 +332,8 @@ static void dump_config() { | |||
| 332 | array_init(&arr); | 332 | array_init(&arr); |
| 333 | add_assoc_string(&arr, "version", PHP_SNUFFLEUPAGUS_VERSION); | 333 | add_assoc_string(&arr, "version", PHP_SNUFFLEUPAGUS_VERSION); |
| 334 | 334 | ||
| 335 | add_assoc_bool(&arr, SP_TOKEN_UNSERIALIZE_NOCLASS "." SP_TOKEN_ENABLE, SPCFG(unserialize_noclass).enable); | ||
| 336 | |||
| 335 | add_assoc_bool(&arr, SP_TOKEN_UNSERIALIZE_HMAC "." SP_TOKEN_ENABLE, SPCFG(unserialize).enable); | 337 | add_assoc_bool(&arr, SP_TOKEN_UNSERIALIZE_HMAC "." SP_TOKEN_ENABLE, SPCFG(unserialize).enable); |
| 336 | add_assoc_bool(&arr, SP_TOKEN_UNSERIALIZE_HMAC "." SP_TOKEN_SIM, SPCFG(unserialize).simulation); | 338 | add_assoc_bool(&arr, SP_TOKEN_UNSERIALIZE_HMAC "." SP_TOKEN_SIM, SPCFG(unserialize).simulation); |
| 337 | ADD_ASSOC_ZSTR(&arr, SP_TOKEN_UNSERIALIZE_HMAC "." SP_TOKEN_DUMP, SPCFG(unserialize).dump); | 339 | ADD_ASSOC_ZSTR(&arr, SP_TOKEN_UNSERIALIZE_HMAC "." SP_TOKEN_DUMP, SPCFG(unserialize).dump); |
| @@ -562,10 +564,8 @@ static PHP_INI_MH(OnUpdateConfiguration) { | |||
| 562 | hook_session(); | 564 | hook_session(); |
| 563 | } | 565 | } |
| 564 | 566 | ||
| 565 | if (NULL != SPCFG(encryption_key)) { | 567 | if ((NULL != SPCFG(encryption_key) && SPCFG(unserialize).enable) || SPCFG(unserialize_noclass).enable) { |
| 566 | if (SPCFG(unserialize).enable) { | 568 | hook_serialize(); |
| 567 | hook_serialize(); | ||
| 568 | } | ||
| 569 | } | 569 | } |
| 570 | 570 | ||
| 571 | hook_execute(); | 571 | hook_execute(); |
diff --git a/src/sp_config.c b/src/sp_config.c index dbccb1a..8bd238a 100644 --- a/src/sp_config.c +++ b/src/sp_config.c | |||
| @@ -8,6 +8,7 @@ | |||
| 8 | static zend_result sp_process_config_root(sp_parsed_keyword *parsed_rule) { | 8 | static zend_result sp_process_config_root(sp_parsed_keyword *parsed_rule) { |
| 9 | sp_config_keyword sp_func[] = { | 9 | sp_config_keyword sp_func[] = { |
| 10 | {parse_unserialize, SP_TOKEN_UNSERIALIZE_HMAC, &(SPCFG(unserialize))}, | 10 | {parse_unserialize, SP_TOKEN_UNSERIALIZE_HMAC, &(SPCFG(unserialize))}, |
| 11 | {parse_unserialize_noclass, SP_TOKEN_UNSERIALIZE_NOCLASS, &(SPCFG(unserialize_noclass))}, | ||
| 11 | {parse_enable, SP_TOKEN_HARDEN_RANDOM, &(SPCFG(random).enable)}, | 12 | {parse_enable, SP_TOKEN_HARDEN_RANDOM, &(SPCFG(random).enable)}, |
| 12 | {parse_log_media, SP_TOKEN_LOG_MEDIA, &(SPCFG(log_media))}, | 13 | {parse_log_media, SP_TOKEN_LOG_MEDIA, &(SPCFG(log_media))}, |
| 13 | {parse_disabled_functions, SP_TOKEN_DISABLE_FUNC, NULL}, | 14 | {parse_disabled_functions, SP_TOKEN_DISABLE_FUNC, NULL}, |
diff --git a/src/sp_config.h b/src/sp_config.h index ec73310..cddf816 100644 --- a/src/sp_config.h +++ b/src/sp_config.h | |||
| @@ -83,6 +83,11 @@ typedef struct { | |||
| 83 | 83 | ||
| 84 | typedef struct { | 84 | typedef struct { |
| 85 | bool enable; | 85 | bool enable; |
| 86 | zend_string *textual_representation; | ||
| 87 | } sp_config_unserialize_noclass; | ||
| 88 | |||
| 89 | typedef struct { | ||
| 90 | bool enable; | ||
| 86 | bool simulation; | 91 | bool simulation; |
| 87 | zend_string *dump; | 92 | zend_string *dump; |
| 88 | zend_string *textual_representation; | 93 | zend_string *textual_representation; |
| @@ -202,6 +207,7 @@ typedef struct { | |||
| 202 | #define SP_TOKEN_HARDEN_RANDOM "harden_random" | 207 | #define SP_TOKEN_HARDEN_RANDOM "harden_random" |
| 203 | #define SP_TOKEN_READONLY_EXEC "readonly_exec" | 208 | #define SP_TOKEN_READONLY_EXEC "readonly_exec" |
| 204 | #define SP_TOKEN_UNSERIALIZE_HMAC "unserialize_hmac" | 209 | #define SP_TOKEN_UNSERIALIZE_HMAC "unserialize_hmac" |
| 210 | #define SP_TOKEN_UNSERIALIZE_NOCLASS "unserialize_noclass" | ||
| 205 | #define SP_TOKEN_UPLOAD_VALIDATION "upload_validation" | 211 | #define SP_TOKEN_UPLOAD_VALIDATION "upload_validation" |
| 206 | #define SP_TOKEN_XXE_PROTECTION "xxe_protection" | 212 | #define SP_TOKEN_XXE_PROTECTION "xxe_protection" |
| 207 | #define SP_TOKEN_EVAL_BLACKLIST "eval_blacklist" | 213 | #define SP_TOKEN_EVAL_BLACKLIST "eval_blacklist" |
diff --git a/src/sp_config_keywords.c b/src/sp_config_keywords.c index fa26635..ff834dd 100644 --- a/src/sp_config_keywords.c +++ b/src/sp_config_keywords.c | |||
| @@ -74,6 +74,24 @@ SP_PARSEKW_FN(parse_log_media) { | |||
| 74 | return SP_PARSER_ERROR; | 74 | return SP_PARSER_ERROR; |
| 75 | } | 75 | } |
| 76 | 76 | ||
| 77 | SP_PARSE_FN(parse_unserialize_noclass) { | ||
| 78 | bool enable = false, disable = false; | ||
| 79 | sp_config_unserialize_noclass *cfg = (sp_config_unserialize_noclass*)retval; | ||
| 80 | |||
| 81 | sp_config_keyword config_keywords[] = { | ||
| 82 | {parse_empty, SP_TOKEN_ENABLE, &(enable)}, | ||
| 83 | {parse_empty, SP_TOKEN_DISABLE, &(disable)}, | ||
| 84 | {0, 0, 0}}; | ||
| 85 | |||
| 86 | SP_PROCESS_CONFIG_KEYWORDS_ERR(); | ||
| 87 | |||
| 88 | SP_SET_ENABLE_DISABLE(enable, disable, cfg->enable); | ||
| 89 | |||
| 90 | cfg->textual_representation = sp_get_textual_representation(parsed_rule); | ||
| 91 | |||
| 92 | return SP_PARSER_STOP; | ||
| 93 | } | ||
| 94 | |||
| 77 | SP_PARSE_FN(parse_unserialize) { | 95 | SP_PARSE_FN(parse_unserialize) { |
| 78 | bool enable = false, disable = false; | 96 | bool enable = false, disable = false; |
| 79 | sp_config_unserialize *cfg = (sp_config_unserialize*)retval; | 97 | sp_config_unserialize *cfg = (sp_config_unserialize*)retval; |
diff --git a/src/sp_config_keywords.h b/src/sp_config_keywords.h index 01eb0d1..27050e3 100644 --- a/src/sp_config_keywords.h +++ b/src/sp_config_keywords.h | |||
| @@ -6,6 +6,7 @@ SP_PARSE_FN(parse_enable); | |||
| 6 | SP_PARSE_FN(parse_global); | 6 | SP_PARSE_FN(parse_global); |
| 7 | SP_PARSE_FN(parse_cookie); | 7 | SP_PARSE_FN(parse_cookie); |
| 8 | SP_PARSE_FN(parse_unserialize); | 8 | SP_PARSE_FN(parse_unserialize); |
| 9 | SP_PARSE_FN(parse_unserialize_noclass); | ||
| 9 | SP_PARSE_FN(parse_readonly_exec); | 10 | SP_PARSE_FN(parse_readonly_exec); |
| 10 | SP_PARSE_FN(parse_disabled_functions); | 11 | SP_PARSE_FN(parse_disabled_functions); |
| 11 | SP_PARSE_FN(parse_upload_validation); | 12 | SP_PARSE_FN(parse_upload_validation); |
diff --git a/src/sp_unserialize.c b/src/sp_unserialize.c index 64cf1b5..641d989 100644 --- a/src/sp_unserialize.c +++ b/src/sp_unserialize.c | |||
| @@ -61,6 +61,10 @@ PHP_FUNCTION(sp_serialize) { | |||
| 61 | orig_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU); | 61 | orig_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU); |
| 62 | } | 62 | } |
| 63 | 63 | ||
| 64 | if (!SPCFG(unserialize).enable) { | ||
| 65 | return; | ||
| 66 | } | ||
| 67 | |||
| 64 | /* Compute the HMAC of the textual representation of the serialized data*/ | 68 | /* Compute the HMAC of the textual representation of the serialized data*/ |
| 65 | zend_string *hmac = sp_do_hash_hmac_sha256(Z_STRVAL_P(return_value), Z_STRLEN_P(return_value), ZSTR_VAL(SPCFG(encryption_key)), ZSTR_LEN(SPCFG(encryption_key))); | 69 | zend_string *hmac = sp_do_hash_hmac_sha256(Z_STRVAL_P(return_value), Z_STRLEN_P(return_value), ZSTR_VAL(SPCFG(encryption_key)), ZSTR_LEN(SPCFG(encryption_key))); |
| 66 | 70 | ||
| @@ -84,19 +88,28 @@ PHP_FUNCTION(sp_serialize) { | |||
| 84 | } | 88 | } |
| 85 | 89 | ||
| 86 | PHP_FUNCTION(sp_unserialize) { | 90 | PHP_FUNCTION(sp_unserialize) { |
| 87 | zif_handler orig_handler; | ||
| 88 | |||
| 89 | char *buf = NULL; | 91 | char *buf = NULL; |
| 90 | char *serialized_str = NULL; | ||
| 91 | char *hmac = NULL; | ||
| 92 | size_t buf_len = 0; | 92 | size_t buf_len = 0; |
| 93 | zval *opts = NULL; | 93 | HashTable *opts = NULL; |
| 94 | 94 | ||
| 95 | const sp_config_unserialize *config_unserialize = &(SPCFG(unserialize)); | 95 | ZEND_PARSE_PARAMETERS_START(1, 2) |
| 96 | Z_PARAM_STRING(buf, buf_len) | ||
| 97 | Z_PARAM_OPTIONAL | ||
| 98 | Z_PARAM_ARRAY_HT(opts) | ||
| 99 | ZEND_PARSE_PARAMETERS_END(); | ||
| 96 | 100 | ||
| 97 | if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|a", &buf, &buf_len, &opts) == | 101 | if (SPCFG(unserialize_noclass).enable) { |
| 98 | FAILURE) { | 102 | #if PHP_VERSION_ID > 80000 |
| 99 | RETURN_FALSE; | 103 | HashTable ht; |
| 104 | zend_hash_init(&ht, 1, NULL, NULL, 0); | ||
| 105 | zval zv; | ||
| 106 | ZVAL_FALSE(&zv); | ||
| 107 | zend_hash_str_add(&ht, "allowed_classes", sizeof("allowed_classes")-1, &zv); | ||
| 108 | php_unserialize_with_options(return_value, buf, buf_len, &ht, "unserialize"); | ||
| 109 | return; | ||
| 110 | #else | ||
| 111 | sp_log_drop("unserialize_noclass", "unserialize_noclass is only supported on PHP8+"); | ||
| 112 | #endif | ||
| 100 | } | 113 | } |
| 101 | 114 | ||
| 102 | /* 64 is the length of HMAC-256 */ | 115 | /* 64 is the length of HMAC-256 */ |
| @@ -104,8 +117,8 @@ PHP_FUNCTION(sp_unserialize) { | |||
| 104 | sp_log_drop("unserialize", "The serialized object is too small."); | 117 | sp_log_drop("unserialize", "The serialized object is too small."); |
| 105 | } | 118 | } |
| 106 | 119 | ||
| 107 | hmac = buf + buf_len - 64; | 120 | char* hmac = buf + buf_len - 64; |
| 108 | serialized_str = ecalloc(buf_len - 64 + 1, 1); | 121 | char* serialized_str = ecalloc(buf_len - 64 + 1, 1); |
| 109 | memcpy(serialized_str, buf, buf_len - 64); | 122 | memcpy(serialized_str, buf, buf_len - 64); |
| 110 | 123 | ||
| 111 | zend_string *expected_hmac = sp_do_hash_hmac_sha256(serialized_str, strlen(serialized_str), ZSTR_VAL(SPCFG(encryption_key)), ZSTR_LEN(SPCFG(encryption_key))); | 124 | zend_string *expected_hmac = sp_do_hash_hmac_sha256(serialized_str, strlen(serialized_str), ZSTR_VAL(SPCFG(encryption_key)), ZSTR_LEN(SPCFG(encryption_key))); |
| @@ -117,11 +130,13 @@ PHP_FUNCTION(sp_unserialize) { | |||
| 117 | } | 130 | } |
| 118 | } else { status = 1; } | 131 | } else { status = 1; } |
| 119 | 132 | ||
| 133 | zif_handler orig_handler; | ||
| 120 | if (0 == status) { | 134 | if (0 == status) { |
| 121 | if ((orig_handler = zend_hash_str_find_ptr(SPG(sp_internal_functions_hook), ZEND_STRL("unserialize")))) { | 135 | if ((orig_handler = zend_hash_str_find_ptr(SPG(sp_internal_functions_hook), ZEND_STRL("unserialize")))) { |
| 122 | orig_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU); | 136 | orig_handler(INTERNAL_FUNCTION_PARAM_PASSTHRU); |
| 123 | } | 137 | } |
| 124 | } else { | 138 | } else { |
| 139 | const sp_config_unserialize *config_unserialize = &(SPCFG(unserialize)); | ||
| 125 | if (config_unserialize->dump) { | 140 | if (config_unserialize->dump) { |
| 126 | sp_log_request(config_unserialize->dump, | 141 | sp_log_request(config_unserialize->dump, |
| 127 | config_unserialize->textual_representation); | 142 | config_unserialize->textual_representation); |
diff --git a/src/tests/unserialize/config/config_serialize_noclass.ini b/src/tests/unserialize/config/config_serialize_noclass.ini new file mode 100644 index 0000000..b84de51 --- /dev/null +++ b/src/tests/unserialize/config/config_serialize_noclass.ini | |||
| @@ -0,0 +1 @@ | |||
| sp.unserialize_noclass.enable(); | |||
diff --git a/src/tests/unserialize/unserialize_noclass_forced.phpt b/src/tests/unserialize/unserialize_noclass_forced.phpt new file mode 100644 index 0000000..3b1e8d3 --- /dev/null +++ b/src/tests/unserialize/unserialize_noclass_forced.phpt | |||
| @@ -0,0 +1,21 @@ | |||
| 1 | --TEST-- | ||
| 2 | Unserialize with noclass forced | ||
| 3 | --SKIPIF-- | ||
| 4 | <?php if (!extension_loaded("snuffleupagus") || PHP_VERSION_ID >= 80000) print "skip"; ?> | ||
| 5 | --INI-- | ||
| 6 | sp.configuration_file={PWD}/config/config_serialize_noclass.ini | ||
| 7 | --FILE-- | ||
| 8 | <?php | ||
| 9 | class C { | ||
| 10 | public $name; | ||
| 11 | } | ||
| 12 | $c = new C; | ||
| 13 | $c->name = "test"; | ||
| 14 | |||
| 15 | $a = serialize($c); | ||
| 16 | var_dump(unserialize($a, ['allowed_classes' => false])); | ||
| 17 | var_dump(unserialize($a, ['allowed_classes' => true ])); | ||
| 18 | var_dump(unserialize($a)); | ||
| 19 | ?> | ||
| 20 | --EXPECTF-- | ||
| 21 | Fatal error: [snuffleupagus][0.0.0.0][unserialize_noclass][drop] unserialize_noclass is only supported on PHP8+ in %s/tests/unserialize/unserialize_noclass_forced.php on line 9 | ||
diff --git a/src/tests/unserialize/unserialize_wrong_call.phpt b/src/tests/unserialize/unserialize_wrong_call.phpt index a6fe140..afa42f6 100644 --- a/src/tests/unserialize/unserialize_wrong_call.phpt +++ b/src/tests/unserialize/unserialize_wrong_call.phpt | |||
| @@ -12,4 +12,4 @@ var_dump(unserialize($a, "too", "many", "aaaaaaaarguments!")); | |||
| 12 | ?> | 12 | ?> |
| 13 | --EXPECTF-- | 13 | --EXPECTF-- |
| 14 | Warning: unserialize() expects at most 2 parameters, 4 given in %a/unserialize_wrong_call.php on line %d | 14 | Warning: unserialize() expects at most 2 parameters, 4 given in %a/unserialize_wrong_call.php on line %d |
| 15 | bool(false) | 15 | NULL |
diff --git a/src/tests/unserialize_php8/config/config_serialize_noclass.ini b/src/tests/unserialize_php8/config/config_serialize_noclass.ini new file mode 100644 index 0000000..b84de51 --- /dev/null +++ b/src/tests/unserialize_php8/config/config_serialize_noclass.ini | |||
| @@ -0,0 +1 @@ | |||
| sp.unserialize_noclass.enable(); | |||
diff --git a/src/tests/unserialize_php8/config/config_serialize_noclass_disabled.ini b/src/tests/unserialize_php8/config/config_serialize_noclass_disabled.ini new file mode 100644 index 0000000..0238772 --- /dev/null +++ b/src/tests/unserialize_php8/config/config_serialize_noclass_disabled.ini | |||
| @@ -0,0 +1 @@ | |||
| sp.unserialize_noclass.disable(); | |||
diff --git a/src/tests/unserialize_php8/unserialize_noclass_forced.phpt b/src/tests/unserialize_php8/unserialize_noclass_forced.phpt new file mode 100644 index 0000000..9f276c5 --- /dev/null +++ b/src/tests/unserialize_php8/unserialize_noclass_forced.phpt | |||
| @@ -0,0 +1,38 @@ | |||
| 1 | --TEST-- | ||
| 2 | Unserialize with noclass forced | ||
| 3 | --SKIPIF-- | ||
| 4 | <?php if (!extension_loaded("snuffleupagus")) print "skip"; ?> | ||
| 5 | --INI-- | ||
| 6 | sp.configuration_file={PWD}/config/config_serialize_noclass.ini | ||
| 7 | --FILE-- | ||
| 8 | <?php | ||
| 9 | class C { | ||
| 10 | public $name; | ||
| 11 | } | ||
| 12 | $c = new C; | ||
| 13 | $c->name = "test"; | ||
| 14 | |||
| 15 | $a = serialize($c); | ||
| 16 | var_dump(unserialize($a, ['allowed_classes' => false])); | ||
| 17 | var_dump(unserialize($a, ['allowed_classes' => true ])); | ||
| 18 | var_dump(unserialize($a)); | ||
| 19 | ?> | ||
| 20 | --EXPECT-- | ||
| 21 | object(__PHP_Incomplete_Class)#2 (2) { | ||
| 22 | ["__PHP_Incomplete_Class_Name"]=> | ||
| 23 | string(1) "C" | ||
| 24 | ["name"]=> | ||
| 25 | string(4) "test" | ||
| 26 | } | ||
| 27 | object(__PHP_Incomplete_Class)#2 (2) { | ||
| 28 | ["__PHP_Incomplete_Class_Name"]=> | ||
| 29 | string(1) "C" | ||
| 30 | ["name"]=> | ||
| 31 | string(4) "test" | ||
| 32 | } | ||
| 33 | object(__PHP_Incomplete_Class)#2 (2) { | ||
| 34 | ["__PHP_Incomplete_Class_Name"]=> | ||
| 35 | string(1) "C" | ||
| 36 | ["name"]=> | ||
| 37 | string(4) "test" | ||
| 38 | } | ||
diff --git a/src/tests/unserialize_php8/unserialize_noclass_forced_disabled.phpt b/src/tests/unserialize_php8/unserialize_noclass_forced_disabled.phpt new file mode 100644 index 0000000..2c4223a --- /dev/null +++ b/src/tests/unserialize_php8/unserialize_noclass_forced_disabled.phpt | |||
| @@ -0,0 +1,35 @@ | |||
| 1 | --TEST-- | ||
| 2 | Unserialize with noclass forced disabled | ||
| 3 | --SKIPIF-- | ||
| 4 | <?php if (!extension_loaded("snuffleupagus")) print "skip"; ?> | ||
| 5 | --INI-- | ||
| 6 | sp.configuration_file={PWD}/config/config_serialize_noclass_disabled.ini | ||
| 7 | --FILE-- | ||
| 8 | <?php | ||
| 9 | class C { | ||
| 10 | public $name; | ||
| 11 | } | ||
| 12 | $c = new C; | ||
| 13 | $c->name = "test"; | ||
| 14 | |||
| 15 | $a = serialize($c); | ||
| 16 | var_dump(unserialize($a, ['allowed_classes' => false])); | ||
| 17 | var_dump(unserialize($a, ['allowed_classes' => true ])); | ||
| 18 | var_dump(unserialize($a)); | ||
| 19 | ?> | ||
| 20 | --EXPECT-- | ||
| 21 | object(__PHP_Incomplete_Class)#2 (2) { | ||
| 22 | ["__PHP_Incomplete_Class_Name"]=> | ||
| 23 | string(1) "C" | ||
| 24 | ["name"]=> | ||
| 25 | string(4) "test" | ||
| 26 | } | ||
| 27 | object(C)#2 (1) { | ||
| 28 | ["name"]=> | ||
| 29 | string(4) "test" | ||
| 30 | } | ||
| 31 | object(C)#2 (1) { | ||
| 32 | ["name"]=> | ||
| 33 | string(4) "test" | ||
| 34 | } | ||
| 35 | |||
