Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add http params to wordpress #2439

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
9586996
Provide path params to appsec on Laravel
estringana Nov 28, 2023
d2d57fb
Avoid sending params when no params provided
estringana Nov 28, 2023
14a63ed
Test laravel static routes
estringana Nov 28, 2023
e7bca43
Fix typo
estringana Nov 28, 2023
6e68154
Generate test appsec events only if appsec initiated
estringana Nov 28, 2023
c2a14b6
Amend error
estringana Nov 28, 2023
8bacd98
Amend issues with appsec mock
estringana Nov 29, 2023
fbce7f5
Amend test broken by new appsec integration
estringana Nov 29, 2023
ee94109
Add fix to other Laravel versions
estringana Nov 29, 2023
67df3c8
Fix common laravel tests
estringana Nov 29, 2023
1ba3632
Add path_params to symfony 5.2
estringana Nov 30, 2023
fe89623
Add url params to rest of symfony versions
estringana Nov 30, 2023
f737e6e
Rename ddappsec_push_address to push_params
estringana Dec 11, 2023
3094875
Send pushed params to helper
estringana Dec 11, 2023
05dc8ae
Amend segmentation fault on PHP 7.0
estringana Dec 12, 2023
3bbef17
Amend symfony 3.3
estringana Dec 14, 2023
723655a
Refactor tags
estringana Dec 22, 2023
8af66e2
Add path params to wordpress
estringana Jan 8, 2024
cc52a81
Add http.route and appsec params to wordpress
estringana Dec 28, 2023
c448bd8
Update snapshots
estringana Dec 28, 2023
a523ae7
Update wordpress 4.8 snapshots
estringana Dec 29, 2023
e46f15d
Fix http route on 4.8 snapshot
estringana Jan 2, 2024
0f464d2
Amend wordpress 5.5 snapshots
estringana Jan 2, 2024
29d2b31
Amend wordpress 5.5 snapshots
estringana Jan 2, 2024
de9a2e1
Refactor wordpress routing
estringana Jan 8, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions appsec/src/extension/tags.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@
// This product includes software developed at Datadog
// (https://www.datadoghq.com/). Copyright 2021 Datadog, Inc.
#include "tags.h"
#include "commands/request_exec.h"
#include "ddappsec.h"
#include "ddtrace.h"
#include "ext/pcre/php_pcre.h"
#include "helper_process.h"
#include "ip_extraction.h"
#include "logging.h"
#include "php_compat.h"
Expand Down Expand Up @@ -39,6 +41,7 @@
#define DD_TAG_HTTP_RH_CONTENT_LANGUAGE "http.response.headers.content-language"
#define DD_TAG_HTTP_CLIENT_IP "http.client_ip"
#define DD_TAG_USER_ID "usr.id"
#define DD_TAG_SERVER_REQUEST_PATH_PARAMS "server.request.path_params"
#define DD_MULTIPLE_IP_HEADERS "_dd.multiple-ip-headers"
#define DD_METRIC_ENABLED "_dd.appsec.enabled"
#define DD_APPSEC_EVENTS_PREFIX "appsec.events."
Expand Down Expand Up @@ -100,6 +103,7 @@ static zend_string *_key_server_name_zstr;
static zend_string *_key_http_user_agent_zstr;
static zend_string *_key_https_zstr;
static zend_string *_key_remote_addr_zstr;
static zend_string *_key_server_request_path_params;
static zend_string *_true_zstr;
static zend_string *_false_zstr;
static zend_string *_track_zstr;
Expand Down Expand Up @@ -174,6 +178,8 @@ void dd_tags_startup()
_key_https_zstr = zend_string_init_interned(LSTRARG("HTTPS"), 1);
_key_remote_addr_zstr =
zend_string_init_interned(LSTRARG("REMOTE_ADDR"), 1);
_key_server_request_path_params = zend_string_init_interned(
LSTRARG(DD_TAG_SERVER_REQUEST_PATH_PARAMS), 1);

