Skip to content

Commit

Permalink
Merge branch 'main' into zachg/add_rcm_for_trace_sampling_rules
Browse files Browse the repository at this point in the history
  • Loading branch information
ZStriker19 authored Apr 30, 2024
2 parents 6c6a2e0 + c46f79b commit a719fa0
Show file tree
Hide file tree
Showing 38 changed files with 1,352 additions and 1,054 deletions.
12 changes: 0 additions & 12 deletions .github/workflows/build_deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,6 @@ on:
# before merging/releasing
- build_deploy*
pull_request:
paths:
- ".github/workflows/build_deploy.yml"
- ".github/workflows/build_python_3.yml"
- "setup.py"
- "setup.cfg"
- "pyproject.toml"
- "**.c"
- "**.h"
- "**.cpp"
- "**.hpp"
- "**.pyx"
- "ddtrace/vendor/**"
release:
types:
- published
Expand Down
5 changes: 2 additions & 3 deletions benchmarks/appsec_iast_propagation/scenario.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
from typing import Any # noqa:F401

import bm

from tests.utils import override_env
from bm.utils import override_env


with override_env({"DD_IAST_ENABLED": "True"}):
Expand Down Expand Up @@ -42,7 +41,7 @@ def aspect_function(internal_loop, tainted):
value = ""
res = value
for _ in range(internal_loop):
res = add_aspect(res, join_aspect(str.join, 1, "_", (tainted, "_", tainted)))
res = add_aspect(res, join_aspect("_".join, 1, "_", (tainted, "_", tainted)))
value = res
res = add_aspect(res, tainted)
value = res
Expand Down
31 changes: 25 additions & 6 deletions ddtrace/appsec/_asm_request_context.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from ddtrace._trace.span import Span
from ddtrace.appsec import _handlers
from ddtrace.appsec._constants import APPSEC
from ddtrace.appsec._constants import EXPLOIT_PREVENTION
from ddtrace.appsec._constants import SPAN_DATA_NAMES
from ddtrace.appsec._constants import WAF_CONTEXT_NAMES
from ddtrace.appsec._ddwaf import DDWaf_result
Expand Down Expand Up @@ -147,6 +148,12 @@ def __init__(self):
"triggered": False,
"timeout": False,
"version": None,
"rasp": {
"called": False,
"eval": {t: 0 for _, t in EXPLOIT_PREVENTION.TYPE},
"match": {t: 0 for _, t in EXPLOIT_PREVENTION.TYPE},
"timeout": {t: 0 for _, t in EXPLOIT_PREVENTION.TYPE},
},
}
env.callbacks[_CONTEXT_CALL] = []

