# V5333. OWASP. Possible insecure deserialization vulnerability. Potentially tainted data is used to create an object during deserialization.

Анализатор обнаружил, что для десериализации объекта через стандартные Java-механизмы используются данные, полученные из внешнего источника. Это может подвергнуть приложение уязвимости.

Атаки, связанные с десериализацией данных извне, выделены в отдельную категорию OWASP Top Ten Application Security Risks:

- A08:2021 – Software and Data Integrity Failures

У атак, осуществляемых через десериализацию данных извне, могут быть различные цели и варианты реализации:

- злоумышленником возможна подмена данных в десериализуемом объекте. К примеру, это может привести к несанкционированному увеличению прав доступа определённому пользователю или к присвоению невалидного значения какому-либо полю объекта;
- удалённое выполнение кода. Здесь у злоумышленника может быть множество целей, в частности, выполнение вредоносных ОС команд, обнародование конфиденциальной информации и т.д.

Существуют советы, следование которым поможет уменьшить вероятность возникновения одной из вышеперечисленных проблем. Главный из них — не предоставлять пользователям возможность отправлять приложению данные для десериализации. Если же это необходимо, следует помнить, что:

- стоит использовать безопасные библиотеки для сериализации / десериализации. Их перечень можно найти в прикреплённой ниже статье от OWASP;
- необходимо контролировать приходящие извне данные.

В случае использования стандартного Java-интерфейса для десериализации один из вариантов защиты от потенциальных проблем — смотреть, какого типа объект десериализуется. Важно помнить, что делать это нужно до того, как объект восстановлен.

Пример небезопасной конфигурации:

    public void notSecure(HttpServletRequest req,
                          HttpServletResponse res) throws .... {
        ServletInputStream servletIS = req.getInputStream();
        ObjectInputStream  objectIS  = new ObjectInputStream(servletIS); // <=
        Object object = objectIS.readObject();
    }

Пример конфигурации с проверкой:

    class SecureObjectInputStream extends ObjectInputStream {
      public SecureObjectInputStream(InputStream in) throws IOException {
        super(in);
      }

      @Override
      protected Class<?> resolveClass(ObjectStreamClass osc) throws .... {
        List<String> allowedClasses = new ArrayList<>();
        allowedClasses.add(AllowedClass1.class.getName());
        allowedClasses.add(AllowedClass2.class.getName());
        if (!allowedClasses.contains(osc.getName())) {
          throw new InvalidClassException("Unauthorized deserialization",
                                          osc.getName());
        }
        return super.resolveClass(osc);
      }
    }

    ....

    public void withCheck(HttpServletRequest req,
                          HttpServletResponse res) throws .... {
      ServletInputStream servletIS = req.getInputStream();
      ObjectInputStream objectIS   = new SecureObjectInputStream(servletIS);
      Object object = objectIS.readObject();
    }

В исправленном примере создан класс `SecureObjectInputStream`. Он является наследником `ObjectInputStream`. В нём переопределён метод `resolveClass`, что позволяет проверить, какого типа объект будет десериализован. Выполняется этот метод до десериализации объекта. Если объект не находится в перечне тех, что мы хотим десериализовать, выбрасывается исключение. Это позволит не допустить десериализацию небезопасного объекта, чьё внутреннее содержимое может навредить приложению.

Полезные ссылки:

- OWASP. Deserialization Cheat Sheet.

Выявляемые диагностикой ошибки классифицируются согласно ГОСТ Р 71207–2024 как критические и относятся к типу: Ошибки непроверенного использования чувствительных данных (ввода пользователя, файлов, сети и пр.).

Данная диагностика классифицируется как:

CWE-502 CERT-SER12-J