diff options
| author | kkadosh | 2018-03-02 13:31:56 +0000 |
|---|---|---|
| committer | jvoisin | 2018-03-02 14:31:56 +0100 |
| commit | 17a09fafa2b569f0ce548220fd099cdf88e3a71e (patch) | |
| tree | 7d07f6ba92635959fbae9b1ec9fa6470d3bf6576 | |
| parent | bdd2cfc430d4b841c24a6c08e7934d667bdc6637 (diff) | |
Add .dump() for eval whitelist/blacklist + simulation mode for whitelist
| -rw-r--r-- | src/sp_config.h | 2 | ||||
| -rw-r--r-- | src/sp_config_keywords.c | 6 | ||||
| -rw-r--r-- | src/sp_disabled_functions.c | 8 | ||||
| -rw-r--r-- | src/sp_execute.c | 26 | ||||
| -rw-r--r-- | src/tests/config/dump_eval_blacklist.ini | 1 | ||||
| -rw-r--r-- | src/tests/config/dump_eval_whitelist.ini | 1 | ||||
| -rw-r--r-- | src/tests/config/eval_whitelist_simulation.ini | 1 | ||||
| -rw-r--r-- | src/tests/dump_eval_blacklist.phpt | 39 | ||||
| -rw-r--r-- | src/tests/dump_eval_whitelist.phpt | 51 | ||||
| -rw-r--r-- | src/tests/dump_request.phpt | 3 | ||||
| -rw-r--r-- | src/tests/dump_request_too_big.phpt | 10 | ||||
| -rw-r--r-- | src/tests/dump_unserialize.phpt | 9 | ||||
| -rw-r--r-- | src/tests/eval_backlist_simulation.phpt | 4 | ||||
| -rw-r--r-- | src/tests/eval_whitelist_simulation.phpt | 28 |
14 files changed, 171 insertions, 18 deletions
diff --git a/src/sp_config.h b/src/sp_config.h index 0ccd11e..e537ec2 100644 --- a/src/sp_config.h +++ b/src/sp_config.h | |||
| @@ -119,6 +119,8 @@ typedef struct { | |||
| 119 | sp_list_node *blacklist; | 119 | sp_list_node *blacklist; |
| 120 | sp_list_node *whitelist; | 120 | sp_list_node *whitelist; |
| 121 | bool simulation; | 121 | bool simulation; |
| 122 | char *dump; | ||
| 123 | char *textual_representation; | ||
| 122 | } sp_config_eval; | 124 | } sp_config_eval; |
| 123 | 125 | ||
| 124 | typedef struct { | 126 | typedef struct { |
diff --git a/src/sp_config_keywords.c b/src/sp_config_keywords.c index a04c88f..9faaafb 100644 --- a/src/sp_config_keywords.c +++ b/src/sp_config_keywords.c | |||
| @@ -153,11 +153,17 @@ int parse_global(char *line) { | |||
| 153 | static int parse_eval_filter_conf(char *line, sp_list_node **list) { | 153 | static int parse_eval_filter_conf(char *line, sp_list_node **list) { |
| 154 | char *token; | 154 | char *token; |
| 155 | char *rest; | 155 | char *rest; |
| 156 | sp_config_eval *eval = SNUFFLEUPAGUS_G(config).config_eval; | ||
| 157 | |||
| 156 | sp_config_functions sp_config_funcs[] = { | 158 | sp_config_functions sp_config_funcs[] = { |
| 157 | {parse_str, SP_TOKEN_EVAL_LIST, &rest}, | 159 | {parse_str, SP_TOKEN_EVAL_LIST, &rest}, |
| 158 | {parse_empty, SP_TOKEN_SIMULATION, | 160 | {parse_empty, SP_TOKEN_SIMULATION, |
| 159 | &(SNUFFLEUPAGUS_G(config).config_eval->simulation)}, | 161 | &(SNUFFLEUPAGUS_G(config).config_eval->simulation)}, |
| 162 | {parse_str, SP_TOKEN_DUMP, &(SNUFFLEUPAGUS_G(config).config_eval->dump)}, | ||
| 160 | {0}}; | 163 | {0}}; |
| 164 | |||
| 165 | eval->textual_representation = estrdup(line); | ||
| 166 | |||
| 161 | int ret = parse_keywords(sp_config_funcs, line); | 167 | int ret = parse_keywords(sp_config_funcs, line); |
| 162 | if (0 != ret) { | 168 | if (0 != ret) { |
| 163 | return ret; | 169 | return ret; |
diff --git a/src/sp_disabled_functions.c b/src/sp_disabled_functions.c index 4d94a97..5a39cdf 100644 --- a/src/sp_disabled_functions.c +++ b/src/sp_disabled_functions.c | |||
| @@ -470,9 +470,15 @@ ZEND_FUNCTION(eval_blacklist_callback) { | |||
| 470 | if (SNUFFLEUPAGUS_G(in_eval) > 0) { | 470 | if (SNUFFLEUPAGUS_G(in_eval) > 0) { |
| 471 | char* filename = get_eval_filename(zend_get_executed_filename()); | 471 | char* filename = get_eval_filename(zend_get_executed_filename()); |
| 472 | const int line_number = zend_get_executed_lineno(TSRMLS_C); | 472 | const int line_number = zend_get_executed_lineno(TSRMLS_C); |
| 473 | if (SNUFFLEUPAGUS_G(config).config_eval->dump) { | ||
| 474 | sp_log_request( | ||
| 475 | SNUFFLEUPAGUS_G(config).config_eval->dump, | ||
| 476 | SNUFFLEUPAGUS_G(config).config_eval->textual_representation, | ||
| 477 | SP_TOKEN_EVAL_BLACKLIST); | ||
| 478 | } | ||
| 473 | if (1 == SNUFFLEUPAGUS_G(config).config_eval->simulation) { | 479 | if (1 == SNUFFLEUPAGUS_G(config).config_eval->simulation) { |
| 474 | sp_log_msg("eval", SP_LOG_SIMULATION, | 480 | sp_log_msg("eval", SP_LOG_SIMULATION, |
| 475 | "A call to %s was tried in eval, in %s:%d, dropping it.", | 481 | "A call to %s was tried in eval, in %s:%d, logging it.", |
| 476 | current_function_name, filename, line_number); | 482 | current_function_name, filename, line_number); |
| 477 | } else { | 483 | } else { |
| 478 | sp_log_msg("eval", SP_LOG_DROP, | 484 | sp_log_msg("eval", SP_LOG_DROP, |
diff --git a/src/sp_execute.c b/src/sp_execute.c index 5cf139a..1517134 100644 --- a/src/sp_execute.c +++ b/src/sp_execute.c | |||
| @@ -51,6 +51,8 @@ static void is_builtin_matching(const char *restrict const filename, | |||
| 51 | 51 | ||
| 52 | static void ZEND_HOT | 52 | static void ZEND_HOT |
| 53 | is_in_eval_and_whitelisted(const zend_execute_data *execute_data) { | 53 | is_in_eval_and_whitelisted(const zend_execute_data *execute_data) { |
| 54 | sp_config_eval *eval = SNUFFLEUPAGUS_G(config).config_eval; | ||
| 55 | |||
| 54 | if (EXPECTED(0 == SNUFFLEUPAGUS_G(in_eval))) { | 56 | if (EXPECTED(0 == SNUFFLEUPAGUS_G(in_eval))) { |
| 55 | return; | 57 | return; |
| 56 | } | 58 | } |
| @@ -71,11 +73,25 @@ is_in_eval_and_whitelisted(const zend_execute_data *execute_data) { | |||
| 71 | 73 | ||
| 72 | if (EXPECTED(NULL != current_function)) { | 74 | if (EXPECTED(NULL != current_function)) { |
| 73 | if (UNEXPECTED(false == check_is_in_eval_whitelist(current_function))) { | 75 | if (UNEXPECTED(false == check_is_in_eval_whitelist(current_function))) { |
| 74 | sp_log_msg( | 76 | if (eval->dump) { |
| 75 | "Eval_whitelist", SP_LOG_DROP, | 77 | sp_log_request( |
| 76 | "The function '%s' isn't in the eval whitelist, dropping its call.", | 78 | SNUFFLEUPAGUS_G(config).config_eval->dump, |
| 77 | current_function); | 79 | SNUFFLEUPAGUS_G(config).config_eval->textual_representation, |
| 78 | sp_terminate(); | 80 | SP_TOKEN_EVAL_WHITELIST); |
| 81 | } | ||
| 82 | if (eval->simulation) { | ||
| 83 | sp_log_msg( | ||
| 84 | "Eval_whitelist", SP_LOG_SIMULATION, | ||
| 85 | "The function '%s' isn't in the eval whitelist, logging its call.", | ||
| 86 | current_function); | ||
| 87 | return; | ||
| 88 | } else { | ||
| 89 | sp_log_msg( | ||
| 90 | "Eval_whitelist", SP_LOG_DROP, | ||
| 91 | "The function '%s' isn't in the eval whitelist, dropping its call.", | ||
| 92 | current_function); | ||
| 93 | sp_terminate(); | ||
| 94 | } | ||
| 79 | } | 95 | } |
| 80 | } | 96 | } |
| 81 | } | 97 | } |
diff --git a/src/tests/config/dump_eval_blacklist.ini b/src/tests/config/dump_eval_blacklist.ini new file mode 100644 index 0000000..503143a --- /dev/null +++ b/src/tests/config/dump_eval_blacklist.ini | |||
| @@ -0,0 +1 @@ | |||
| sp.eval_blacklist.list("strlen").dump("/tmp/dump_result/").simulation(); | |||
diff --git a/src/tests/config/dump_eval_whitelist.ini b/src/tests/config/dump_eval_whitelist.ini new file mode 100644 index 0000000..2a6c909 --- /dev/null +++ b/src/tests/config/dump_eval_whitelist.ini | |||
| @@ -0,0 +1 @@ | |||
| sp.eval_whitelist.list("my_fun,cos").simulation().dump("/tmp/dump_result/"); | |||
diff --git a/src/tests/config/eval_whitelist_simulation.ini b/src/tests/config/eval_whitelist_simulation.ini new file mode 100644 index 0000000..9d94db3 --- /dev/null +++ b/src/tests/config/eval_whitelist_simulation.ini | |||
| @@ -0,0 +1 @@ | |||
| sp.eval_whitelist.list("my_fun,cos").simulation(); | |||
diff --git a/src/tests/dump_eval_blacklist.phpt b/src/tests/dump_eval_blacklist.phpt new file mode 100644 index 0000000..19da8cd --- /dev/null +++ b/src/tests/dump_eval_blacklist.phpt | |||
| @@ -0,0 +1,39 @@ | |||
| 1 | --TEST-- | ||
| 2 | Dump eval blacklist | ||
| 3 | --SKIPIF-- | ||
| 4 | <?php | ||
| 5 | if (!extension_loaded("snuffleupagus")) die "skip"; | ||
| 6 | ?> | ||
| 7 | --POST-- | ||
| 8 | post_a=data_post_a&post_b=data_post_b | ||
| 9 | --GET-- | ||
| 10 | get_a=data_get_a&get_b=data_get_b | ||
| 11 | --COOKIE-- | ||
| 12 | cookie_a=data_cookie_a&cookie_b=data_cookie_b | ||
| 13 | --INI-- | ||
| 14 | sp.configuration_file={PWD}/config/dump_eval_blacklist.ini | ||
| 15 | --FILE-- | ||
| 16 | <?php | ||
| 17 | @mkdir("/tmp/dump_result/"); | ||
| 18 | foreach (glob("/tmp/dump_result/sp_dump.*") as $dump) { | ||
| 19 | @unlink($dump); | ||
| 20 | } | ||
| 21 | |||
| 22 | $a = strlen("1337 1337 1337"); | ||
| 23 | echo "Outside of eval: $a\n"; | ||
| 24 | eval('$a = strlen("1234");'); | ||
| 25 | echo "After eval: $a\n"; | ||
| 26 | $filename = glob('/tmp/dump_result/sp_dump.*')[0]; | ||
| 27 | $res = file($filename); | ||
| 28 | if ($res[2] != "GET:get_a='data_get_a' get_b='data_get_b' \n") { | ||
| 29 | echo "1\n"; | ||
| 30 | } elseif ($res[3] != "POST:post_a='data_post_a' post_b='data_post_b' \n") { | ||
| 31 | echo "2\n"; | ||
| 32 | } elseif ($res[4] != "COOKIE:cookie_a='data_cookie_a&cookie_b=data_cookie_b' \n") { | ||
| 33 | echo "3\n"; | ||
| 34 | } | ||
| 35 | ?> | ||
| 36 | --EXPECTF-- | ||
| 37 | Outside of eval: 14 | ||
| 38 | [snuffleupagus][0.0.0.0][eval][simulation] A call to strlen was tried in eval, in %a/dump_eval_blacklist.php:1, logging it. | ||
| 39 | After eval: 4 | ||
diff --git a/src/tests/dump_eval_whitelist.phpt b/src/tests/dump_eval_whitelist.phpt new file mode 100644 index 0000000..24ca1d1 --- /dev/null +++ b/src/tests/dump_eval_whitelist.phpt | |||
| @@ -0,0 +1,51 @@ | |||
| 1 | --TEST-- | ||
| 2 | Dump eval whitelist | ||
| 3 | --SKIPIF-- | ||
| 4 | <?php | ||
| 5 | if (!extension_loaded("snuffleupagus")) die "skip"; | ||
| 6 | ?> | ||
| 7 | --POST-- | ||
| 8 | post_a=data_post_a&post_b=data_post_b | ||
| 9 | --GET-- | ||
| 10 | get_a=data_get_a&get_b=data_get_b | ||
| 11 | --COOKIE-- | ||
| 12 | cookie_a=data_cookie_a&cookie_b=data_cookie_b | ||
| 13 | --INI-- | ||
| 14 | sp.configuration_file={PWD}/config/dump_eval_whitelist.ini | ||
| 15 | --FILE-- | ||
| 16 | <?php | ||
| 17 | @mkdir("/tmp/dump_result/"); | ||
| 18 | foreach (glob("/tmp/dump_result/sp_dump.*") as $dump) { | ||
| 19 | @unlink($dump); | ||
| 20 | } | ||
| 21 | |||
| 22 | function my_fun($p) { | ||
| 23 | return "my_fun: $p"; | ||
| 24 | } | ||
| 25 | |||
| 26 | function my_other_fun($p) { | ||
| 27 | return "my_other_fun: $p"; | ||
| 28 | } | ||
| 29 | |||
| 30 | $a = my_fun("1337 1337 1337"); | ||
| 31 | echo "Outside of eval: $a\n"; | ||
| 32 | eval('$a = my_fun("1234");'); | ||
| 33 | echo "After allowed eval: $a\n"; | ||
| 34 | eval('$a = my_other_fun("1234");'); | ||
| 35 | echo "After eval: $a\n"; | ||
| 36 | $filename = glob('/tmp/dump_result/sp_dump.*')[0]; | ||
| 37 | $res = file($filename); | ||
| 38 | if ($res[2] != "GET:get_a='data_get_a' get_b='data_get_b' \n") { | ||
| 39 | echo "1\n"; | ||
| 40 | } elseif ($res[3] != "POST:post_a='data_post_a' post_b='data_post_b' \n") { | ||
| 41 | echo "2\n"; | ||
| 42 | } elseif ($res[4] != "COOKIE:cookie_a='data_cookie_a&cookie_b=data_cookie_b' \n") { | ||
| 43 | echo "3\n"; | ||
| 44 | } | ||
| 45 | |||
| 46 | ?> | ||
| 47 | --EXPECTF-- | ||
| 48 | Outside of eval: my_fun: 1337 1337 1337 | ||
| 49 | After allowed eval: my_fun: 1234 | ||
| 50 | [snuffleupagus][0.0.0.0][Eval_whitelist][simulation] The function 'my_other_fun' isn't in the eval whitelist, logging its call. | ||
| 51 | After eval: my_other_fun: 1234 | ||
diff --git a/src/tests/dump_request.phpt b/src/tests/dump_request.phpt index 23cafdc..abff870 100644 --- a/src/tests/dump_request.phpt +++ b/src/tests/dump_request.phpt | |||
| @@ -22,6 +22,9 @@ sp.configuration_file={PWD}/config/dump_request.ini | |||
| 22 | --FILE-- | 22 | --FILE-- |
| 23 | <?php | 23 | <?php |
| 24 | @mkdir("/tmp/dump_result/"); | 24 | @mkdir("/tmp/dump_result/"); |
| 25 | foreach (glob("/tmp/dump_result/sp_dump.*") as $dump) { | ||
| 26 | @unlink($dump); | ||
| 27 | } | ||
| 25 | echo "1\n"; | 28 | echo "1\n"; |
| 26 | system("echo 1337;"); | 29 | system("echo 1337;"); |
| 27 | $filename = glob('/tmp/dump_result/sp_dump.*')[0]; | 30 | $filename = glob('/tmp/dump_result/sp_dump.*')[0]; |
diff --git a/src/tests/dump_request_too_big.phpt b/src/tests/dump_request_too_big.phpt index 795a5c2..d67ce6f 100644 --- a/src/tests/dump_request_too_big.phpt +++ b/src/tests/dump_request_too_big.phpt | |||
| @@ -4,12 +4,7 @@ Dump request -- to big, so it's truncated. | |||
| 4 | <?php | 4 | <?php |
| 5 | if (!extension_loaded("snuffleupagus")) { | 5 | if (!extension_loaded("snuffleupagus")) { |
| 6 | print "skip"; | 6 | print "skip"; |
| 7 | } | ||
| 8 | |||
| 9 | foreach (glob("/tmp/dump_result/sp_dump.*") as $dump) { | ||
| 10 | @unlink($dump); | ||
| 11 | } | 7 | } |
| 12 | @rmdir("/tmp/dump_result/"); | ||
| 13 | ?> | 8 | ?> |
| 14 | --POST-- | 9 | --POST-- |
| 15 | post_a=data_post_a&post_b=data_post_b&post_c=c | 10 | post_a=data_post_a&post_b=data_post_b&post_c=c |
| @@ -25,6 +20,11 @@ END; | |||
| 25 | sp.configuration_file={PWD}/config/dump_request.ini | 20 | sp.configuration_file={PWD}/config/dump_request.ini |
| 26 | --FILE-- | 21 | --FILE-- |
| 27 | <?php | 22 | <?php |
| 23 | @mkdir("/tmp/dump_result/"); | ||
| 24 | foreach (glob("/tmp/dump_result/sp_dump.*") as $dump) { | ||
| 25 | @unlink($dump); | ||
| 26 | } | ||
| 27 | |||
| 28 | echo "1\n"; | 28 | echo "1\n"; |
| 29 | system("echo 1337;"); | 29 | system("echo 1337;"); |
| 30 | $filename = glob('/tmp/dump_result/*')[0]; | 30 | $filename = glob('/tmp/dump_result/*')[0]; |
diff --git a/src/tests/dump_unserialize.phpt b/src/tests/dump_unserialize.phpt index 9c3906d..dfa8501 100644 --- a/src/tests/dump_unserialize.phpt +++ b/src/tests/dump_unserialize.phpt | |||
| @@ -5,11 +5,6 @@ Dump unserialize | |||
| 5 | if (!extension_loaded("snuffleupagus")) { | 5 | if (!extension_loaded("snuffleupagus")) { |
| 6 | print "skip"; | 6 | print "skip"; |
| 7 | } | 7 | } |
| 8 | |||
| 9 | foreach (glob("/tmp/dump_result/sp_dump.*") as $dump) { | ||
| 10 | @unlink($dump); | ||
| 11 | } | ||
| 12 | @rmdir("/tmp/dump_result/"); | ||
| 13 | ?> | 8 | ?> |
| 14 | --POST-- | 9 | --POST-- |
| 15 | post_a=data_post_a&post_b=data_post_b | 10 | post_a=data_post_a&post_b=data_post_b |
| @@ -22,6 +17,10 @@ sp.configuration_file={PWD}/config/dump_unserialize.ini | |||
| 22 | --FILE-- | 17 | --FILE-- |
| 23 | <?php | 18 | <?php |
| 24 | @mkdir("/tmp/dump_result/"); | 19 | @mkdir("/tmp/dump_result/"); |
| 20 | foreach (glob("/tmp/dump_result/sp_dump.*") as $dump) { | ||
| 21 | @unlink($dump); | ||
| 22 | } | ||
| 23 | |||
| 25 | echo "1\n"; | 24 | echo "1\n"; |
| 26 | var_dump(unserialize('s:1:"a";alyualskdufyhalkdjsfhalkjdhflaksjdfhlkasdhflkahdawkuerylksjdfhlkssjgdflaksjdhflkasjdf')); | 25 | var_dump(unserialize('s:1:"a";alyualskdufyhalkdjsfhalkjdhflaksjdfhlkasdhflkahdawkuerylksjdfhlkssjgdflaksjdhflkasjdf')); |
| 27 | $filename = glob('/tmp/dump_result/sp_dump.*')[0]; | 26 | $filename = glob('/tmp/dump_result/sp_dump.*')[0]; |
diff --git a/src/tests/eval_backlist_simulation.phpt b/src/tests/eval_backlist_simulation.phpt index ddeae60..bea5115 100644 --- a/src/tests/eval_backlist_simulation.phpt +++ b/src/tests/eval_backlist_simulation.phpt | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | --TEST-- | 1 | --TEST-- |
| 2 | Eval blacklist | 2 | Eval blacklist simulation |
| 3 | --SKIPIF-- | 3 | --SKIPIF-- |
| 4 | <?php if (!extension_loaded("snuffleupagus")) die "skip"; ?> | 4 | <?php if (!extension_loaded("snuffleupagus")) die "skip"; ?> |
| 5 | --INI-- | 5 | --INI-- |
| @@ -13,5 +13,5 @@ echo "After eval: $a\n"; | |||
| 13 | ?> | 13 | ?> |
| 14 | --EXPECTF-- | 14 | --EXPECTF-- |
| 15 | Outside of eval: 14 | 15 | Outside of eval: 14 |
| 16 | [snuffleupagus][0.0.0.0][eval][simulation] A call to strlen was tried in eval, in %a/tests/eval_backlist_simulation.php:1, dropping it. | 16 | [snuffleupagus][0.0.0.0][eval][simulation] A call to strlen was tried in eval, in %a/tests/eval_backlist_simulation.php:1, logging it. |
| 17 | After eval: 4 | 17 | After eval: 4 |
diff --git a/src/tests/eval_whitelist_simulation.phpt b/src/tests/eval_whitelist_simulation.phpt new file mode 100644 index 0000000..ff2f970 --- /dev/null +++ b/src/tests/eval_whitelist_simulation.phpt | |||
| @@ -0,0 +1,28 @@ | |||
| 1 | --TEST-- | ||
| 2 | Eval whitelist simulation | ||
| 3 | --SKIPIF-- | ||
| 4 | <?php if (!extension_loaded("snuffleupagus")) die "skip"; ?> | ||
| 5 | --INI-- | ||
| 6 | sp.configuration_file={PWD}/config/eval_whitelist_simulation.ini | ||
| 7 | --FILE-- | ||
| 8 | <?php | ||
| 9 | function my_fun($p) { | ||
| 10 | return "my_fun: $p"; | ||
| 11 | } | ||
| 12 | |||
| 13 | function my_other_fun($p) { | ||
| 14 | return "my_other_fun: $p"; | ||
| 15 | } | ||
| 16 | |||
| 17 | $a = my_fun("1337 1337 1337"); | ||
| 18 | echo "Outside of eval: $a\n"; | ||
| 19 | eval('$a = my_fun("1234");'); | ||
| 20 | echo "After allowed eval: $a\n"; | ||
| 21 | eval('$a = my_other_fun("1234");'); | ||
| 22 | echo "After eval: $a\n"; | ||
| 23 | ?> | ||
| 24 | --EXPECTF-- | ||
| 25 | Outside of eval: my_fun: 1337 1337 1337 | ||
| 26 | After allowed eval: my_fun: 1234 | ||
| 27 | [snuffleupagus][0.0.0.0][Eval_whitelist][simulation] The function 'my_other_fun' isn't in the eval whitelist, logging its call. | ||
| 28 | After eval: my_other_fun: 1234 \ No newline at end of file | ||
