CTF 初體驗:Intigriti 10 月份挑戰

Andy Chen
Starbugs Weekly 星巴哥技術專欄
11 min readNov 22, 2021

--

前言

不曉得大家有沒有聽過 CTF 這個比賽,CTF 全名為 Capture The Flag,簡單來說就是要在該網站拿取某個 flag 並送出,或者是達到該網站的一些要求像是讓網站可以一進入的時候就彈出 alert 視窗等等,身為一位前端工程師的我原本以為自己本身就有一點優勢了,畢竟 web 本來就是前端工程師的天下,殊不知自從玩了 CTF 後才知道,原來自己對於前端的認知只能說是冰山一角而已還有許多知識等著我學習,而這篇文章就會闡述筆者在挑戰 Intigriti 的 10 月份挑戰的心路歷程,接下來就正式進入文章正文吧!

如果對於 CTF 的一些基礎知識想要更了解的讀者歡迎參考團隊中 Larry 寫的:跨出成為駭客的第一步,來打打看 CTF Web 吧!有了一些基本觀念再來看這篇文章才會更有收穫喔!

什麼 Intigriti?

在開始進入心路歷程前先來介紹一下 Intigriti 這個網站,Intigriti 每個月月底都會想出一道題目讓大家試著在該網站找出漏洞進行 XSS 攻擊,而 Intigriti 本身也是一個提供 bug 回報的平台,希望藉由這個平台可以讓整個網頁的生態更加安全。

但 Intigriti 每個月的挑戰難易度不一,這次 10 月份的挑戰網址可以點擊這個連結,如果自己都有下來玩玩看的話就會獲得一些意想不到的知識,所以如果有讀者也想踏入資安的領域,尋找一些網站的漏洞的話筆者蠻推薦 Intigriti 的挑戰,保證每個月都會有一些奇怪的知識增加喔XD

解題心路歷程

首先一進入 Intigriti 10 月挑戰的連結就會發現要想辦法讓下面的網站可以一進入後就執行 alert(document.domain) 也就是彈出一個 alert 視窗並且這個視窗的內容是這個網站的 domain。

這時候我們按下 F12 叫出開發人員選項會發現裡面內嵌了一個網站叫 challenge.php 看來我們要做的事情就是在這個網站想辦法彈出 alert 視窗了。

接下來進到 challenge.php 這個網站後一樣先按下 F12 叫出開發人員選項後開始一一檢視一下這個網站裡面的元素,可以發現這邊有一段 script:

可能有讀者比較不熟 JavaScript,這邊筆者稍微解釋一下這段程式碼在做甚麼事情:

  1. 首先當網站讀取完畢後會從 URL 中的 query string 抓取一個叫 xss 的 key。
  2. 接著會抓取在 body 這個 tag 內的最後一個元素,假如這個元素的 id 為 intigriti 的話就會抓取這個 id 為 intigriti 元素內的最後一個元素,並且把該元素內容中最後 4 個字元抓出來與 query string 中 xss 這個 key 的 value 結合在一起。
  3. 最後會產生一個 script 的 tag 來執行這些內容。

經由上面的說明想必這次的挑戰方向很明確了:

  1. URL 中必須要有 xss 這個 key 的 query string。
  2. 我們必須要想辦法產生一個 id 為 intigriti 的元素,且這個元素必須要在 body 這個 tag 中的最後一個。
  3. 由於還會抓取 id 為 intigriti 這個元素內的最後一個元素,並且把這些內容轉成 string 去抓取最後 4 個字元使其與 )]}' 這 4 個字元結合,所以也要想辦法讓這 8 個字元是合法的 JavaScript 程式碼。
  4. 最後就是加上 alert 的語法,讓我們可以順利地彈出 alert 視窗。

首先第一個步驟很簡單只要在網址後面加上 ?xss=xxx 就可以產生一個 key 為 xss 的 query string,執行之後的確也會發現順利把 xss 這個 key 的 value 擺在 script tag 中,而前面也會有 )]}' 這 4 個元素。

這時候看到第二步相信讀者就會開始思考要如何產生一個元素,這時候我們一樣來解析一下網站的元素,可以發現 Intigriti 偷偷埋了一個小彩蛋:

I USE ?html= TO CONVEY THESE MESSAGES

看來我們可以試試看使用 html 這個 key 擺在 query string 中,應該就可以順利的替換掉上方圖片的內容吧!

我們來嘗試使用 html=123 這個 query string。

果然利用 html 這個 key 就順利替換掉裡面的文字了,這時候不經就會思考一下,既然我們都可以替換文字了,那我們是否也可以產生 HTML 元素呢?畢竟我們的第二步驟的目標可是要產生一個 id 為 intigriti 的元素呢XD

這時候可以嘗試 html=<div>123</div> 這個 query string。

沒想到除了可以替換掉文字外還可以自己產生元素,這真的是天大的漏洞XD

看來我們第二步的方向就確定了,要利用 html 這個 key 來產生一個 id 為 intigriti 的元素,並且這個元素要是 body tag 內的最後一個元素。

要產生一個 id 為 intigriti 的元素不難,隨便打個 <div id="intigriti" /> 就可以產生了,但是要如何讓這個元素跳脫目前的結構呢?也就是讓這個元素不會被這個 div 以及 h1 包住呢?

