From e777a3df94051fde36408f1b3fff5f73e3cf1a49 Mon Sep 17 00:00:00 2001 From: David Roe Date: Tue, 10 Oct 2023 15:23:27 +0100 Subject: [PATCH] feat: add symfony insecure cookie rule --- rules/php/symfony/insecure_cookie.yml | 125 +++++ .../__snapshots__/test.js.snap | 430 ++++++++++++++++++ tests/php/symfony/insecure_cookie/test.js | 16 + .../symfony/insecure_cookie/testdata/bad.php | 21 + .../symfony/insecure_cookie/testdata/ok.php | 27 ++ 5 files changed, 619 insertions(+) create mode 100644 rules/php/symfony/insecure_cookie.yml create mode 100644 tests/php/symfony/insecure_cookie/__snapshots__/test.js.snap create mode 100644 tests/php/symfony/insecure_cookie/test.js create mode 100644 tests/php/symfony/insecure_cookie/testdata/bad.php create mode 100644 tests/php/symfony/insecure_cookie/testdata/ok.php diff --git a/rules/php/symfony/insecure_cookie.yml b/rules/php/symfony/insecure_cookie.yml new file mode 100644 index 000000000..e0ff310e9 --- /dev/null +++ b/rules/php/symfony/insecure_cookie.yml @@ -0,0 +1,125 @@ +imports: + - php_shared_lang_instance +patterns: + - pattern: | + $::create($<_>, $<_>, $<_>, $<_>, $<_>, $$<...>) + filters: + - variable: CLASS + regex: \A(Symfony\\Component\\HttpFoundation\\)?Cookie\z + - variable: SECURE + detection: php_symfony_insecure_cookie_false + scope: cursor + - pattern: | + $::create(secure: $) + filters: + - variable: CLASS + regex: \A(Symfony\\Component\\HttpFoundation\\)?Cookie\z + - variable: SECURE + detection: php_symfony_insecure_cookie_false + scope: cursor + - pattern: | + $::create($<_>, $<_>, $<_>, $<_>, $<_>, $<_>, $$<...>) + filters: + - variable: CLASS + regex: \A(Symfony\\Component\\HttpFoundation\\)?Cookie\z + - variable: HTTP_ONLY + detection: php_symfony_insecure_cookie_false + scope: cursor + - pattern: | + $::create(httpOnly: $) + filters: + - variable: CLASS + regex: \A(Symfony\\Component\\HttpFoundation\\)?Cookie\z + - variable: HTTP_ONLY + detection: php_symfony_insecure_cookie_false + scope: cursor + - pattern: | + new $($<_>, $<_>, $<_>, $<_>, $<_>, $$<...>) + filters: + - variable: CLASS + regex: \A(Symfony\\Component\\HttpFoundation\\)?Cookie\z + - variable: SECURE + detection: php_symfony_insecure_cookie_false + scope: cursor + - pattern: | + new $(secure: $) + filters: + - variable: CLASS + regex: \A(Symfony\\Component\\HttpFoundation\\)?Cookie\z + - variable: SECURE + detection: php_symfony_insecure_cookie_false + scope: cursor + - pattern: | + new $($<_>, $<_>, $<_>, $<_>, $<_>, $<_>, $$<...>) + filters: + - variable: CLASS + regex: \A(Symfony\\Component\\HttpFoundation\\)?Cookie\z + - variable: HTTP_ONLY + detection: php_symfony_insecure_cookie_false + scope: cursor + - pattern: | + new $(httpOnly: $) + filters: + - variable: CLASS + regex: \A(Symfony\\Component\\HttpFoundation\\)?Cookie\z + - variable: HTTP_ONLY + detection: php_symfony_insecure_cookie_false + scope: cursor + - pattern: $->withSecure($) + filters: + - variable: COOKIE + detection: php_symfony_insecure_cookie_instance + scope: cursor + - variable: SECURE + detection: php_symfony_insecure_cookie_false + scope: cursor + - pattern: $->withHttpOnly($) + filters: + - variable: COOKIE + detection: php_symfony_insecure_cookie_instance + scope: cursor + - variable: HTTP_ONLY + detection: php_symfony_insecure_cookie_false + scope: cursor +auxiliary: + - id: php_symfony_insecure_cookie_false + patterns: + - "false;" + - id: php_symfony_insecure_cookie_instance + patterns: + - pattern: $; + filters: + - variable: INSTANCE + detection: php_shared_lang_instance + scope: cursor + filters: + - variable: CLASS + regex: \A(Symfony\\Component\\HttpFoundation\\)?Cookie\z + - pattern: | + $::create() + filters: + - variable: CLASS + regex: \A(Symfony\\Component\\HttpFoundation\\)?Cookie\z + - pattern: $->$<_>() + filters: + - variable: COOKIE + detection: php_symfony_insecure_cookie_instance + scope: cursor +languages: + - php +metadata: + description: "Insecure options for cookie detected." + remediation_message: | + ## Description + To make sure cookies don't open your application up to exploits or + unauthorized access, make sure to set security options appropriately. + + ## Remediations + ✅ Set `httpOnly` to `true` to avoid the cookie being sent by client-side scripts. + + ✅ Set `secure` to `true` to force cookies to only send over HTTPS. + cwe_id: + - 1004 + - 614 + id: php_symfony_insecure_cookie + documentation_url: https://docs.bearer.com/reference/rules/php_symfony_insecure_cookie diff --git a/tests/php/symfony/insecure_cookie/__snapshots__/test.js.snap b/tests/php/symfony/insecure_cookie/__snapshots__/test.js.snap new file mode 100644 index 000000000..1f12c3ebe --- /dev/null +++ b/tests/php/symfony/insecure_cookie/__snapshots__/test.js.snap @@ -0,0 +1,430 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`php_symfony_insecure_cookie bad 1`] = ` +"{ + "low": [ + { + "cwe_ids": [ + "1004", + "614" + ], + "id": "php_symfony_insecure_cookie", + "title": "Insecure options for cookie detected.", + "description": "## Description\\nTo make sure cookies don't open your application up to exploits or\\nunauthorized access, make sure to set security options appropriately.\\n\\n## Remediations\\n✅ Set \`httpOnly\` to \`true\` to avoid the cookie being sent by client-side scripts.\\n\\n✅ Set \`secure\` to \`true\` to force cookies to only send over HTTPS.\\n", + "documentation_url": "https://docs.bearer.com/reference/rules/php_symfony_insecure_cookie", + "line_number": 5, + "full_filename": "/tmp/bearer-scan/bad.php", + "filename": ".", + "source": { + "start": 5, + "end": 5, + "column": { + "start": 1, + "end": 73 + } + }, + "sink": { + "start": 5, + "end": 5, + "column": { + "start": 1, + "end": 73 + }, + "content": "Cookie::create($name, $value, $expire, $path, $domain, false, $httpOnly)" + }, + "parent_line_number": 5, + "snippet": "Cookie::create($name, $value, $expire, $path, $domain, false, $httpOnly)", + "fingerprint": "f484c2971d8bbfaf6f441c6ef90da20f_0", + "old_fingerprint": "96c5c5872ba704b3d97886248732d0bb_0", + "code_extract": "Cookie::create($name, $value, $expire, $path, $domain, false, $httpOnly);" + }, + { + "cwe_ids": [ + "1004", + "614" + ], + "id": "php_symfony_insecure_cookie", + "title": "Insecure options for cookie detected.", + "description": "## Description\\nTo make sure cookies don't open your application up to exploits or\\nunauthorized access, make sure to set security options appropriately.\\n\\n## Remediations\\n✅ Set \`httpOnly\` to \`true\` to avoid the cookie being sent by client-side scripts.\\n\\n✅ Set \`secure\` to \`true\` to force cookies to only send over HTTPS.\\n", + "documentation_url": "https://docs.bearer.com/reference/rules/php_symfony_insecure_cookie", + "line_number": 6, + "full_filename": "/tmp/bearer-scan/bad.php", + "filename": ".", + "source": { + "start": 6, + "end": 6, + "column": { + "start": 1, + "end": 45 + } + }, + "sink": { + "start": 6, + "end": 6, + "column": { + "start": 1, + "end": 45 + }, + "content": "Cookie::create($name, $value, secure: false)" + }, + "parent_line_number": 6, + "snippet": "Cookie::create($name, $value, secure: false)", + "fingerprint": "f484c2971d8bbfaf6f441c6ef90da20f_1", + "old_fingerprint": "96c5c5872ba704b3d97886248732d0bb_1", + "code_extract": "Cookie::create($name, $value, secure: false);" + }, + { + "cwe_ids": [ + "1004", + "614" + ], + "id": "php_symfony_insecure_cookie", + "title": "Insecure options for cookie detected.", + "description": "## Description\\nTo make sure cookies don't open your application up to exploits or\\nunauthorized access, make sure to set security options appropriately.\\n\\n## Remediations\\n✅ Set \`httpOnly\` to \`true\` to avoid the cookie being sent by client-side scripts.\\n\\n✅ Set \`secure\` to \`true\` to force cookies to only send over HTTPS.\\n", + "documentation_url": "https://docs.bearer.com/reference/rules/php_symfony_insecure_cookie", + "line_number": 7, + "full_filename": "/tmp/bearer-scan/bad.php", + "filename": ".", + "source": { + "start": 7, + "end": 7, + "column": { + "start": 1, + "end": 77 + } + }, + "sink": { + "start": 7, + "end": 7, + "column": { + "start": 1, + "end": 77 + }, + "content": "Cookie::create($name, $value, $expire, $path, $domain, $secure, false, $raw)" + }, + "parent_line_number": 7, + "snippet": "Cookie::create($name, $value, $expire, $path, $domain, $secure, false, $raw)", + "fingerprint": "f484c2971d8bbfaf6f441c6ef90da20f_2", + "old_fingerprint": "96c5c5872ba704b3d97886248732d0bb_2", + "code_extract": "Cookie::create($name, $value, $expire, $path, $domain, $secure, false, $raw);" + }, + { + "cwe_ids": [ + "1004", + "614" + ], + "id": "php_symfony_insecure_cookie", + "title": "Insecure options for cookie detected.", + "description": "## Description\\nTo make sure cookies don't open your application up to exploits or\\nunauthorized access, make sure to set security options appropriately.\\n\\n## Remediations\\n✅ Set \`httpOnly\` to \`true\` to avoid the cookie being sent by client-side scripts.\\n\\n✅ Set \`secure\` to \`true\` to force cookies to only send over HTTPS.\\n", + "documentation_url": "https://docs.bearer.com/reference/rules/php_symfony_insecure_cookie", + "line_number": 8, + "full_filename": "/tmp/bearer-scan/bad.php", + "filename": ".", + "source": { + "start": 8, + "end": 8, + "column": { + "start": 1, + "end": 47 + } + }, + "sink": { + "start": 8, + "end": 8, + "column": { + "start": 1, + "end": 47 + }, + "content": "Cookie::create($name, $value, httpOnly: false)" + }, + "parent_line_number": 8, + "snippet": "Cookie::create($name, $value, httpOnly: false)", + "fingerprint": "f484c2971d8bbfaf6f441c6ef90da20f_3", + "old_fingerprint": "96c5c5872ba704b3d97886248732d0bb_3", + "code_extract": "Cookie::create($name, $value, httpOnly: false);" + }, + { + "cwe_ids": [ + "1004", + "614" + ], + "id": "php_symfony_insecure_cookie", + "title": "Insecure options for cookie detected.", + "description": "## Description\\nTo make sure cookies don't open your application up to exploits or\\nunauthorized access, make sure to set security options appropriately.\\n\\n## Remediations\\n✅ Set \`httpOnly\` to \`true\` to avoid the cookie being sent by client-side scripts.\\n\\n✅ Set \`secure\` to \`true\` to force cookies to only send over HTTPS.\\n", + "documentation_url": "https://docs.bearer.com/reference/rules/php_symfony_insecure_cookie", + "line_number": 11, + "full_filename": "/tmp/bearer-scan/bad.php", + "filename": ".", + "source": { + "start": 11, + "end": 11, + "column": { + "start": 1, + "end": 43 + } + }, + "sink": { + "start": 11, + "end": 11, + "column": { + "start": 1, + "end": 43 + }, + "content": "$cookie->withRaw(false)->withSecure(false)" + }, + "parent_line_number": 11, + "snippet": "$cookie->withRaw(false)->withSecure(false)", + "fingerprint": "f484c2971d8bbfaf6f441c6ef90da20f_4", + "old_fingerprint": "96c5c5872ba704b3d97886248732d0bb_4", + "code_extract": "$cookie->withRaw(false)->withSecure(false);" + }, + { + "cwe_ids": [ + "1004", + "614" + ], + "id": "php_symfony_insecure_cookie", + "title": "Insecure options for cookie detected.", + "description": "## Description\\nTo make sure cookies don't open your application up to exploits or\\nunauthorized access, make sure to set security options appropriately.\\n\\n## Remediations\\n✅ Set \`httpOnly\` to \`true\` to avoid the cookie being sent by client-side scripts.\\n\\n✅ Set \`secure\` to \`true\` to force cookies to only send over HTTPS.\\n", + "documentation_url": "https://docs.bearer.com/reference/rules/php_symfony_insecure_cookie", + "line_number": 12, + "full_filename": "/tmp/bearer-scan/bad.php", + "filename": ".", + "source": { + "start": 12, + "end": 12, + "column": { + "start": 1, + "end": 45 + } + }, + "sink": { + "start": 12, + "end": 12, + "column": { + "start": 1, + "end": 45 + }, + "content": "$cookie->withRaw(false)->withHttpOnly(false)" + }, + "parent_line_number": 12, + "snippet": "$cookie->withRaw(false)->withHttpOnly(false)", + "fingerprint": "f484c2971d8bbfaf6f441c6ef90da20f_5", + "old_fingerprint": "96c5c5872ba704b3d97886248732d0bb_5", + "code_extract": "$cookie->withRaw(false)->withHttpOnly(false);" + }, + { + "cwe_ids": [ + "1004", + "614" + ], + "id": "php_symfony_insecure_cookie", + "title": "Insecure options for cookie detected.", + "description": "## Description\\nTo make sure cookies don't open your application up to exploits or\\nunauthorized access, make sure to set security options appropriately.\\n\\n## Remediations\\n✅ Set \`httpOnly\` to \`true\` to avoid the cookie being sent by client-side scripts.\\n\\n✅ Set \`secure\` to \`true\` to force cookies to only send over HTTPS.\\n", + "documentation_url": "https://docs.bearer.com/reference/rules/php_symfony_insecure_cookie", + "line_number": 14, + "full_filename": "/tmp/bearer-scan/bad.php", + "filename": ".", + "source": { + "start": 14, + "end": 14, + "column": { + "start": 1, + "end": 69 + } + }, + "sink": { + "start": 14, + "end": 14, + "column": { + "start": 1, + "end": 69 + }, + "content": "new Cookie($name, $value, $expire, $path, $domain, false, $httpOnly)" + }, + "parent_line_number": 14, + "snippet": "new Cookie($name, $value, $expire, $path, $domain, false, $httpOnly)", + "fingerprint": "f484c2971d8bbfaf6f441c6ef90da20f_6", + "old_fingerprint": "96c5c5872ba704b3d97886248732d0bb_6", + "code_extract": "new Cookie($name, $value, $expire, $path, $domain, false, $httpOnly);" + }, + { + "cwe_ids": [ + "1004", + "614" + ], + "id": "php_symfony_insecure_cookie", + "title": "Insecure options for cookie detected.", + "description": "## Description\\nTo make sure cookies don't open your application up to exploits or\\nunauthorized access, make sure to set security options appropriately.\\n\\n## Remediations\\n✅ Set \`httpOnly\` to \`true\` to avoid the cookie being sent by client-side scripts.\\n\\n✅ Set \`secure\` to \`true\` to force cookies to only send over HTTPS.\\n", + "documentation_url": "https://docs.bearer.com/reference/rules/php_symfony_insecure_cookie", + "line_number": 15, + "full_filename": "/tmp/bearer-scan/bad.php", + "filename": ".", + "source": { + "start": 15, + "end": 15, + "column": { + "start": 1, + "end": 41 + } + }, + "sink": { + "start": 15, + "end": 15, + "column": { + "start": 1, + "end": 41 + }, + "content": "new Cookie($name, $value, secure: false)" + }, + "parent_line_number": 15, + "snippet": "new Cookie($name, $value, secure: false)", + "fingerprint": "f484c2971d8bbfaf6f441c6ef90da20f_7", + "old_fingerprint": "96c5c5872ba704b3d97886248732d0bb_7", + "code_extract": "new Cookie($name, $value, secure: false);" + }, + { + "cwe_ids": [ + "1004", + "614" + ], + "id": "php_symfony_insecure_cookie", + "title": "Insecure options for cookie detected.", + "description": "## Description\\nTo make sure cookies don't open your application up to exploits or\\nunauthorized access, make sure to set security options appropriately.\\n\\n## Remediations\\n✅ Set \`httpOnly\` to \`true\` to avoid the cookie being sent by client-side scripts.\\n\\n✅ Set \`secure\` to \`true\` to force cookies to only send over HTTPS.\\n", + "documentation_url": "https://docs.bearer.com/reference/rules/php_symfony_insecure_cookie", + "line_number": 16, + "full_filename": "/tmp/bearer-scan/bad.php", + "filename": ".", + "source": { + "start": 16, + "end": 16, + "column": { + "start": 1, + "end": 73 + } + }, + "sink": { + "start": 16, + "end": 16, + "column": { + "start": 1, + "end": 73 + }, + "content": "new Cookie($name, $value, $expire, $path, $domain, $secure, false, $raw)" + }, + "parent_line_number": 16, + "snippet": "new Cookie($name, $value, $expire, $path, $domain, $secure, false, $raw)", + "fingerprint": "f484c2971d8bbfaf6f441c6ef90da20f_8", + "old_fingerprint": "96c5c5872ba704b3d97886248732d0bb_8", + "code_extract": "new Cookie($name, $value, $expire, $path, $domain, $secure, false, $raw);" + }, + { + "cwe_ids": [ + "1004", + "614" + ], + "id": "php_symfony_insecure_cookie", + "title": "Insecure options for cookie detected.", + "description": "## Description\\nTo make sure cookies don't open your application up to exploits or\\nunauthorized access, make sure to set security options appropriately.\\n\\n## Remediations\\n✅ Set \`httpOnly\` to \`true\` to avoid the cookie being sent by client-side scripts.\\n\\n✅ Set \`secure\` to \`true\` to force cookies to only send over HTTPS.\\n", + "documentation_url": "https://docs.bearer.com/reference/rules/php_symfony_insecure_cookie", + "line_number": 17, + "full_filename": "/tmp/bearer-scan/bad.php", + "filename": ".", + "source": { + "start": 17, + "end": 17, + "column": { + "start": 1, + "end": 43 + } + }, + "sink": { + "start": 17, + "end": 17, + "column": { + "start": 1, + "end": 43 + }, + "content": "new Cookie($name, $value, httpOnly: false)" + }, + "parent_line_number": 17, + "snippet": "new Cookie($name, $value, httpOnly: false)", + "fingerprint": "f484c2971d8bbfaf6f441c6ef90da20f_9", + "old_fingerprint": "96c5c5872ba704b3d97886248732d0bb_9", + "code_extract": "new Cookie($name, $value, httpOnly: false);" + }, + { + "cwe_ids": [ + "1004", + "614" + ], + "id": "php_symfony_insecure_cookie", + "title": "Insecure options for cookie detected.", + "description": "## Description\\nTo make sure cookies don't open your application up to exploits or\\nunauthorized access, make sure to set security options appropriately.\\n\\n## Remediations\\n✅ Set \`httpOnly\` to \`true\` to avoid the cookie being sent by client-side scripts.\\n\\n✅ Set \`secure\` to \`true\` to force cookies to only send over HTTPS.\\n", + "documentation_url": "https://docs.bearer.com/reference/rules/php_symfony_insecure_cookie", + "line_number": 20, + "full_filename": "/tmp/bearer-scan/bad.php", + "filename": ".", + "source": { + "start": 20, + "end": 20, + "column": { + "start": 1, + "end": 43 + } + }, + "sink": { + "start": 20, + "end": 20, + "column": { + "start": 1, + "end": 43 + }, + "content": "$cookie->withRaw(false)->withSecure(false)" + }, + "parent_line_number": 20, + "snippet": "$cookie->withRaw(false)->withSecure(false)", + "fingerprint": "f484c2971d8bbfaf6f441c6ef90da20f_10", + "old_fingerprint": "96c5c5872ba704b3d97886248732d0bb_10", + "code_extract": "$cookie->withRaw(false)->withSecure(false);" + }, + { + "cwe_ids": [ + "1004", + "614" + ], + "id": "php_symfony_insecure_cookie", + "title": "Insecure options for cookie detected.", + "description": "## Description\\nTo make sure cookies don't open your application up to exploits or\\nunauthorized access, make sure to set security options appropriately.\\n\\n## Remediations\\n✅ Set \`httpOnly\` to \`true\` to avoid the cookie being sent by client-side scripts.\\n\\n✅ Set \`secure\` to \`true\` to force cookies to only send over HTTPS.\\n", + "documentation_url": "https://docs.bearer.com/reference/rules/php_symfony_insecure_cookie", + "line_number": 21, + "full_filename": "/tmp/bearer-scan/bad.php", + "filename": ".", + "source": { + "start": 21, + "end": 21, + "column": { + "start": 1, + "end": 45 + } + }, + "sink": { + "start": 21, + "end": 21, + "column": { + "start": 1, + "end": 45 + }, + "content": "$cookie->withRaw(false)->withHttpOnly(false)" + }, + "parent_line_number": 21, + "snippet": "$cookie->withRaw(false)->withHttpOnly(false)", + "fingerprint": "f484c2971d8bbfaf6f441c6ef90da20f_11", + "old_fingerprint": "96c5c5872ba704b3d97886248732d0bb_11", + "code_extract": "$cookie->withRaw(false)->withHttpOnly(false);" + } + ] +}" +`; + +exports[`php_symfony_insecure_cookie ok 1`] = `"{}"`; diff --git a/tests/php/symfony/insecure_cookie/test.js b/tests/php/symfony/insecure_cookie/test.js new file mode 100644 index 000000000..bca0fa61e --- /dev/null +++ b/tests/php/symfony/insecure_cookie/test.js @@ -0,0 +1,16 @@ +const { createInvoker, getEnvironment } = require("../../../helper.js") +const { ruleId, ruleFile, testBase } = getEnvironment(__dirname) + +describe(ruleId, () => { + const invoke = createInvoker(ruleId, ruleFile, testBase) + + test("bad", () => { + const testCase = "bad.php" + expect(invoke(testCase)).toMatchSnapshot() + }) + + test("ok", () => { + const testCase = "ok.php" + expect(invoke(testCase)).toMatchSnapshot() + }) +}) diff --git a/tests/php/symfony/insecure_cookie/testdata/bad.php b/tests/php/symfony/insecure_cookie/testdata/bad.php new file mode 100644 index 000000000..21d46cd76 --- /dev/null +++ b/tests/php/symfony/insecure_cookie/testdata/bad.php @@ -0,0 +1,21 @@ +withRaw(false)->withSecure(false); +$cookie->withRaw(false)->withHttpOnly(false); + +new Cookie($name, $value, $expire, $path, $domain, false, $httpOnly); +new Cookie($name, $value, secure: false); +new Cookie($name, $value, $expire, $path, $domain, $secure, false, $raw); +new Cookie($name, $value, httpOnly: false); + +$cookie = new Cookie($name, $value); +$cookie->withRaw(false)->withSecure(false); +$cookie->withRaw(false)->withHttpOnly(false); diff --git a/tests/php/symfony/insecure_cookie/testdata/ok.php b/tests/php/symfony/insecure_cookie/testdata/ok.php new file mode 100644 index 000000000..5966258cc --- /dev/null +++ b/tests/php/symfony/insecure_cookie/testdata/ok.php @@ -0,0 +1,27 @@ +withRaw(false)->withSecure(null); +$cookie->withRaw(false)->withSecure(true); +$cookie->withRaw(false)->withHttpOnly(true); + +new Cookie($name, $value, $expire, $path, $domain, true, $httpOnly); +new Cookie($name, $value, $expire, $path, $domain, null, $httpOnly); +new Cookie($name, $value, secure: true); +new Cookie($name, $value, secure: null); +new Cookie($name, $value, $expire, $path, $domain, $secure, true, $raw); +new Cookie($name, $value, httpOnly: true); + +$cookie = new Cookie($name, $value); +$cookie->withRaw(false)->withSecure(true); +$cookie->withRaw(false)->withSecure(null); +$cookie->withRaw(false)->withHttpOnly(true);