一. 了解Node.js
簡單的說 Node.js 就是運行在服務端的 JavaScript
(一) node.js的常見文件目錄

(二) 了解jwt
Json web token (JWT), 是為了在網絡應用環境間傳遞聲明而執行的一種基於JSON的開放標准((RFC 7519).該token被設計為緊湊且安全的,特別適用於分布式站點的單點登錄(SSO)場景。JWT的聲明一般被用來在身份提供者和服務提供者間傳遞被認證的用戶身份信息,以便於從資源服務器獲取資源,也可以增加一些額外的其它業務邏輯所必須的聲明信息,該token也可直接被用於認證,也可被加密。
它分為head payload和Signature。這串數據以(.)作為分隔符分為三個部分的
signature:
簽名哈希部分是對上面兩部分數據簽名,通過指定的算法生成哈希,以確保數據不會被篡改。
首先,需要指定一個密碼(secret)。該密碼僅僅為保存在服務器中,並且不能向用戶公開。
然后,使用標頭中指定的簽名算法(默認情況下為HMAC SHA256)根據以下公式生成簽名。
WT安全問題一般有以下
1. 修改算法為none
2. 修改算法從RS256到HS256
3. 信息泄漏 密鑰泄漏
4. 爆破密鑰
二. 解題:
ctfhub已經上線hfctf的部分題目,想復現的可以去試試。
當時再比賽的時候發現了這個

然后后面我就一直試着繞過get flag函數,但是沒找到方法。后面又看到一篇文章也是偽造jwt,但是再偽造密鑰那部分沒整出來🙃
現在看了下網上的wp之后才明白過來。下面就是正經的解題步驟了!o(* ̄▽ ̄*)o
我們在發現上面這個頁面后,再嘗試以下nodejs常見的主頁面能不能訪問
嘗試讀取常見的app.js

我們注意到了/controller這個目錄,那我們試一下把這個加上,發現如下

仔細觀察這個頁面,發現好像該環境的驗證源碼?嘗試代碼審計
我們發現當沒注冊和注冊的賬號為admin時會報錯,並且會生成一個私鑰,把私鑰存在global.sectets這個全局數組中。還會生成一個jwt。

這一段代碼表示,賬號和密碼的驗證,並且給jwt一個索引sid,通過判斷sid來檢驗該賬戶能否登陸成功。那就以為着我們只需要偽造成admin的jwt就可以拿到最高權限,為所欲為了。
注意這里,它是把session中的usernam當作登陸成功的username
然后再最后一段代碼中,判斷 session 中的用戶名是否為 admin,是的話就直接給 flag。

既然知道了jwt的常見安全問題,那么我們就使用最常見的將簽名算法設置為none試試
再把私鑰部分設為空數組就可以啦。這樣只需要頭部和payload部分進行base64加密就可以得到admin的token了。
os:payload部分的username要改為admin,不然驗證通過不了的。(●ˇ∀ˇ●)然后注冊,登陸抓包

然后分析報文,以及根據前面的代碼審計。我們發現他是根據對authorization進行驗證來判斷你是否有權限獲得flag的,
那么我只需要將這段jwt進行偽造,讓服務器認為我們是admin就可以了
我們進行base64加解密


然后將HS256和admin233改成none和admin,secretid改成一個空數組和admin就可以了

記得兩串密文之間用.連接喔U•ェ•*U
然后將加密得到的密文復制到authorization即可。因為你修改算法為none,那么
Signature就不用加進去了。None是沒有的意思,既然沒有加密算法,
那么把部分就沒用了。記得把username=哪里也要改成admin(o゚v゚)ノ

然后放包,再登陸,訪問 api/flag就可以啦。因為這時服務器已經把你當作admin用戶啦ヾ(≧▽≦*)o

總結:這題的主要考點就是jwt偽造
難點是怎么把密鑰偽造出來。經過代碼審計,我們發現當簽名算法為none時,
將私鑰id設置為空就可以繞過服務器對私鑰的的驗證。
當時沒做出來時一位內代碼審計沒過關,需要繼續增強!(〃>目<)
大家一起加油!沖沖沖!
