Today’s task is to fulfill the rich text requirements of the product
After I finished writing, one of my classmates put forward an excellent question: “Our… Are XSS attacks prevented?”
React provides an attribute for inserting HTML content. It is named dangerouslySetInnerHTML to remind us that this is a dangerous operation
What is a XSS
XSS (Cross Site Script) has been one of the most common and dangerous Web security vulnerabilities. It is usually caused by data with parsable content inserted directly into the page without processing, and is classified as stored, reflected, or DOM. Generally speaking, malicious attackers insert malicious Script codes into Web pages. When users browse the page, the Script codes embedded in the Web will be executed, so as to achieve the purpose of malicious attacks on users.
Traditional solutions to XSS attacks are as follows:
- escape
- disinfection
-
What is escape
For my work this time, if I don’t do anything with the input and I type
When I’m rendering a page using dangerouslySetInnerHTML
<div dangerouslySetInnerHTML={{__html: inputValue}} /> Copy codeCopy the code
This is what happens
Because the input is fully inserted into the DOM with innerHTML, the onError method is executed because there is no err.jpg image path
Therefore, we will escape the input, i.e
<
convert<
>
convert>
This destroys the tag in the input, which will look like this when we enter the HTML with the attack again
<p>< Img SRC ="error.jpg" onerror=alert(' I want XSS to attack ')> </p> Copy the codeCopy the code
Thus preventing XSS
-
What is disinfection
For escaping, sometimes we want to safely insert a piece of HTML that will lose its original style and become a string after escaping
<em> I am italic </em> // after escape < em> I'm italic. /em> Copy the codeCopy the code
So we’re launching a new API called Sanitizer
Sanitizer API: Disinfectant
The effect is to remove risky tags or attributes directly
For example, in the example above, when we type it is processed through Sanitizer
Const $div = document.querySelector('div') const Content = '<em> I'm italic </em><img SRC ="error.jpg" Onerror =alert(' I want XSS to attack ')> 'const sanitizer = new sanitizer () $div.sethTML (Content, sanitizer) duplicates codeCopy the code
The result is that the secure HTML content is preserved and removed as a potentially malicious attribute such as onError
If you don’t want to insert DOM directly, you can also generate an HTMLElement as follows
Sanitizer. SanitizeFor ("div", content) //HTMLDivElement <div> Copies codeCopy the code
Custom Configuration
Because Sanitizer by default removes any attributes or tags that could trigger malicious attacks, we can customize the configuration to keep what we need
const config = { allowElements: [], blockElements: [], dropElements: [], allowAttributes: {}, dropAttributes: {}, allowCustomElements: true, allowComments: true }; // Sanitized result is customized by configuration new Sanitizer(config) Replication codeCopy the code
AllowElements: Sanitizer Allows an array of elements to remain blockElements: Sanitizer should remove an array of elements and keep their children dropElements: Sanitizer should remove arrays of elements and remove their child elements allowAttributes: allow reserved attributes dropAttributes: should remove attributes
const text = 'text1 <b style="font-weight: bold" class="test-class"><i>text 2</i></b><em>text 3</em>'; // <div>text1 <b style="font-weight: bold" class="test-class">text 2</b>text 3</div>. new Sanitizer({allowElements: [ "b" ]}).sanitizeFor('div',text); // <div>text1 <i>text 2</i><em>text 3</em></div>. new Sanitizer({blockElements: [ "b" ]}).sanitizeFor('div',text); // <div>text1 <em>text 3</em></div>. new Sanitizer({dropElements: [ "b" ]}).sanitizeFor('div',text); // <div>text1 <b style="font-weight: bold"><i>text 2</i></b><em>text 3</em></div>. new Sanitizer({allowAttributes: {"style": ["b"]}}).sanitizeFor("div", text) // <div>text1 <b><i>text 2</i></b><em>text 3</em></div>. new Sanitizer({allowAttributes: {"style": ["div"]}}).sanitizeFor("div", text) // <div>text1 <b class="test-class"><i>text 2</i></b><em>text 3</em></div>. new Sanitizer({dropAttributes: {"style": ["b"]}}). SanitizeFor ("div", textCopy the code
compatibility
Sanitizer API is a new proposal that the major browsers are working on and currently only available in Chrome 93, You can try out this API by turning on about://flags/#enable-experimental-web-platform-features. Before that we can use DOMPurify as backup