Skip to content

Commit

Permalink
Add multiple rasp endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
estringana committed Feb 5, 2025
1 parent 2377809 commit d86e0ab
Show file tree
Hide file tree
Showing 7 changed files with 329 additions and 1 deletion.
11 changes: 11 additions & 0 deletions docs/weblog/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -768,6 +768,17 @@ Examples:
- `GET`: `/rasp/ssrf?user_id="' OR 1 = 1 --"`
- `POST`: `{"user_id": "' OR 1 = 1 --"}`

### \[GET,POST\] /rasp/multiple
The idea of this endpoint is to have an endpoint where multiple rasp operation take place. All of them will generate a MATCH on the WAF but none of them will block. The goal of this endpoint is to verify that the `rasp.rule.match` telemetry entry is updated properly. While this seems easy, the WAF requires that data given on `call` is passed as ephemeral and not as persistent.

In order to make the test easier, the operation used here need to generate LFI matches. The request will have two get parameters(`file1`, `file2`) which will contain a path that needs to be used as the parameters of the choosen lfi function. Then there will be another call to the lfi function with a harcoded parameter `'../etc/passwd'`. This will make `rasp.rule.match` to be equal to 3. A code example look like:

```
lfi_operation($request->get('file1'))
lfi_operation($request->get('file2'))
lfi_operation('../etc/passwd') //This one is harcoded
```

### GET /dsm/inject
This endpoint is used to validate DSM context injection injects the correct encoding to a headers carrier.

Expand Down
1 change: 1 addition & 0 deletions manifests/php.yml
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ tests/:
Test_Lfi_Rules_Version: v1.6.2
Test_Lfi_StackTrace: v1.6.2
Test_Lfi_Telemetry: missing_feature
Test_Lfi_Telemetry_Multiple_Exploits: v1.7.0
Test_Lfi_UrlQuery: v1.6.2
Test_Lfi_Waf_Version: v1.6.2
test_shi.py:
Expand Down
282 changes: 282 additions & 0 deletions tests/appsec/rasp/rasp_ruleset_non_blocking.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,282 @@
{
"version": "2.1",
"metadata": {
"rules_version": "1.99.0"
},
"rules": [
{
"id": "rasp-930-111",
"name": "Local file inclusion exploit",
"tags": {
"type": "lfi",
"category": "vulnerability_trigger",
"cwe": "22",
"capec": "1000/255/153/126",
"confidence": "0",
"module": "rasp"
},
"conditions": [
{
"parameters": {
"inputs": [
{
"address": "server.request.query"
}
],
"regex": "asdnjakslnbdklasbdkasbdkl"
},
"operator": "match_regex"
}
],
"transformers": [],
"on_match": [
"stack_trace"
]
},

{
"id": "rasp-930-100",
"name": "Local file inclusion exploit",
"tags": {
"type": "lfi",
"category": "vulnerability_trigger",
"cwe": "22",
"capec": "1000/255/153/126",
"confidence": "0",
"module": "rasp"
},
"conditions": [
{
"parameters": {
"resource": [
{
"address": "server.io.fs.file"
}
],
"params": [
{
"address": "server.request.query"
},
{
"address": "server.request.body"
},
{
"address": "server.request.path_params"
},
{
"address": "grpc.server.request.message"
},
{
"address": "graphql.server.all_resolvers"
},
{
"address": "graphql.server.resolver"
}
]
},
"operator": "lfi_detector"
}
],
"transformers": [],
"on_match": [
"stack_trace"
]
},
{
"id": "rasp-934-100",
"name": "Server-side request forgery exploit",
"tags": {
"type": "ssrf",
"category": "vulnerability_trigger",
"cwe": "918",
"capec": "1000/225/115/664",
"confidence": "0",
"module": "rasp"
},
"conditions": [
{
"parameters": {
"resource": [
{
"address": "server.io.net.url"
}
],
"params": [
{
"address": "server.request.query"
},
{
"address": "server.request.body"
},
{
"address": "server.request.path_params"
},
{
"address": "grpc.server.request.message"
},
{
"address": "graphql.server.all_resolvers"
},
{
"address": "graphql.server.resolver"
}
]
},
"operator": "ssrf_detector"
}
],
"transformers": [],
"on_match": [
"stack_trace"
]
},
{
"id": "rasp-942-100",
"name": "SQL injection exploit",
"tags": {
"type": "sql_injection",
"category": "vulnerability_trigger",
"cwe": "89",
"capec": "1000/152/248/66",
"confidence": "0",
"module": "rasp"
},
"conditions": [
{
"parameters": {
"resource": [
{
"address": "server.db.statement"
}
],
"params": [
{
"address": "server.request.query"
},
{
"address": "server.request.body"
},
{
"address": "server.request.path_params"
},
{
"address": "graphql.server.all_resolvers"
},
{
"address": "graphql.server.resolver"
}
],
"db_type": [
{
"address": "server.db.system"
}
]
},
"operator": "sqli_detector"
}
],
"transformers": [],
"on_match": [
"stack_trace"
]
},
{
"id": "rasp-932-100",
"name": "Shell injection exploit",
"enabled": true,
"tags": {
"type": "command_injection",
"category": "vulnerability_trigger",
"cwe": "77",
"capec": "1000/152/248/88",
"confidence": "0",
"module": "rasp"
},
"conditions": [
{
"parameters": {
"resource": [
{
"address": "server.sys.shell.cmd"
}
],
"params": [
{
"address": "server.request.query"
},
{
"address": "server.request.body"
},
{
"address": "server.request.path_params"
},
{
"address": "grpc.server.request.message"
},
{
"address": "graphql.server.all_resolvers"
},
{
"address": "graphql.server.resolver"
}
]
},
"operator": "shi_detector"
}
],
"transformers": [],
"on_match": [
"stack_trace"
]
},
{
"id": "rasp-932-110",
"name": "OS command injection exploit",
"enabled": true,
"tags": {
"type": "command_injection",
"category": "vulnerability_trigger",
"cwe": "77",
"capec": "1000/152/248/88",
"confidence": "0",
"module": "rasp"
},
"conditions": [
{
"parameters": {
"resource": [
{
"address": "server.sys.exec.cmd"
}
],
"params": [
{
"address": "server.request.query"
},
{
"address": "server.request.body"
},
{
"address": "server.request.path_params"
},
{
"address": "grpc.server.request.message"
},
{
"address": "graphql.server.all_resolvers"
},
{
"address": "graphql.server.resolver"
}
]
},
"operator": "cmdi_detector"
}
],
"transformers": [],
"on_match": [
"stack_trace"
]
}
]
}
19 changes: 19 additions & 0 deletions tests/appsec/rasp/test_lfi.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
# This product includes software developed at Datadog (https://www.datadoghq.com/).
# Copyright 2021 Datadog, Inc.


