Skip to content

Commit

Permalink
Merge branch 'master' into ugaitz/collect-headers-on-user-event
Browse files Browse the repository at this point in the history
  • Loading branch information
uurien authored Jun 12, 2024
2 parents 6b1b221 + 5278b1c commit 3cd1943
Show file tree
Hide file tree
Showing 11 changed files with 528 additions and 13 deletions.
6 changes: 5 additions & 1 deletion packages/dd-trace/src/appsec/rasp.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ const addresses = require('./addresses')
const { httpClientRequestStart } = require('./channels')
const waf = require('./waf')

const RULE_TYPES = {
SSRF: 'ssrf'
}

function enable () {
httpClientRequestStart.subscribe(analyzeSsrf)
}
Expand All @@ -26,7 +30,7 @@ function analyzeSsrf (ctx) {
// TODO: Currently this is only monitoring, we should
// block the request if SSRF attempt and
// generate stack traces
waf.run({ persistent }, req)
waf.run({ persistent }, req, RULE_TYPES.SSRF)
}

module.exports = {
Expand Down
211 changes: 208 additions & 3 deletions packages/dd-trace/src/appsec/recommended.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"version": "2.2",
"metadata": {
"rules_version": "1.11.0"
"rules_version": "1.12.0"
},
"rules": [
{
Expand Down Expand Up @@ -1921,7 +1921,6 @@
"$ifs",
"$oldpwd",
"$ostype",
"$path",
"$pwd",
"dev/fd/",
"dev/null",
Expand Down Expand Up @@ -5849,7 +5848,8 @@
"/website.php",
"/stats.php",
"/assets/plugins/mp3_id/mp3_id.php",
"/siteminderagent/forms/smpwservices.fcc"
"/siteminderagent/forms/smpwservices.fcc",
"/eval-stdin.php"
]
}
}
Expand Down Expand Up @@ -6236,6 +6236,155 @@
],
"transformers": []
},
{
"id": "rasp-930-100",
"name": "Local file inclusion exploit",
"enabled": false,
"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",
"enabled": false,
"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",
"enabled": false,
"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": "sqr-000-001",
"name": "SSRF: Try to access the credential manager of the main cloud services",
Expand Down Expand Up @@ -8391,6 +8540,34 @@
}
],
"scanners": [
{
"id": "406f8606-52c4-4663-8db9-df70f9e8766c",
"name": "ZIP Code",
"key": {
"operator": "match_regex",
"parameters": {
"regex": "\\b(?:zip|postal)\\b",
"options": {
"case_sensitive": false,
"min_length": 3
}
}
},
"value": {
"operator": "match_regex",
"parameters": {
"regex": "^[0-9]{5}(?:-[0-9]{4})?$",
"options": {
"case_sensitive": true,
"min_length": 5
}
}
},
"tags": {
"type": "zipcode",
"category": "address"
}
},
{
"id": "JU1sRk3mSzqSUJn6GrVn7g",
"name": "American Express Card Scanner (4+4+4+3 digits)",
Expand Down Expand Up @@ -9157,6 +9334,34 @@
"category": "payment"
}
},
{
"id": "18b608bd7a764bff5b2344c0",
"name": "Phone number",
"key": {
"operator": "match_regex",
"parameters": {
"regex": "\\bphone|number|mobile\\b",
"options": {
"case_sensitive": false,
"min_length": 3
}
}
},
"value": {
"operator": "match_regex",
"parameters": {
"regex": "^(?:\\(\\+\\d{1,3}\\)|\\+\\d{1,3}|00\\d{1,3})?[-\\s\\.]?(?:\\(\\d{3}\\)[-\\s\\.]?)?(?:\\d[-\\s\\.]?){6,10}$",
"options": {
"case_sensitive": false,
"min_length": 6
}
}
},
"tags": {
"type": "phone",
"category": "pii"
}
},
{
"id": "de0899e0cbaaa812bb624cf04c912071012f616d-mod",
"name": "UK National Insurance Number Scanner",
Expand Down
22 changes: 19 additions & 3 deletions packages/dd-trace/src/appsec/reporter.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ const { ipHeaderList } = require('../plugins/util/ip_extractor')
const {
incrementWafInitMetric,
updateWafRequestsMetricTags,
updateRaspRequestsMetricTags,
incrementWafUpdatesMetric,
incrementWafRequestsMetric,
getRequestMetrics
Expand Down Expand Up @@ -98,16 +99,19 @@ function reportWafInit (wafVersion, rulesVersion, diagnosticsRules = {}) {
incrementWafInitMetric(wafVersion, rulesVersion)
}

function reportMetrics (metrics) {
function reportMetrics (metrics, raspRuleType) {
const store = storage.getStore()
const rootSpan = store?.req && web.root(store.req)
if (!rootSpan) return

if (metrics.rulesVersion) {
rootSpan.setTag('_dd.appsec.event_rules.version', metrics.rulesVersion)
}

updateWafRequestsMetricTags(metrics, store.req)
if (raspRuleType) {
updateRaspRequestsMetricTags(metrics, store.req, raspRuleType)
} else {
updateWafRequestsMetricTags(metrics, store.req)
}
}

function reportAttack (attackData) {
Expand Down Expand Up @@ -181,6 +185,18 @@ function finishRequest (req, res) {
rootSpan.setTag('_dd.appsec.waf.duration_ext', metrics.durationExt)
}

if (metrics?.raspDuration) {
rootSpan.setTag('_dd.appsec.rasp.duration', metrics.raspDuration)
}

if (metrics?.raspDurationExt) {
rootSpan.setTag('_dd.appsec.rasp.duration_ext', metrics.raspDurationExt)
}

if (metrics?.raspEvalCount) {
rootSpan.setTag('_dd.appsec.rasp.rule.eval', metrics.raspEvalCount)
}

incrementWafRequestsMetric(req)

// collect some headers even when no attack is detected
Expand Down
34 changes: 33 additions & 1 deletion packages/dd-trace/src/appsec/telemetry.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,10 @@ function newStore () {
return {
[DD_TELEMETRY_REQUEST_METRICS]: {
duration: 0,
durationExt: 0
durationExt: 0,
raspDuration: 0,
raspDurationExt: 0,
raspEvalCount: 0
}
}
}
Expand Down Expand Up @@ -76,6 +79,28 @@ function getOrCreateMetricTags (store, versionsTags) {
return metricTags
}

function updateRaspRequestsMetricTags (metrics, req, raspRuleType) {
if (!req) return

const store = getStore(req)

// it does not depend on whether telemetry is enabled or not
addRaspRequestMetrics(store, metrics)

if (!enabled) return

const tags = { rule_type: raspRuleType, waf_version: metrics.wafVersion }
appsecMetrics.count('appsec.rasp.rule.eval', tags).inc(1)

if (metrics.wafTimeout) {
appsecMetrics.count('appsec.rasp.timeout', tags).inc(1)
}

if (metrics.ruleTriggered) {
appsecMetrics.count('appsec.rasp.rule.match', tags).inc(1)
}
}

function updateWafRequestsMetricTags (metrics, req) {
if (!req) return

Expand Down Expand Up @@ -141,6 +166,12 @@ function addRequestMetrics (store, { duration, durationExt }) {
store[DD_TELEMETRY_REQUEST_METRICS].durationExt += durationExt || 0
}

function addRaspRequestMetrics (store, { duration, durationExt }) {
store[DD_TELEMETRY_REQUEST_METRICS].raspDuration += duration || 0
store[DD_TELEMETRY_REQUEST_METRICS].raspDurationExt += durationExt || 0
store[DD_TELEMETRY_REQUEST_METRICS].raspEvalCount++
}

function getRequestMetrics (req) {
if (req) {
const store = getStore(req)
Expand All @@ -153,6 +184,7 @@ module.exports = {
disable,

updateWafRequestsMetricTags,
updateRaspRequestsMetricTags,
incrementWafInitMetric,
incrementWafUpdatesMetric,
incrementWafRequestsMetric,
Expand Down
Loading

0 comments on commit 3cd1943

Please sign in to comment.