// Event related strings
_track_zstr =
Expand Down Expand Up @@ -1138,6 +1144,46 @@ static PHP_FUNCTION(datadog_appsec_track_custom_event)
dd_tags_set_sampling_priority();
}

static PHP_FUNCTION(datadog_appsec_push_params)
{
UNUSED(return_value);
if (DDAPPSEC_G(enabled) != ENABLED) {
mlog(dd_log_debug, "Trying to access to push_params "
"function while appsec is disabled");
return;
}

zval *parameters = NULL;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &parameters) == FAILURE ||
Z_TYPE_P(parameters) != IS_ARRAY) {
mlog(dd_log_warning, "Unexpected parameters type. Expected array");
return;
}

zval parameters_zv;
zend_array *parameters_arr = zend_new_array(1);
ZVAL_ARR(&parameters_zv, parameters_arr);
zval *res = zend_hash_add(
Z_ARRVAL(parameters_zv), _key_server_request_path_params, parameters);
if (res == NULL) {
zval_ptr_dtor(&parameters_zv);
mlog_g(dd_log_debug, "Parameters could not be added");
return;
}
Z_ADDREF_P(parameters);

dd_conn *conn = dd_helper_mgr_cur_conn();
if (conn == NULL) {
zval_ptr_dtor(&parameters_zv);
mlog_g(dd_log_debug, "No connection; skipping push_params");
return;
}

dd_request_exec(conn, &parameters_zv);

zval_ptr_dtor(&parameters_zv);
}

