
CVE-2024-57521の静的コード監査。RuoYi-Vueのジェネレータモジュールにおける認証済みSQLインジェクションで、ソースからシンクへの分析と%0bフィルタバイパスPoCを含む。
図 1:CVE-2024-57521 SQL インジェクション脆弱性データフロー監査図
本リポジトリはセキュリティ研究および教育目的でのみ使用されます。本文書の技術を利用した未承認の攻撃行為は行わないでください。すべてのテストはローカルの静的コード監査環境で実施されました。
ruoyi-generator モジュール)ruoyi-generator/src/main/java/com/ruoyi/generator/controller/GenController.java主要コード:
@PostMapping("/createTable")
public AjaxResult createTableSave(@RequestParam("sql") String sql, @RequestParam("tplWebType") String tplWebType)
{
try
{
SqlUtil.filterKeyword(sql); // 在进入业务前调用过滤器
分析:バックエンド管理者は、HTTP POST リクエストの sql パラメータを通じて任意のデータベーステーブル作成文を渡すことができます。エントリポイントはユーザー入力を十分に制限せず、そのまま後続のフィルターに渡しています。
スクリーンショットの証拠:

· ファイルの場所:ruoyi-common/src/main/java/com/ruoyi/common/utils/sql/SqlUtil.java
中核となる欠陥コード:
// 第16行:黑名单定义,注意关键词带有【尾随空格】
public static String SQL_REGEX = "\u0008|%0A|and |extractvalue|updatexml|sleep|information_schema|exec...";
// 第61-66行:过滤逻辑
String normalizedValue = value.replaceAll("\\p{Z}|\\s", ""); // 先清空了输入里的所有空格
String[] sqlKeywords = StringUtils.split(SQL_REGEX, "\\|");
for (String sqlKeyword : sqlKeywords)
{
if (StringUtils.indexOfIgnoreCase(normalizedValue, sqlKeyword) > -1)
{
throw new UtilException("请求参数包含敏感关键词" + sqlKeyword + ",可能存在安全风险");
}
}
脆弱性分析:フィルターはまず replaceAll("\p{Z}|\s", "") を実行して入力内のすべての空白文字を削除します。しかし、ブラックリスト SQL_REGEX 内のキーワード(「and 」「select 」など)には末尾に空白が付いています。このためマッチングは必ず失敗し、攻撃者がキーワードの後に %0b(垂直タブ)を使って空白を置き換えるだけで、ブラックリストチェックを完全にバイパスできます。
スクリーンショットの証拠:
· ファイルの場所:ruoyi-generator/src/main/resources/mapper/generator/GenTableMapper.xml
主要なコード:
<update id="createTable">
${sql}
</update>
分析:MyBatis では ${} は安全なプリコンパイル #{} ではなく、文字列を直接連結します。そのため、フィルターを回避した悪意のある SQL がデータベースに送られ実行されます。これは典型的な「ブラックリストフィルタリング + 安全でない連結」の組み合わせ脆弱性です。
スクリーンショットの証拠:
· 方法:攻撃者は %0b(MySQL の垂直タブ文字で、\s のマッチ範囲に含まれる)を SQL 文のスペースの代わりに使用します。
· 検出原理:IF(<条件>, 1, 1/0) をブール型ブラインドインジェクションの検出器として利用します。 · 条件が偽:ゼロ除算エラーが発生し、サーバーは HTTP 500 を返します。 · 条件が真:正常でエラーは発生しません。 · 抽出方法:二分法を用いることで、データベースのデータを1ビットずつ推測できます。
この脆弱性は、典型的な「修正が不完全」なことによる回避です。開発者は以前の同種の SQL インジェクションを修正する際にブラックリスト機構を導入しましたが、ブラックリストがスペースに依存していることを見落としました。そして、スペースを除去する前処理ロジックがブラックリストのマッチ条件を破壊し、最終的に新たな回避(CVE-2024-57521)を引き起こしました。
· ブラックリスト機構の廃止:ブラックリストに依存せず、ホワイトリスト方式こそが安全の基盤です。 · プリコンパイルの使用:MyBatis の ${sql} を #{} のプリコンパイル方式に変更します。どうしても SQL を動的に渡す必要がある場合(テーブル作成、Order By など)は、厳密な抽象構文木(AST)解析や厳密なパラメータ検証を使用すべきです。 · フィルターの改善:どうしてもブラックリストを使用する必要がある場合は、ブラックリストのキーワードの末尾のスペースを除去し、比較前に統一的な正規化(小文字への統一、%0b などをスペースに置換するなど)を行う必要があります。
· NVD - CVE-2024-57521 · RuoYi-Vue Gitee リポジトリ
poc/poc_boolean.py(注:実際のロジックに合わせて、後でファイル名を poc_error_based.py に変更することを推奨します)extractvalue() 関数を利用して XPath エラーを発生させ、正規表現で XPATH syntax error: '~...~' をマッチさせてデータを抽出します。Payload では /**/ をスペースの代わりに使用し、ブラックリストフィルタリングを回避します。
CREATE//table//{随机表名}//as//SELECT/**/extractvalue(1,concat(0x7e,({查询语句}),0x7e))
%0b による WAF バイパスおよび extractvalue エラーベースインジェクションの実行可能性を検証することに成功しました。スクリプトは MySQL バージョン (5.7.26)、現在のデータベース名 (ry)、およびデータベース接続ユーザー (root@localhost) を安定して抽出できています。