早上刷某特時推送了三上悠ya的動態,猛點雙擊後卻發現是pwnfunction更新了一道xss-challenge的wp(上當了上當了)。看了下題目難度是hard,質量很高,考點也很有趣。官方wp的payload和解題思路看起來不是很複雜,實際上還是隱藏了很多知識點,如果大家復現這個題目,希望這篇文章能夠對你有幫助。
題目信息
題目名稱:WW題目難度:Hard題目地址:https://xss.pwnfunction.com/challenges/ww3/思路:bypass DOMPurify+DOM clobbering
可控的輸入的點有兩個text,img
let text = new URL(location).searchParams.get('text')let img = new URL(location).searchParams.get('img')
img作為img標籤的src屬性被寫入,且被過濾了關鍵符號。
const escape = (dirty) => unescape(dirty).replace(/[<>'"=]/g, '');
text作為文本被渲染,渲染前都經過一次DOMPurify.sanitize處理
//part1document.write(...Creating meme... (${DOMPurify.sanitize(text)}))//part2 html = (`Meme created from ${DOMPurify.sanitize(text)}`)notify ? ($('#notify').html(html)) : ''
DOMpurify bypass via Jquery.html()
乍一看經過DOMPurify後的這些交互點都很安全,但是使用html()解析會存在標籤逃逸問題。
題目作者在wp中提到了兩種解析html的方式:jquery.html&innerhtml。innerHTML是原生js的寫法,Jqury.html()也是調用原生的innerHTML方法,但是加了自己的解析規則(後文介紹)。
關於兩種方式:Jquery.html()和innerHTMl的區別我們用示例來看。
對於innerHTML:模擬瀏覽器自動補全標籤,不處理非法標籤。同時,
對於Jqury.html(),最終對標籤的處理是在htmlPrefilter()中實現:jquery-src,其後再進行原生innerHTML的調用來加載到頁面。
rxhtmlTag = /x20trnf]*)[^>]*)/>/gi/x20trnf]*)[^>]*)/>/gijQuery.extend( { htmlPrefilter: function( html ) { return html.replace( rxhtmlTag, "$2>" ); } ...})tmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ];
有意思的是,這個正則表達式在匹配之後會重新生成一對標籤(區別於直接調用innerHTML)
所以相同的語句
閱讀更多 安全客 的文章