Expand Down Expand Up @@ -330,15 +337,27 @@ def asm_request_context_set(


def set_waf_telemetry_results(
rules_version: Optional[str], is_triggered: bool, is_blocked: bool, is_timeout: bool
rules_version: Optional[str],
is_triggered: bool,
is_blocked: bool,
is_timeout: bool,
rule_type: Optional[str],
) -> None:
result = get_value(_TELEMETRY, _TELEMETRY_WAF_RESULTS)
if result is not None:
result["triggered"] |= is_triggered
result["blocked"] |= is_blocked
result["timeout"] |= is_timeout
if rules_version is not None:
result["version"] = rules_version
if rule_type is None:
# Request Blocking telemetry
result["triggered"] |= is_triggered
result["blocked"] |= is_blocked
result["timeout"] |= is_timeout
if rules_version is not None:
result["version"] = rules_version
else:
# Exploit Prevention telemetry
result["rasp"]["called"] = True
result["rasp"]["eval"][rule_type] += 1
result["rasp"]["match"][rule_type] += int(is_triggered)
result["rasp"]["timeout"][rule_type] += int(is_timeout)


def get_waf_telemetry_results() -> Optional[Dict[str, Any]]:
Expand Down
28 changes: 24 additions & 4 deletions ddtrace/appsec/_common_module_patches.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

import ctypes
import gc
import os
from typing import Any
from typing import Callable
from typing import Dict
Expand Down Expand Up @@ -48,14 +49,23 @@ def wrapped_open_CFDDB7ABBA9081B6(original_open_callable, instance, args, kwargs
try:
from ddtrace.appsec._asm_request_context import call_waf_callback
from ddtrace.appsec._asm_request_context import in_context
from ddtrace.appsec._constants import EXPLOIT_PREVENTION
except ImportError:
# open is used during module initialization
# and shouldn't be changed at that time
return original_open_callable(*args, **kwargs)

filename = args[0] if args else kwargs.get("file", None)
filename_arg = args[0] if args else kwargs.get("file", None)
try:
filename = os.fspath(filename_arg)
except Exception:
filename = ""
if filename and in_context():
call_waf_callback({"LFI_ADDRESS": filename}, crop_trace="wrapped_open_CFDDB7ABBA9081B6")
call_waf_callback(
{EXPLOIT_PREVENTION.ADDRESS.LFI: filename},
crop_trace="wrapped_open_CFDDB7ABBA9081B6",
rule_type=EXPLOIT_PREVENTION.TYPE.LFI,
)
# DEV: Next part of the exploit prevention feature: add block here
return original_open_callable(*args, **kwargs)

Expand All @@ -72,6 +82,7 @@ def wrapped_open_ED4CF71136E15EBF(original_open_callable, instance, args, kwargs
try:
from ddtrace.appsec._asm_request_context import call_waf_callback
from ddtrace.appsec._asm_request_context import in_context
from ddtrace.appsec._constants import EXPLOIT_PREVENTION
except ImportError:
# open is used during module initialization
# and shouldn't be changed at that time
Expand All @@ -82,7 +93,11 @@ def wrapped_open_ED4CF71136E15EBF(original_open_callable, instance, args, kwargs
if url.__class__.__name__ == "Request":
url = url.get_full_url()
if isinstance(url, str):
call_waf_callback({"SSRF_ADDRESS": url}, crop_trace="wrapped_open_ED4CF71136E15EBF")
call_waf_callback(
{EXPLOIT_PREVENTION.ADDRESS.SSRF: url},
crop_trace="wrapped_open_ED4CF71136E15EBF",
rule_type=EXPLOIT_PREVENTION.TYPE.SSRF,
)
# DEV: Next part of the exploit prevention feature: add block here
return original_open_callable(*args, **kwargs)

Expand All @@ -100,6 +115,7 @@ def wrapped_request_D8CB81E472AF98A2(original_request_callable, instance, args,
try:
from ddtrace.appsec._asm_request_context import call_waf_callback
from ddtrace.appsec._asm_request_context import in_context
from ddtrace.appsec._constants import EXPLOIT_PREVENTION
except ImportError:
# open is used during module initialization
# and shouldn't be changed at that time
Expand All @@ -108,7 +124,11 @@ def wrapped_request_D8CB81E472AF98A2(original_request_callable, instance, args,
url = args[1] if len(args) > 1 else kwargs.get("url", None)
if url and in_context():
if isinstance(url, str):
call_waf_callback({"SSRF_ADDRESS": url}, crop_trace="wrapped_request_D8CB81E472AF98A2")
call_waf_callback(
{EXPLOIT_PREVENTION.ADDRESS.SSRF: url},
crop_trace="wrapped_request_D8CB81E472AF98A2",
rule_type=EXPLOIT_PREVENTION.TYPE.SSRF,
)
# DEV: Next part of the exploit prevention feature: add block here
return original_request_callable(*args, **kwargs)

Expand Down
9 changes: 9 additions & 0 deletions ddtrace/appsec/_constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -248,3 +248,12 @@ class EXPLOIT_PREVENTION(metaclass=Constant_Class):
STACK_TRACE_ENABLED = "DD_APPSEC_STACK_TRACE_ENABLED"
MAX_STACK_TRACES = "DD_APPSEC_MAX_STACK_TRACES"
MAX_STACK_TRACE_DEPTH = "DD_APPSEC_MAX_STACK_TRACE_DEPTH"

class TYPE(metaclass=Constant_Class):
LFI = "lfi"
SSRF = "ssrf"
SQLI = "sql_injection"

class ADDRESS(metaclass=Constant_Class):
LFI = "LFI_ADDRESS"
SSRF = "SSRF_ADDRESS"
4 changes: 4 additions & 0 deletions ddtrace/appsec/_iast/_evidence_redaction/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
from ddtrace.appsec._iast._evidence_redaction._sensitive_handler import sensitive_handler


sensitive_handler
Loading

0 comments on commit a719fa0

Please sign in to comment.