Host Header Injection

Атаки на HTTP-заголовок Host используют уязвимые веб-сайты, которые обрабатывают значение заголовка Host небезопасным способом. Если сервер неявно доверяет заголовку Host и не проверяет или не экранирует его должным образом, злоумышленник может использовать этот ввод для внедрения вредоносной полезной нагрузки, которая манипулирует поведением сервера. Атаки, связанные с внедрением полезной нагрузки непосредственно в заголовок Host, часто называются атаками "внедрения заголовка Host".

Готовые веб-приложения обычно не знают, в каком домене они развернуты, если это не указано вручную в конфигурационном файле во время установки.

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

  • Отравление веб-кэша.

  • Недостатки бизнес-логики в конкретной функциональности.

  • SSRF на основе маршрутизации.

  • Классические уязвимости на стороне сервера, такие как SQL-инъекции.

2. Типичный уязвимый код:

Сброс пароля - одна из самых распространенных целей для Header Injection; вот пример того, как выглядит уязвимый код:

public void resetPasswordLink(HttpServletRequest request) {

    // retrieves the host from the request header
    String host = request.getHeader("Host");
    
    String email = request.getParameter("email");
    HttpSession session = request.getSession();

    if (session != null) {
        String token = generateResetToken(email);
        
        // Password reset link is constructed with the retrieved host
        // for the token that has just been generated.
        StringBuilder resetLinkBuilder = new StringBuilder()
                .append(host)
                .append("?reset")
                .append(token);
        
        // Send the email
        sendEmail(email, resetLinkBuilder.toString());
    }
}

Обратите внимание, что в параметре Хост заголовка. Злоумышленник может воспользоваться этим и перехватить POST запрос, чтобы произвольно изменить Host из заголовка запроса. Таким образом, письмо, которое получит жертва, будет выглядеть безопасным, однако при переходе по ссылке, которая была сгенерирована (с атакующим Host ), злоумышленник получит токен сброса пароля, а значит, сможет полностью сбросить пароль жертвы.

3. Смягчения:

Чтобы предотвратить атаки на HTTP-заголовок Host, самый простой подход заключается в том, чтобы не использовать Host в коде на стороне сервера. Дважды проверьте, действительно ли каждый URL должен быть абсолютным. Часто оказывается, что вместо него можно использовать относительный URL. Это простое изменение поможет вам предотвратить уязвимости отравления веб-кэша, в частности.

3.1. Белый список разрешенных доменов:

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

public void resetPasswordLink(HttpServletRequest request) {

    // retrieves the host from the request header
    String host = request.getHeader("Host");
    
    String email = request.getParameter("email");
    HttpSession session = request.getSession();
    
    // create the whitelist for the allowed domains
    List <String> allowedDomains = Arrays.asList(
        "bobisecure.com",
        "bank.bobisecure.com",
        "s3.bobisecure.com"
    );
    
    // check whether the given `host` exists in the whitelist
    if (session != null && allowedDomains.contains(host)) {
        String token = generateResetToken(email);
        
        // Password reset link is constructed with the retrieved host
        // for the token that has just been generated.
        StringBuilder resetLinkBuilder = new StringBuilder()
                .append(host)
                .append("?reset")
                .append(token);
        
        // Send the email
        sendEmail(email, resetLinkBuilder.toString());
    }
}

3.2. Защита абсолютных URL-адресов:

Если вам приходится использовать абсолютные URL, то необходимо вручную указать текущий домен в конфигурационном файле и ссылаться на это значение вместо заголовка Host. В отличие от предыдущего пункта, конечная точка вашего приложения будет иметь дело только с единственным возможным URL. Такой подход устраняет угрозу, например, отравления при сбросе пароля.

Также важно убедиться, что вы не поддерживаете дополнительные заголовки, которые могут быть использованы для построения таких атак, в частности X-Forwarded-Host . Помните, что они могут поддерживаться по умолчанию.

4. Выводы:

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

Помните, что в целом вы никогда не должны доверять заголовку Host, если это не является действительно необходимым!

Last updated