Код-ревью Junior XSS и CSP обновлено

Ревью: сервлет поиска на Java

Вопрос

Найдите уязвимости в выводе страницы поиска.

protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
    String q = req.getParameter("q");
    resp.setContentType("text/html");
    PrintWriter out = resp.getWriter();
    out.println("<h1>Результаты по запросу: " + q + "</h1>");
    out.println("<input name='q' value='" + q + "'>");
    out.println("<script>var query = '" + q + "';</script>");
}

Коротко

Одно значение выводится в трёх контекстах, и каждому нужна своя кодировка. Лучше использовать шаблонизатор с автоэкранированием (Thymeleaf) вместо ручной сборки HTML.

Что должен найти ревьюер

  1. Безопасностьстрока 5
    Отражённый XSS в тексте HTML: q выводится без экранирования. Нужна HTML-кодировка (например OWASP Java Encoder Encode.forHtml).
  2. Безопасностьстрока 6
    XSS в атрибуте: одинарная кавычка в q закрывает value и добавляет обработчик. Нужно экранирование для атрибута.
  3. Безопасностьстрока 7
    XSS внутри <script>: строка JS обрывается кавычкой или </script>. Данные в скрипт нужно передавать через data-атрибут или JSON с JS-экранированием.
  4. Стильстрока 3
    Нет кодировки в Content-Type (text/html; charset=UTF-8): браузер может угадать кодировку, что исторически давало обходы.

Разбор

Одно значение выводится в трёх контекстах, и каждому нужна своя кодировка. Лучше использовать шаблонизатор с автоэкранированием (Thymeleaf) вместо ручной сборки HTML.

Ответьте сами, а не прочитайте

В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.