Skip to content

Commit 0cb75ee

Browse files
committed
No SameSite cookie vulnerability detection
1 parent 2f14ee8 commit 0cb75ee

File tree

5 files changed

+155
-0
lines changed

5 files changed

+155
-0
lines changed

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ module.exports = {
55
'INSECURE_COOKIE_ANALYZER': require('./insecure-cookie-analyzer'),
66
'LDAP_ANALYZER': require('./ldap-injection-analyzer'),
77
'NO_HTTPONLY_COOKIE_ANALYZER': require('./no-httponly-cookie-analyzer'),
8+
'NO_SAMESITE_COOKIE_ANALYZER': require('./no-samesite-cookie-analyzer'),
89
'PATH_TRAVERSAL_ANALYZER': require('./path-traversal-analyzer'),
910
'SQL_INJECTION_ANALYZER': require('./sql-injection-analyzer'),
1011
'SSRF': require('./ssrf-analyzer'),
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
'use strict'
2+
3+
const { NO_SAMESITE_COOKIE } = require('../vulnerabilities')
4+
const CookieAnalyzer = require('./cookie-analyzer')
5+
6+
class NoSamesiteCookieAnalyzer extends CookieAnalyzer {
7+
constructor () {
8+
super(NO_SAMESITE_COOKIE, 'SameSite=strict')
9+
}
10+
}
11+
12+
module.exports = new NoSamesiteCookieAnalyzer()

packages/dd-trace/src/appsec/iast/vulnerabilities.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ module.exports = {
33
INSECURE_COOKIE: 'INSECURE_COOKIE',
44
LDAP_INJECTION: 'LDAP_INJECTION',
55
NO_HTTPONLY_COOKIE: 'NO_HTTPONLY_COOKIE',
6+
NO_SAMESITE_COOKIE: 'NO_SAMESITE_COOKIE',
67
PATH_TRAVERSAL: 'PATH_TRAVERSAL',
78
SQL_INJECTION: 'SQL_INJECTION',
89
SSRF: 'SSRF',
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
'use strict'
2+
3+
const { prepareTestServerForIastInExpress } = require('../utils')
4+
const fs = require('fs')
5+
const os = require('os')
6+
const path = require('path')
7+
describe('no SameSite cookie vulnerability', () => {
8+
let setCookieFunctions
9+
const setCookieFunctionsFilename = 'set-cookie-express-functions.js'
10+
const setCookieFunctionsPath = path.join(os.tmpdir(), setCookieFunctionsFilename)
11+
12+
before(() => {
13+
fs.copyFileSync(path.join(__dirname, 'resources', 'set-cookie-express-functions.js'), setCookieFunctionsPath)
14+
setCookieFunctions = require(setCookieFunctionsPath)
15+
})
16+
17+
after(() => {
18+
fs.unlinkSync(setCookieFunctionsPath)
19+
})
20+
21+
withVersions('express', 'express', '>=4.15.0', version => {
22+
// Oldest express4 versions do not support sameSite property in cookie method
23+
prepareTestServerForIastInExpress('in express', version,
24+
(testThatRequestHasVulnerability, testThatRequestHasNoVulnerability) => {
25+
testThatRequestHasVulnerability((req, res) => {
26+
setCookieFunctions.insecureWithResCookieMethod('insecure', 'cookie', res)
27+
}, 'NO_SAMESITE_COOKIE', {
28+
occurrences: 1,
29+
location: {
30+
path: setCookieFunctionsFilename,
31+
line: 4
32+
}
33+
})
34+
35+
testThatRequestHasVulnerability((req, res) => {
36+
setCookieFunctions.insecureWithResCookieMethod('insecure', 'cookie', res)
37+
setCookieFunctions.insecureWithResCookieMethod('insecure2', 'cookie2', res)
38+
}, 'NO_SAMESITE_COOKIE', {
39+
occurrences: 2,
40+
location: {
41+
path: setCookieFunctionsFilename,
42+
line: 4
43+
}
44+
})
45+
46+
testThatRequestHasVulnerability((req, res) => {
47+
setCookieFunctions.insecureWithResHeaderMethod('insecure', 'cookie', res)
48+
}, 'NO_SAMESITE_COOKIE', {
49+
occurrences: 1,
50+
location: {
51+
path: setCookieFunctionsFilename,
52+
line: 8
53+
}
54+
})
55+
56+
testThatRequestHasVulnerability((req, res) => {
57+
setCookieFunctions.insecureWithResHeaderMethodWithArray('insecure', 'cookie', 'insecure2', 'cookie2', res)
58+
}, 'NO_SAMESITE_COOKIE', {
59+
occurrences: 2,
60+
location: {
61+
path: setCookieFunctionsFilename,
62+
line: 12
63+
}
64+
})
65+
66+
testThatRequestHasNoVulnerability((req, res) => {
67+
res.cookie('secure', 'cookie', { secure: true, httpOnly: true, sameSite: 'strict' })
68+
res.cookie('secure', 'cookie', { secure: true, httpOnly: true, sameSite: true })
69+
res.clearCookie('deleteinsecure')
70+
res.header('set-cookie', 'other=secure; Secure; HttpOnly; SameSite=strict')
71+
res.header('set-cookie', ['other=safe; ; SameSite=strict', 'more=safe2; Secure; HttpOnly; SameSite=strict'])
72+
}, 'NO_SAMESITE_COOKIE')
73+
})
74+
})
75+
})
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
'use strict'
2+
3+
const { prepareTestServerForIast } = require('../utils')
4+
const Analyzer = require('../../../../src/appsec/iast/analyzers/vulnerability-analyzer')
5+
const { NO_SAMESITE_COOKIE } = require('../../../../src/appsec/iast/vulnerabilities')
6+
const analyzer = new Analyzer()
7+
8+
describe('no SameSite cookie analyzer', () => {
9+
it('Expected vulnerability identifier', () => {
10+
expect(NO_SAMESITE_COOKIE).to.be.equals('NO_SAMESITE_COOKIE')
11+
})
12+
13+
// In these test, even when we are having multiple vulnerabilities, all the vulnerabilities
14+
// are in the same cookies method, and it is expected to detect both even when the max operations is 1
15+
const iastConfig = {
16+
enabled: true,
17+
requestSampling: 100,
18+
maxConcurrentRequests: 1,
19+
maxContextOperations: 1
20+
}
21+
prepareTestServerForIast('no HttpOnly cookie analyzer',
22+
(testThatRequestHasVulnerability, testThatRequestHasNoVulnerability) => {
23+
testThatRequestHasVulnerability((req, res) => {
24+
res.setHeader('set-cookie', 'key=value')
25+
}, NO_SAMESITE_COOKIE, 1, function (vulnerabilities) {
26+
expect(vulnerabilities[0].evidence.value).to.be.equals('key')
27+
expect(vulnerabilities[0].hash).to.be.equals(analyzer._createHash('NO_SAMESITE_COOKIE:key'))
28+
})
29+
30+
testThatRequestHasVulnerability((req, res) => {
31+
res.setHeader('set-cookie', ['key=value'])
32+
}, NO_SAMESITE_COOKIE, 1)
33+
34+
testThatRequestHasVulnerability((req, res) => {
35+
res.setHeader('set-cookie', ['key=value; SameSite=Lax'])
36+
}, NO_SAMESITE_COOKIE, 1)
37+
38+
testThatRequestHasVulnerability((req, res) => {
39+
res.setHeader('set-cookie', ['key=value; SameSite=None'])
40+
}, NO_SAMESITE_COOKIE, 1)
41+
42+
testThatRequestHasVulnerability((req, res) => {
43+
res.setHeader('set-cookie', ['key=value', 'key2=value2'])
44+
}, NO_SAMESITE_COOKIE, 2)
45+
46+
testThatRequestHasVulnerability((req, res) => {
47+
res.setHeader('set-cookie', ['key=value', 'key2=value2; Secure'])
48+
}, NO_SAMESITE_COOKIE, 2)
49+
50+
testThatRequestHasVulnerability((req, res) => {
51+
res.setHeader('set-cookie', ['key=value', 'key2=value2; SameSite=strict'])
52+
}, NO_SAMESITE_COOKIE, 1)
53+
54+
testThatRequestHasVulnerability((req, res) => {
55+
res.setHeader('set-cookie', ['key=value; SameSite=strict', 'key2=value2; Secure'])
56+
}, NO_SAMESITE_COOKIE, 1)
57+
58+
testThatRequestHasNoVulnerability((req, res) => {
59+
res.setHeader('set-cookie', 'key=value; SameSite=strict')
60+
}, NO_SAMESITE_COOKIE)
61+
62+
testThatRequestHasNoVulnerability((req, res) => {
63+
res.setHeader('set-cookie', 'key=')
64+
}, NO_SAMESITE_COOKIE)
65+
}, iastConfig)
66+
})

0 commit comments

Comments
 (0)