dd-trace 2.23.0 → 2.25.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE-3rdparty.csv +2 -0
- package/index.d.ts +33 -1
- package/package.json +10 -7
- package/packages/datadog-instrumentations/src/helpers/hooks.js +1 -0
- package/packages/datadog-instrumentations/src/helpers/register.js +7 -0
- package/packages/datadog-instrumentations/src/http/server.js +7 -1
- package/packages/datadog-instrumentations/src/ldapjs.js +91 -0
- package/packages/datadog-instrumentations/src/mocha.js +33 -8
- package/packages/datadog-instrumentations/src/pg.js +6 -2
- package/packages/datadog-plugin-http/src/client.js +1 -1
- package/packages/datadog-plugin-http/src/server.js +7 -3
- package/packages/datadog-plugin-jest/src/index.js +2 -2
- package/packages/datadog-plugin-mocha/src/index.js +2 -2
- package/packages/datadog-plugin-pg/src/index.js +1 -1
- package/packages/datadog-plugin-router/src/index.js +6 -3
- package/packages/dd-trace/src/appsec/addresses.js +3 -1
- package/packages/dd-trace/src/appsec/blocking.js +44 -0
- package/packages/dd-trace/src/appsec/callbacks/ddwaf.js +1 -1
- package/packages/dd-trace/src/appsec/gateway/engine/engine.js +1 -1
- package/packages/dd-trace/src/appsec/gateway/engine/index.js +6 -1
- package/packages/dd-trace/src/appsec/gateway/engine/runner.js +0 -1
- package/packages/dd-trace/src/appsec/iast/analyzers/analyzers.js +2 -1
- package/packages/dd-trace/src/appsec/iast/analyzers/ldap-injection-analyzer.js +11 -0
- package/packages/dd-trace/src/appsec/iast/analyzers/sql-injection-analyzer.js +1 -1
- package/packages/dd-trace/src/appsec/iast/analyzers/vulnerability-analyzer.js +41 -3
- package/packages/dd-trace/src/appsec/iast/iast-context.js +3 -1
- package/packages/dd-trace/src/appsec/iast/index.js +15 -3
- package/packages/dd-trace/src/appsec/iast/overhead-controller.js +20 -1
- package/packages/dd-trace/src/appsec/iast/path-line.js +6 -5
- package/packages/dd-trace/src/appsec/iast/taint-tracking/csi-methods.js +17 -0
- package/packages/dd-trace/src/appsec/iast/taint-tracking/operations.js +2 -29
- package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter.js +16 -15
- package/packages/dd-trace/src/appsec/iast/taint-tracking/taint-tracking-impl.js +103 -0
- package/packages/dd-trace/src/appsec/iast/vulnerability-reporter.js +63 -41
- package/packages/dd-trace/src/appsec/index.js +68 -27
- package/packages/dd-trace/src/{plugins/util → appsec}/ip_blocklist.js +0 -0
- package/packages/dd-trace/src/appsec/ip_extractor.js +98 -0
- package/packages/dd-trace/src/appsec/recommended.json +75 -8
- package/packages/dd-trace/src/appsec/remote_config/index.js +2 -1
- package/packages/dd-trace/src/appsec/remote_config/manager.js +2 -2
- package/packages/dd-trace/src/appsec/templates/blocked.html +99 -0
- package/packages/dd-trace/src/appsec/templates/blocked.json +8 -0
- package/packages/dd-trace/src/ci-visibility/exporters/agent-proxy/index.js +4 -0
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/index.js +18 -2
- package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +12 -6
- package/packages/dd-trace/src/config.js +49 -8
- package/packages/dd-trace/src/exporters/common/request.js +33 -1
- package/packages/dd-trace/src/format.js +5 -1
- package/packages/dd-trace/src/lambda/handler.js +72 -0
- package/packages/dd-trace/src/lambda/index.js +5 -0
- package/packages/dd-trace/src/lambda/runtime/errors.js +20 -0
- package/packages/dd-trace/src/lambda/runtime/patch.js +74 -0
- package/packages/dd-trace/src/lambda/runtime/ritm.js +143 -0
- package/packages/dd-trace/src/plugin_manager.js +5 -11
- package/packages/dd-trace/src/plugins/ci_plugin.js +6 -0
- package/packages/dd-trace/src/plugins/database.js +4 -4
- package/packages/dd-trace/src/plugins/log_plugin.js +2 -2
- package/packages/dd-trace/src/plugins/util/ci.js +5 -2
- package/packages/dd-trace/src/plugins/util/test.js +2 -2
- package/packages/dd-trace/src/plugins/util/user-provided-git.js +14 -1
- package/packages/dd-trace/src/plugins/util/web.js +1 -104
- package/packages/dd-trace/src/priority_sampler.js +6 -2
- package/packages/dd-trace/src/proxy.js +4 -3
- package/packages/dd-trace/src/ritm.js +7 -1
- package/packages/dd-trace/src/span_processor.js +13 -0
- package/packages/dd-trace/src/span_sampler.js +1 -4
|
@@ -10,31 +10,42 @@ const Gateway = require('./gateway/engine')
|
|
|
10
10
|
const addresses = require('./addresses')
|
|
11
11
|
const Reporter = require('./reporter')
|
|
12
12
|
const web = require('../plugins/util/web')
|
|
13
|
+
const { extractIp } = require('./ip_extractor')
|
|
14
|
+
const { HTTP_CLIENT_IP } = require('../../../../ext/tags')
|
|
15
|
+
const { block, loadTemplates, loadTemplatesAsync } = require('./blocking')
|
|
13
16
|
|
|
14
17
|
let isEnabled = false
|
|
18
|
+
let config
|
|
15
19
|
|
|
16
|
-
function enable (
|
|
20
|
+
function enable (_config) {
|
|
17
21
|
if (isEnabled) return
|
|
18
22
|
|
|
19
23
|
try {
|
|
20
|
-
|
|
24
|
+
loadTemplates(_config)
|
|
25
|
+
const rules = fs.readFileSync(_config.appsec.rules || path.join(__dirname, 'recommended.json'))
|
|
26
|
+
enableFromRules(_config, JSON.parse(rules))
|
|
27
|
+
} catch (err) {
|
|
28
|
+
abortEnable(err)
|
|
29
|
+
}
|
|
30
|
+
}
|
|
21
31
|
|
|
22
|
-
|
|
23
|
-
|
|
32
|
+
async function enableAsync (_config) {
|
|
33
|
+
if (isEnabled) return
|
|
24
34
|
|
|
25
|
-
|
|
26
|
-
|
|
35
|
+
try {
|
|
36
|
+
await loadTemplatesAsync(_config)
|
|
37
|
+
const rules = await fs.promises.readFile(_config.appsec.rules || path.join(__dirname, 'recommended.json'))
|
|
38
|
+
enableFromRules(_config, JSON.parse(rules))
|
|
27
39
|
} catch (err) {
|
|
28
|
-
|
|
29
|
-
log.error(err)
|
|
30
|
-
|
|
31
|
-
// abort AppSec start
|
|
32
|
-
RuleManager.clearAllRules()
|
|
33
|
-
remoteConfig.disableAsmData()
|
|
34
|
-
return
|
|
40
|
+
abortEnable(err)
|
|
35
41
|
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function enableFromRules (_config, rules) {
|
|
45
|
+
RuleManager.applyRules(rules, _config.appsec)
|
|
46
|
+
remoteConfig.enableAsmData(_config.appsec)
|
|
36
47
|
|
|
37
|
-
Reporter.setRateLimit(
|
|
48
|
+
Reporter.setRateLimit(_config.appsec.rateLimit)
|
|
38
49
|
|
|
39
50
|
incomingHttpRequestStart.subscribe(incomingHttpStartTranslator)
|
|
40
51
|
incomingHttpRequestEnd.subscribe(incomingHttpEndTranslator)
|
|
@@ -46,27 +57,55 @@ function enable (config) {
|
|
|
46
57
|
Gateway.manager.addresses.add(addresses.HTTP_INCOMING_REMOTE_IP)
|
|
47
58
|
|
|
48
59
|
isEnabled = true
|
|
60
|
+
config = _config
|
|
49
61
|
}
|
|
50
62
|
|
|
51
|
-
function
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
})
|
|
59
|
-
}
|
|
63
|
+
function abortEnable (err) {
|
|
64
|
+
log.error('Unable to start AppSec')
|
|
65
|
+
log.error(err)
|
|
66
|
+
|
|
67
|
+
// abort AppSec start
|
|
68
|
+
RuleManager.clearAllRules()
|
|
69
|
+
remoteConfig.disableAsmData()
|
|
60
70
|
}
|
|
61
71
|
|
|
62
|
-
function
|
|
72
|
+
function incomingHttpStartTranslator ({ req, res, abortController }) {
|
|
73
|
+
const topSpan = web.root(req)
|
|
74
|
+
if (!topSpan) return
|
|
75
|
+
|
|
76
|
+
const clientIp = extractIp(config, req)
|
|
77
|
+
|
|
78
|
+
topSpan.addTags({
|
|
79
|
+
'_dd.appsec.enabled': 1,
|
|
80
|
+
'_dd.runtime_family': 'nodejs',
|
|
81
|
+
[HTTP_CLIENT_IP]: clientIp
|
|
82
|
+
})
|
|
83
|
+
|
|
63
84
|
const store = Gateway.startContext()
|
|
64
85
|
|
|
65
|
-
store.set('req',
|
|
66
|
-
store.set('res',
|
|
86
|
+
store.set('req', req)
|
|
87
|
+
store.set('res', res)
|
|
67
88
|
|
|
68
89
|
const context = store.get('context')
|
|
69
90
|
|
|
91
|
+
if (clientIp) {
|
|
92
|
+
const results = Gateway.propagate({
|
|
93
|
+
[addresses.HTTP_CLIENT_IP]: clientIp
|
|
94
|
+
}, context)
|
|
95
|
+
|
|
96
|
+
if (!results || !abortController) return
|
|
97
|
+
|
|
98
|
+
for (const entry of results) {
|
|
99
|
+
if (entry && entry.includes('block')) {
|
|
100
|
+
block(req, res, topSpan, abortController)
|
|
101
|
+
break
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function incomingHttpEndTranslator (data) {
|
|
108
|
+
const context = Gateway.getContext()
|
|
70
109
|
if (!context) return
|
|
71
110
|
|
|
72
111
|
const requestHeaders = Object.assign({}, data.req.headers)
|
|
@@ -107,7 +146,7 @@ function incomingHttpEndTranslator (data) {
|
|
|
107
146
|
payload[addresses.HTTP_INCOMING_COOKIES] = {}
|
|
108
147
|
|
|
109
148
|
for (const k of Object.keys(data.req.cookies)) {
|
|
110
|
-
payload[addresses.HTTP_INCOMING_COOKIES][k] = [
|
|
149
|
+
payload[addresses.HTTP_INCOMING_COOKIES][k] = [data.req.cookies[k]]
|
|
111
150
|
}
|
|
112
151
|
}
|
|
113
152
|
|
|
@@ -118,6 +157,7 @@ function incomingHttpEndTranslator (data) {
|
|
|
118
157
|
|
|
119
158
|
function disable () {
|
|
120
159
|
isEnabled = false
|
|
160
|
+
config = null
|
|
121
161
|
|
|
122
162
|
RuleManager.clearAllRules()
|
|
123
163
|
remoteConfig.disableAsmData()
|
|
@@ -129,6 +169,7 @@ function disable () {
|
|
|
129
169
|
|
|
130
170
|
module.exports = {
|
|
131
171
|
enable,
|
|
172
|
+
enableAsync,
|
|
132
173
|
disable,
|
|
133
174
|
incomingHttpStartTranslator,
|
|
134
175
|
incomingHttpEndTranslator
|
|
File without changes
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const BlockList = require('./ip_blocklist')
|
|
4
|
+
const net = require('net')
|
|
5
|
+
const log = require('../log')
|
|
6
|
+
|
|
7
|
+
const ipHeaderList = [
|
|
8
|
+
'x-forwarded-for',
|
|
9
|
+
'x-real-ip',
|
|
10
|
+
'client-ip',
|
|
11
|
+
'x-forwarded',
|
|
12
|
+
'x-cluster-client-ip',
|
|
13
|
+
'forwarded-for',
|
|
14
|
+
'forwarded',
|
|
15
|
+
'via',
|
|
16
|
+
'true-client-ip'
|
|
17
|
+
]
|
|
18
|
+
|
|
19
|
+
const privateCIDRs = [
|
|
20
|
+
'127.0.0.0/8',
|
|
21
|
+
'10.0.0.0/8',
|
|
22
|
+
'172.16.0.0/12',
|
|
23
|
+
'192.168.0.0/16',
|
|
24
|
+
'169.254.0.0/16',
|
|
25
|
+
'::1/128',
|
|
26
|
+
'fec0::/10',
|
|
27
|
+
'fe80::/10',
|
|
28
|
+
'fc00::/7',
|
|
29
|
+
'fd00::/8'
|
|
30
|
+
]
|
|
31
|
+
|
|
32
|
+
const privateIPMatcher = new BlockList()
|
|
33
|
+
|
|
34
|
+
for (const cidr of privateCIDRs) {
|
|
35
|
+
const [address, prefix] = cidr.split('/')
|
|
36
|
+
|
|
37
|
+
privateIPMatcher.addSubnet(address, parseInt(prefix), net.isIPv6(address) ? 'ipv6' : 'ipv4')
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function extractIp (config, req) {
|
|
41
|
+
const headers = req.headers
|
|
42
|
+
if (config.clientIpHeader) {
|
|
43
|
+
if (!headers) return
|
|
44
|
+
const header = headers[config.clientIpHeader]
|
|
45
|
+
if (!header) return
|
|
46
|
+
|
|
47
|
+
return findFirstIp(header)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const foundHeaders = []
|
|
51
|
+
if (headers) {
|
|
52
|
+
for (let i = 0; i < ipHeaderList.length; i++) {
|
|
53
|
+
if (headers[ipHeaderList[i]]) {
|
|
54
|
+
foundHeaders.push(ipHeaderList[i])
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (foundHeaders.length === 1) {
|
|
60
|
+
const header = headers[foundHeaders[0]]
|
|
61
|
+
const firstIp = findFirstIp(header)
|
|
62
|
+
|
|
63
|
+
if (firstIp) return firstIp
|
|
64
|
+
} else if (foundHeaders.length > 1) {
|
|
65
|
+
log.error(`Cannot find client IP: multiple IP headers detected ${foundHeaders}`)
|
|
66
|
+
return
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return req.socket && req.socket.remoteAddress
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function findFirstIp (str) {
|
|
73
|
+
let firstPrivateIp
|
|
74
|
+
const splitted = str.split(',')
|
|
75
|
+
|
|
76
|
+
for (let i = 0; i < splitted.length; i++) {
|
|
77
|
+
const chunk = splitted[i].trim()
|
|
78
|
+
|
|
79
|
+
// TODO: strip port and interface data ?
|
|
80
|
+
|
|
81
|
+
const type = net.isIP(chunk)
|
|
82
|
+
if (!type) continue
|
|
83
|
+
|
|
84
|
+
if (!privateIPMatcher.check(chunk, type === 6 ? 'ipv6' : 'ipv4')) {
|
|
85
|
+
// it's public, return it immediately
|
|
86
|
+
return chunk
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// it's private, only save the first one found
|
|
90
|
+
if (!firstPrivateIp) firstPrivateIp = chunk
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return firstPrivateIp
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
module.exports = {
|
|
97
|
+
extractIp
|
|
98
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": "2.2",
|
|
3
3
|
"metadata": {
|
|
4
|
-
"rules_version": "1.4.
|
|
4
|
+
"rules_version": "1.4.3"
|
|
5
5
|
},
|
|
6
6
|
"rules": [
|
|
7
7
|
{
|
|
@@ -1802,7 +1802,7 @@
|
|
|
1802
1802
|
"address": "server.request.path_params"
|
|
1803
1803
|
}
|
|
1804
1804
|
],
|
|
1805
|
-
"regex": "^(?i:file|ftps?|
|
|
1805
|
+
"regex": "^(?i:file|ftps?|http)://.*?\\?+$",
|
|
1806
1806
|
"options": {
|
|
1807
1807
|
"case_sensitive": true,
|
|
1808
1808
|
"min_length": 4
|
|
@@ -2694,8 +2694,9 @@
|
|
|
2694
2694
|
"address": "grpc.server.request.message"
|
|
2695
2695
|
}
|
|
2696
2696
|
],
|
|
2697
|
-
"regex": "\\b(?:s(?:e(?:t(?:_(?:e(?:xception|rror)_handler|magic_quotes_runtime|include_path)|defaultstub)|ssion_s(?:et_save_handler|tart))|qlite_(?:(?:(?:unbuffered|single|array)_)?query|create_(?:aggregate|function)|p?open|exec)|tr(?:eam_(?:context_create|socket_client)|ipc?slashes|rev)|implexml_load_(?:string|file)|ocket_c(?:onnect|reate)|h(?:ow_sourc|a1_fil)e|pl_autoload_register|ystem)|p(?:r(?:eg_(?:replace(?:_callback(?:_array)?)?|match(?:_all)?|split)|oc_(?:(?:terminat|clos|nic)e|get_status|open)|int_r)|o(?:six_(?:get(?:(?:e[gu]|g)id|login|pwnam)|mk(?:fifo|nod)|ttyname|kill)|pen)|hp(?:_(?:strip_whitespac|unam)e|version|info)|g_(?:(?:execut|prepar)e|connect|query)|a(?:rse_(?:ini_file|str)|ssthru)|utenv)|r(?:unkit_(?:function_(?:re(?:defin|nam)e|copy|add)|method_(?:re(?:defin|nam)e|copy|add)|constant_(?:redefine|add))|e(?:(?:gister_(?:shutdown|tick)|name)_function|ad(?:(?:gz)?file|_exif_data|dir))|awurl(?:de|en)code)|i(?:mage(?:createfrom(?:(?:jpe|pn)g|x[bp]m|wbmp|gif)|(?:jpe|pn)g|g(?:d2?|if)|2?wbmp|xbm)|s_(?:(?:(?:execut|write?|read)ab|fi)le|dir)|ni_(?:get(?:_all)?|set)|terator_apply|ptcembed)|g(?:et(?:_(?:c(?:urrent_use|fg_va)r|meta_tags)|my(?:[gpu]id|inode)|(?:lastmo|cw)d|imagesize|env)|z(?:(?:(?:defla|wri)t|encod|fil)e|compress|open|read)|lob)|a(?:rray_(?:u(?:intersect(?:_u?assoc)?|diff(?:_u?assoc)?)|intersect_u(?:assoc|key)|diff_u(?:assoc|key)|filter|reduce|map)|ssert(?:_options)?|lert|tob)|h(?:tml(?:specialchars(?:_decode)?|_entity_decode|entities)|(?:ash(?:_(?:update|hmac))?|ighlight)_file|e(?:ader_register_callback|x2bin))|f(?:i(?:le(?:(?:[acm]tim|inod)e|(?:_exist|perm)s|group)?|nfo_open)|tp_(?:nb_(?:ge|pu)|connec|ge|pu)t|(?:unction_exis|pu)ts|write|open)|o(?:b_(?:get_(?:c(?:ontents|lean)|flush)|end_(?:clean|flush)|clean|flush|start)|dbc_(?:result(?:_all)?|exec(?:ute)?|connect)|pendir)|m(?:b_(?:ereg(?:_(?:replace(?:_callback)?|match)|i(?:_replace)?)?|parse_str)|(?:ove_uploaded|d5)_file|ethod_exists|ysql_query|kdir)|e(?:x(?:if_(?:t(?:humbnail|agname)|imagetype|read_data)|ec)|scapeshell(?:arg|cmd)|rror_reporting|val)|c(?:url_(?:file_create|exec|init)|onvert_uuencode|reate_function|hr)|u(?:n(?:serialize|pack)|rl(?:de|en)code|[ak]?sort)|b(?:(?:son_(?:de|en)|ase64_en)code|zopen|toa)|(?:json_(?:de|en)cod|debug_backtrac|tmpfil)e|var_dump)(?:\\s|/\\*.*\\*/|//.*|#.*|\\\")*\\(.*\\)",
|
|
2697
|
+
"regex": "\\b(?:s(?:e(?:t(?:_(?:e(?:xception|rror)_handler|magic_quotes_runtime|include_path)|defaultstub)|ssion_s(?:et_save_handler|tart))|qlite_(?:(?:(?:unbuffered|single|array)_)?query|create_(?:aggregate|function)|p?open|exec)|tr(?:eam_(?:context_create|socket_client)|ipc?slashes|rev)|implexml_load_(?:string|file)|ocket_c(?:onnect|reate)|h(?:ow_sourc|a1_fil)e|pl_autoload_register|ystem)|p(?:r(?:eg_(?:replace(?:_callback(?:_array)?)?|match(?:_all)?|split)|oc_(?:(?:terminat|clos|nic)e|get_status|open)|int_r)|o(?:six_(?:get(?:(?:e[gu]|g)id|login|pwnam)|mk(?:fifo|nod)|ttyname|kill)|pen)|hp(?:_(?:strip_whitespac|unam)e|version|info)|g_(?:(?:execut|prepar)e|connect|query)|a(?:rse_(?:ini_file|str)|ssthru)|utenv)|r(?:unkit_(?:function_(?:re(?:defin|nam)e|copy|add)|method_(?:re(?:defin|nam)e|copy|add)|constant_(?:redefine|add))|e(?:(?:gister_(?:shutdown|tick)|name)_function|ad(?:(?:gz)?file|_exif_data|dir))|awurl(?:de|en)code)|i(?:mage(?:createfrom(?:(?:jpe|pn)g|x[bp]m|wbmp|gif)|(?:jpe|pn)g|g(?:d2?|if)|2?wbmp|xbm)|s_(?:(?:(?:execut|write?|read)ab|fi)le|dir)|ni_(?:get(?:_all)?|set)|terator_apply|ptcembed)|g(?:et(?:_(?:c(?:urrent_use|fg_va)r|meta_tags)|my(?:[gpu]id|inode)|(?:lastmo|cw)d|imagesize|env)|z(?:(?:(?:defla|wri)t|encod|fil)e|compress|open|read)|lob)|a(?:rray_(?:u(?:intersect(?:_u?assoc)?|diff(?:_u?assoc)?)|intersect_u(?:assoc|key)|diff_u(?:assoc|key)|filter|reduce|map)|ssert(?:_options)?|lert|tob)|h(?:tml(?:specialchars(?:_decode)?|_entity_decode|entities)|(?:ash(?:_(?:update|hmac))?|ighlight)_file|e(?:ader_register_callback|x2bin))|f(?:i(?:le(?:(?:[acm]tim|inod)e|(?:_exist|perm)s|group)?|nfo_open)|tp_(?:nb_(?:ge|pu)|connec|ge|pu)t|(?:unction_exis|pu)ts|write|open)|o(?:b_(?:get_(?:c(?:ontents|lean)|flush)|end_(?:clean|flush)|clean|flush|start)|dbc_(?:result(?:_all)?|exec(?:ute)?|connect)|pendir)|m(?:b_(?:ereg(?:_(?:replace(?:_callback)?|match)|i(?:_replace)?)?|parse_str)|(?:ove_uploaded|d5)_file|ethod_exists|ysql_query|kdir)|e(?:x(?:if_(?:t(?:humbnail|agname)|imagetype|read_data)|ec)|scapeshell(?:arg|cmd)|rror_reporting|val)|c(?:url_(?:file_create|exec|init)|onvert_uuencode|reate_function|hr)|u(?:n(?:serialize|pack)|rl(?:de|en)code|[ak]?sort)|b(?:(?:son_(?:de|en)|ase64_en)code|zopen|toa)|(?:json_(?:de|en)cod|debug_backtrac|tmpfil)e|var_dump)(?:\\s|/\\*.*\\*/|//.*|#.*|\\\"|')*\\((?:(?:\\s|/\\*.*\\*/|//.*|#.*)*(?:\\$\\w+|[A-Z\\d]\\w*|\\w+\\(.*\\)|\\\\?\"(?:[^\"]|\\\\\"|\"\"|\"\\+\")*\\\\?\"|\\\\?'(?:[^']|''|'\\+')*\\\\?')(?:\\s|/\\*.*\\*/|//.*|#.*)*(?:(?:::|\\.|->)(?:\\s|/\\*.*\\*/|//.*|#.*)*\\w+(?:\\(.*\\))?)?,)*(?:(?:\\s|/\\*.*\\*/|//.*|#.*)*(?:\\$\\w+|[A-Z\\d]\\w*|\\w+\\(.*\\)|\\\\?\"(?:[^\"]|\\\\\"|\"\"|\"\\+\")*\\\\?\"|\\\\?'(?:[^']|''|'\\+')*\\\\?')(?:\\s|/\\*.*\\*/|//.*|#.*)*(?:(?:::|\\.|->)(?:\\s|/\\*.*\\*/|//.*|#.*)*\\w+(?:\\(.*\\))?)?)?\\)",
|
|
2698
2698
|
"options": {
|
|
2699
|
+
"case_sensitive": true,
|
|
2699
2700
|
"min_length": 5
|
|
2700
2701
|
}
|
|
2701
2702
|
},
|
|
@@ -3524,7 +3525,7 @@
|
|
|
3524
3525
|
"address": "grpc.server.request.message"
|
|
3525
3526
|
}
|
|
3526
3527
|
],
|
|
3527
|
-
"regex": "\\b(?i:eval|settimeout|setinterval|new\\s+Function)\\s*\\(",
|
|
3528
|
+
"regex": "\\b(?i:eval|settimeout|setinterval|new\\s+Function|alert|prompt)\\s*\\([^\\)]",
|
|
3528
3529
|
"options": {
|
|
3529
3530
|
"case_sensitive": true,
|
|
3530
3531
|
"min_length": 5
|
|
@@ -3770,7 +3771,7 @@
|
|
|
3770
3771
|
"address": "grpc.server.request.message"
|
|
3771
3772
|
}
|
|
3772
3773
|
],
|
|
3773
|
-
"regex": "(?i:(?:\\[?\\$(?:(?:s(?:lic|iz)|wher)e|e(?:lemMatch|xists|q)|n(?:o[rt]|in?|e)|l(?:ike|te?)|t(?:ext|ype)|a(?:ll|nd)|jsonSchema|between|regex|x?or|div|mod)\\]?))",
|
|
3774
|
+
"regex": "(?i:(?:\\[?\\$(?:(?:s(?:lic|iz)|wher)e|e(?:lemMatch|xists|q)|n(?:o[rt]|in?|e)|l(?:ike|te?)|t(?:ext|ype)|a(?:ll|nd)|jsonSchema|between|regex|x?or|div|mod)\\]?)\\b)",
|
|
3774
3775
|
"options": {
|
|
3775
3776
|
"case_sensitive": true,
|
|
3776
3777
|
"min_length": 3
|
|
@@ -3808,7 +3809,7 @@
|
|
|
3808
3809
|
"address": "grpc.server.request.message"
|
|
3809
3810
|
}
|
|
3810
3811
|
],
|
|
3811
|
-
"regex": "(?:^[\\W\\d]+\\s*?(?:alter\\s*(?:a(?:(?:pplication\\s*rol|ggregat)e|s(?:ymmetric\\s*ke|sembl)y|u(?:thorization|dit)|vailability\\s*group)|c(?:r(?:yptographic\\s*provider|edential)|o(?:l(?:latio|um)|nversio)n|ertificate|luster)|s(?:e(?:rv(?:ice|er)|curity|quence|ssion|arch)|y(?:mmetric\\s*key|nonym)|togroup|chema)|m(?:a(?:s(?:ter\\s*key|k)|terialized)|e(?:ssage\\s*type|thod)|odule)|l(?:o(?:g(?:file\\s*group|in)|ckdown)|a(?:ngua|r)ge|ibrary)|t(?:(?:abl(?:espac)?|yp)e|r(?:igger|usted)|hreshold|ext)|p(?:a(?:rtition|ckage)|ro(?:cedur|fil)e|ermission)|d(?:i(?:mension|skgroup)|atabase|efault|omain)|r(?:o(?:l(?:lback|e)|ute)|e(?:sourc|mot)e)|f(?:u(?:lltext|nction)|lashback|oreign)|e(?:xte(?:nsion|rnal)|(?:ndpoi|ve)nt)|in(?:dex(?:type)?|memory|stance)|b(?:roker\\s*priority|ufferpool)|x(?:ml\\s*schema|srobject)|w(?:ork(?:load)?|rapper)|hi(?:erarchy|stogram)|o(?:perator|utline)|(?:nicknam|queu)e|us(?:age|er)|group|java|view)
|
|
3812
|
+
"regex": "(?:^[\\W\\d]+\\s*?(?:alter\\s*(?:a(?:(?:pplication\\s*rol|ggregat)e|s(?:ymmetric\\s*ke|sembl)y|u(?:thorization|dit)|vailability\\s*group)|c(?:r(?:yptographic\\s*provider|edential)|o(?:l(?:latio|um)|nversio)n|ertificate|luster)|s(?:e(?:rv(?:ice|er)|curity|quence|ssion|arch)|y(?:mmetric\\s*key|nonym)|togroup|chema)|m(?:a(?:s(?:ter\\s*key|k)|terialized)|e(?:ssage\\s*type|thod)|odule)|l(?:o(?:g(?:file\\s*group|in)|ckdown)|a(?:ngua|r)ge|ibrary)|t(?:(?:abl(?:espac)?|yp)e|r(?:igger|usted)|hreshold|ext)|p(?:a(?:rtition|ckage)|ro(?:cedur|fil)e|ermission)|d(?:i(?:mension|skgroup)|atabase|efault|omain)|r(?:o(?:l(?:lback|e)|ute)|e(?:sourc|mot)e)|f(?:u(?:lltext|nction)|lashback|oreign)|e(?:xte(?:nsion|rnal)|(?:ndpoi|ve)nt)|in(?:dex(?:type)?|memory|stance)|b(?:roker\\s*priority|ufferpool)|x(?:ml\\s*schema|srobject)|w(?:ork(?:load)?|rapper)|hi(?:erarchy|stogram)|o(?:perator|utline)|(?:nicknam|queu)e|us(?:age|er)|group|java|view)|union\\s*(?:(?:distin|sele)ct|all))\\b|\\b(?:(?:(?:trunc|cre|upd)at|renam)e|(?:inser|selec)t|de(?:lete|sc)|alter|load)\\s+(?:group_concat|load_file|char)\\b\\s*\\(?|[\\s(]load_file\\s*?\\(|[\\\"'`]\\s+regexp\\W)",
|
|
3812
3813
|
"options": {
|
|
3813
3814
|
"min_length": 5
|
|
3814
3815
|
}
|
|
@@ -4177,7 +4178,7 @@
|
|
|
4177
4178
|
"address": "grpc.server.request.message"
|
|
4178
4179
|
}
|
|
4179
4180
|
],
|
|
4180
|
-
"regex": "[#%$]{[^}]+[^\\w\\s][^}]+}",
|
|
4181
|
+
"regex": "[#%$]{(?:[^}]+[^\\w\\s}\\-_][^}]+|\\d+-\\d+)}",
|
|
4181
4182
|
"options": {
|
|
4182
4183
|
"case_sensitive": true
|
|
4183
4184
|
}
|
|
@@ -4352,6 +4353,38 @@
|
|
|
4352
4353
|
],
|
|
4353
4354
|
"transformers": []
|
|
4354
4355
|
},
|
|
4356
|
+
{
|
|
4357
|
+
"id": "dog-931-001",
|
|
4358
|
+
"name": "RFI: URL Payload to well known RFI target",
|
|
4359
|
+
"tags": {
|
|
4360
|
+
"type": "rfi",
|
|
4361
|
+
"category": "attack_attempt"
|
|
4362
|
+
},
|
|
4363
|
+
"conditions": [
|
|
4364
|
+
{
|
|
4365
|
+
"parameters": {
|
|
4366
|
+
"inputs": [
|
|
4367
|
+
{
|
|
4368
|
+
"address": "server.request.query"
|
|
4369
|
+
},
|
|
4370
|
+
{
|
|
4371
|
+
"address": "server.request.body"
|
|
4372
|
+
},
|
|
4373
|
+
{
|
|
4374
|
+
"address": "server.request.path_params"
|
|
4375
|
+
}
|
|
4376
|
+
],
|
|
4377
|
+
"regex": "^(?i:file|ftps?|https?).*/rfiinc\\.txt\\?+$",
|
|
4378
|
+
"options": {
|
|
4379
|
+
"case_sensitive": true,
|
|
4380
|
+
"min_length": 17
|
|
4381
|
+
}
|
|
4382
|
+
},
|
|
4383
|
+
"operator": "match_regex"
|
|
4384
|
+
}
|
|
4385
|
+
],
|
|
4386
|
+
"transformers": []
|
|
4387
|
+
},
|
|
4355
4388
|
{
|
|
4356
4389
|
"id": "nfd-000-001",
|
|
4357
4390
|
"name": "Detect common directory discovery scans",
|
|
@@ -5160,7 +5193,7 @@
|
|
|
5160
5193
|
"address": "grpc.server.request.message"
|
|
5161
5194
|
}
|
|
5162
5195
|
],
|
|
5163
|
-
"regex": "^(jar:)?(http|https):\\/\\/([0-9oq]{1,5}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}|[0-9]{1,10}
|
|
5196
|
+
"regex": "^(jar:)?(http|https):\\/\\/([0-9oq]{1,5}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}|[0-9]{1,10})(:[0-9]{1,5})?(\\/.*|)$"
|
|
5164
5197
|
},
|
|
5165
5198
|
"operator": "match_regex"
|
|
5166
5199
|
}
|
|
@@ -6417,6 +6450,40 @@
|
|
|
6417
6450
|
],
|
|
6418
6451
|
"transformers": []
|
|
6419
6452
|
},
|
|
6453
|
+
{
|
|
6454
|
+
"id": "ua0-600-56x",
|
|
6455
|
+
"name": "Datadog test scanner - blocking version: user-agent",
|
|
6456
|
+
"tags": {
|
|
6457
|
+
"type": "security_scanner",
|
|
6458
|
+
"category": "attack_attempt"
|
|
6459
|
+
},
|
|
6460
|
+
"conditions": [
|
|
6461
|
+
{
|
|
6462
|
+
"parameters": {
|
|
6463
|
+
"inputs": [
|
|
6464
|
+
{
|
|
6465
|
+
"address": "server.request.headers.no_cookies",
|
|
6466
|
+
"key_path": [
|
|
6467
|
+
"user-agent"
|
|
6468
|
+
]
|
|
6469
|
+
},
|
|
6470
|
+
{
|
|
6471
|
+
"address": "grpc.server.request.metadata",
|
|
6472
|
+
"key_path": [
|
|
6473
|
+
"dd-canary"
|
|
6474
|
+
]
|
|
6475
|
+
}
|
|
6476
|
+
],
|
|
6477
|
+
"regex": "^dd-test-scanner-log-block$"
|
|
6478
|
+
},
|
|
6479
|
+
"operator": "match_regex"
|
|
6480
|
+
}
|
|
6481
|
+
],
|
|
6482
|
+
"transformers": [],
|
|
6483
|
+
"on_match": [
|
|
6484
|
+
"block"
|
|
6485
|
+
]
|
|
6486
|
+
},
|
|
6420
6487
|
{
|
|
6421
6488
|
"id": "ua0-600-5xx",
|
|
6422
6489
|
"name": "Blind SQL Injection Brute Forcer",
|
|
@@ -23,7 +23,7 @@ function enable (config) {
|
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
if (shouldEnable) {
|
|
26
|
-
require('..').
|
|
26
|
+
require('..').enableAsync(config).catch(() => {})
|
|
27
27
|
} else {
|
|
28
28
|
require('..').disable()
|
|
29
29
|
}
|
|
@@ -34,6 +34,7 @@ function enable (config) {
|
|
|
34
34
|
|
|
35
35
|
function enableAsmData (appsecConfig) {
|
|
36
36
|
if (rc && appsecConfig && appsecConfig.rules === undefined) {
|
|
37
|
+
rc.updateCapabilities(RemoteConfigCapabilities.ASM_IP_BLOCKING, true)
|
|
37
38
|
rc.on('ASM_DATA', _asmDataListener)
|
|
38
39
|
}
|
|
39
40
|
}
|
|
@@ -9,7 +9,6 @@ const log = require('../../log')
|
|
|
9
9
|
|
|
10
10
|
const clientId = uuid()
|
|
11
11
|
|
|
12
|
-
const POLL_INTERVAL = 5e3
|
|
13
12
|
const DEFAULT_CAPABILITY = Buffer.alloc(1).toString('base64') // 0x00
|
|
14
13
|
|
|
15
14
|
// There MUST NOT exist separate instances of RC clients in a tracer making separate ClientGetConfigsRequest
|
|
@@ -18,7 +17,8 @@ class RemoteConfigManager extends EventEmitter {
|
|
|
18
17
|
constructor (config) {
|
|
19
18
|
super()
|
|
20
19
|
|
|
21
|
-
|
|
20
|
+
const pollInterval = config.remoteConfig.pollInterval * 1000
|
|
21
|
+
this.scheduler = new Scheduler((cb) => this.poll(cb), pollInterval)
|
|
22
22
|
|
|
23
23
|
this.requestOptions = {
|
|
24
24
|
url: config.url,
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
<!-- Sorry, you’ve been blocked -->
|
|
2
|
+
<!DOCTYPE html>
|
|
3
|
+
<html lang="en">
|
|
4
|
+
|
|
5
|
+
<head>
|
|
6
|
+
<meta charset="UTF-8">
|
|
7
|
+
<meta name="viewport" content="width=device-width,initial-scale=1">
|
|
8
|
+
<title>You've been blocked</title>
|
|
9
|
+
<style>
|
|
10
|
+
a,
|
|
11
|
+
body,
|
|
12
|
+
div,
|
|
13
|
+
html,
|
|
14
|
+
span {
|
|
15
|
+
margin: 0;
|
|
16
|
+
padding: 0;
|
|
17
|
+
border: 0;
|
|
18
|
+
font-size: 100%;
|
|
19
|
+
font: inherit;
|
|
20
|
+
vertical-align: baseline
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
body {
|
|
24
|
+
background: -webkit-radial-gradient(26% 19%, circle, #fff, #f4f7f9);
|
|
25
|
+
background: radial-gradient(circle at 26% 19%, #fff, #f4f7f9);
|
|
26
|
+
display: -webkit-box;
|
|
27
|
+
display: -ms-flexbox;
|
|
28
|
+
display: flex;
|
|
29
|
+
-webkit-box-pack: center;
|
|
30
|
+
-ms-flex-pack: center;
|
|
31
|
+
justify-content: center;
|
|
32
|
+
-webkit-box-align: center;
|
|
33
|
+
-ms-flex-align: center;
|
|
34
|
+
align-items: center;
|
|
35
|
+
-ms-flex-line-pack: center;
|
|
36
|
+
align-content: center;
|
|
37
|
+
width: 100%;
|
|
38
|
+
min-height: 100vh;
|
|
39
|
+
line-height: 1;
|
|
40
|
+
flex-direction: column
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
p {
|
|
44
|
+
display: block
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
main {
|
|
49
|
+
text-align: center;
|
|
50
|
+
flex: 1;
|
|
51
|
+
display: -webkit-box;
|
|
52
|
+
display: -ms-flexbox;
|
|
53
|
+
display: flex;
|
|
54
|
+
-webkit-box-pack: center;
|
|
55
|
+
-ms-flex-pack: center;
|
|
56
|
+
justify-content: center;
|
|
57
|
+
-webkit-box-align: center;
|
|
58
|
+
-ms-flex-align: center;
|
|
59
|
+
align-items: center;
|
|
60
|
+
-ms-flex-line-pack: center;
|
|
61
|
+
align-content: center;
|
|
62
|
+
flex-direction: column
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
p {
|
|
66
|
+
font-size: 18px;
|
|
67
|
+
line-height: normal;
|
|
68
|
+
color: #646464;
|
|
69
|
+
font-family: sans-serif;
|
|
70
|
+
font-weight: 400
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
a {
|
|
74
|
+
color: #4842b7
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
footer {
|
|
78
|
+
width: 100%;
|
|
79
|
+
text-align: center
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
footer p {
|
|
83
|
+
font-size: 16px
|
|
84
|
+
}
|
|
85
|
+
</style>
|
|
86
|
+
</head>
|
|
87
|
+
|
|
88
|
+
<body>
|
|
89
|
+
<main>
|
|
90
|
+
<p>Sorry, you cannot access this page. Please contact the customer service team.</p>
|
|
91
|
+
</main>
|
|
92
|
+
<footer>
|
|
93
|
+
<p>Security provided by <a
|
|
94
|
+
href="https://www.datadoghq.com/product/security-platform/application-security-monitoring/"
|
|
95
|
+
target="_blank">Datadog</a></p>
|
|
96
|
+
</footer>
|
|
97
|
+
</body>
|
|
98
|
+
|
|
99
|
+
</html>
|
|
@@ -4,6 +4,7 @@ const URL = require('url').URL
|
|
|
4
4
|
const Writer = require('./writer')
|
|
5
5
|
const CoverageWriter = require('./coverage-writer')
|
|
6
6
|
const CiVisibilityExporter = require('../ci-visibility-exporter')
|
|
7
|
+
const log = require('../../../log')
|
|
7
8
|
|
|
8
9
|
class AgentlessCiVisibilityExporter extends CiVisibilityExporter {
|
|
9
10
|
constructor (config) {
|
|
@@ -19,11 +20,26 @@ class AgentlessCiVisibilityExporter extends CiVisibilityExporter {
|
|
|
19
20
|
this._coverageUrl = url || new URL(`https://event-platform-intake.${site}`)
|
|
20
21
|
this._coverageWriter = new CoverageWriter({ url: this._coverageUrl })
|
|
21
22
|
|
|
23
|
+
this._apiUrl = url || new URL(`https://api.${site}`)
|
|
24
|
+
|
|
22
25
|
if (isGitUploadEnabled) {
|
|
23
|
-
|
|
24
|
-
|
|
26
|
+
this.sendGitMetadata({ url: this._getApiUrl() })
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
setUrl (url, coverageUrl = url, apiUrl = url) {
|
|
31
|
+
this._setUrl(url, coverageUrl)
|
|
32
|
+
try {
|
|
33
|
+
apiUrl = new URL(apiUrl)
|
|
34
|
+
this._apiUrl = apiUrl
|
|
35
|
+
} catch (e) {
|
|
36
|
+
log.error(e)
|
|
25
37
|
}
|
|
26
38
|
}
|
|
39
|
+
|
|
40
|
+
_getApiUrl () {
|
|
41
|
+
return this._apiUrl
|
|
42
|
+
}
|
|
27
43
|
}
|
|
28
44
|
|
|
29
45
|
module.exports = AgentlessCiVisibilityExporter
|
|
@@ -63,9 +63,7 @@ class CiVisibilityExporter extends AgentInfoExporter {
|
|
|
63
63
|
}
|
|
64
64
|
|
|
65
65
|
canReportCodeCoverage () {
|
|
66
|
-
return this._canUseCiVisProtocol
|
|
67
|
-
this._itrConfig &&
|
|
68
|
-
this._itrConfig.isCodeCoverageEnabled
|
|
66
|
+
return this._canUseCiVisProtocol
|
|
69
67
|
}
|
|
70
68
|
|
|
71
69
|
// We can't call the skippable endpoint until git upload has finished,
|
|
@@ -79,7 +77,7 @@ class CiVisibilityExporter extends AgentInfoExporter {
|
|
|
79
77
|
return callback(gitUploadError, [])
|
|
80
78
|
}
|
|
81
79
|
const configuration = {
|
|
82
|
-
url: this.
|
|
80
|
+
url: this._getApiUrl(),
|
|
83
81
|
site: this._config.site,
|
|
84
82
|
env: this._config.env,
|
|
85
83
|
service: this._config.service,
|
|
@@ -103,13 +101,17 @@ class CiVisibilityExporter extends AgentInfoExporter {
|
|
|
103
101
|
return callback(null, {})
|
|
104
102
|
}
|
|
105
103
|
const configuration = {
|
|
106
|
-
url: this.
|
|
104
|
+
url: this._getApiUrl(),
|
|
107
105
|
env: this._config.env,
|
|
108
106
|
service: this._config.service,
|
|
109
107
|
isEvpProxy: !!this._isUsingEvpProxy,
|
|
110
108
|
...testConfiguration
|
|
111
109
|
}
|
|
112
110
|
getItrConfigurationRequest(configuration, (err, itrConfig) => {
|
|
111
|
+
/**
|
|
112
|
+
* **Important**: this._itrConfig remains empty in testing frameworks
|
|
113
|
+
* where the tests run in a subprocess, because `getItrConfiguration` is called only once.
|
|
114
|
+
*/
|
|
113
115
|
this._itrConfig = itrConfig
|
|
114
116
|
callback(err, itrConfig)
|
|
115
117
|
})
|
|
@@ -179,7 +181,7 @@ class CiVisibilityExporter extends AgentInfoExporter {
|
|
|
179
181
|
this._coverageBuffer = []
|
|
180
182
|
}
|
|
181
183
|
|
|
182
|
-
|
|
184
|
+
_setUrl (url, coverageUrl = url) {
|
|
183
185
|
try {
|
|
184
186
|
url = new URL(url)
|
|
185
187
|
coverageUrl = new URL(coverageUrl)
|
|
@@ -191,6 +193,10 @@ class CiVisibilityExporter extends AgentInfoExporter {
|
|
|
191
193
|
log.error(e)
|
|
192
194
|
}
|
|
193
195
|
}
|
|
196
|
+
|
|
197
|
+
_getApiUrl () {
|
|
198
|
+
return this._url
|
|
199
|
+
}
|
|
194
200
|
}
|
|
195
201
|
|
|
196
202
|
module.exports = CiVisibilityExporter
|