Skip to content

Commit

Permalink
feat: add raw html using user input rule
Browse files Browse the repository at this point in the history
  • Loading branch information
didroe committed Sep 28, 2023
1 parent 47900d3 commit 94e30cf
Show file tree
Hide file tree
Showing 5 changed files with 129 additions and 0 deletions.
61 changes: 61 additions & 0 deletions rules/php/lang/raw_html_using_user_input.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
languages:
- php
imports:
- php_shared_lang_user_input
patterns:
- pattern: $<STRING>;
filters:
- variable: STRING
string_regex: <\w+(\s[^>]*)?>
- variable: STRING
detection: php_lang_raw_html_using_user_input_html_user_input
scope: result
auxiliary:
- id: php_lang_raw_html_using_user_input_html_user_input
sanitizer: php_lang_raw_html_using_user_input_html_sanitizer
patterns:
- pattern: $<USER_INPUT>;
filters:
- variable: USER_INPUT
detection: php_shared_lang_user_input
scope: cursor
- id: php_lang_raw_html_using_user_input_html_sanitizer
patterns:
- pattern: $<FUNCTION>($<!>$<_>$<...>)
filters:
- variable: FUNCTION
values:
- htmlspecialchars
- htmlentities
- strip_tags
severity: high
metadata:
description: "Unsanitized user input detected in raw HTML string."
remediation_message: |
## Description
Applications should not include unsanitized user input in HTML. This
can allow cross-site scripting (XSS) attacks.
## Remediations
❌ Avoid including user input directly in HTML strings:
```php
$html = "<h1>{$_GET["title"]}</h1>";
```
✅ Use a templating language such as Twig, and place the template in a separate file.
✅ When HTML strings must be used, sanitize user input:
```php
$html = "<h1>${htmlspecialchars($_GET["title"])}</h1>";
```
## Resources
- [OWASP Cross-Site Scripting (XSS) Cheatsheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html)
cwe_id:
- 79
id: php_lang_raw_html_using_user_input
documentation_url: https://docs.bearer.com/reference/rules/php_lang_raw_html_using_user_input
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`php_lang_raw_html_using_user_input bad 1`] = `
"{
"high": [
{
"cwe_ids": [
"79"
],
"id": "php_lang_raw_html_using_user_input",
"title": "Unsanitized user input detected in raw HTML string.",
"description": "## Description\\n\\nApplications should not include unsanitized user input in HTML. This\\ncan allow cross-site scripting (XSS) attacks.\\n\\n## Remediations\\n\\n❌ Avoid including user input directly in HTML strings:\\n\\n\`\`\`php\\n$html = \\"<h1>{$_GET[\\"title\\"]}</h1>\\";\\n\`\`\`\\n\\n✅ Use a templating language such as Twig, and place the template in a separate file.\\n\\n✅ When HTML strings must be used, sanitize user input:\\n\\n\`\`\`php\\n$html = \\"<h1>\${htmlspecialchars($_GET[\\"title\\"])}</h1>\\";\\n\`\`\`\\n\\n## Resources\\n- [OWASP Cross-Site Scripting (XSS) Cheatsheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html)\\n",
"documentation_url": "https://docs.bearer.com/reference/rules/php_lang_raw_html_using_user_input",
"line_number": 3,
"full_filename": "/tmp/bearer-scan/bad.php",
"filename": ".",
"source": {
"start": 3,
"end": 3,
"column": {
"start": 1,
"end": 36
}
},
"sink": {
"start": 3,
"end": 3,
"column": {
"start": 1,
"end": 36
},
"content": "$html = \\"<h1>{$_GET[\\"title\\"]}</h1>\\""
},
"parent_line_number": 3,
"snippet": "$html = \\"<h1>{$_GET[\\"title\\"]}</h1>\\"",
"fingerprint": "7804aa0c200111a69c4f26fb6429429d_0",
"old_fingerprint": "ffde275847344753aea9d67164d28200_0",
"code_extract": "$html = \\"<h1>{$_GET[\\"title\\"]}</h1>\\";"
}
]
}"
`;

exports[`php_lang_raw_html_using_user_input ok 1`] = `"{}"`;
16 changes: 16 additions & 0 deletions tests/php/lang/raw_html_using_user_input/test.js
Original file line number Diff line number Diff line change
@@ -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()
})
})
3 changes: 3 additions & 0 deletions tests/php/lang/raw_html_using_user_input/testdata/bad.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<?php

$html = "<h1>{$_GET["title"]}</h1>";
5 changes: 5 additions & 0 deletions tests/php/lang/raw_html_using_user_input/testdata/ok.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?php

$html = "<h1>{strip_tags($_GET["title"])}</h1>";

$html = "<h1>{$ok}</h1>";

0 comments on commit 94e30cf

Please sign in to comment.