這時候我們不妨可以思考一下,假如我們自己偷偷寫上這些元素的 end tag 像 div 就加上 </div> 而 h1 就加上 </h1> ,這樣是不是就可以順利逃出這個結構了!這樣 <div id="intigriti" /> 這個元素就一定不會被包在剛剛那個結構上了!

而這串 query string 就會像這樣: html=</h1></div><div id="intigriti" />

看來剛剛的想法成功了,但剛剛產生的元素並不是 body tag 內的最後一個元素,他下面還有一個 id 為 container 的元素。

其實有時候瀏覽器為了讓網站可以順利被執行,會自己自作聰明的修正這些非法的元素,讓網頁可以順利被執行,所以剛剛的 <div id="intigriti" /> 我們不妨可以試試看先不要讓他是合法的元素,把他變成 <div id="intigriti" 像這種感覺,這時候我們來看看瀏覽器做了哪些事情。

query string 的部分會長得像這樣: html=</h1></div><div id="intigriti"

想不到瀏覽器竟然自作聰明的把剛剛的 container 元素包進去我們寫的 intigriti 這個元素內了,這時候 intigriti 的元素就順其自然地成為了 body tag 內的最後一個元素了。

其實到這裡算是完成 87% 了,上面的第三步就是要想辦法讓 id 為 intigriti 的元素內的最後一個元素的最後 4 個字元可以跟 )]}' 結合後變成一個合法的 JavaScript 程式碼。

這時候筆者要介紹另一個觀念是:其實我們可以在網頁中產生一些不存在於規範內的 html tag,這些 tag 一樣也會被執行而且不會出現任何錯誤,換句話說就是我們可以產生一個 <test></test> 這種元素也沒事,瀏覽器都會幫我們當成一般的元素。

query string 的部分像這樣:html=</h1></div><div id="intigriti"><div><test><div>

上面的結構簡單來說就是我在 intigriti 的元素中再產生一個 div 的元素,並且不要給他 end tag,透過瀏覽器的自動修正會讓我們的 div 元素順理成章地變成 intigriti 的最後一個元素,這時候我們又給一個自定義的 tag test,一樣也不給他 end tag 讓瀏覽器自動修正,最後再隨便加上一個 tag 使我們自定義的 tag 可以把 container 元素全部包裝起來,這樣最後 4 個字元就會是我們自定義 tag 的 end tag 了。

但怎麼想都知道 est>)]}' 絕對不是個合法的 JavaScript 程式碼,但要如何讓他變成合法呢?其實方法有百百種,筆者當初想到的方法就是前面給一個 ' 使其變成字串,這樣就不用理會裡面的內容了反正通通變成字串了,所以這時候我們只要想辦法讓自定義 tag 有 ' 這個字元就好。

query string 的部分像這樣:html=</h1></div><div id="intigriti"><div><a'aa><div>

大功告成最後第四步只剩利用 xss 這個 query string 產生 alert 視窗了,但在那之前我們要先想辦法讓這個字串不會影響到後面的 alert 視窗,方法也是百百種這邊筆者提供兩個方法,第一個是利用 ; 讓字串直接被終止執行。

query string 的部分像這樣:html=</h1></div><div id="intigriti"><div><a'aa><div>&xss=;alert(document.domain)

另一種是利用換行的方式,畢竟 JavaScript 本身不一定要加上分號,可以利用換行的方式來執行下一行的程式碼XD

但因為我們都是用網址的方式來加入這些元素,所以換行的部份我們就必須其他方法來代替,這時候就必須要用到 urlencode 的技術,而換行的 urlencode 是 %0a

query string 的部分像這樣:html=</h1></div><div id="intigriti"><div><a'aa><div>&xss=%0aalert(document.domain)

到這步恭喜讀者順利完成 Intigriti 10 月份挑戰了,整體來說是不是相當好玩的挑戰呢!筆者也會盡量想辦法破解其他月份的挑戰,就讓我們一起玩轉前端世界吧XD

小結

這次的 CTF 可以說是讓我對於前端又有了不一樣的見解了,像是可以自己產生一個自定義的 tag,甚至是原來瀏覽器會有自動修正的功能讓我們可以產生一些意想不到的結構,其實 Intigriti 自己也有公布 10 月份的解法,有興趣的讀者可以點擊這個連結來看其他大神的解法。

裡面有一個解法真的讓我太驚訝了,我們可以利用 select 這個 tag,由於 select 中的最後一個元素一定會是 option,所以我們要做的事情就是把 option 中的內容變成 ' 這樣就可以產生字串了。

query string 的部分像這樣:html=</h1></div><select id="intigriti"><option>'</option>&xss=;alert(document.domain)

甚至更進階的寫法也可以用註解的方式,然後再配合換行這樣 )]}' 這 4 個字元就完全不用理會了相當高明。

query string 的部分像這樣:html=</h1></div><select id="intigriti"><option>//</option>&xss=%0aalert(document.domain)

最後可能會有讀者想說這個網址看起來那麼複雜,正常人應該不會隨便點擊才對,但假如有不肖人士利用短網址的技術包裝起來,這時候就很難察覺了,所以筆者真的要再三提醒各位讀者千萬不要點擊來入不明的網址喔!

參考資料

--

--

Andy Chen
Starbugs Weekly 星巴哥技術專欄

嗨嗨我是Andy,用嘴巴工作的工程師😂,喜歡學習不同領域的內容,專長為網頁開發,歡迎大家跟我聊技術~