
CVE-2026-53629 の PoC。GLPI の履歴ログフィルターにおけるブラインド SQL インジェクション
GLPI の履歴ログフィルターにおけるブラインド SQL インジェクション。CVE-2026-53629。11.0.8 および 10.0.26 で修正され、9.4.0 以降で発生。
logs の READ 権限を持つ任意のアカウントが必要。標準の Read-Only プロファイルにはこの権限があります。
セキュリティアドバイザリ: GHSA-cpcj-x335-5cmh 解説記事: 見つけた経緯
Log::convertFiltersValuesToSqlCriteria() は affected_fields フィルターを key:operator:values に分割します。CVE-2026-29047 のパッチは演算子を検証し配列インデックスをキャストしましたが、$key はそのままでした。
DBmysqlIterator::analyseCrit() は OR、、 を列名として引用符で囲みません。その値に対して再帰し、その再帰は非推奨の分岐に到達して、素の文字列をそのまま生の SQL として返します。
ANDNOTそのため、キーとして OR を使うと、任意の内容を WHERE 句に注入できます。
/front/log/export.php?itemtype=Entity&id=0&filter[affected_fields][0]=OR::1 AND sleep(5)
SELECT * FROM `glpi_logs`
WHERE `items_id` = '0' AND `itemtype` = 'Entity'
AND (((((1 AND sleep(5))))))
履歴タブも filters[affected_fields][0] を通じて同じことを行います。
explode(',', $values) はカンマを含むものを壊すため、SUBSTRING(s,1,1) と IF(a,b,c) は使用できません。CASE WHEN ... THEN ... ELSE ... END と MID(s FROM n FOR 1) なら機能します。引用符の代わりに16進リテラルを使います。0x676c7069 は glpi です。
ペイロードは glpi_logs の行ごとに1回実行されるため、sleep が掛け算されます。6行で sleep(5) なら30秒です。実際のインスタンスでは 0.1 に下げないと、リクエストが応答を返さなくなります。
pip install requests
python3 glpi_sqli_extract.py http://glpi.lab.local -u readonly -p readonly
glpi_users.password をバイナリサーチで1文字ずつ読み取ります。--id で別のユーザーを指定でき、--sleep と --threshold は反応が遅いターゲット向けです。
同じ手法で api_token、personal_token、および glpi_configs 内の SMTP と LDAP の認証情報を読み取れます。
アップグレードしてください。できない場合は、必要のないプロファイルから logs の READ 権限を外してください。アップストリームではキーを許可リストに追加しました:
$allowed_keys = ['linked_action', 'id_search_option', 'itemtype_link'];
if (!in_array($key, $allowed_keys, true)) {
continue;
}
修正公開後に公開されたツールです。自分が所有していない対象に対して実行しないでください。