Я просмотрел десятку основных уязвимостей OWASP и обнаружил, что межсайтовый скриптинг — это то, что нам нужно делать. Было несколько рекомендуемых решений. Один заявил, что не используйте проверку «черного списка» для обнаружения XSS на входе или для кодирования вывода. Поиск и замена всего нескольких символов (<
и >
и других подобных символов или фраз, таких как script
) неэффективны и успешно атакованы. Даже непроверенный тег “<b>”
в некоторых контекстах небезопасен. XSS имеет удивительное количество вариантов, позволяющих легко обойти проверку черного списка. В другом решении говорилось, что сильная кодировка вывода. Перед визуализацией убедитесь, что все предоставленные пользователем данные закодированы соответствующим образом (в HTML или XML в зависимости от механизма вывода). Итак, каков наилучший способ предотвратить межсайтовые сценарии для проверки и замены ввода или кодирования вывода?
Лучшие практики Java для предотвращения межсайтовых сценариев
Ответы (3)
Обычной практикой является HTML-экранирование любых управляемых пользователем данных во время повторного отображения в JSP, а не во время обработки отправленных данных в сервлете или во время < em>сохранение в БД. В JSP вы можете использовать JSTL (чтобы установить его, просто поместите jstl-1.2.jar в /WEB-INF/lib
) < тег href="http://java.sun.com/products/jsp/jstl/1.1/docs/tlddocs/c/out.html" rel="noreferrer"><c:out>
или fn:escapeXml
для этого. Например.
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
...
<p>Welcome <c:out value="${user.name}" /></p>
и
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>
...
<input name="username" value="${fn:escapeXml(param.username)}">
Вот и все. Черный список не нужен. Обратите внимание, что данные, контролируемые пользователем, охватывают все данные, поступающие по HTTP-запросу: параметры запроса, тело и заголовки (!!).
Если вы HTML-экранируете его во время обработки отправленных данных и/или сохранения в БД, то все это распространяется по бизнес-коду и/или в базе данных. Это только проблемы с обслуживанием, и вы рискуете получить двойное экранирование или больше, когда делаете это в разных местах (например, &
станет &amp;
вместо &
, так что конечный пользователь буквально увидит &
вместо &
в поле зрения. Бизнес-код и БД находятся в поворот не чувствителен к XSS. Только представление. Вы должны избегать его только прямо здесь в представлении.
Смотрите также:
Jsoup#clean()
для удаления потенциально вредоносного HTML из строки. См. также stackoverflow.com/questions/7722159/
- person BalusC; 04.10.2012
Используйте оба. На самом деле обратитесь к такому руководству, как памятка OWASP XSS Prevention, на возможные случаи использования кодирования вывода и проверки ввода.
Проверка ввода помогает, когда вы не можете полагаться на кодировку вывода в определенных случаях. Например, вам лучше проверять входные данные, появляющиеся в URL-адресах, а не кодировать сами URL-адреса (Apache не будет обслуживать URL-адрес, закодированный в URL-адресе). Или, если на то пошло, проверьте входные данные, которые появляются в выражениях JavaScript.
В конечном счете, поможет простое эмпирическое правило: если вы недостаточно доверяете пользовательскому вводу или подозреваете, что определенные источники могут привести к XSS-атакам, несмотря на кодировку вывода, проверьте его по белому списку.
Взгляните на исходный код OWASP ESAPI, чтобы узнать, как работают выходные кодировщики и входные валидаторы. написано в библиотеке безопасности.
Я предпочитаю кодировать все небуквенно-цифровые символы как объекты числовых символов HTML. Поскольку почти, если не все атаки требуют неалфавитных символов (таких как ‹, и т. д.), это должно устранить большую часть опасного вывода.
Формат — N;, где N — числовое значение символа (вы можете просто привести символ к типу int и объединить его со строкой, чтобы получить десятичное значение). Например:
// java-ish pseudocode StringBuffer safestrbuf = new StringBuffer(string.length()*4); foreach(char c : string.split() ){ if( Character.isAlphaNumeric(c) ) safestrbuf.append(c); else safestrbuf.append(""+(int)symbol);
Вы также должны быть уверены, что кодируете непосредственно перед выводом в браузер, чтобы избежать двойного кодирования или кодирования для HTML, но с отправкой в другое место.