from utils import features, weblog, interfaces, scenarios, rfc
from utils import remote_config as rc
from utils.dd_constants import Capabilities
Expand Down Expand Up @@ -134,6 +135,24 @@ def test_lfi_span_tags(self):
validate_span_tags(self.r, expected_metrics=["_dd.appsec.rasp.duration_ext", "_dd.appsec.rasp.rule.eval"])


@rfc("https://docs.google.com/document/d/1vmMqpl8STDk7rJnd3YBsa6O9hCls_XHHdsodD61zr_4/edit#heading=h.96mezjnqf46y")
@features.rasp_span_tags
@features.rasp_local_file_inclusion
@scenarios.appsec_runtime_activation
class Test_Lfi_Telemetry_Multiple_Exploits:
"""Validate rasp match telemetry metric works"""

def setup_rasp_match_tag(self):
self.config_state_1 = rc.rc_state.reset().set_config(*RC_CONSTANTS.CONFIG_ENABLED).apply()
self.config_state_1b = rc.rc_state.set_config(*RC_CONSTANTS.RULES_NON_BLOCKING).apply()
self.r = weblog.get("/rasp/multiple", params={"file1": "../etc/passwd", "file2": "../etc/group"})

def test_rasp_match_tag(self):
series_eval = find_series(True, "appsec", "rasp.rule.match")
assert series_eval
assert series_eval[0]["points"][0][1] == 3.0


@rfc("https://docs.google.com/document/d/1vmMqpl8STDk7rJnd3YBsa6O9hCls_XHHdsodD61zr_4/edit#heading=h.enmf90juqidf")
@features.rasp_stack_trace
@features.rasp_local_file_inclusion
Expand Down
5 changes: 5 additions & 0 deletions tests/appsec/rasp/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,11 @@ class RC_CONSTANTS:
_load_file("./tests/appsec/rasp/rasp_ruleset.json"),
)

RULES_NON_BLOCKING = (
"datadog/2/ASM_DD/rules/config",
_load_file("./tests/appsec/rasp/rasp_ruleset_non_blocking.json"),
)


class Base_Rules_Version:
"""Test libddwaf version"""
Expand Down
6 changes: 5 additions & 1 deletion utils/_context/_scenarios/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,11 @@ class _Scenarios:
rc_api_enabled=True,
appsec_enabled=False,
iast_enabled=False,
weblog_env={"DD_APPSEC_WAF_TIMEOUT": "10000000", "DD_APPSEC_TRACE_RATE_LIMIT": "10000"}, # 10 seconds
weblog_env={
"DD_APPSEC_WAF_TIMEOUT": "10000000",
"DD_APPSEC_TRACE_RATE_LIMIT": "10000",
"DD_APPSEC_RASP_ENABLED": "true",
}, # 10 seconds
doc="",
scenario_groups=[ScenarioGroup.APPSEC, ScenarioGroup.APPSEC_RASP],
)
Expand Down
6 changes: 6 additions & 0 deletions utils/build/docker/php/common/rasp/multiple.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?php
@file_get_contents(urldecode($_GET["file1"]));
@file_get_contents(urldecode($_GET["file2"]));
@file_get_contents('../etc/passwd');

echo "Hello, multiple rasp!";

0 comments on commit d86e0ab

Please sign in to comment.