Рекомендации по безопасности Java (серия из 3 частей)
Сериализация в Java позволяет нам преобразовать объект в поток байтов. Этот поток байтов либо сохраняется на диске, либо переносится в другую систему. С другой стороны, поток байтов может быть десериализован и позволяет нам воссоздать исходный объект.
Самая большая проблема связана с десериализующей частью. Обычно это выглядит примерно так:
ObjectInputStream in = new ObjectInputStream( inputStream ); return (Data)in.readObject();
Невозможно узнать, что вы десериализуете, прежде чем вы это решите. Возможно, злоумышленник сериализует вредоносные объекты и отправляет их в ваше приложение. Как только вы вызовете readObject()
, вредоносные объекты уже будут созданы. Вы можете полагать, что такого рода атаки невозможны, потому что вам нужен уязвимый класс на вашем пути к классам. Однако, если учесть количество классов в вашем пути к классам, которое включает ваш собственный код, библиотеки Java, сторонние библиотеки и фреймворки, весьма вероятно, что существует уязвимый доступный класс.
Сериализацию Java также называют “подарком, который продолжает дарить” из-за множества проблем, которые она создавала на протяжении многих лет. Oracle планирует в конечном итоге удалить сериализацию Java в рамках проекта Amber. Однако это может занять некоторое время, и вряд ли это будет исправлено в предыдущих версиях. Поэтому разумно избегать сериализации Java, насколько это возможно. Если вам нужно реализовать сериализуемые объекты в вашем домене, лучше всего реализовать собственный readObject()
, как показано ниже. Это предотвращает десериализацию.
private final void readObject(ObjectInputStream in) throws java.io.IOException { throw new java.io.IOException("Deserialized not allowed"); }
Если вам нужно десериализовать входной поток самостоятельно, вы должны использовать Objectinputstream
с ограничениями. Хорошим примером этого является ValidatingObjectInputStream
из ввода-вывода Apache Commons. Этот ObjectInputStream
проверяет, разрешен ли десериализованный объект или нет.
FileInputStream fileInput = new FileInputStream(fileName); ValidatingObjectInputStream in = new ValidatingObjectInputStream(fileInput); in.accept(Foo.class); Foo foo_ = (Foo) in.readObject();
Проблемы десериализации объектов не ограничиваются сериализацией Java. Десериализация из JSON в объект Java может содержать аналогичные проблемы. Пример такой проблемы десериализации с библиотекой Джексона приведен в сообщении в блоге “Уязвимость десериализации Джексона”
Это был всего лишь 1 из 10 лучших методов обеспечения безопасности Java. Взгляните на полные 10 и доступные для печати одностраничные
Рекомендации по безопасности Java (серия из 3 частей)
Оригинал: “https://dev.to/brianverm/avoid-java-serialization-5g0b”