V5333. OWASP. Possible insecure deserialization vulnerability. Potentially tainted data is used to create an object during deserialization.
Анализатор обнаружил, что для десериализации объекта через стандартные Java-механизмы используются данные, полученные из внешнего источника. Это может подвергнуть приложение уязвимости.
Атаки, связанные с десериализацией данных извне, выделены в отдельную категорию OWASP Top Ten Application Security Risks:
У атак, осуществляемых через десериализацию данных извне, могут быть различные цели и варианты реализации:
- злоумышленником возможна подмена данных в десериализуемом объекте. К примеру, это может привести к несанкционированному увеличению прав доступа определённому пользователю или к присвоению невалидного значения какому-либо полю объекта;
- удалённое выполнение кода. Здесь у злоумышленника может быть множество целей, в частности, выполнение вредоносных ОС команд, обнародование конфиденциальной информации и т.д.
Существуют советы, следование которым поможет уменьшить вероятность возникновения одной из вышеперечисленных проблем. Главный из них — не предоставлять пользователям возможность отправлять приложению данные для десериализации. Если же это необходимо, следует помнить, что:
- стоит использовать безопасные библиотеки для сериализации / десериализации. Их перечень можно найти в прикреплённой ниже статье от 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 как критические и относятся к типу: Ошибки непроверенного использования чувствительных данных (ввода пользователя, файлов, сети и пр.). |
Данная диагностика классифицируется как:
|