コース目次 / 第1章
まず、再現する
mini-ctf-webと同じarena-webを立て直し、隠しエンドポイントとrole=adminの2つのexploitがまだ成功することを確認します。修正前の基準点を作ります。
修正の効果を確かめるには、修正前の状態でexploitが確実に成功することを、まず確認しておく必要があります。
arena-webを、立て直す
arena-web.js として保存します。mini-ctf-webで攻めたのと同じコードです。
// arena-web.js — CTF練習用ギャラリーアプリ。127.0.0.1:4500。
const http = require('node:http');
const PAGE = `<!doctype html><meta charset="utf-8"><body>
<h1>Arena Gallery</h1>
<p>ようこそ。画像一覧は /api/photos から取得しています。</p>
<script>
// TODO: 本番公開前に /api/internal/debug-status を消す
fetch('/api/photos?role=guest').then(r=>r.json()).then(d=>console.log(d));
</script>
</body>`;
http.createServer((req, res) => {
const url = new URL(req.url, 'http://127.0.0.1:4500');
res.setHeader('Content-Type', 'application/json; charset=utf-8');
if (url.pathname === '/') { res.setHeader('Content-Type', 'text/html; charset=utf-8'); res.end(PAGE); return; }
if (url.pathname === '/api/internal/debug-status') {
res.end(JSON.stringify({ status: 'debug mode', flag: 'flag{????????????????}' }));
return;
}
if (url.pathname === '/api/photos') {
const role = url.searchParams.get('role') || 'guest';
if (role === 'admin') {
res.end(JSON.stringify({ photos: ['public1.jpg', 'public2.jpg'], flag: 'flag{????????????????}' }));
return;
}
res.end(JSON.stringify({ photos: ['public1.jpg', 'public2.jpg'] }));
return;
}
res.writeHead(404); res.end(JSON.stringify({ error: 'not found' }));
}).listen(4500, '127.0.0.1', () => console.log('arena-web: http://127.0.0.1:4500 (Ctrl+C で停止)'));
node arena-web.js
2つのexploitを、再実行する
別のターミナルから。
curl -s http://127.0.0.1:4500/api/internal/debug-status
{"status":"debug mode","flag":"flag{????????????????}"}
curl -s "http://127.0.0.1:4500/api/photos?role=admin"
{"photos":["public1.jpg","public2.jpg"],"flag":"flag{????????????????}"}
どちらもまだ成功します。これが「修正前」の基準点です。次の章で、この2つが失敗するように直します。Ctrl+Cでサーバーを止めずに、そのまま次に進んでください。
こうなっていればOK
卒業まであと3章です。
この章はまだ完了していません。
保存できませんでした(プライベートブラウズ中かもしれません)。この端末に進捗は残りませんが、先へは進めます。