Предотвращение атаки CSRF, XSS и SQL Injection в JSF

У меня есть веб-приложение, построенное на JSF с MySQL как DB. Я уже реализовал код для предотвращения использования CSRF в своем приложении.

Теперь, поскольку моя базовая структура JSF, я думаю, мне не нужно обрабатывать атаку XSS, поскольку она уже обрабатывается UIComponent. Я не использую JavaScript на любой странице просмотра. Даже если я использую, мне действительно нужно реализовать код для предотвращения атак XSS?

Для БД мы используем подготовленные операторы и хранимые процедуры во всех взаимодействиях БД.

Есть ли что-то еще для предотвращения этих 3 общих атак? Я уже прошел через OWASP и их чит-листы.

Нужно ли мне заботиться о любых других потенциальных атакующих векторах?

Ответ 1

XSS

JSF имеет встроенную функцию предотвращения XSS. Вы можете безопасно повторно отображать все вводимые пользователем данные (заголовки запросов (включая файлы cookie!), Параметры запросов (также те, которые сохраняются в БД!) И тела запросов (загруженные текстовые файлы и т.д.)), Используя любой JSF-компонент.

<h:outputText value="#{user.name}" />
<h:outputText value="#{user.name}" escape="true" />
<h:inputText value="#{user.name}" />
etc...

Обратите внимание, что при использовании JSF 2.0 в Facelets вы можете использовать EL в тексте шаблона следующим образом:

<p>Welcome, #{user.name}</p>

Это также будет неявно избежать. Вам не обязательно нужен <h:outputText> здесь.

Только, когда вы явно удаляете пользовательский ввод с помощью escape="false":

<h:outputText value="#{user.name}" escape="false" />

тогда у вас есть потенциальная дыра в атаке XSS!

Если вы хотите снова отобразить ввод, управляемый пользователем, в виде HTML, в котором вы хотите разрешить только определенное подмножество тегов HTML, таких как <b>, <i>, <u> и т.д., То вам необходимо санировать ввод с помощью Белый список. HTML-анализатор Jsoup очень полезен в этом.

itemLabelEscaped ошибка в Мохарре & lt; 2.2.6

В более старых версиях Mojarra до 2.2.6 была ошибка, из-за которой <f:selectItems itemLabel> неправильно отображал метку без экранирования, когда предоставлял List<T> через <f:selectItems var> вместо List<SelectItem> или SelectItem[] в качестве значения (Issue 3143), Другими словами, если вы повторно отображаете данные, контролируемые пользователем, в качестве меток элементов через List<T>, то у вас есть потенциальная дыра в XSS. Если обновление по крайней мере до Mojarra 2.2.6 не вариант, вам нужно явно установить атрибут itemLabelEscaped в true, чтобы предотвратить это.

<f:selectItems value="#{bean.entities}" var="entity" itemValue="#{entity}"
    itemLabel="#{entity.someUserControlledProperty}" itemLabelEscaped="true" />

CSRF

JSF 2.x уже имеет встроенную функцию предотвращения CSRF в виде скрытого поля javax.faces.ViewState в форме при использовании сохранения состояния на стороне сервера. В JSF 1.x это значение было довольно слабым и слишком легко предсказуемым (фактически оно никогда не предназначалось для предотвращения CSRF). В JSF 2.0 это было улучшено за счет использования длинного и сильного автоматически сгенерированного значения вместо довольно предсказуемого значения последовательности и, таким образом, превращения его в надежное предотвращение CSRF.

В JSF 2.2 это еще более улучшилось, сделав его обязательной частью спецификации JSF вместе с настраиваемым ключом AES для шифрования состояния на стороне клиента, если включено сохранение состояния на стороне клиента. См. также выпуск спецификации JSF 869 и Повторное использование значения ViewState в другом сеансе (CSRF). Новое в JSF 2.2 - защита CSRF от GET-запросов <protected-views>.

Только когда вы используете представления без сохранения состояния, как в <f:view transient="true">, или где-то есть дыра для атаки XSS в приложении, у вас есть потенциальная дыра для атаки CSRF.


SQL-инъекция

Это не ответственность JSF. Как это предотвратить, зависит от используемого вами API персистентности (необработанный JDBC, современный JPA или хороший старый Hibernate), но все сводится к тому, что вы не должны никогда объединять контролируемый пользователем ввод в строки SQL, например, так

