
code.jsの難読化解除からルートまで、CVE-2023-0386
.envファイルにデータベースの資格情報が含まれていることが判明し、パスワードの再利用により、攻撃者はボックス上でadminユーザーとしてログインできます。システムカーネルが古いことが判明したため、CVE-2023-0386を使用してrootシェルを獲得できます。| ポート | サービス | 詳細 |
|---|---|---|
| 22/tcp | ssh | syn-ack ttl 63 OpenSSH 8.9p1 Ubuntu 3ubuntu0.1 (Ubuntu Linux; protocol 2.0) |
| 80/tcp | http | syn-ack ttl 63 nginx 2million.htb |
2million.htb を /etc/hots ファイルに追加しました。
gobuster を使用して 2million.htb 全体のパス探索を実行しました。
列挙中に /invite エンドポイントを発見しました。

/invite ページに移動した後

ページを調査していると、inviteapi.min.js という名前のJavaScriptファイルが読み込まれており、難読化されたコードが含まれていることに気付きました:
eval(function(p,a,c,k,e,d){e=function(c){return c.toString(36)};if(!''.replace(/^/,String)){while(c--){d[c.toString(a)]=k[c]||c.toString(a)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('1 i(4){h 8={"4":4};$.9({a:"7",5:"6",g:8,b:\'/d/e/n\',c:1(0){3.2(0)},f:1(0){3.2(0)}})}1 j(){$.9({a:"7",5:"6",b:\'/d/e/k/l/m\',c:1(0){3.2(0)},f:1(0){3.2(0)}})}',24,24,'response|function|log|console|code|dataType|json|POST|formData|ajax|type|url|success|api/v1|invite|error|data|var|verifyInviteCode|makeInviteCode|how|to|generate|verify'.split('|'),0,{}))
de4js を使用してコードの難読化を解除し、以下の読みやすいJavaScriptが得られました:

function verifyInviteCode(code) {
var formData = {
"code": code
};
$.ajax({
type: "POST",
dataType: "json",
data: formData,
url: '/api/v1/invite/verify',
success: function (response) {
console.log(response)
},
error: function (response) {
console.log(response)
}
})
}
function makeInviteCode() {
$.ajax({
type: "POST",
dataType: "json",
url: '/api/v1/invite/how/to/generate',
success: function (response) {
console.log(response)
},
error: function (response) {
console.log(response)
}
})
}
makeInviteCode() : 新しい招待コードを生成する
verefyInviteCode(code) : コードが有効かどうかをチェックする
さらに理解を深めるため、検証リクエストを傍受しました:

API は JSON レスポンスを使用します
ブラウザのコンソールに移動し、makeInviteCode() を実行しました。

データが ROT13 暗号で暗号化されていることに気付きました。

復号後、エンドポイント /api/v1/invite/generate を発見し、招待コードを生成しました。

Base64デコード

キー
キー 2F4BN-YI8OH-B0SCL-L8OE6 を挿入し、正常に受理されました。

登録

ホームページ

アクセスページ
このサイトで正常に動作するページは多くありませんが、アクセスページが興味深い箇所です。

APIエンドポイントの列挙
connection pack ボタンをクリックしてVPNファイルをアップロードし、GETリクエスト を傍受しました。

次に、verboseオプションとsilentオプションを指定したcurlリクエストを実行し、利用可能なAPIエンドポイントを列挙しました。


サーバーはAPIエンドポイントのJSONリストで応答しました。
管理者には、GET、POST、PUTメソッドを持つ3つのAPIエンドポイントがありました。
管理者エンドポイント /api/v1/admin/vpn/generate で管理者キーの生成を試みたところ、管理者ではなかったためキーは生成されませんでした。最初の管理者エンドポイント /api/v1/admin/auth がこれを確認しました。


Content-Type: application/json と必須パラメータを備えた正しいPUTリクエストの形式を発見した後、自分のユーザーを管理者に昇格させることに成功しました。









ユーザー名フィールドに ;whoami; を注入しました。管理者専用機能に共通し、適切なサニタイズ処理が欠けていることの多い exec() や system() というPHP関数が原因ではないかと推測しました。
例えば、脆弱なコードはおそらく次のようなものだったでしょう:
$username = $json->username;
exec("/usr/bin/cat /var/www/html/VPN/user/$username.ovpn");