Разбираем уязвимость в фреймворке Apache Struts 2

Разбираем уязвимость в фреймворке Apache Struts 2

https://t.me/plastikru

Сегодня мы вернемся к Apache Struts, популярному веб-фреймворку, который за последнее время натерпелся от исследователей безопасности и явил миру несколько критических уязвимостей. В этой статье я хочу обсудить уязвимость в модуле, отвечающем за REST API. Она приводит к выполнению произвольного кода и открывает широкие возможности (такие, например, как слив личных данных половины населения США).

Наш подопытный

Все свои манипуляции я буду производить на ОС Windows 10. В качестве сервера я использую Apache Tomcat 8.5.20. Версию фреймворка Apache Struts я возьму из ветки 2.5, и это последняя уязвимая до патча — 2.5.12. Скачать можно, разумеется, на официальном сайте. Чтобы не пришлось искать, вот тебе прямая ссылочка (ZIP). Также можешь скачать только исходники, если захочешь заглянуть внутрь и лучше понять, как все устроено.

После установки сервера нужно распаковать архив с фреймворком, взять из папки apps приложение struts2-rest (файл struts2-rest-showcase.war) и положить в папку webapps сервера Tomcat. После этого можно запускать сервер.

Теперь, перейдя по адресу http://127.0.0.1:8080/struts2-rest-showcase, ты можешь наблюдать нашего подопытного.

Готовое к экспериментам приложение

 Копаемся в исходниках

Для начала несколько слов о ContentTypeHandler. Это интерфейс, который предоставляется фреймворком для конвертирования данных в объекты Java. Десериализацию здесь используют, чтобы преобразовать переданные данные в объекты. Поэтому каждый класс, реализующий этот интерфейс, представляет потенциальный интерес для нас как исследователей. Ведь все мы любим десериализацию юзердаты.

Так вот, в Struts имеется такой класс, как XStreamHandler.

/plugins/rest/src/main/java/org/apache/struts2/rest/handler/XStreamHandler.java

30: /**
31:  * Handles XML content
32:  */
33: public class XStreamHandler implements ContentTypeHandler {


Он используется при обработке данных в формате XML, отправленных на сервер.

Заглянем в конфигурационный файл.

/plugins/rest/src/main/resources/struts-plugin.xml

35:     <bean type="org.apache.struts2.rest.handler.ContentTypeHandler" name="xml" class="org.apache.struts2.rest.handler.XStreamHandler" />
...
47:     <constant name="struts.action.extension" value="xhtml,,xml,json" />


Как видишь, обработка XML-запросов включена по умолчанию, и занимается этим именно класс XStreamHandler.

Во время обработки пользовательского запроса класс ContentTypeInterceptor определяет MIME-тип отправленных данных и направляет выполнение кода в нужное русло — для обработки данных выбирается соответствующий обработчик.

/plugins/rest/src/main/java/org/apache/struts2/rest/ContentTypeInterceptor.java

38: public class ContentTypeInterceptor extends AbstractInterceptor {
...
48:     public String intercept(ActionInvocation invocation) throws Exception {
49:         HttpServletRequest request = ServletActionContext.getRequest();
50:         ContentTypeHandler handler = selector.getHandlerForRequest(request);

Чтобы превратить переданные данные в объект, существует метод с подходящим названием toObject. Он и вызывается из обработчика, определенного с помощью intercept.

/plugins/rest/src/main/java/org/apache/struts2/rest/ContentTypeInterceptor.java

59:             InputStreamReader reader = new InputStreamReader(is);
60:             handler.toObject(reader, target);

/plugins/rest/src/main/java/org/apache/struts2/rest/handler/XStreamHandler.java

43:     public void toObject(Reader in, Object target) {
44:         XStream xstream = createXStream();
45:         xstream.fromXML(in, target);
46:     }

Объект in — это не что иное, как пользовательские данные, отправленные определенному методу REST API. Эти данные передаются в XStream.fromXML.

Report Page