Cross site scripting (XSS) is a code injection attack. The attacker injects malicious script into the target website to make it run on the user's browser. By using these malicious scripts, attackers can obtain sensitive information of users, such as cookie, sessionid, etc., thus endangering data security.
There are two main elements of
1. The attacker submits malicious code.
2. The browser executes malicious code.
For the first element: can we filter out malicious code input by users in the process of user input?
When the user submits, the input is filtered by the front end and then submitted to the back end. Is this feasible?
The answer is No. Once the attacker bypasses the front-end filter and constructs the request directly, the malicious code can be submitted.
Then, change the filtering time: the back-end filters the input before writing to the database, and then returns the "safe" content to the front-end. Is this feasible?
Let's take an example. A normal user enters 5 < 7, which is escaped and becomes 5 & lt; 7 before it is written to the database.
The problem is: during the commit phase, we're not sure where the content is going to be exported.
Here, "not sure where to output the content" has two meanings
1. The user's input content may be provided to both the front end and the client. Once the escape HTML () is passed, the content displayed by the client will become garbled (5 & lt; 7).
2. In the front end, different positions need different codes.
When 5 & lt; 7 is used as HTML splicing page, it can display normally: < div title = "comment" > 5 & lt; 7 < / div >.
Therefore, input side filtering can solve specific XSS problems in some cases, but it will introduce a lot of uncertainty and garbled code problems. This kind of method should be avoided when defending against XSS attack.
Of course, for specific input types, such as numbers, URLs, phone numbers, email addresses, etc., input filtering is still necessary.
Since input filtering is not completely reliable, we should prevent XSS by "preventing browsers from executing malicious code". This part is divided into two categories
1. Prevent injection in HTML.
Preventing stored and reflective
The stored XSS and reflective XSS are inserted into the response HTML after the server takes out the malicious code, and the "data" deliberately written by the attacker is embedded into the "code" and executed by the browser.
There are two common ways to prevent these two kinds of loopholes
1. Change to pure front-end rendering to separate code and data.
2. Fully translate HTML.
Pure front end rendering
The process of pure front-end rendering:
1. The browser first loads a static HTML, which does not contain any business related data.
In pure front-end rendering, we will clearly tell the browser whether the content to be set is text (. InnerText), attribute (. SetAttribute), style (. Style), etc. Browsers will not be easily cheated into executing unexpected code.
However, for pure front-end rendering, attention should also be paid to avoiding DOM type XSS vulnerabilities (such as onload event and j in HTML) avascript:xxx Please refer to the "prevention of DOM type XSS attacks" section below.
In many internal and management systems, the use of pure front-end rendering is very appropriate. But for the pages with high performance requirements or SEO requirements, we still have to face the problem of splicing HTML.
If it is necessary to splice HTML, we need to use appropriate escape library to fully escape the insertion points of HTML template.
Common template engines, such as doT.js , EJS, FreeMarker, and so on, there is only one rule for HTML escape, that is, escaping the characters - < > "/ can play a certain role in XSS protection, but it is not perfect
|XSS security vulnerability | whether simple escape has protective effect|
|HTML tag text content|
|HTML attribute value|
|CSS inline style | none|
|Inline JSON | none|
|Jump link | none|
Therefore, to improve the XSS protection measures, we need to use more perfect and detailed escape strategy.
For example, in Java project, the common escape library is org.owasp.encoder 。 The following code is referenced from org.owasp.encoder The official statement.
<! -- text content in HTML tag -- >
< div > < %= Encode.forHtml ( UNTRUSTED ) %> </ div >
<! -- HTML tag attribute value -- >
< input value = "<%= Encode.forHtml (UNTRUSTED) %>" />
<! -- CSS property value -- >
< div style = "width:<= Encode.forCssString (UNTRUSTED) %>" >
<!-- CSS URL -->
< div style = "background:<= Encode.forCssUrl (UNTRUSTED) %>" >
< script >
</ script >
< script >
</ script >
<! -- HTML tag inline listener -- >
</ button >
<! -- URL parameter -- >
< a href = "/search?value=<%= Encode.forUriComponent (UNTRUSTED) %>&order=1#top" >
<! -- URL path -- >
< a href = "/page/<%= Encode.forUriComponent (UNTRUSTED) %>" >
< a href = '<%=
urlValidator.isValid (UNTRUSTED) ?
Encode.forHtml (UNTRUSTED) :
</ a >
It can be seen that the encoding of HTML is very complex, and the corresponding escape rules should be used in different contexts.
Prevent DOM XSS attack
When using. InnerHTML,. Outerhtml document.write Be careful not to insert untrusted data into the page as HTML. Instead, try to use. Textcontent,. Setattribute(), etc.
If Vue / react stack is used and v-html / dangerously set innerHTML function is not used, the XSS hidden danger of innerHTML and outerhtml can be avoided in the front-end render stage.
<! -- the inline event listener contains malicious code -- >
< img onclick = "UNTRUSTED" onerror = "UNTRUSTED" src = " data:image/png ," >
<! -- links contain malicious code -- >
< a href = "UNTRUSTED" > 1 </ a >
< script >
/ / setTimeout () /setInterval () calls malicious code.
setTimeout( "UNTRUSTED" )
setInterval( "UNTRUSTED" )
//Location calls malicious code
location.href = 'UNTRUSTED'
/ / Eval () calling malicious code
eval ( "UNTRUSTED" )
</ script >
If you use these in your project, you must avoid splicing untrusted data in strings.
Other XSS precautions
Content Security Policy
Strict CSP can play the following roles in XSS prevention:
It is forbidden to load external code to prevent complex attack logic.
Prohibit external domain submission. After the website is attacked, the user's data will not be disclosed to the foreign domain.
Prohibit inline script execution (strict rules, GitHub is currently found).
The new version of Google map is not allowed to execute.
Reasonable use of reporting can find XSS in time, which is conducive to repairing problems as soon as possible.
For more information on CSP, please follow the following articles in the front end security series.
Input content length control
All untrusted inputs should be limited to a reasonable length. Although XSS cannot be prevented completely, it can increase the difficulty of XSS attack.
Other safety measures
Captcha: prevent scripts from submitting dangerous operations as users.