From bdd2cfc430d4b841c24a6c08e7934d667bdc6637 Mon Sep 17 00:00:00 2001 From: kkadosh Date: Fri, 2 Mar 2018 13:31:36 +0000 Subject: Implement dump() for execution of writable PHP files --- src/sp_config.h | 2 + src/sp_config_keywords.c | 33 +++++++++-- src/sp_execute.c | 7 ++- src/sp_unserialize.c | 5 +- src/sp_utils.c | 6 +- src/tests/config/dump_deny_writable_execution.ini | 1 + src/tests/dump_deny_writable_execution.phpt | 67 +++++++++++++++++++++++ 7 files changed, 113 insertions(+), 8 deletions(-) create mode 100644 src/tests/config/dump_deny_writable_execution.ini create mode 100644 src/tests/dump_deny_writable_execution.phpt diff --git a/src/sp_config.h b/src/sp_config.h index ba1542c..0ccd11e 100644 --- a/src/sp_config.h +++ b/src/sp_config.h @@ -45,6 +45,8 @@ typedef struct { typedef struct { bool enable; bool simulation; + char *dump; + char *textual_representation; } sp_config_readonly_exec; typedef struct { bool enable; } sp_config_global_strict; diff --git a/src/sp_config_keywords.c b/src/sp_config_keywords.c index c58a227..a04c88f 100644 --- a/src/sp_config_keywords.c +++ b/src/sp_config_keywords.c @@ -82,7 +82,8 @@ int parse_global_strict(char *line) { int parse_unserialize(char *line) { bool enable = false, disable = false; - sp_config_unserialize *unserialize = SNUFFLEUPAGUS_G(config).config_unserialize; + sp_config_unserialize *unserialize = + SNUFFLEUPAGUS_G(config).config_unserialize; sp_config_functions sp_config_funcs[] = { {parse_empty, SP_TOKEN_ENABLE, &(enable)}, @@ -110,9 +111,33 @@ int parse_unserialize(char *line) { } int parse_readonly_exec(char *line) { - return parse_enable( - line, &(SNUFFLEUPAGUS_G(config).config_readonly_exec->enable), - &(SNUFFLEUPAGUS_G(config).config_readonly_exec->simulation)); + bool enable = false, disable = false; + sp_config_readonly_exec *readonly_exec = + SNUFFLEUPAGUS_G(config).config_readonly_exec; + + sp_config_functions sp_config_funcs[] = { + {parse_empty, SP_TOKEN_ENABLE, &(enable)}, + {parse_empty, SP_TOKEN_DISABLE, &(disable)}, + {parse_empty, SP_TOKEN_SIMULATION, &(readonly_exec->simulation)}, + {parse_str, SP_TOKEN_DUMP, &(readonly_exec->dump)}, + {0}}; + + readonly_exec->textual_representation = estrdup(line); + int ret = parse_keywords(sp_config_funcs, line); + + if (0 != ret) { + return ret; + } + + if (!(enable ^ disable)) { + sp_log_err("config", "A rule can't be enabled and disabled on line %zu.", + sp_line_no); + return -1; + } + + SNUFFLEUPAGUS_G(config).config_readonly_exec->enable = enable; + + return ret; } int parse_global(char *line) { diff --git a/src/sp_execute.c b/src/sp_execute.c index 20fe509..5cf139a 100644 --- a/src/sp_execute.c +++ b/src/sp_execute.c @@ -1,5 +1,4 @@ #include "php_snuffleupagus.h" - #include #include @@ -14,6 +13,12 @@ static int (*orig_zend_stream_open)(const char *filename, // FIXME handle symlink ZEND_COLD static inline void terminate_if_writable(const char *filename) { if (0 == access(filename, W_OK)) { + if (SNUFFLEUPAGUS_G(config).config_readonly_exec->dump) { + sp_log_request( + SNUFFLEUPAGUS_G(config).config_readonly_exec->dump, + SNUFFLEUPAGUS_G(config).config_readonly_exec->textual_representation, + SP_TOKEN_READONLY_EXEC); + } if (true == SNUFFLEUPAGUS_G(config).config_readonly_exec->simulation) { sp_log_msg("readonly_exec", SP_LOG_SIMULATION, "Attempted execution of a writable file (%s).", filename); diff --git a/src/sp_unserialize.c b/src/sp_unserialize.c index b2875e2..60ef7be 100644 --- a/src/sp_unserialize.c +++ b/src/sp_unserialize.c @@ -96,7 +96,10 @@ PHP_FUNCTION(sp_unserialize) { } } if (SNUFFLEUPAGUS_G(config).config_unserialize->dump) { - sp_log_request(SNUFFLEUPAGUS_G(config).config_unserialize->dump, SNUFFLEUPAGUS_G(config).config_unserialize->textual_representation, SP_TOKEN_UNSERIALIZE_HMAC); + sp_log_request( + SNUFFLEUPAGUS_G(config).config_unserialize->dump, + SNUFFLEUPAGUS_G(config).config_unserialize->textual_representation, + SP_TOKEN_UNSERIALIZE_HMAC); } efree(serialized_str); return; diff --git a/src/sp_utils.c b/src/sp_utils.c index 1b707d0..0f58fbb 100644 --- a/src/sp_utils.c +++ b/src/sp_utils.c @@ -225,7 +225,8 @@ void sp_log_disable(const char* restrict path, const char* restrict arg_name, } } if (dump) { - sp_log_request(config_node->dump, config_node->textual_representation, SP_TOKEN_DISABLE_FUNC); + sp_log_request(config_node->dump, config_node->textual_representation, + SP_TOKEN_DISABLE_FUNC); } } @@ -252,7 +253,8 @@ void sp_log_disable_ret(const char* restrict path, zend_get_executed_lineno(TSRMLS_C), ret_value ? ret_value : "?", path); } if (dump) { - sp_log_request(dump, config_node->textual_representation, SP_TOKEN_DISABLE_FUNC); + sp_log_request(dump, config_node->textual_representation, + SP_TOKEN_DISABLE_FUNC); } } diff --git a/src/tests/config/dump_deny_writable_execution.ini b/src/tests/config/dump_deny_writable_execution.ini new file mode 100644 index 0000000..c49f893 --- /dev/null +++ b/src/tests/config/dump_deny_writable_execution.ini @@ -0,0 +1 @@ +sp.readonly_exec.enable().simulation().dump("/tmp/dump_result/"); diff --git a/src/tests/dump_deny_writable_execution.phpt b/src/tests/dump_deny_writable_execution.phpt new file mode 100644 index 0000000..c6dd6cd --- /dev/null +++ b/src/tests/dump_deny_writable_execution.phpt @@ -0,0 +1,67 @@ +--TEST-- +Readonly execution attempt (simulation mode) +--SKIPIF-- + +--POST-- +post_a=data_post_a_readonly&post_b=data_post_b_readonly +--GET-- +get_a=data_get_a_readonly&get_b=data_get_b_readonly +--COOKIE-- +cookie_a=data_cookie_a_readonly&cookie_b=data_cookie_b_readonly +--INI-- +sp.configuration_file={PWD}/config/dump_deny_writable_execution.ini +--FILE-- + +--EXPECTF-- +%a +WIN +--CLEAN-- + -- cgit v1.3