Skip to content
This repository was archived by the owner on Nov 19, 2024. It is now read-only.

Commit 9e98ebd

Browse files
authored
Merge branch 'master' into ds_upd-rakecicd
2 parents feb676b + 44e840b commit 9e98ebd

File tree

1 file changed

+173
-26
lines changed

1 file changed

+173
-26
lines changed

guides/v2.2/extension-dev-guide/xss-protection.md

Lines changed: 173 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -6,45 +6,192 @@ menu_title: XSS prevention strategies
66
menu_order: 1100
77
---
88

9-
### Overview
9+
## Overview
1010

11-
[Cross-site scripting](https://en.wikipedia.org/wiki/Cross-site_scripting){:target="_blank"}, or XSS, is a security vulnerability that can be found in web applications. This vulnerability allows attackers to inject malicious code into a web page viewed by users. Magento [extension](https://glossary.magento.com/extension) developers should be aware of these vulnerabilities to avoid introducing them in their code.
11+
[Cross-site scripting](https://www.owasp.org/index.php/Cross-site_Scripting_(XSS)){:target="_blank"}, or XSS, is a security vulnerability that can be found in web applications. This vulnerability allows attackers to inject malicious code/styles into a web page viewed by users. Magento [extension](https://glossary.magento.com/extension) developers should be aware of these vulnerabilities to avoid introducing them in their code.
1212

1313
There are mainly three types of XSS vulnerabilities:
1414

15-
* **Persisted XSS** - In this type of vulnerability, the source of unvalidated data comes from the Database or [Backend](https://glossary.magento.com/backend) permanent store.
16-
* **Reflected (non-persistent) XSS** - This type of vulnerability occurs when data provided by a web client is used immediately by server-side scripts to parse and display a page to a user without properly sanitizing the request.
17-
* **DOM XSS** - For this vulnerability, the malicious data does not touch the web server. Rather, it is being reflected by the [JavaScript](https://glossary.magento.com/javascript) code, fully on the client side.
15+
- **Persisted XSS** - In this type of vulnerability, the source of unvalidated data comes from the Database or [Backend](https://glossary.magento.com/backend) permanent store.
16+
- **Reflected (non-persistent) XSS** - This type of vulnerability occurs when data provided by a web client is used immediately by server-side scripts to parse and display a page to a user without properly sanitizing the request.
17+
- **DOM XSS** - For this vulnerability, the malicious data does not touch the web server. Rather, it is being reflected by the [JavaScript](https://glossary.magento.com/javascript) code, fully on the client side.
1818

19-
### Preventing XSS
19+
## Preventing XSS
2020

21-
XSS vulnerabilities can be prevented by always validating and sanitizing both user input and output, i.e., user input should never be trusted. Both the [PHP](https://glossary.magento.com/php) language and Magento provides classes and functions to help secure your extension from XSS vulnerabilities.
21+
XSS vulnerabilities can be prevented by validating and sanitizing user input as well as sanitizing dynamic values when rendering the view (HTML, mobile).
2222

23-
#### Input Processing
23+
### Input Processing
2424

25-
Any data you receive from an external source needs to be validated and sanitized to prevent the storage or execution of malicious code. Input data needs to be validated such that it is within the accepted possible values for that data item. This can vary depending on what that data is used for, but certain field validations can be applied almost universally such as checking for control characters.
25+
Any request data can be manipulated by attackers and can contain malicious values such as:
2626

27-
#### Output Processing
27+
- form fields filled with control characters ("<", ">" etc)
28+
- headers containg false IDs
29+
- URIs contaings fake parts/query parameters
30+
- tampered cookies
2831

29-
Output processing involves sanitizing strings that may have come from external data sources before sending it to the browser to be rendered with templates. It is the main method of protecting your extension from XSS attacks.
32+
To combat this developers, must validate any value coming in from requests.
3033

31-
For more information, see the article on [templates XSS security]({{ page.baseurl }}/frontend-dev-guide/templates/template-security.html){:target="_blank"}.
34+
It is better to validate/sanitize values as close as possible to the view context because only then you can be sure of the restrictions you have to impose on dynamic values and you are not risking security requirements for buisness requirements.
3235

33-
### Using the Escaper classes
36+
There is no reason, from a business standpoint, to disallow `<` `>` symbols in your users' "About me" section. By escaping control symbols when rendering HTML, allowing these characters would not be problematic. User "About me" data may be delivered via RESTful API, where "{" "}" could cause issues. If sanitized earlier, the user data would be damaged and contain HTML control symbols (`< >`).
3437

35-
Magento provides the [Escaper]({{ site.mage2bloburl }}/{{ page.guide_version }}/lib/internal/Magento/Framework/Escaper.php){:target="_blank"} class for escaping [HTML](https://glossary.magento.com/html) output. This class contains the following useful functions:
38+
### Output Processing
3639

37-
Function | Description
38-
--- | ---
39-
`escapeHtml()` | Escapes string inside HTML content
40-
`escapeHtmlAttr()` | Escapes strings in HTML tag attributes
41-
`escapeCss()` | Used for escaping strings inside a [CSS](https://glossary.magento.com/css) context.
42-
`escapeJs()` | Escapes strings inside a JavaScript context
43-
`escapeJsQuote()` | Escapes quotes in JavaScript
44-
`escapeQuote()` | Escapes quotes inside HTML attributes
45-
`escapeUrl()` | Used for escaping strings that will be used in a [URL](https://glossary.magento.com/url).
46-
`escapeXssInUrl()` | Escapes XSS in URLs
40+
Output processing involves sanitizing strings that may have come from external data sources before using it to render views. It is the main method of protecting your extension from XSS attacks.
4741

48-
### Related Topics
42+
In general - do not trust any dynamic values.
4943

50-
* [Templates XSS security]({{ page.baseurl }}/frontend-dev-guide/templates/template-security.html){:target="_blank"}
44+
#### PHTML templates
45+
46+
An 'Escaper' class is provided for .phtml templates and PHP classes responsible for generating HTML. It contains HTML sanitization methods for a variety of contexts.
47+
48+
The `$block` local variable available inside .phtml templates duplicates these methods.
49+
50+
See [Template guide](https://devdocs.magento.com/guides/v2.3/frontend-dev-guide/templates/template-overview.html) to read more about templates in Magento.
51+
52+
When using the Escaper:
53+
54+
- If a method indicates that the content is escaped, do not escape: getTitleHtml(), getHtmlTitle() (the title is ready for HTML output)
55+
- Type casting and the php function `count()` do not need escaping (for example `echo (int)$var`, `echo (bool)$var`, `echo count($var)`)
56+
- Output in single quotes does not need escaping (for example echo 'some text')
57+
- Output in double quotes without variables does not need escaping (for example echo "some text")
58+
- For all other cases, escape the data using context-specific escape functions.
59+
60+
**The following code sample illustrates XSS-safe output in templates:**
61+
62+
```php
63+
<?php echo $block->getTitleHtml() ?>
64+
<?php echo $block->getHtmlTitle() ?>
65+
<?php echo $block->escapeHtml($block->getTitle()) ?>
66+
<?php echo (int)$block->getId() ?>
67+
<?php echo count($var); ?>
68+
<?php echo 'some text' ?>
69+
<?php echo "some text" ?>
70+
<a href="<?php echo $block->escapeUrl($block->getUrl()) ?>"><?php echo $block->getAnchorTextHtml() ?></a>
71+
```
72+
73+
**When to use Escaper methods:**
74+
75+
**Case**: JSON inside an HTML attribute
76+
**Escaper method**: escapeHtmlAttribute
77+
78+
```php
79+
<div data-bind='settings: <?= $block->escapeHtmlAttribute($myJson) ?>'></div>
80+
```
81+
82+
**Case**: JSON inside script tag
83+
**Escaper method**: _no sanitization needed_
84+
85+
```php
86+
<script>
87+
let settings = <?= $myJson ?>
88+
</script>
89+
```
90+
91+
**Case**: HTML tag content that should not contain HTML
92+
**Escaper method**: escapeHtml
93+
94+
You can pass in an optional array of allowed tags that will not be escaped.
95+
96+
If a tag is allowed, the following attributes will not be escaped: `id`, `class`, `href`, `target`, `style` and `title`. Any other attribute for that allowed tag will be escaped.
97+
98+
`embed`, `iframe`, `video`, `source`, `object`, `audio`, `script` and `img` tags are not allowed, regardless of the content of this array.
99+
100+
```php
101+
<span class="label"><?php echo $block->escapeHtml($block->getLabel()) ?></span>
102+
// Escaping translation
103+
<div id='my-element'>
104+
<?php echo $block->escapeHtml(__('Only registered users can write reviews. Please <a href="%1">Sign in</a> or <a href="%2">create an account</a>', $block->getLoginUrl(), $block->getCreateAccountUrl()), ['a']) ?>
105+
</div>
106+
```
107+
108+
**Case**: URL inside certain HTML attributes
109+
**Escaper method**: escapeUrl
110+
111+
Certain attributes like `a.href` accept URIs of various types and must be sanitized.
112+
113+
```php
114+
<a href="<?= $block->escapeUrl($myUrl) ?>">Click me</a>
115+
<div attr-js-extracts="<?= $block->escapeHtmlAttribute($myOtherUrl) ?>"></div>
116+
```
117+
118+
**Case**: JavaScript string that must not contain JS/HTML
119+
**Escaper method**: escapeJS
120+
121+
```php
122+
<script>
123+
let phrase = "Hi, my name is <?= $block->escapeJs($myName) ?>";
124+
//Do not use HTMl context methods like escapeUrl
125+
let redirectUrl = "<?= $block->escapeJs($myUrl) ?>";
126+
location.href = redirectUrl;
127+
</script>
128+
```
129+
130+
**Case**: JavaScript variable that must not contain JS/HTML
131+
**Escaper method**: escapeJS
132+
133+
```php
134+
<script>
135+
let <?= $block->escapeJs($dynamicVariable) ?> = <?= $myJson ?>;
136+
settings.<?= $block->escapeJs($myProperty) ?> = true;
137+
</script>
138+
```
139+
140+
#### Knockout templates
141+
142+
In knockout templates, you can bind a UI component's property/function as 'inner HTML' of an element. Such properties may contain dynamic data and must be sanitized inside componenets. See [Magento binding syntax](https://devdocs.magento.com/guides/v2.3/ui_comp_guide/concepts/magento-bindings.html) to learn more about UI component templates.
143+
144+
In order to notify developers that these properties/function results may contain HTML, Magento requires (with the help of a static test) that you name such properties/functions using "UnsanitizedHtml" suffix.
145+
146+
```html
147+
<div data-bind="html: propUnsanitizedHtml"></div>
148+
<p html="returnUnsanitizedHtml()"></p>
149+
```
150+
151+
#### Dynamically created DOM elements
152+
153+
When using variables that are not supposed to contain HTML, the safest way to generate DOM elements is to create them programatically using appropriate APIs, instead of using the _innerHtml_ property or jQuery's _.html()_ function.
154+
155+
```javascript
156+
let newDiv = document.createElement("div");
157+
newDiv.innerText = userName;
158+
newDiv.setAttribute("custom-attribute", myAttribute);
159+
parentElement.appendChild(newDiv);
160+
```
161+
162+
#### UI component data providers
163+
164+
UI component data providers pass dynamic (user generated) data to UI components. The data they return is being rendered in order to support component dynamic linking. Since user data is supposed to be treated a a literal value which is not refering to any other component, rendering of these properties must be disabled. See [UI component data providers](https://devdocs.magento.com/guides/v2.3/ui_comp_guide/concepts/ui_comp_data_source.html) to read more about data providers and component linking.
165+
166+
```php
167+
$uiData = ['linkProperty' => '${ $.otherComponent.value }'];
168+
$uiData['customer'] = $customer->getData();
169+
//Customer data will be taken as is, linkProperty will be retrieved from otherComponent and taken as is
170+
$uiData['__disableTmpl'] = ['customer' => true, 'linkProperty' => 1];
171+
172+
return $uiData;
173+
```
174+
175+
### Static Test
176+
177+
To check your .phtml template for XSS vulnerabilities, you can use the _Magento2.Security.XssTemplate_ sniff from [Magento Coding Standard](https://github.com/magento/magento-coding-standard).
178+
179+
This sniff finds all _echo_ calls in PHTML-templates and determines if the output is properly escaped.
180+
181+
It covers the following cases:
182+
183+
- /_ @noEscape _/ before output. Output does not require escaping. Test is green.
184+
185+
- /_ @escapeNotVerified _/ before output. Output escaping is not checked and should be verified. Test is green.
186+
187+
- Methods which contain "html" in their names (for example echo $object->{suffix}Html{postfix}()). Data is ready for the HTML output. Test is green.
188+
189+
- AbstractBlock methods `escapeHtml`, `escapeHtmlAttr`, `escapeUrl`, `escapeJs` are allowed. Test is green.
190+
191+
- Type casting and php function `count()` are allowed (for example `echo (int)$var`, `(bool)$var`, `count($var)`). Test is green.
192+
193+
- Output in single quotes (for example echo 'some text'). Test is green.
194+
195+
- Output in double quotes without variables (for example echo "some text"). Test is green.
196+
197+
- Other of previously mentioned. Output is not escaped. Test is red.

0 commit comments

Comments
 (0)