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

Test multiple rasp during one request #3989

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
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
3 changes: 3 additions & 0 deletions .github/workflows/run-end-to-end.yml
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,9 @@ jobs:
- name: Run APPSEC_RASP scenario
if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"APPSEC_RASP"')
run: ./run.sh APPSEC_RASP
- name: Run APPSEC_RASP_NON_BLOCKING scenario
if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"APPSEC_RASP_NON_BLOCKING"')
run: ./run.sh APPSEC_RASP_NON_BLOCKING
- name: Run APPSEC_META_STRUCT_DISABLED scenario
if: always() && steps.build.outcome == 'success' && contains(inputs.scenarios, '"APPSEC_META_STRUCT_DISABLED"')
run: ./run.sh APPSEC_META_STRUCT_DISABLED
Expand Down
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\] /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/dotnet.yml
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ tests/:
Test_Lfi_Rules_Version: v3.7.0
Test_Lfi_StackTrace: v2.51.0
Test_Lfi_Telemetry: v2.51.0
Test_Lfi_Telemetry_Multiple_Exploits: missing_feature
Test_Lfi_UrlQuery: v2.51.0
Test_Lfi_Waf_Version: v3.4.1
test_shi.py:
Expand Down
1 change: 1 addition & 0 deletions manifests/java.yml
Original file line number Diff line number Diff line change
Expand Up @@ -678,6 +678,7 @@ tests/:
Test_Lfi_Telemetry:
'*': v1.40.0
spring-boot-3-native: missing_feature (GraalVM. Tracing support only)
Test_Lfi_Telemetry_Multiple_Exploits: missing_feature
Test_Lfi_UrlQuery:
'*': v1.40.0
spring-boot-3-native: missing_feature (GraalVM. Tracing support only)
Expand Down
1 change: 1 addition & 0 deletions manifests/nodejs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -386,6 +386,7 @@ tests/:
Test_Lfi_Rules_Version: *ref_5_26_0
Test_Lfi_StackTrace: *ref_5_24_0
Test_Lfi_Telemetry: *ref_5_24_0
Test_Lfi_Telemetry_Multiple_Exploits: missing_feature
Test_Lfi_UrlQuery:
'*': *ref_5_24_0
express5: *ref_5_29_0
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
1 change: 1 addition & 0 deletions manifests/python.yml
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,7 @@ tests/:
Test_Lfi_Rules_Version: v2.18.0.dev
Test_Lfi_StackTrace: v2.10.0
Test_Lfi_Telemetry: v2.10.0
Test_Lfi_Telemetry_Multiple_Exploits: missing_feature
Test_Lfi_UrlQuery: v2.10.0
Test_Lfi_Waf_Version: v2.15.0
test_shi.py:
Expand Down
282 changes: 282 additions & 0 deletions tests/appsec/rasp/rasp_non_blocking_ruleset.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"
]
}
]
}
16 changes: 16 additions & 0 deletions tests/appsec/rasp/test_lfi.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,22 @@ 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_rasp_non_blocking
class Test_Lfi_Telemetry_Multiple_Exploits:
"""Validate rasp match telemetry metric works"""

def setup_rasp_match_tag(self):
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
14 changes: 14 additions & 0 deletions utils/_context/_scenarios/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -820,6 +820,20 @@ class _Scenarios:
scenario_groups=[ScenarioGroup.APPSEC, ScenarioGroup.APPSEC_RASP],
)

appsec_rasp_non_blocking = EndToEndScenario(
"APPSEC_RASP_NON_BLOCKING",
weblog_env={"DD_APPSEC_RASP_ENABLED": "true", "DD_APPSEC_RULES": "/appsec_rasp_non_blocking_ruleset.json"},
weblog_volumes={
"./tests/appsec/rasp/rasp_non_blocking_ruleset.json": {
"bind": "/appsec_rasp_non_blocking_ruleset.json",
"mode": "ro",
}
},
doc="Enable APPSEC RASP",
github_workflow="endtoend",
scenario_groups=[ScenarioGroup.APPSEC],
)

agent_not_supporting_span_events = EndToEndScenario(
"AGENT_NOT_SUPPORTING_SPAN_EVENTS",
span_events=False,
Expand Down
Loading
Loading