
Анализатор байт-кода для поиска цепочек гаджетов десериализации в Java-приложениях
Этот проект инспектирует Java-библиотеки и classpath'ы на наличие цепочек гаджетов (gadget chains). Цепочки гаджетов используются для создания эксплойтов для уязвимостей десериализации. Автоматически обнаруживая возможные цепочки гаджетов в classpath приложения, специалисты по пентесту могут быстро создавать эксплойты, а инженеры по безопасности приложений — оценивать влияние уязвимости десериализации и определять приоритеты её устранения.
Этот проект был представлен на Black Hat USA 2018. Узнайте больше об этом там! (Ссылки в ожидании)
ПРЕДУПРЕЖДЕНИЕ: Этот проект находится на стадии альфа. Ему требуются тесты и документация. Помогите, добавив то или другое!
Если в вашей системе установлен JDK, вы должны иметь возможность просто запустить ./gradlew shadowJar. Затем вы можете запустить приложение с помощью java -jar build/libs/gadget-inspector-all.jar <аргументы>.
Это приложение ожидает в качестве аргумента(ов) либо путь к war-файлу (в этом случае war будет распакован, а все его классы и библиотеки будут использоваться как classpath), либо любое количество jar-файлов.
Обратите внимание, что анализ может быть ресурсоёмким по памяти (и на данный момент gadget inspector никак не оптимизирован для уменьшения потребления памяти). Для небольших библиотек вам, вероятно, нужно выделить не менее 2 ГБ памяти кучи (т.е. с флагом -Xmx2G). Для более крупных приложений используйте столько памяти, сколько сможете выделить.
Инструментарий пройдёт через несколько этапов проверки classpath, чтобы собрать наборы данных для использования на последующих этапах. Эти наборы данных записываются в файлы с расширением .dat и могут быть удалены после вашего запуска (они записываются в основном для того, чтобы более ранние этапы можно было пропустить во время разработки).
После завершения анализа будет записан файл gadget-chains.txt.
Ниже приведён пример запуска против commons-collections-3.2.1.jar, например, с помощью:
wget http://central.maven.org/maven2/commons-collections/commons-collections/3.2.1/commons-collections-3.2.1.jar
java -Xmx2G -jar build/libs/gadget-inspector-all.jar commons-collections-3.2.1.jar
В gadget-chains.txt содержится следующая цепочка:
com/sun/corba/se/spi/orbutil/proxy/CompositeInvocationHandlerImpl.invoke(Ljava/lang/Object;Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object; (-1)
com/sun/corba/se/spi/orbutil/proxy/CompositeInvocationHandlerImpl.invoke(Ljava/lang/Object;Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object; (0)
org/apache/commons/collections/map/DefaultedMap.get(Ljava/lang/Object;)Ljava/lang/Object; (0)
org/apache/commons/collections/functors/InvokerTransformer.transform(Ljava/lang/Object;)Ljava/lang/Object; (0)
java/lang/reflect/Method.invoke(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object; (0)
Точкой входа в эту цепочку является реализация класса JDK InvocationHandler. Используя тот же трюк, что и в оригинальной цепочке гаджетов commons-collections, любой сериализуемый экземпляр этого класса достижим в цепочке гаджетов, поэтому обнаруженная цепочка начинается здесь. Этот метод вызывает classToInvocationHandler.get(). Обнаруженная цепочка гаджетов показывает, что classToInvocationHandler может быть сериализован как DefaultedMap, так что этот вызов переходит к DefaultedMap.get(). Следующий шаг в цепочке вызывает value.transform() из этого метода. Параметр value в этом классе может быть сериализован как InvokerTransformer. Внутри метода transform этого класса мы видим, что вызываем cls.getMethodName(iMethodName, ...).invoke(...). Gadget inspector определил, что iMethodName контролируется атакующим как сериализуемый член, и, следовательно, атакующий может выполнить произвольный метод в классе.
Эта цепочка гаджетов является строительным блоком полной цепочки гаджетов commons-collections, обнаруженной Frohoff. В приведённом выше случае gadget inspector случайно обнаружил вход через CompositeInvocationHandlerImpl и DefaultedMap вместо AnnotationInvocationHandler и LazyMap, но в целом это то же самое.
Если вы ищете больше примеров того, какие цепочки может найти этот инструмент, следующие библиотеки также содержат интересные результаты:
Не забывайте, что вы также можете указать gadget inspector на полное приложение (упакованное как JAR или WAR). Например, при анализе war-файла приложения Zksample2 мы получаем следующую цепочку гаджетов:
net/sf/jasperreports/charts/design/JRDesignPieDataset.readObject(Ljava/io/ObjectInputStream;)V (1)
org/apache/commons/collections/FastArrayList.add(Ljava/lang/Object;)Z (0)
java/util/ArrayList.clone()Ljava/lang/Object; (0)
org/jfree/data/KeyToGroupMap.clone()Ljava/lang/Object; (0)
org/jfree/data/KeyToGroupMap.clone(Ljava/lang/Object;)Ljava/lang/Object; (0)
java/lang/reflect/Method.invoke(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object; (0)
Как видите, здесь используются несколько различных библиотек, содержащихся в приложении, для построения цепочки.
В: Если gadget inspector находит цепочку гаджетов, можно ли на её основе построить эксплойт?
О: Не всегда. Анализ использует некоторые упрощающие предположения и может сообщать о ложных срабатываниях (цепочках гаджетов, которые на самом деле не существуют). В качестве простого примера, он не пытается решить задачу выполнимости условий ветвления. Таким образом, он сообщит о следующем коде как о цепочке гаджетов:
public class MySerializableClass implements Serializable {
public void readObject(ObjectInputStream ois) {
if (false) System.exit(0);
ois.defaultReadObject();
}
}
Кроме того, у gadget inspector довольно широкие условия для тех функций, которые он считает интересными. Например, он считает рефлексию интересной (т.е. вызовы Method.invoke(), когда атакующий может контролировать метод), но часто упускаемые из виду утверждения означают, что атакующий может влиять на вызываемый метод, но не имеет полного контроля. Например, атакующий может быть в состоянии вызвать метод "getError()" в любом классе, но не любое другое имя метода.
В: Если цепочек гаджетов не найдено, значит ли это, что моё приложение защищено от эксплуатации?
О: Нет! Во-первых, gadget inspector имеет очень узкий набор «стоковых» функций (sink functions), которые он считает имеющими «интересные» побочные эффекты. Это, безусловно, не означает, что нет других интересных или опасных поведений, не включённых в список.
Кроме того, существует ряд ограничений статического анализа, из-за которых у gadget inspector всегда будут слепые зоны. Например, gadget inspector в настоящее время пропустит следующий код, потому что он не отслеживает рефлексивные вызовы.
public class MySerializableClass implements Serializable {
public void readObject(ObjectInputStream ois) {
System.class.getMethod("exit", int.class).invoke(null, 0);
}
}