static bool _set_appsec_enabled(zval *metrics_zv)
{
zval zv;
Expand Down Expand Up @@ -1228,11 +1274,16 @@ ZEND_ARG_INFO(0, event_name)
ZEND_ARG_INFO(0, metadata)
ZEND_END_ARG_INFO()

ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(push_params_arginfo, 0, 0, IS_VOID, 1)
ZEND_ARG_INFO(0, parameters)
ZEND_END_ARG_INFO()

static const zend_function_entry functions[] = {
ZEND_RAW_FENTRY(DD_APPSEC_NS "track_user_signup_event", PHP_FN(datadog_appsec_track_user_signup_event), datadog_appsec_track_user_signup_event_arginfo, 0)
ZEND_RAW_FENTRY(DD_APPSEC_NS "track_user_login_success_event", PHP_FN(datadog_appsec_track_user_login_success_event), track_user_login_success_event_arginfo, 0)
ZEND_RAW_FENTRY(DD_APPSEC_NS "track_user_login_failure_event", PHP_FN(datadog_appsec_track_user_login_failure_event), track_user_login_failure_event_arginfo, 0)
ZEND_RAW_FENTRY(DD_APPSEC_NS "track_custom_event", PHP_FN(datadog_appsec_track_custom_event), track_custom_event_arginfo, 0)
ZEND_RAW_FENTRY(DD_APPSEC_NS "push_params", PHP_FN(datadog_appsec_push_params), push_params_arginfo, 0)
PHP_FE_END
};

Expand Down
10 changes: 10 additions & 0 deletions appsec/tests/extension/inc/mock_helper.php
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,16 @@ function print_commands($sort = true) {
print_r($commands);
}

function get_command($command) {
$commands = $this->get_commands();
foreach($commands as $c) {
if ($c[0] == $command) {
return $c;
}
}
return [];
}

static function ksort_recurse(&$arr) {
if (!is_array($arr)) {
return;
Expand Down
53 changes: 53 additions & 0 deletions appsec/tests/extension/push_params.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
--TEST--
Push params ara sent on request_exec
--INI--
extension=ddtrace.so
datadog.appsec.log_file=/tmp/php_appsec_test.log
datadog.appsec.waf_timeout=42
datadog.appsec.log_level=debug
datadog.appsec.enabled=1
--ENV--
DD_TRACE_GENERATE_ROOT_SPAN=0
REQUEST_URI=/static01/dynamic01/static02/dynamic02
URL_SCHEME=http
HTTP_CONTENT_TYPE=text/plain
HTTP_CONTENT_LENGTH=0
--FILE--
<?php
use function datadog\appsec\testing\{rinit,rshutdown};
use function datadog\appsec\push_params;

include __DIR__ . '/inc/mock_helper.php';

$helper = Helper::createInitedRun([
response_list(response_request_init(['ok', []])),
response_list(response_request_exec(['ok', [], [], [], [], false]))
]);

var_dump(rinit());
push_params(["some" => "params", "more" => "parameters"]);
var_dump(rshutdown());

var_dump($helper->get_command("request_exec"));

?>
--EXPECTF--
bool(true)
bool(true)
array(2) {
[0]=>
string(12) "request_exec"
[1]=>
array(1) {
[0]=>
array(1) {
["server.request.path_params"]=>
array(2) {
["some"]=>
string(6) "params"
["more"]=>
string(10) "parameters"
}
}
}
}
6 changes: 6 additions & 0 deletions src/Integrations/Integrations/Laravel/LaravelIntegration.php
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,12 @@ function ($This, $scope, $args, $route) use ($integration) {
if (\method_exists($route, 'uri')) {
$rootSpan->meta[Tag::HTTP_ROUTE] = $route->uri();
}
if (\method_exists($route, 'parameters') && function_exists('\datadog\appsec\push_params')) {
$parameters = $route->parameters();
if (count($parameters) > 0) {
\datadog\appsec\push_params($parameters);
}
}
$rootSpan->meta[Tag::HTTP_METHOD] = $request->method();
$rootSpan->meta[Tag::SPAN_KIND] = 'server';
}
Expand Down
7 changes: 7 additions & 0 deletions src/Integrations/Integrations/Symfony/SymfonyIntegration.php
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,13 @@ function (SpanData $span, $args, $response) use ($integration) {
$rootSpan->meta[Tag::HTTP_STATUS_CODE] = $response->getStatusCode();
}

$parameters = $request->get('_route_params');
if (!empty($parameters) &&
is_array($parameters) &&
function_exists('\datadog\appsec\push_params')) {
\datadog\appsec\push_params($parameters);
}

$route = $request->get('_route');
if (null !== $route && null !== $request) {
if (dd_trace_env_config("DD_HTTP_SERVER_ROUTE_BASED_NAMING")) {
Expand Down
17 changes: 17 additions & 0 deletions src/Integrations/Integrations/WordPress/WordPressIntegration.php
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,23 @@ public function init()
return true;
});

\DDTrace\hook_method('WP', 'main', null, function ($This, $scope, $args) {
if (\property_exists($This, 'did_permalink') && $This->did_permalink === true &&
function_exists('is_404') && is_404() === false) {
$rootSpan = \DDTrace\root_span();
if (\property_exists($This, 'matched_rule')) {
$rootSpan->meta[Tag::HTTP_ROUTE] = $This->matched_rule;
}
if (function_exists('\datadog\appsec\push_params') &&
\property_exists($This, 'query_vars')) {
$parameters = $This->query_vars;
if (count($parameters) > 0) {
\datadog\appsec\push_params($parameters);
}
}
}
});

\DDTrace\hook_function(
'wp_authenticate',
null,
Expand Down
35 changes: 29 additions & 6 deletions tests/Appsec/Mock.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,6 @@ class AppsecStatus {

private static $instance = null;

protected function __construct() {
}

public static function getInstance()
{
if (!self::$instance) {
Expand All @@ -23,33 +20,51 @@ protected function getDbPdo()
return new \PDO('mysql:host=mysql_integration;dbname=test', 'test', 'test');
}

/**
* Not all test are interested on events but frameworks are instrumented so this check is to avoid errors
*/
private function initiated()
{
return $this->getDbPdo()->query("SELECT * FROM information_schema.tables WHERE table_name = 'appsec_events'")->rowCount() > 0;
}

public function init()
{
$this->getDbPdo()->exec("CREATE TABLE IF NOT EXISTS appsec_events (event varchar(1000))");
$this->initiated = true;
}

public function destroy()
{
$this->getDbPdo()->exec("DROP TABLE appsec_events");
}

}

public function setDefaults()
{
if (!$this->initiated()) {
return;
}
$this->getDbPdo()->exec("DELETE FROM appsec_events");

}

public function addEvent(array $event, $eventName)
{
if (!$this->initiated()) {
return;
}
$event['eventName'] = $eventName;
$this->getDbPdo()->exec(sprintf("INSERT INTO appsec_events VALUES ('%s')", json_encode($event)));
}

public function getEvents()
{
$result = [];


if (!$this->initiated()) {
return result;
}

$events = $this->getDbPdo()->query("SELECT * FROM appsec_events")->fetchAll();

foreach ($events as $event) {
Expand Down Expand Up @@ -99,3 +114,11 @@ function track_user_signup_event($userId, $metadata, $automated) {
];
AppsecStatus::getInstance()->addEvent($event, 'track_user_signup_event');
}

/**
* This function is exposed by appsec but here we are mocking it for tests
* @param array $params
*/
function push_params($params) {
AppsecStatus::getInstance()->addEvent($params, 'push_params');
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,16 @@ public function simpleViewAction(Request $request)
]);
}

/**
* @Route("/dynamic_route/{param01}/{param02}", name="dynamic route with optionals")
*/
public function dynamicWithOptionalsAction($param01, $param02)
{
return new Response(
'Hi!'
);
}

/**
* @Route("/error", name="error")
* @throws \Exception
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,16 @@ public function simpleViewAction(Request $request)
]);
}

/**
* @Route("/dynamic_route/{param01}/{param02?}", name="dynamic route with optionals")
*/
public function dynamicWithOptionalsAction($param01, $param02)
{
return new Response(
'Hi!'
);
}

/**
* @Route("/error", name="error")
* @throws \Exception
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,16 @@ public function simpleViewAction(Request $request)
]);
}

/**
* @Route("/dynamic_route/{param01}/{param02?}", name="dynamic route with optionals")
*/
public function dynamicWithOptionalsAction($param01, $param02)
{
return new Response(
'Hi!'
);
}

/**
* @Route("/error", name="error")
* @throws \Exception
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,16 @@ public function simpleViewAction(Request $request)
]);
}

/**
* @Route("/dynamic_route/{param01}/{param02?}", name="dynamic route with optionals")
*/
public function dynamicWithOptionalsAction($param01, $param02)
{
return new Response(
'Hi!'
);
}

/**
* @Route("/error", name="error")
* @throws \Exception
Expand Down
3 changes: 3 additions & 0 deletions tests/Frameworks/WordPress/Version_4_8/wp-config.php
Original file line number Diff line number Diff line change
Expand Up @@ -89,5 +89,8 @@
if ( !defined('ABSPATH') )
define('ABSPATH', dirname(__FILE__) . '/');

//Appsec mock. This wont be needed on customer apps since this functions will be exposed by appsec
require __DIR__.'/../../../Appsec/Mock.php';

/** Sets up WordPress vars and included files. */
require_once(ABSPATH . 'wp-settings.php');
3 changes: 0 additions & 3 deletions tests/Frameworks/WordPress/Version_4_8/wp-login.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,6 @@
/** Make sure that the WordPress bootstrap has run before continuing. */
require( dirname(__FILE__) . '/wp-load.php' );

//Appsec mock. This wont be needed on customer apps since this functions will be exposed by appsec
require __DIR__.'/../../../Appsec/Mock.php';

// Redirect to https login if forced to use SSL
if ( force_ssl_admin() && ! is_ssl() ) {
if ( 0 === strpos($_SERVER['REQUEST_URI'], 'http') ) {
Expand Down
3 changes: 3 additions & 0 deletions tests/Frameworks/WordPress/Version_5_5/wp-config.php

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading