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
varpassword=prompt('input password')while(!/^[a-zA-Z0-9]+$/.test(password)){console.log('invalid password')password=prompt('input password')}password=''// 如果可以在底下動態執行程式碼,拿得到 password 嗎?eval(prompt('try to get password'))
總之呢,在使用 global RegExp 的時候要小心這個特性。而對資安來說,則是可以關注這些潛在的 bug,看看有沒有能利用的地方。
RegExp 的神奇紀錄屬性
延續開頭的小挑戰:
varpassword=prompt('input password')while(!/^[a-zA-Z0-9]+$/.test(password)){console.log('invalid password')password=prompt('input password')}password=''// 如果可以在底下動態執行程式碼,拿得到 password 嗎?eval(prompt('try to get password'))
簡單記錄幾個最近碰到的神奇特性,直接講不有趣,先來幾個小挑戰:
挑戰一
猜猜底下程式碼的執行結果是什麼?
挑戰二
先讓你輸入一個密碼,然後讓你輸入一段程式碼,可以拿到已經不見的變數嗎?
挑戰三
底下的寫法會出事嗎?會的話是出什麼事?怎麼觸發?
有狀態的 RegExp
猜猜底下程式碼的執行結果是什麼?
無論是誰來看都會覺得兩個都是 true 吧?但答案是 true 跟 false,甚至你寫成這樣,第二個也是 false:
會有這樣的結果,是因為 RegExp 是 stateful 的,如果有 global 或是 sticky 的 flag 的話。
RegExp 有一個
lastIndex
的屬性,會記錄上次符合的位置,下次再使用test
時就會從lastIndex
開始找起。如果找不到的話,lastIndex
會自動歸零。所以根據上面所講的
lastIndex
的特性,這樣乍看之下是沒問題的:但並不代表沒有 bug。
上面這一段之所以看起來沒問題,只是因為第一次找完以後
lastIndex
是 4,而剛好 str2 中 huli 出現的位置是從 5 開始,所以一樣找得到,如果把最後兩行位置對調,就會產生預期外的結果。總之呢,在使用 global RegExp 的時候要小心這個特性。而對資安來說,則是可以關注這些潛在的 bug,看看有沒有能利用的地方。
RegExp 的神奇紀錄屬性
延續開頭的小挑戰:
變數已經被清空了,所以是拿不到變數的。
但我們可以靠著 RegExp 上的一個神奇屬性來拿到,叫做:RegExp.input,這個屬性會紀錄上一次
regepx.test()
符合時的 input:除此之外,還有其他參數也會被記錄:
第一次知道這技巧是在 DiceCTF 2022 - web/nocookies
RegExp 的特殊變數
開頭的挑戰三中我們給出了底下這段程式碼:
雙引號被濾掉了,所以照理來說應該沒辦法跳脫出屬性才對,
>
也被拿掉了,所以也沒辦法關閉標籤。但是呢,在做字串取代的時候,有種東西叫做:special replacement patterns,舉例來說 $` 可以拿到字串取代的地方的「前面」,
$'
則是可以拿到後面,看個範例會更容易理解:因此回到我們的題目:
{{value}} 的後面是
">
,雖然這兩個字元都被過濾掉,但我們可以用$'
來拿到這兩個字元。因此這題的答案是
$'<style onload=alert(1)
:先用
$'
也就是">
來關閉標籤,就可以用其他標籤進行 XSS,最後產生的結果是:我第一次知道這個是在 PlaidCTF 2022 - YACA,但在 DragonCTF 2021 - Webpwn 中似乎也出現過類似的技巧。
The text was updated successfully, but these errors were encountered: