コース目次 / 第1章

まず、再現する

mini-ctf-webと同じarena-webを立て直し、隠しエンドポイントとrole=adminの2つのexploitがまだ成功することを確認します。修正前の基準点を作ります。

第1章 / 全5章目安 約8分この章のゴール: 修正前の状態で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章です。

この章はまだ完了していません。