﻿# 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](https://owasp.org/Top10/A08_2021-Software_and_Data_Integrity_Failures/)

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

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

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

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

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

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

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

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

```cpp
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`, что позволяет проверить, какого типа объект будет десериализован\. Выполняется этот метод до десериализации объекта\. Если объект не находится в перечне тех, что мы хотим десериализовать, выбрасывается исключение\. Это позволит не допустить десериализацию небезопасного объекта, чьё внутреннее содержимое может навредить приложению\.

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

1. OWASP\. [Deserialization Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html)\.