# Week10 r3:0 異世界網站挑戰心得 ###### tags: `BE101` `PHP` `進度筆記第十周` `Lidemy心得` *** 一共十關,看你能闖到第幾關:r3:0 異世界網站挑戰(特別感謝第三期 @minw 製作遊戲)。 *** ## lv0 https://r30challenge.herokuapp.com/lv0.php 想辦法利用 token 來獲取網址位置,系統提示如下: \[系統\] 例如: /lv1.php?token=xxx,xxx 不包含大括號 \[系統\] 得到技能 hint: 利用 help 可以縮小 token 所在的範圍 \[系統\] 例如: /lv1.php?hint=help \[系統\] 前往 lv1 : 請透過 query string 傳入 token 透過這些資訊用 `/lv1.php?token=r30:start` 就可以去往 lv1 的位址~ --- ## lv1 為了去到 lv2 系統給了幾個資訊: \[求救訊息\] 100101001001100001110 \[系統\] 前往 lv2: 透過 token 將怪物的名字轉成十八進位傳給 m3nt0r 經過宣告求救訊息 `parseInt()` 、 `toString` 可以得知怪物名字是 `bad18` ~~先用 http://www.kwuntung.net/hkunit/base/base.php 偷看了答案~~ ### 複習了一下 [`parseInt()`](https://medium.com/unalai/%E8%AA%8D%E8%AD%98-parseint-parsefloat-%E8%88%87-number-%E8%BD%89%E6%8F%9B%E6%88%90%E6%95%B8%E5%AD%97%E7%9A%84%E4%B8%89%E7%A8%AE%E6%96%B9%E6%B3%95-276640aedb4e) 的用法 ``` let num = '100101001001100001110'; // 先做字串轉換, 將 num 當做2進位值, 並轉成 10 進位。 let result = parseInt(num, '2'); console.log(result); let res18 = result.toString(18); console.log(res18); ``` // 依照 ECMA 規範, 基數如果是 10 以外的值, 如填入 18 則轉成 18 進位。 代入 token 得到: `lv2.php?token=bad18` --- ## lv2 進入 lv2 後看到: ![](https://i.imgur.com/7boCZIS.png) 有個 `<div class="hidden"> {divsurprise} </div>` 固定躲在最上層。 ~~如果是 Firefox 瀏覽器有可能會直接顯示~~ 但其實可以開啟 Devtool 來看~ 因此帶入 token : `lv3.php?token=divsurprise` 。 --- ## lv3 進入 lv3 後看到: ![](https://i.imgur.com/M97Eb29.png) 水面一片黑, 這就是小提示了, 再度開啟除錯工具, 點 `body` 的部分可以看到在 `body` 最底下藏了一個 ` <--!{commentfaker}--> ` 於是代入。 Token:`lv4.php?token=commentfaker` --- ## lv4 ![](https://i.imgur.com/Z7eXBD3.png) 仔細觀察後, 會發現 CSS 有動過, 是 CSS 偽元素 ``:: after`` 隱藏了字串。 `html` 的部分: ``` <span class="special">{csspersona!}</span> ``` 行內樣式表的部分: ``` .special::after { content: '{tRaNspar3nT}'; margin-left: -160px; background-color: #000; } ``` 以 ``csspersona!`` 代入, 馬上就 fail XD 但其實已經到了 lv5 ! --- ## lv5 原因是出在網頁的跳轉, 仔細一看, 輸入 token 的瞬間, 網址列瞬間從 lv5 跳到 lv6 XDDD 轉址的瞬間按下 ESC 會看到 windowhack 。 p.s. 別忘了 ESC 可以停止載入網頁! --- ## lv6 基於停止載入網頁後, 使用 token: `lv6.php?token=windowhack` 會進入到新的挑戰, 這關的挑戰更ㄎ一ㄤ, 更有趣了XD 前往 lv7:解出檔案裡面顏文字的秘密,或找到 window 裡面隱藏的 token 資訊。 短短的提示僅有這樣?! 開啟除錯看之後, 我到底看了些甚麼???? ![](https://i.imgur.com/OqswdYf.png) 於是去 console 輸入提到的關鍵字 "window" 試試看。 會跳出, ``__IamToken: "emojicute"``: ![](https://i.imgur.com/6z8nBKh.png) 試著代入看看: `lv7.php?token=emojicute` --- ## lv7 進來之後, 這個勇者真的沒問題嗎XD 開始要賄賂惡魔是哪招XDDD" 這時候的提示是, [系統] 請找到放在包包深處的餅乾 token 。 打開除錯會發現, 由於 Cookie「TokenIsMe」的「SameSite」屬性設定為「None」或無效值,卻缺少「secure」屬性,此 Cookie 未來將被拒絕。 因此前往儲存空間, 找到餅乾 Cookie 並且看到了值 `%7Bcookieyumyum%7D` ! ![](https://i.imgur.com/O8NN1xu.png) `%7B %7D` 相當於 `{}` 因此去掉後代入 token: `lv8.php?token=cookieyumyum` 。 --- ## lv8 惡魔會吃個資啊...看到一個無頭騎士說他的 KDA 很高, 嗯??? 提示告訴你 [系統] 前往 lv9:請在 response 找出無頭騎士的頭的密碼,讓他解開封印。 這個一定是工程師笑話XD Response Header 我猜, 除錯下去找後果然發現 `Tokenisme {headshot}`: ![](https://i.imgur.com/hD468AQ.png) 代入 token: `lv9.php?token=headshot` --- ## lv9 一進來, 話不多說, 看到了: [系統] 前往 lv10: 請解開留在 html 裡面的 php 程式碼,輸入正確的 token 這時候開啟除錯來看~ ![](https://i.imgur.com/7VlI6BT.png) 稍微翻了一下資料可以發現 php 語法的 `strlen()` 是計算字串長度的函數, 但它不會判斷字串的編碼( `mb_strlen()`則會 ), 而 `ord()` 則可將字串轉成 ASCII 碼。 也因此這段程式碼的規則是: ``` <?php function isTokenValid($token) { if (strlen($token) !== 8) return false; for($i = 1; $i <= 7; $i+=2) { if ((ord($token[$i]) * ord($token[$i - 1])) % $i !== 0) { return false; } } return true; } ?> 當我有個函式名為 `($token)` 假如這個 Token 的字母數 不相等於 8 的時候返回 也因此 Token 字母數應不超過 8 位 迴圈內的 ``$i = 1`` 會一直加總直到 ``<=7`` 假如 2 * (2-1) % 1 不會等於 0 則返回 以此類推找 8 個值餘數為 0 應該可以過關。 ``` 將 `aaccddii` 代入 Token~ 參考資料: https://www.wibibi.com/info.php?tid=91 https://www.wibibi.com/info.php?tid=92 https://expect7.pixnet.net/blog/post/44229026 https://www.wibibi.com/info.php?tid=PHP_ord_%E5%87%BD%E6%95%B8 --- ## lv10 看了一下提示 "[系統] 前往 lv11: 請從 POST 中找到密碼進入城堡" 。 這次大概要看一下 CORS 的甚麼東西, 嗯 果然主控台告訴你: ``` 已封鎖跨來源請求: 同源政策不允許讀取 https://glacial-everglades-11859.herokuapp.com/api.php 的遠端資源。(原因: 缺少 CORS 'Access-Control-Allow-Origin' 檔頭)。 ``` 大概要 request CORS, 在裝有 NPM 的情況下試著寫寫看: ``` const request = require('request') request( 'https://glacial-everglades-11859.herokuapp.com/api.php', function (error, response, body){ console.log(body) } ) ``` 並用 `node.js` 去執行, 不過搜了幾次, 也試著用 `request.post` 還是代不到 token 出來, 上網搜了一下 CORS 的議題後, 也發現頁面是 404 的狀態: ![](https://i.imgur.com/7ALp2ep.png) ~~試著從網路上代 Token: sosdan 進入下一關~~ --- ## lv11 一進來點開, 先開 Dev tool (O), 發現: ![](https://i.imgur.com/YUts0wy.png) 然後畫面中有個前往另一個網站: http://r30challenge.herokuapp.com/news.php 的位址。 點進去後還以為跑到八卦版(?), 每個文章左上角似乎都有文章 ID , 有個文章被刪除了, 試著代入那個被刪除的文章 ID 到 Token看看。 ``` const request = require('request') request( 'http://r30challenge.herokuapp.com/news_api.php?id=888888', function (error, response, body){ console.log(body) } ) ``` 總之就是到偽八卦的留言板那邊使用代入 `id` 的方式, 進去被刪除的文章頁面。 出現: 能看到這則留言的你,想必就是天選之人吧! {fakeituntilyoumakeit} 拯救這個世界吧! --- ## lv12 這次的提示是 [系統] 前往 lv13: 找找看關於 cookie 的秘密打倒小餅乾, 利用除錯去看看 Cookie 發生甚麼事情。 ![](https://i.imgur.com/DVxjuAC.png) 嗯, Cookie 一切正常, 看看 response header 有沒有甚麼狀況: ![](https://i.imgur.com/DJh8QgA.png) 答案好像藏在這裡? 代 `you_are_cookie_master` 進去看看! 然後就進到下一關了?! 伺服器會透過 set-cookie 傳遞 response header 給瀏覽器, 瀏覽器收到後把會把 cookie 存起來, 如果之後登入相同網站會傳同樣的 cookie 給伺服器。 網路上找一下 set-cookie 的相關捏他: https://segmentfault.com/a/1190000019586281 https://shubo.io/cookies/ --- ## lv13 這次的提示是: [系統] 前往 lv14: 請拿四碼數字測試看看送信人的拖延症,直到找出正確的密碼出來。 提示數字會造成 delay 的話, 只好代代看到 token 內。 代入 8901, 5678, 1357, 0157 都會比較慢, 只好慢慢找是哪幾個數字會造成回應延遲: ![](https://i.imgur.com/ZUdN5vA.png) 發現這幾個數字會比較慢後, 代到 5371, 就成功了~ --- ## lv.14 一進去就發現左上角有個 timer, 試著用除錯看看網頁發生甚麼事情: ``` secret logic function isTokenValid($token) { $h = date('H'); $m = date('i'); $a = $h * $m + 42; $count = 0; for($i = 0; $i < 8; $i++) { $count += ord($token[$i]) - 65; } if ($count <= 100) { return false; } return $a % $count === 0; } ``` 看了一下這段 code, 猜測: token 的條件可能小於八個字 count 從 0 開始 這幾個字的 ASCII 減去 65 後必須大於 100 返回到 `$a` 的條件是 小時乘以分鐘 +42 後必須能整除 `count `