You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The Content Security Policy 'default-src 'self'; img-src https://*; child-src 'none';' was delivered via a element outside the document's , which is disallowed. The policy has been ignored.
不過,過了三秒之後確實有重新導向。所以只有 CSP header 一定要放在 head,其他放在 body 也可以。
This method fetches an element with selector, scrolls it into view if needed, and then uses page.mouse to click in the center of the element. If there's no element matching selector, the method throws an error.
/** * This method scrolls element into view if needed, and then * uses {@link Page.mouse} to click in the center of the element. * If the element is detached from DOM, the method throws an error. */
async click(options: ClickOptions={}): Promise<void>{awaitthis._scrollIntoViewIfNeeded();const{x,y}=awaitthis.clickablePoint(options.offset);awaitthis._page.mouse.click(x,y,options);}
原本想要寫得詳細一點再 po 的,但我發現如果要這樣的話,可能要過很久才會 po,所以還是趕快先寫一篇簡短版的。
這次寫的是以下四題,都是 web:
先記幾個 keyword 以後比較容易找:
<svg><style>
<meta name="referrer" content="unsafe-url" />
<meta http-equiv="refresh" content="3;url">
Fancy Notes
這題的核心程式碼如下:
會從 cookie 去斷你是哪一個 user,序列化跟反序列化的程式碼如下:
而產生 cookie 的程式碼長這樣:
目標是想辦法偽造成 admin 登入,就可以拿到 flag。
正常的狀況下,假設我們的 user 叫做 abc 好了,locale 是 en,產生出來的 user_string 就會是:
username=abc,locale=en
。從
serialize_user
中可以看出前面的屬性會被後面蓋掉,所以如果我們的 user_string 是username=a,locale=en,username=admin
,還原回 user 時身份就會變成 admin。在產生 cookie 時,後面有特別加上一個簽名(
sha256(secret + user_string)
)來驗證資料完整性。所以在我們不知道 key 的狀況下,照理來說我們沒有辦法偽造 user_string,因為完整性的檢查過不了。
但是呢,這題用的這種驗證方式可以用一種叫做長度擴充攻擊(Length extension attack)的方式來打。
簡單來說呢,如果今天有一個操作是:
M1 = hash(secret + data)
,你只要知道 secret+data 的「長度」就好,不需要知道內容是什麼,以及產生出來的結果 M1,那你就可以在secret+data
後面拼接任意字串,並且知道合法的hash(secret + data + padding + 任意 data)
舉例來說,你今天知道
"{secret}username=a"
在 md5 過後會變成781e5e245d69b566979b86e28d23f2c7
,在不知道 secret 為何的狀況之下,你還是能知道"{secret}username=a{padding},username=admin"
的 md5 是多少。上面的
{padding}
,這跟 hash 演算法的原理有關。總之呢,透過這個攻擊方式,我們可以在不知道 secret 的狀況下把已知的字串延長並且產生出合法的 hash 值,就能繞過這題的檢查。
至於詳細的原理跟攻擊方式,先留幾篇參考文章,未來有機會再回來補這個坑:
Dumb Forum
這題有個 SSTI:
username 跟 aboutme 都有被檢查,不能用
}{
,而 email 只有檢查是不是合法的 email 地址,是的話就能用。因此
abc{{7*7}}@abc.com
在界面上呈現的會是abc49@abc.com
,因為在這套 library 中 email 地址如果有()
的話會被視為不合法,所以沒辦法用()
。flag 在環境變數裡面,所以只要這樣就 win 了:
LESN
這題可以建立一個 post,內容可以控制但會被 sanitized,最後會 render 成這樣:
過濾的程式碼長這樣:
最後有經過 DOMPurify,所以危險的 tag 都不能用。
這題的重點是我在看的時候,發現有時候 console 會出現
redirect_error_image is undefined
的錯誤。這是因為 script 是用 async 來載入,所以有個 race condition 的問題。如果 img 的
onerror
在 script 載入前就被觸發,那redirect_error_image
就會是 undefined。利用這個特點,勝利方程式就是用 DOM clobbering 去控制
redirect_error_image
,再加上setTimeout
第一個參數傳字串就跟eval
差不多的特性去執行任意程式碼。DOM clobbering 的部分要先繞掉自訂的 parser,這部分由隊友完成,原理大概就是這篇:HTML sanitization bypass in Ruby Sanitize < 5.2.1 講的,利用 namespace confusiion 來製造出 mXSS,payload 長這樣:
jsdom 會把上面的段落 parse 成這樣:
就只是一個 style 有著內容,沒什麼,但是用
document.body.innerHTML
還原回去時會變成這樣:就產生出了這個
<a>
的 tag,讓我們可以 DOM clobbering。而內容其實放個http:import(script)
就好,http:
會被當作是 label,後面的程式碼會直接被執行。接著就是要怎麼讓 onerror 發生的比腳本載入快,根據作者的 writeup,在圖片網址的部分可以放上
http://localhost
之類的網址,讓它趕快失敗,放http://not_exist
感覺也行。然後可以用 iframe 去載入你的 post,再把自訂頁面丟給 bot,就可以避免使用到 cached 的
script.js
。我那時是想說瀏覽器載入資源都有 priority,如果可以製造出一個 priority 比 script.js 還高的組合,就能延緩腳本的載入之類的,所以試著在頁面中加入一堆圖片:
不過好像沒什麼用就是了,圖片順序應該也不會比 script 還高。當時也沒有繼續研究有哪些可以做到我理想中的狀況。
最後是想到之前 @lbrnli1234 在解我出的一題 XSS 時也碰到 race condition,它後來就塞了一堆 iframe 來增加成功機率,可見:Notes XSS Challenge Author Writeup
我也照著做,塞了一堆 iframe:
最後就解掉了,first blood。
ptMD
本次最難,全場一解。
先附上作者 wirteup:https://github.com/xatophi/m0leconteaser2022-ptMD/blob/main/writeup.md
簡單來說你有個頁面,你可以插入任意 HTML,但是 CSP 是
script-src 'self'
,所以沒辦法 XSS。目標是偷到 admin note 的內容,由於網址是唯一的而且沒有權限管理,所以偷到網址其實就行了。在 client 的頁面有個
last
可以點,點下去之後就會到最新的 note 頁面去。這邊因為是用 react 做的,所以如果你直接把網址設定成
/last
是沒用的,因為剛載入的時候 notes 是空的,所以並不會重新導向到最新的 note 去。這題的 admin bot 長這樣:
最後一步我在看的時候就覺得怪怪的,就是去點擊那個 logout button,我就在想為什麼要點那個,賽後才知道那也是關鍵之一。
我在解的時候有想到可能跟 referrer policy 有關,但用了
<iframe referrerPolicy="unsafe-url"></iframe>
似乎沒有效果。解答確實跟這個有關,但是是這樣的:
用
<meta>
來設置 referrer,然後再用meta refresh
設定三秒後把頁面重新導向。然後再用 CSS 把 logout button 的位置藏到
last
button 後面,這樣 admin bot 實際上就會點到last
button,跳到 note 頁面,接著靠著 referrer policy 就可以 leak 出 URL。最後這個答案打破了三件我以為的認知:
針對這三件事情,我們都可以來做一個小實驗。
第一點我做了一個簡單的網頁:
打開後在 cosnole 看到錯誤:
不過,過了三秒之後確實有重新導向。所以只有 CSP header 一定要放在 head,其他放在 body 也可以。
第二點改一下網頁即可:
可以看到雖然 meta 確實被移除掉,不過 3 秒後還是重新導向了,所以效果還在,原來真的這麼神奇。
第三點其實文件有寫到 page
.click
(selector[, options])
去翻 source code 的話也可以看到:src/common/JSHandle.ts
這邊其實只是用
_page.mouse.click
去點擊一個指定的座標而已。所以如果有元素蓋在上面,就會點到蓋在上面的元素。真的是學習了。
The text was updated successfully, but these errors were encountered: