10 месяцев назад
🖥 Basic Java Deserialization (2 part) Теперь поговорим о том, как защищаться от десериализации Пример безопасного кода: import java.io.*; import java.net.ServerSocket; import java.net.Socket; import java.util.HashSet; import java.util.Set; public class SecureServer { private static final Set<String> ALLOWED_CLASSES = new HashSet<>(); static { ALLOWED_CLASSES.add("java.lang.String"); ALLOWED_CLASSES.add("java.util.ArrayList"); } public static void main(String[] args) { try (ServerSocket serverSocket = new ServerSocket(1234)) { System.out.println("Сервер запущен. Ожидание подключений..."); while (true) { try (Socket clientSocket = serverSocket.accept(); ObjectInputStream ois = new ObjectInputStream(clientSocket.getInputStream()) { @Override protected Class<?> resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException { if (!ALLOWED_CLASSES.contains(desc.getName())) { throw new InvalidClassException("Недопустимый класс", desc.getName()); } return super.resolveClass(desc); } }) { Object obj = ois.readObject(); System.out.println("Получен объект: " + obj); } catch (Exception e) { e.printStackTrace(); } } } catch (IOException e) { e.printStackTrace(); } } } Исправления: ➡️Создан белый список разрешенных классов (ALLOWED_CLASSES). ➡️Переопределен метод resolveClass для проверки классов перед десериализацией. ➡️Выбрасывается исключение при попытке десериализовать недопустимый класс. Также есть другие практики по защите от десеров. К примеру Java SecurityManager, transient. С другой стороны вы можете закостылить защиту через сторонние библиотеки: SerialKiller, fastjson2, YamlBeans ➡️ В завершение хочу сказать, что если вы нашли у меня ошибку, напишите об этом, пожалуйста в комментариях) ➡️ А если вам понравилось и вы хотите продолжить изучение, то предлагаю почитать Java Deserialization Cheat Sheet 🌚 @poxek | 📺 RuTube | 🌚 Мерч Похек
10 месяцев назад
🖥 Basic Java Deserialization (1 part) #java #deser #deserialization Все мы когда-нибудь дорастаем до того момента, когда к нам на проекте попадется приложение на Java и вы в судорожном фаззинге случайно натыкаетесь на что-то непонятное, а это оказывается десериализация. Но сначала надо разобраться, что такое сериализация. Это процесс преобразования объекта или структуры данных в последовательность байтов для хранения или передачи. Это позволяет сохранить состояние объекта и позже восстановить его. Соответственно десериализация - обратный процесс, при котором последовательность байтов преобразуется обратно в объект или структуру данных. Вот вам пример кода: import java.io.*; // Класс, который мы будем сериализовать class User implements Serializable { private static final long serialVersionUID = 1L; private String name; private int age; public User(String name, int age) { this.name = name; this.age = age; } @Override public String toString() { return "User{name='" + name + "', age=" + age + "}"; } } public class SerializationExample { public static void main(String[] args) { // Создаем объект для сериализации User user = new User("Sergey", 20); // Сериализация try (FileOutputStream fileOut = new FileOutputStream("user.ser"); ObjectOutputStream out = new ObjectOutputStream(fileOut)) { out.writeObject(user); System.out.println("Объект сериализован в файл user.ser"); } catch (IOException i) { i.printStackTrace(); } // Десериализация User deserializedUser = null; try (FileInputStream fileIn = new FileInputStream("user.ser"); ObjectInputStream in = new ObjectInputStream(fileIn)) { deserializedUser = (User) in.readObject(); } catch (IOException i) { i.printStackTrace(); } catch (ClassNotFoundException c) { System.out.println("Класс User не найден"); c.printStackTrace(); } if (deserializedUser != null) { System.out.println("Десериализованный объект: " + deserializedUser); } } } Атака десериализации - это тип атаки, при котором злоумышленник манипулирует сериализованными данными, чтобы вызвать нежелательное поведение в приложении при их десериализации. Вот пример уязвимого кода: import java.io.*; import java.net.ServerSocket; import java.net.Socket; public class VulnerableServer { public static void main(String[] args) { try (ServerSocket serverSocket = new ServerSocket(1234)) { System.out.println("Сервер запущен. Ожидание подключений..."); while (true) { try (Socket clientSocket = serverSocket.accept(); ObjectInputStream ois = new ObjectInputStream(clientSocket.getInputStream())) { // Уязвимый код: прямая десериализация без проверок Object obj = ois.readObject(); System.out.println("Получен объект: " + obj); } catch (Exception e) { e.printStackTrace(); } } } catch (IOException e) { e.printStackTrace(); } } } Уязвимость в строке: javaCopyObject obj = ois.readObject(); Здесь происходит прямая десериализация объекта без каких-либо проверок. Это позволяет злоумышленнику отправить любой сериализованный объект, который будет десериализован и выполнен в контексте сервера. Подобный код может привести к RCE. 🌚 @poxek | 📺 RuTube | 🌚 Мерч Похек