background
It happened before the National Holiday. One afternoon, I was trying to write (MO) code for (Yu) suddenly received an email, opened a security work order issued by the Security Department, the content is “the following code may lead to security vulnerability”, and then look at the risk level — high risk
I felt my heart racing and started to get scared, so I clicked on the link and found that v-HTML instructions used in the code base were judged to be at risk of XSS vulnerability. After some discussion with colleagues, it was decided to replace the original directive with VUe-domPurify – HTML and solve the work order.
Just when I thought it was over, a little more than a week later I received the same security work order, but with a different code base, which was solved as quickly as possible and then the holiday of October. However, in the first week when I came back, I received the third safety work order emMMM.
Three safety orders in a row has forced me to take a second look at XSS, so learn while it’s still hot.
What is a XSS
XSS, or Cross Site Script, is translated in Chinese as cross-site scripting attack, originally abbreviated CSS, but this can be confused with Cascading Style Sheets (CSS). Therefore, in the security world we abbreviate cross-site scripting attacks to XSS.
Cross-site scripting (XSS) is the most common Web application security vulnerability. This vulnerability enables attackers to embed malicious script codes into pages that normal users will access. When normal users access this page, the embedded malicious script codes will be executed, so as to achieve the purpose of malicious attacks on users.
XSS vulnerabilities date back to the 1990s. A large number of websites have been attacked or discovered with XSS vulnerabilities. According to the statistics released by the Open Web Application Security Project, XSS ranked second in the top 10 Web Security threats before 2010, next to code Injection.
And according to the latest 2021 OWASP Top 10 (owasp.org/www-project… In terms of ranking, XSS was classified into Injection category, ranking the third, which accounted for a much smaller proportion than ten years ago. Failure to control access and disclosure of sensitive information were the Top1 and 2 bugs.
Type of XSS attack
According to attack sources, XSS attacks can be classified into storage XSS, reflection XSS, and DOM XSS.
Type stored XSS
As the name implies, stored XSS is a persistent and relatively stable XSS that can store vulnerabilities in the database that can cause XSS attacks.
Stored XSS attacks are common on web features with user-saved data, such as forum posts, product reviews, and user messages.
The procedure for storage XSS attack is as follows:
- Find sites where scripts can be injected, such as comment boxes, private message bars, forms and other places where text can be entered, and store scripts in the database through injection points;
- When the user opens the target site, the page pulls the malicious script from the database, splices it into HTML and returns it to the browser.
- The user’s browser parses the web page with the malicious script, and the malicious script starts doing something (stealing your data, or using a cookie to pretend to be a normal user to call the interface, etc.).
It is one of the most dangerous types of cross-site scripting, more inside-out than reflective and DOM XSS, and therefore more harmful because it does not require manual triggering by the user. Any Web program that allows users to store data may have stored XSS vulnerability. When an attacker submits a piece of XSS code, it will be received and stored by the server, and all visitors will be attacked by XSS when they visit a page.
Reflective XSS
Reflective XSS is different from stored XSS because it cannot be persisted. Therefore, it needs to attack with media, for example, by adding malicious scripts to urls containing dynamic parameters.
The steps of a reflective XSS attack are as follows:
- Find urls containing dynamic parameters in websites and construct urls containing malicious scripts.
- The URL is sent to an ordinary user by some means, and the user clicks on the link to enter the website. The malicious code is removed from the URL, spliced in HTML and returned to the browser.
- The user’s browser parses the page, where malicious code is executed. Malicious code can do something
Reflective XSS is commonly used in functions that send parameters through URL, such as jump and search, and can be triggered only when users actively open the URL. In order to make the attack effective, attackers often use inducing means. In other words nothing happens if the user doesn’t click on the link.
The DOM model XSS
DOM XSS is actually a special kind of reflective XSS. However, DOM XSS attacks occur completely in the front end, from injecting malicious code to executing malicious code is done by DOM, without passing through the server and will not be stored in the database.
The steps of DOM XSS attack are as follows:
- Find urls containing dynamic parameters in websites and construct urls containing malicious scripts.
- Through some means to send the URL to ordinary users, users click the link to enter the website, front-end JS from the URL to get malicious code and execute;
- The user’s browser receives a parsed page in which the malicious code is executed. Malicious code can do something (you get the idea)
DOM XSS attacks are entirely due to front-end JS vulnerabilities, while the other two types of XSS are server-side vulnerabilities.
Compare the summary
We make a comparative analysis of the three XSS:
Attack types | Injection point | persistence | The user interaction | The location of the vulnerability |
---|---|---|---|---|
Type stored XSS | Input field (point that can input the user into storage) | If yes, it is stored in the database | Don’t need | The service side |
Reflective XSS | Dynamic parameters in the URL | no | You need the user to click on the URL | The service side |
The DOM model XSS | Dynamic parameters in the URL | no | You need the user to click on the URL | The client |
To summarize the requirements for the three XSS attacks:
- There are injection points (dynamic parameters in urls, forms that accept user input, and so on);
- The result returned by the server is not escaped, fully trusted by the client, and rendered to HTML;
- For DOM-based XSS, the client completely trusts dynamic parameters in the URL and does not escape them, rendering them to HTML.
Practical cases
So let’s combine the case to see how XSS vulnerability attacks our service.
One day when you are at work, your boss suddenly finds you and says, “Xiao Ming, our page has been poisoned, please take a look” and gives you the link to ceshi.com:8080/ Wenzhang. Xiao Ming immediately becomes nervous and opens the link, and a popup window pops up on the page:
Xiao Ming wondered, where did this popover come from? F12 looks at the page’s code and finds this:
<p>B:
<script>
setTimeout(function(){
alert('You won the lottery.')},3000)
</script>
</p>
Copy the code
Seeing this, Ming immediately went to the code library to search for the code, and found that there was no js.
As a confident front-end instinct told him it was the back-end interface that was at fault, and sure enough, he found the unescaped text in the message returned by the back-end interface. Xiao Ming was very happy and transferred the problem to the back end classmate, thinking that the pot is not mine, now he is ok, the back end classmate spent ten minutes to escape the text returned by the interface, fixed the bug, so Xiao Ming went back to work (MO) and (Yu).
But as a front-end student who loves learning, Ming began to wonder: does this place really need to be rendered into HTML? Is there room for precaution? Therefore, in view of the above storage TYPE XSS, Xiaoming thought of some measures to prevent:
- Specify input points in the page and limit the length of the text (to prevent long malicious scripts).
- Specify the type of the output data portion of the page, whether to render as plain text or HTML, and render as text without rendering as HTML.
- If you must render to HTML, make sure you escape the output from the backend interface.
Xiao Ming wrote the above summary with satisfaction. Two days later the boss again to jilt to xiao Ming a link: http://ceshi.com:8080/article?key= “> < script > alert (‘ winning again ‘); , Xiao Ming hesitated to enter the link, the page popped up XSS popup window.
Xiao Ming is getting nervous, but he has to see what the problem is. CtrlF after finding this is the search article keyword page, the code is written like this:
<div><%= getParameter("keyword") %></div>
Copy the code
> the server returns the following HTML after concatenating the keywords:
<div>"> < p style = "max-width: 100%;<script>alert('XSS');</script> </div>
Copy the code
The script is then executed on the page.
In that case, Ming thought, why not let the browser render the text without executing the script? So Ming found a library that can escape HTML, and solved the reflective XSS vulnerability.
Measures to prevent
After such two XSS vulnerability attacks, Xiao Ming learned a lot, from which he also summed up some experience in preventing XSS attacks.
First, analyze the necessary path of XSS attack:
- The client has an input point
- The server returns unmoved malicious code, which is executed by the client.
Do we do anything to prevent client input points? Such as:
- Limit the length of input points to prevent the input of long malicious code;
- Filter for possible code characters;
- Restrict the types of arguments that can occur in URL arguments
- .
While all of the above conditions can limit client input to some extent, they are useless if an attacker bypassing the client-side enablers (such as Postman) to construct parameters to invoke the server-side interface. Therefore, the most efficient and effective way to prevent XSS attacks is to prevent the server from returning malicious code and the client from executing unexpected code.
For the server side we need to do is to escape the content, as much as possible to prevent malicious code directly transmitted to the client side; For the client side, it is necessary to specify whether the render type is text or DOM for the content returned by the server side, and to escape the parts where DOM may appear. For example, the innerText method is used when only text content is needed, the source of the data is trusted (from the server or the client) when it needs to be rendered as A DOM, and if the data is from the client it needs to be processed to avoid DOM-type XSS attacks.
For modern front-end development, most projects are already separated from the front and back ends. Using frameworks such as Vue/React, the separation of front-end code and back-end data has reduced the possibility of XSS attacks to a large extent. For front-end developers, there is still a need to guard against DOM-type XSS attacks, such as V-HTML instructions.
That said, while there is a lot we can do to protect against XSS, not all vulnerabilities will be protected. Our goal is to maximize the cost of using XSS attacks. The character limits, filters, and type limits mentioned above do not prevent 100% of attacks, but they do increase the cost, so it makes sense.
Refer to the article
Front-end Security Series 1: How do I Prevent XSS attacks? (Meituan’s article is well written and worth reading)
XSS combat: How do I take down your Baidu account (vulnerability case)
(7) XSS attack and CSRF attack