Как стать автором
Обновить

Комментарии 32

По поводу ViewState: ни в коем случае в web.xml не делать так:
<context-param>
    <param-name>javax.faces.STATE_SAVING_METHOD</param-name>
    <param-value>client</param-value>
</context-param>


Кстати, Spring и Groovy тоже под ударом, судя по этому.
… 10 month ago (судя по истории git репозитория)
Судя по этой январской презентации, Ruby, PHP, Python имеют аналогичные проблемы с десериализацией данных, полученных от недоверенных источников.
Java сериализация давно уж как моветон
Расскажите это какому-нибудь JSF :)
Ах да, точно)
А можно узнать почему? Или вы так неудачно сократили «Java сериализация (для обмена данными с внешними ресурсами) давно уж как моветон»?
Даже внутри распределенного java приложения не часто выбирают java сериализацию из-за производительности, совместимости разных версий объекта, объема данных и прочих связанных с стандартной сериализацией проблем. Достаточно бенчмарков и материалов на тему сериализации
О, кстати. У нас тут через JMS передаются объекты (в основном byte[], String и классы, отнаследованные от пары интерфейсов). Что из быстрого использовать вместо сериализации?
не знаю как с jms, а с Solace API некоторые компании успешно используют avro/protobuff
Отлично, коротко и по делу!

Я так понимаю, проблему не тяжело пофиксить через Security Manager, или кастомный class loader. Общая практика — надо описать разрешённые для загрузки классы (именно загрузка, а не сериализация) и запретить все остальные. Мало ли в какой библиотеке, какая дырка ещё не найдена.
Этакий WAF для Java? Да, интересно, но только внутри той-же сферы сотни тысяч классов. И еще какие-то генерятся в памяти ORM'ами.
И таки да, сериализуются туда-сюда.
Согласен, хотя WAF реализовать и легко, толково наполнить разрешениями уже посложнее. Просто у меня перед глазами мой маленький проект с небольшим числом гуляющих по сети классов. Не люблю я энтерпрайз-решения.
Общая практика

Общая хорошая практика в Java не использовать сериализацию для любых внешних запросов, когда есть Rest, Soup и иже с ними. За десяток лет в Java энтерпрайзе не разу не видел случая использования сериализации для обмена данными с внешними системами и считал само собой разумеющимся, что прием сериализационных классов из недостоверных источников небезопасный от слова совсем.
Т.е. вы за «сериализовать только java.lang.String»? Хороший, строгий частный случай ;)
Нет, я за то чтобы передавать не бинарные объекты, а json или xml, если речь не идет о модулях одной системы. Зачем придумывать хитрые песочницы, которые все равно могут протекать, если намного проще вообще не запускать непонятно от кого исполняемые файлы. Вроде бы пользователи уже привыкли не запускать непонятные exe'шники, какие совершенные антивирусы их не проверили, зачем делать такую же ошибку на сервере? Или другими словами, логичнее стрелять холостыми, чем стрелять боевыми в бронежелет, надеясь что он достаточно крепкий.
Либо я чего-то не понимаю, но что мешает взять любой протокол, который использует сериализацию/десериализацию, посмотреть какие классы ходят и сделать override default constructor/readObject и там написать что надо. Только нужно чуть больше работы, чем просто взять exploit для commons-collections
То что при сериализации сериализуются поля, но не методы. При десериализации вызывается конструктор по-умолчанию. А классов на стороне сервера, у которых конструктор может что-то исполнить вот такое, их почти и нету. Собственно InvokerTransformer и есть один из таких классов.
У InvokerTransformer нет дефолтного конструктора, там все запутанее: у PriorityQueue в readObject() есть вызов compare у объекта, в качестве которого передаётся экземпляр TransformerComparator'а, который в свою очередь вызывает метод transform() у переданного InvokerTransformer. А там уже Method.invoke(), которому передаётся трэш, угар и содомия, например, Runtime.getRuntime().exec().

Так что надо искать не дефолтные конструкторы, а readObject(), которые вызывают интерфейсные методы, реализации которых где-то там в глубине стека вызывают invoke()
О, спасибо. Можно добавить в статью?
Добавляй
> "...remove the «risky» class files (InvokerTransformer, InstantiateFactory, and InstantiateTransfromer) in all commons-collections jars used by your app".

Ещё из spring'а (если используете в своих приложениях) выкинуть org.springframework.beans.factory.support.AutowireUtils, ну может ещё чего найдёте (наверняка есть что-то в классах, обслуживающих xml-конфигурацию приложения). Правда, IoC в Spring после этого вряд ли взлетит.
Странно. Хотел попробовать прогнать этот эксплоид на нашем приложении, но что-то пошло не так.

Даже если я просто создаю объект, как написано в статье, сериализую его, а потом тут же десериализую, то получаю ошибку десериализации:

Stacktrace
Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.util.Set
	at com.sun.proxy.$Proxy0.entrySet(Unknown Source)
	at sun.reflect.annotation.AnnotationInvocationHandler.readObject(AnnotationInvocationHandler.java:443)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:606)
	at java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:1017)
	at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1893)
	at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1798)
	at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1350)
	at java.io.ObjectInputStream.readObject(ObjectInputStream.java:370)
	at ru.krista.exploid.Exploid1.deserialize(Exploid1.java:113)
	at ru.krista.exploid.Exploid1.send(Exploid1.java:75)
	at ru.krista.exploid.Exploid1.main(Exploid1.java:30)



Есть подозрение, что код специально подпорчен. Но вот где ошибка — понять не могу.
Берите лучше отсюда рабочий код.
Если будет во viewstate инжектить, то вот удобная утилита для снятия дампов с viewstate

Спасибо. К счастью ViewState'а у нас нету. Но вот то, что в Wildfly все коммуникации повесили на один порт (и http и EJB) — неприятно. Пытаюсь сообразить какие могут быть вектора атаки с учётом нашей инфраструктуры. Но для этого надо иметь на руках рабочий экспоид.
Всё. С помощью автора разобрался.

Оказывается ошибка и должна быть. Но она происходит уже после срабатывания уязвимости. Просто я неудачную команду для выполнения выбрал.

echo test > /tmp/hacked.txt

Не работает. А вот

touch /tmp/hacked

уже отрабатывает.
А, ну шелловскую строку пытались выполнить, надо было /bin/bash -e '...' использовать
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории