Я использую JSF 2.2 (Glassfish 4.1). Наше веб-приложение имеет Primefaces 6.0 и Omnifaces 2.6.9 в качестве зависимостей. Состояние JSF хранится на сервере. В качестве примера скажем, что у меня есть эта форма, где userModel
- это javax.faces.view.ViewScoped
bean.
<h:form id="user">
<p:inputText id="name" value="#{userModel.name}"/>
<p:inputText id="pass" value="#{userModel.pass}"/>
<p:commandButton id="create" value="#{msgs.lbl_add}" action="#{userModel.addUser()}"/>
</h:form>
Компания просканировала наше веб-приложение на наличие проблем с безопасностью и заявила, что оно имеет уязвимость CSRF. Злоумышленник может предоставить одному из пользователей нашего приложения созданную форму для выполнения нежелательных действий.
<!DOCTYPE html>
<html>
<body>
<form action="http://appserver:8080/myapp/users.jsf" method="POST">
<input type="hidden" name="javax.faces.source" value="user:create"/>
<input type="hidden" name="user:create" value="user:create"/>
<input type="hidden" name="user" value="user"/>
<div>
<input type="text" name="user:name" value="FAKEUSER"/>
<input type="text" name="user:pass" value="FAKEPASSWORD"/>
<input type="text" name="javax.faces.ViewState" value="1185295409278172717:-3206872038807094332"/>
</div>
<input type="submit" name="submit" value="Create User"/>
</form>
</body>
</html>
Я читал на SO, что ViewState - это JSF-способ предотвращения CSRF. Но в нашем веб-приложении возможен следующий сценарий (с протоколом HTTP, если это имеет значение).
- Злоумышленник посещает страницу входа в наше приложение, чтобы найти допустимый ViewState в исходном коде своей страницы.
- Злоумышленник подготавливает HTML-файл, упомянутый выше, со своим ViewState и отправляет жертве.
- Жертва открывает файл HTML в браузере и отправляет (из локальной файловой системы, например,
file:///C:/...
, или размещенной на локальном веб-сервере) - Пользователь создан.
Вывод состоит в том, что наше веб-приложение/JSF в этом сценарии не проверяет, принадлежит ли полученное ViewState сеансу, идентифицированному JSESSIONID.
Разве это не уязвимость? Как я могу этого избежать?