diff --git a/appsec/tests/extension/push_params_block_02.phpt b/appsec/tests/extension/push_params_block_02.phpt new file mode 100644 index 0000000000..a11c052a8f --- /dev/null +++ b/appsec/tests/extension/push_params_block_02.phpt @@ -0,0 +1,43 @@ +--TEST-- +Push address gets blocked even when within a hook +--INI-- +extension=ddtrace.so +datadog.appsec.enabled=1 +--FILE-- + '404', 'type' => 'html']]], ['{"found":"attack"}','{"another":"attack"}']])), +]); +rinit(); + +class SomeIntegration { + public function init() + { + DDTrace\install_hook("ltrim", self::hooked_function(), null); + } + + private static function hooked_function() + { + return static function (DDTrace\HookData $hook) { + push_address("server.request.path_params", ["some" => "params", "more" => "parameters"]); + var_dump("This should be executed"); + }; + } +} + +$integration = new SomeIntegration(); +$integration->init(); +var_dump(ltrim(" Calling wrapped function")); +var_dump("THIS SHOULD NOT GET IN THE OUTPUT"); +?> +--EXPECTHEADERS-- +Status: 404 Not Found +Content-type: text/html;charset=UTF-8 +--EXPECTF-- +You've been blocked

Sorry, you cannot access this page. Please contact the customer service team.

\ No newline at end of file diff --git a/appsec/tests/extension/push_params_block_03.phpt b/appsec/tests/extension/push_params_block_03.phpt new file mode 100644 index 0000000000..eba1d26d4a --- /dev/null +++ b/appsec/tests/extension/push_params_block_03.phpt @@ -0,0 +1,43 @@ +--TEST-- +Push address gets blocked even when within a hook +--INI-- +extension=ddtrace.so +datadog.appsec.enabled=1 +--FILE-- + '404', 'type' => 'html']]], ['{"found":"attack"}','{"another":"attack"}']])), +]); +rinit(); + +class SomeIntegration { + public function init() + { + DDTrace\install_hook("ltrim", self::hooked_function(), null); + } + + private static function hooked_function() + { + return static function (DDTrace\HookData $hook) { + push_address("server.request.path_params", ["some" => "params", "more" => "parameters"]); + var_dump("This should be executed"); + }; + } +} + +$integration = new SomeIntegration(); +$integration->init(); +echo "Something here to force partially booking"; +var_dump(ltrim(" Calling wrapped function")); +var_dump("THIS SHOULD NOT GET IN THE OUTPUT"); +?> +--EXPECTHEADERS-- +Content-type: text/html; charset=UTF-8 +--EXPECTF-- +Something here to force partially booking \ No newline at end of file diff --git a/zend_abstract_interface/sandbox/php7/sandbox.c b/zend_abstract_interface/sandbox/php7/sandbox.c index dadc09afa5..e6efd13e16 100644 --- a/zend_abstract_interface/sandbox/php7/sandbox.c +++ b/zend_abstract_interface/sandbox/php7/sandbox.c @@ -6,6 +6,7 @@ extern inline void zai_sandbox_open(zai_sandbox *sandbox); extern inline void zai_sandbox_close(zai_sandbox *sandbox); extern inline void zai_sandbox_bailout(zai_sandbox *sandbox); extern inline bool zai_sandbox_timed_out(void); +extern inline bool zai_is_request_blocked(void); extern inline void zai_sandbox_error_state_backup(zai_error_state *es); extern inline void zai_sandbox_error_state_restore(zai_error_state *es); diff --git a/zend_abstract_interface/sandbox/php8/sandbox.c b/zend_abstract_interface/sandbox/php8/sandbox.c index 92fc0589ea..ddd93bb2b1 100644 --- a/zend_abstract_interface/sandbox/php8/sandbox.c +++ b/zend_abstract_interface/sandbox/php8/sandbox.c @@ -7,6 +7,7 @@ extern inline void zai_sandbox_open(zai_sandbox *sandbox); extern inline void zai_sandbox_close(zai_sandbox *sandbox); extern inline void zai_sandbox_bailout(zai_sandbox *sandbox); extern inline bool zai_sandbox_timed_out(void); +extern inline bool zai_is_request_blocked(void); extern inline void zai_sandbox_error_state_backup(zai_error_state *es); diff --git a/zend_abstract_interface/sandbox/sandbox.h b/zend_abstract_interface/sandbox/sandbox.h index c441b5bc16..4ce65f4b9c 100644 --- a/zend_abstract_interface/sandbox/sandbox.h +++ b/zend_abstract_interface/sandbox/sandbox.h @@ -76,7 +76,9 @@ * * This function should be invoked when a bailout has been caught. * - * It will restore engine state and continue in all but the case of a timeout + * It will restore engine state and continue in all cases except: + * - Timeout + * - Request is blocked by the extension */ /* ######### Timeout ########## @@ -218,8 +220,25 @@ inline bool zai_sandbox_timed_out(void) { return false; } +inline bool zai_is_request_blocked(void) +{ + if (!PG(last_error_message)) { + return false; + } + + if (strcmp("Datadog blocked the request and presented a static error page", ZSTR_VAL(PG(last_error_message))) == 0) { + return true; + } + + if (strcmp("Datadog blocked the request, but the response has already been partially committed", ZSTR_VAL(PG(last_error_message))) == 0) { + return true; + } + + return false; +} + inline void zai_sandbox_bailout(zai_sandbox *sandbox) { - if (!zai_sandbox_timed_out()) { + if (!zai_sandbox_timed_out() && !zai_is_request_blocked()) { zai_sandbox_engine_state_restore(&sandbox->engine_state); return; @@ -356,8 +375,25 @@ inline bool zai_sandbox_timed_out(void) { return false; } +inline bool zai_is_request_blocked(void) +{ + if (!PG(last_error_message)) { + return false; + } + + if (strcmp("Datadog blocked the request and presented a static error page", ZSTR_VAL(PG(last_error_message))) == 0) { + return true; + } + + if (strcmp("Datadog blocked the request, but the response has already been partially committed", ZSTR_VAL(PG(last_error_message))) == 0) { + return true; + } + + return false; +} + inline void zai_sandbox_bailout(zai_sandbox *sandbox) { - if (!zai_sandbox_timed_out()) { + if (!zai_sandbox_timed_out() && !zai_is_request_blocked()) { zai_sandbox_engine_state_restore(&sandbox->engine_state); return;