
تدقيق ثابت للشيفرة البرمجية للثغرة CVE-2024-57521، وهي حقن SQL بعد المصادقة في وحدة المولّد في RuoYi-Vue، مع تحليل من المصدر إلى النقطة الحرجة وإثبات مفهوم لتجاوز المرشّح %0b.
هذا المستودع مخصص لأغراض البحث الأمني والتعليمي فقط. يُرجى عدم استخدام التقنيات الواردة في هذه الوثيقة لتنفيذ هجمات غير مصرح بها. تم إجراء جميع الاختبارات في بيئة تدقيق ثابت للكود المصدري محليًا.
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); // 在进入业务前调用过滤器
التحليل: يمكن لمدير النظام تمرير أي عبارة إنشاء جدول قاعدة بيانات عبر معامل sql في طلب HTTP POST. نقطة الدخول لا تفرض قيودًا كافية على إدخال المستخدم، وتُمرّره مباشرة إلى الفلتر اللاحق.
دليل لقطة الشاشة:

· موقع الملف: 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. · الشرط صحيح: يعمل بشكل طبيعي دون خطأ. · طريقة الاستخراج: يمكن استخدام طريقة التنصيف لتخمين بيانات قاعدة البيانات بتًا بتًا.
هذه الثغرة ناتجة عن تجاوز ناجم عن "إصلاح غير كامل" نموذجي. أدخل المطورون آلية القائمة السوداء عند إصلاح ثغرة حقن SQL مماثلة سابقة، لكنهم أغفلوا أن القائمة السوداء تعتمد على المسافات، وأن منطق حذف المسافات المسبق يُفسد شرط مطابقة القائمة السوداء، مما أدى في النهاية إلى تجاوز جديد (CVE-2024-57521).
· إلغاء آلية القائمة السوداء: لا تعتمد على القائمة السوداء، فآلية القائمة البيضاء هي أساس الأمان. · استخدام التجميع المسبق: تغيير ${sql} في MyBatis إلى #{} بطريقة التجميع المسبق. إذا كان لا بد من تمرير SQL ديناميكيًا (مثل إنشاء الجداول، Order By)، فيجب استخدام تحليل صارم لشجرة التركيب المجردة (AST) أو تحقق صارم من المعاملات. · تحسين الفلتر: إذا كان لا بد من استخدام القائمة السوداء، فيجب إزالة المسافات اللاحقة من الكلمات المفتاحية في القائمة السوداء، وإجراء توحيد قياسي قبل المقارنة (مثل التحويل الموحد إلى أحرف صغيرة، واستبدال %0b وغيرها بمسافات).
· NVD - CVE-2024-57521 · مستودع RuoYi-Vue على Gitee