Skip to content

Commit 3d05ac2

Browse files
iunanuauurien
andauthored
Report IAST metrics via telemetry (#2805)
Co-authored-by: Ugaitz Urien <[email protected]>
1 parent 3a2347c commit 3d05ac2

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+2150
-184
lines changed

packages/dd-trace/src/appsec/iast/analyzers/command-injection-analyzer.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ const { COMMAND_INJECTION } = require('../vulnerabilities')
55
class CommandInjectionAnalyzer extends InjectionAnalyzer {
66
constructor () {
77
super(COMMAND_INJECTION)
8+
}
9+
10+
onConfigure () {
811
this.addSub('datadog:child_process:execution:start', ({ command }) => this.analyze(command))
912
}
1013
}

packages/dd-trace/src/appsec/iast/analyzers/cookie-analyzer.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,13 @@ class CookieAnalyzer extends Analyzer {
99
constructor (type, propertyToBeSafe) {
1010
super(type)
1111
this.propertyToBeSafe = propertyToBeSafe.toLowerCase()
12-
this.addSub('datadog:iast:set-cookie', (cookieInfo) => this.analyze(cookieInfo))
12+
}
13+
14+
onConfigure () {
15+
this.addSub(
16+
{ channelName: 'datadog:iast:set-cookie', moduleName: 'http' },
17+
(cookieInfo) => this.analyze(cookieInfo)
18+
)
1319
}
1420

1521
_isVulnerable ({ cookieProperties, cookieValue }) {

packages/dd-trace/src/appsec/iast/analyzers/ldap-injection-analyzer.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ const { LDAP_INJECTION } = require('../vulnerabilities')
55
class LdapInjectionAnalyzer extends InjectionAnalyzer {
66
constructor () {
77
super(LDAP_INJECTION)
8+
}
9+
10+
onConfigure () {
811
this.addSub('datadog:ldapjs:client:search', ({ base, filter }) => this.analyzeAll(base, filter))
912
}
1013
}

packages/dd-trace/src/appsec/iast/analyzers/path-traversal-analyzer.js

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,34 @@
11
'use strict'
22

33
const path = require('path')
4+
5+
const InjectionAnalyzer = require('./injection-analyzer')
46
const { getIastContext } = require('../iast-context')
57
const { storage } = require('../../../../../datadog-core')
6-
const InjectionAnalyzer = require('./injection-analyzer')
78
const { PATH_TRAVERSAL } = require('../vulnerabilities')
89

910
const ignoredOperations = ['dir.close', 'close']
1011

1112
class PathTraversalAnalyzer extends InjectionAnalyzer {
1213
constructor () {
1314
super(PATH_TRAVERSAL)
14-
this.addSub('apm:fs:operation:start', obj => {
15+
16+
this.exclusionList = [
17+
path.join('node_modules', 'send') + path.sep
18+
]
19+
20+
this.internalExclusionList = [
21+
'node:fs',
22+
'node:internal/fs',
23+
'node:internal\\fs',
24+
'fs.js',
25+
'internal/fs',
26+
'internal\\fs'
27+
]
28+
}
29+
30+
onConfigure () {
31+
this.addSub('apm:fs:operation:start', (obj) => {
1532
if (ignoredOperations.includes(obj.operation)) return
1633

1734
const pathArguments = []
@@ -44,19 +61,6 @@ class PathTraversalAnalyzer extends InjectionAnalyzer {
4461
}
4562
this.analyze(pathArguments)
4663
})
47-
48-
this.exclusionList = [
49-
path.join('node_modules', 'send') + path.sep
50-
]
51-
52-
this.internalExclusionList = [
53-
'node:fs',
54-
'node:internal/fs',
55-
'node:internal\\fs',
56-
'fs.js',
57-
'internal/fs',
58-
'internal\\fs'
59-
]
6064
}
6165

6266
_isExcluded (location) {

packages/dd-trace/src/appsec/iast/analyzers/sql-injection-analyzer.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ const EXCLUDED_PATHS = getNodeModulesPaths('mysql2', 'sequelize')
1313
class SqlInjectionAnalyzer extends InjectionAnalyzer {
1414
constructor () {
1515
super(SQL_INJECTION)
16+
}
17+
18+
onConfigure () {
1619
this.addSub('apm:mysql:query:start', ({ sql }) => this.analyze(sql, 'MYSQL'))
1720
this.addSub('apm:mysql2:query:start', ({ sql }) => this.analyze(sql, 'MYSQL'))
1821
this.addSub('apm:pg:query:start', ({ query }) => this.analyze(query.text, 'POSTGRES'))
@@ -41,10 +44,9 @@ class SqlInjectionAnalyzer extends InjectionAnalyzer {
4144

4245
analyze (value, dialect) {
4346
const store = storage.getStore()
44-
4547
if (!(store && store.sqlAnalyzed)) {
4648
const iastContext = getIastContext(store)
47-
if (store && !iastContext) return
49+
if (this._isInvalidContext(store, iastContext)) return
4850
this._reportIfVulnerable(value, iastContext, dialect)
4951
}
5052
}
@@ -66,6 +68,7 @@ class SqlInjectionAnalyzer extends InjectionAnalyzer {
6668
addVulnerability(context, vulnerability)
6769
}
6870
}
71+
6972
_getExcludedPaths () {
7073
return EXCLUDED_PATHS
7174
}

packages/dd-trace/src/appsec/iast/analyzers/ssrf-analyzer.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ const { SSRF } = require('../vulnerabilities')
66
class SSRFAnalyzer extends InjectionAnalyzer {
77
constructor () {
88
super(SSRF)
9+
}
910

11+
onConfigure () {
1012
this.addSub('apm:http:client:request:start', ({ args }) => {
1113
if (typeof args.originalUrl === 'string') {
1214
this.analyze(args.originalUrl)

packages/dd-trace/src/appsec/iast/analyzers/unvalidated-redirect-analyzer.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,16 @@ const InjectionAnalyzer = require('./injection-analyzer')
44
const { UNVALIDATED_REDIRECT } = require('../vulnerabilities')
55
const { getNodeModulesPaths } = require('../path-line')
66
const { getRanges } = require('../taint-tracking/operations')
7-
const { HTTP_REQUEST_HEADER_VALUE } = require('../taint-tracking/origin-types')
7+
const { HTTP_REQUEST_HEADER_VALUE } = require('../taint-tracking/source-types')
88

99
const EXCLUDED_PATHS = getNodeModulesPaths('express/lib/response.js')
1010

1111
class UnvalidatedRedirectAnalyzer extends InjectionAnalyzer {
1212
constructor () {
1313
super(UNVALIDATED_REDIRECT)
14+
}
1415

16+
onConfigure () {
1517
this.addSub('datadog:http:server:response:set-header:finish', ({ name, value }) => this.analyze(name, value))
1618
}
1719

packages/dd-trace/src/appsec/iast/analyzers/vulnerability-analyzer.js

Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,18 @@
11
'use strict'
22

3-
const Plugin = require('../../../../src/plugins/plugin')
43
const { storage } = require('../../../../../datadog-core')
5-
const iastLog = require('../iast-log')
64
const { getFirstNonDDPathAndLine } = require('../path-line')
75
const { addVulnerability } = require('../vulnerability-reporter')
86
const { getIastContext } = require('../iast-context')
97
const overheadController = require('../overhead-controller')
8+
const { SinkIastPlugin } = require('../iast-plugin')
109

11-
class Analyzer extends Plugin {
10+
class Analyzer extends SinkIastPlugin {
1211
constructor (type) {
1312
super()
1413
this._type = type
1514
}
1615

17-
_wrapHandler (handler) {
18-
return (message, name) => {
19-
try {
20-
handler(message, name)
21-
} catch (e) {
22-
iastLog.errorAndPublish(e)
23-
}
24-
}
25-
}
26-
27-
addSub (channelName, handler) {
28-
super.addSub(channelName, this._wrapHandler(handler))
29-
}
30-
3116
_isVulnerable (value, context) {
3217
return false
3318
}
@@ -64,17 +49,23 @@ class Analyzer extends Plugin {
6449

6550
_getExcludedPaths () {}
6651

52+
_isInvalidContext (store, iastContext) {
53+
return store && !iastContext
54+
}
55+
6756
analyze (value) {
6857
const store = storage.getStore()
6958
const iastContext = getIastContext(store)
70-
if (store && !iastContext) return
59+
if (this._isInvalidContext(store, iastContext)) return
60+
7161
this._reportIfVulnerable(value, iastContext)
7262
}
7363

7464
analyzeAll (...values) {
7565
const store = storage.getStore()
7666
const iastContext = getIastContext(store)
77-
if (store && !iastContext) return
67+
if (this._isInvalidContext(store, iastContext)) return
68+
7869
for (let i = 0; i < values.length; i++) {
7970
const value = values[i]
8071
if (this._isVulnerable(value, iastContext)) {
@@ -119,6 +110,14 @@ class Analyzer extends Plugin {
119110
}
120111
return hash
121112
}
113+
114+
addSub (iastSubOrChannelName, handler) {
115+
const iastSub = typeof iastSubOrChannelName === 'string'
116+
? { channelName: iastSubOrChannelName }
117+
: iastSubOrChannelName
118+
119+
super.addSub({ tag: this._type, ...iastSub }, handler)
120+
}
122121
}
123122

124123
module.exports = Analyzer

packages/dd-trace/src/appsec/iast/analyzers/weak-cipher-analyzer.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ const INSECURE_CIPHERS = new Set([
1414
class WeakCipherAnalyzer extends Analyzer {
1515
constructor () {
1616
super(WEAK_CIPHER)
17+
}
18+
19+
onConfigure () {
1720
this.addSub('datadog:crypto:cipher:start', ({ algorithm }) => this.analyze(algorithm))
1821
}
1922

packages/dd-trace/src/appsec/iast/analyzers/weak-hash-analyzer.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ const EXCLUDED_PATHS_FROM_STACK = [
2525
class WeakHashAnalyzer extends Analyzer {
2626
constructor () {
2727
super(WEAK_HASH)
28+
}
29+
30+
onConfigure () {
2831
this.addSub('datadog:crypto:hashing:start', ({ algorithm }) => this.analyze(algorithm))
2932
}
3033

0 commit comments

Comments
 (0)