はじめに
— なぜ “動いているコード” は危険なのか
Hospital Management System は、数年前に公開された PHP ベースの Web アプリケーションです。
機能的には問題なく動作しますが、セキュリティ更新が一切行われていないという、ある意味とても“教育的”な状態にあります。
その結果、Stored XSS(永続型 XSS) が発見され、
CVE-2021-38757 として登録されました。
しかもこの脆弱性、
いまだに未修正です。
CVE-2021-38757 とは?
- 種類: Stored Cross-Site Scripting
- 影響範囲: Receptionist(管理者)アカウント
- 難易度: 極めて低い
- 再現性: 100%
なぜ危険か?
- 攻撃者は ログイン不要
- Contact フォームに payload を送るだけ
- 管理者がログインした瞬間に JS 実行
つまりこれは:
「患者の問い合わせが、管理者をハッキングする」脆弱性
です。
脆弱な機能:Contact フォーム
攻撃は非常にシンプルです。
-
Contactページを開く - 適当に情報を入力
- Message 欄に以下を入力:
<script>alert(document.cookie)</script>
- 送信
- 管理者(Receptionist)がログイン
- XSS 発動
問題の核心:contact.php
脆弱性の根本原因は、以下のコードです。
<?php
$con=mysqli_connect("localhost","root","","myhmsdb");
if(isset($_POST['btnSubmit']))
{
$name = $_POST['txtName'];
$email = $_POST['txtEmail'];
$contact = $_POST['txtPhone'];
$message = $_POST['txtMsg'];
$query="insert into contact(name,email,contact,message)
values('$name','$email','$contact','$message');";
}
何が問題か?
1. ユーザー入力を そのまま DB に保存
- HTML / JavaScript を一切無加工で保存
- XSS payload が永続化される
2. SQL を文字列連結で生成
- SQL Injection も同時に成立
- つまり 二重で危険
なぜ「入力チェック」だけではダメなのか?
よくある誤解:
「
<script>を弾けばいいのでは?」
答え:ダメです。
理由:
<img onerror=...><svg onload=...><details ontoggle=...>
HTML は逃げ道だらけ。
入力時フィルタリングは補助輪でしかない。
正しい修正方針
原則はこの2つだけ
| 対策 | 目的 |
|---|---|
| Prepared Statement | SQL Injection 防止 |
| Output Escaping | Stored XSS 防止 |
修正①:Prepared Statement(SQLi対策)
<?php
$con = new mysqli("localhost", "root", "", "myhmsdb");
$con->set_charset("utf8mb4");
if (isset($_POST['btnSubmit'])) {
$name = $_POST['txtName'];
$email = $_POST['txtEmail'];
$contact = $_POST['txtPhone'];
$message = $_POST['txtMsg'];
$stmt = $con->prepare(
"INSERT INTO contact (name, email, contact, message) VALUES (?, ?, ?, ?)"
);
$stmt->bind_param("ssss", $name, $email, $contact, $message);
$stmt->execute();
}
これで SQL Injection は終了
修正②:出力時エスケープ(XSS対策)
管理画面側で必ずエスケープします。
<?php
function e($s) {
return htmlspecialchars($s, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
}
echo e($row['message']);
これだけで:
<script>alert(1)</script>
は
<script>alert(1)</script>
になり、ただの文字列になります。
Stored XSS が特に危険な理由
| 種類 | 特徴 |
|---|---|
| Reflected XSS | 被害は一時的 |
| Stored XSS | 永続・自動・管理者直撃 |
Stored XSS は:
- 攻撃者が離脱しても
- 管理者が後から踏む
- 最悪、全権限乗っ取り
という「時限爆弾型」です。
まとめ
- CVE-2021-38757 は 典型的だが致命的な Stored XSS
- 原因は:
- 入力の無検証保存
- 出力時エスケープ不在
- 修正は難しくない
- 難しくないからこそ、放置は罪
https://www.cve.org/CVERecord?id=CVE-2021-38757
https://github.com/kishan0725/Hospital-Management-System
https://packetstorm.news/files/id/163869