String sql = "SELECT * FROM user WHERE username = '" + username + "' AND password = md5(" + password + ")";
String jpql = "SELECT u FROM User u WHERE u.username = '" + username + "' AND u.password = md5('" + password + "')";

Представьте, что произойдет, если конечный пользователь выберет следующее имя:

x'; DROP TABLE user; --

Вы должны всегда использовать параметризованные запросы, где это применимо.

String sql = "SELECT * FROM user WHERE username = ? AND password = md5(?)";
String jpql = "SELECT u FROM User u WHERE u.username = ?1 AND u.password = md5(?2)";

В простом JDBC вам нужно использовать PreparedStatement для заполнения значений параметров, а в JPA (и Hibernate) объект Query также предлагает для этого сеттеры.

Ответ 2

Я не использую JavaScript на любой странице просмотра. Даже если я использую, мне действительно нужно реализовать код, чтобы обойти XSS Attack.

Вы можете быть уязвимы для XSS, даже если вы не используете JavaScript на своих страницах. XSS возникает, когда вы включаете контент, контролируемый злоумышленником, без должного кодирования.

В любое время вы делаете что-то вроде

response.write("<b>" + x + "</b>")

где злоумышленник может заставить x содержать HTML, содержащий JavaScript, тогда вы уязвимы для XSS.

Решение, как правило, не должно писать большие объемы кода. Обычно решение заключается в кодировании $x и любых других значениях, контролируемых злоумышленником, прежде чем включать их в создаваемый HTML.

response.write("<b>" + escapePlainTextToHtml(x) + "</b>")

Фильтрующие или дезинфицирующие входы могут обеспечить дополнительный уровень защиты.

<shameless-plug>

Вы также можете использовать язык шаблона, который автоматически кодирует выходные данные для защиты от XSS.

Closure Template является одним из таких вариантов для Java.

Контекстное аутоаудирование работает путем расширения шаблонов закрытия для правильного кодирования каждого динамического значения на основе контекста, в котором он появляется, тем самым защищая от уязвимостей XSS в значениях, которые контролируются злоумышленником.

ИЗМЕНИТЬ

Поскольку вы используете JSF, вы должны прочитать XSS-смягчение в JSF:

Выходной текст выхода

<h:outputText/> и <h:outputLabel/> по умолчанию имеет атрибут escape, равный True. Используя этот тег для отображения выходов, вы можете уменьшить большинство уязвимостей XSS.

SeamTextParser и <s:formattedText/>

Если вы хотите, чтобы пользователи использовали некоторые базовые теги html для настройки своих входов, JBoss Seam предоставляет тег <s:formattedText/>, который позволяет использовать некоторые основные теги и стили html, указанные пользователями.

Ответ 3

При использовании <h:outputText escape="false"> с неэкранированными значениями (например, из текстовых редакторов html) вы открыты для неприятных XSS-атак. В таких случаях я использую JSF-конвертер, который использует Jsoup для удаления javascript из текста, оставляя HTML нетронутым. Конвертер также можно использовать для очистки пользовательских входов. Вы можете использовать это так:

<h:outputText value="{bean.value}" escape="false" converter="htmlSanitizingConverter"/>

И сам конвертер:

/**
 * Prevents from XSS attack if output text is not escaped.
 */
@FacesConverter("htmlSanitizingConverter")
public class HtmlSanitizingConverter implements Converter {

    private static final Whitelist JSOUP_WHITELIST = Whitelist.relaxed()
            .preserveRelativeLinks(true)
            .addAttributes(":all","style");
            /*
             Optionally - add support for hyperlinks and base64 encoded images.
            .addTags("img")
            .addAttributes("img", "height", "src", "width")
            .addAttributes("a", "href")
            .addProtocols("img", "src", "http", "https", "data");
            */

    @Override
    public Object getAsObject(FacesContext context, UIComponent component, String submittedValue) {
        return (submittedValue != null) ? Jsoup.clean(submittedValue, JSOUP_WHITELIST) : null;
    }

    @Override
    public String getAsString(FacesContext context, UIComponent component, Object value) {
        return (value != null) ? Jsoup.clean(value.toString(), JSOUP_WHITELIST) : "";
    }

}

Примечание: Когда вы используете JSF с PrimeFaces, остерегайтесь <p:textEditor> - более старых версий (до 6.2) по умолчанию не очищали пользовательский ввод.