HTML Diff
0 added 0 removed
Original 2026-01-01
Modified 2026-02-26
1 <p>Проблемы с безопасностью могут привести к утечке данных пользователей или даже к полному уничтожению сайта. Исследования показывают, что большинство сайтов имеют проблемы с безопасностью и уязвимостью к атакам. Время от времени случаются громкие взломы и утечки данных сотен тысяч и миллионов пользователей.</p>
1 <p>Проблемы с безопасностью могут привести к утечке данных пользователей или даже к полному уничтожению сайта. Исследования показывают, что большинство сайтов имеют проблемы с безопасностью и уязвимостью к атакам. Время от времени случаются громкие взломы и утечки данных сотен тысяч и миллионов пользователей.</p>
2 <p>Безопасность веб-приложений - важная тема, которой мы уделим весь этот урок.</p>
2 <p>Безопасность веб-приложений - важная тема, которой мы уделим весь этот урок.</p>
3 <h2>Главное правило безопасности</h2>
3 <h2>Главное правило безопасности</h2>
4 <p>Оно звучит так:</p>
4 <p>Оно звучит так:</p>
5 <blockquote><p>Никогда не доверяйте пользователям</p>
5 <blockquote><p>Никогда не доверяйте пользователям</p>
6 </blockquote><p>В первую очередь, это правило касается данных, которые пользователи вводят на сайте. Предположим, что у нас есть страница профиля пользователя, где выводится его ник, взятый из адресной строки:</p>
6 </blockquote><p>В первую очередь, это правило касается данных, которые пользователи вводят на сайте. Предположим, что у нас есть страница профиля пользователя, где выводится его ник, взятый из адресной строки:</p>
7 <p>Когда код реализует эту функциональность, он рассчитывает, что в адресе используются только допустимые имена. А теперь попробуем открыть такой адрес:</p>
7 <p>Когда код реализует эту функциональность, он рассчитывает, что в адресе используются только допустимые имена. А теперь попробуем открыть такой адрес:</p>
8 <p>Если мы доверимся данным от пользователей и откроем такой адрес, случится вот это:</p>
8 <p>Если мы доверимся данным от пользователей и откроем такой адрес, случится вот это:</p>
9 <p>В этом адресе<a>закодирован</a>JavaScript-код, который в оригинале выглядит так:</p>
9 <p>В этом адресе<a>закодирован</a>JavaScript-код, который в оригинале выглядит так:</p>
10 <p>Проблема в том, что код не отобразился, но попал в HTML страницы и выполнился. Так произошло, потому что для браузера такой JavaScript-код выглядит как часть страницы.</p>
10 <p>Проблема в том, что код не отобразился, но попал в HTML страницы и выполнился. Так произошло, потому что для браузера такой JavaScript-код выглядит как часть страницы.</p>
11 <p>Если открыть получившийся HTML, то он будет выглядеть так:</p>
11 <p>Если открыть получившийся HTML, то он будет выглядеть так:</p>
12 <p>Именно так происходит XSS-атака (<a>межсайтовый скриптинг</a>). На страницу внедряется вредоносный код, который выполняется в браузере пользователя и отправляет информацию о пользователе на сервер злоумышленника. XSS - это одна из самых распространенных атак. Очень много подобных уязвимостей есть даже на сайтах больших компаний.</p>
12 <p>Именно так происходит XSS-атака (<a>межсайтовый скриптинг</a>). На страницу внедряется вредоносный код, который выполняется в браузере пользователя и отправляет информацию о пользователе на сервер злоумышленника. XSS - это одна из самых распространенных атак. Очень много подобных уязвимостей есть даже на сайтах больших компаний.</p>
13 <p>Специфика подобных атак в том, что вредоносный код может использовать авторизацию пользователя в веб-системе. Так злоумышленник может получить расширенный доступ к системе или логины и пароли пользователей. Если в исходном коде встречается конструкция &lt;текст&gt;, то браузер автоматически считает ее тегом.</p>
13 <p>Специфика подобных атак в том, что вредоносный код может использовать авторизацию пользователя в веб-системе. Так злоумышленник может получить расширенный доступ к системе или логины и пароли пользователей. Если в исходном коде встречается конструкция &lt;текст&gt;, то браузер автоматически считает ее тегом.</p>
14 <p>Вернемся к коду из начала урока:</p>
14 <p>Вернемся к коду из начала урока:</p>
15 <p>Здесь мы выводим слаг без какой-либо предварительной обработки. В таком случае браузер пытается интерпретировать как HTML все, что похоже на HTML. Любой пользователь может внедрить на сайт исполняемый JavaScript-код без нашего ведома. Другими словами, мы проявили доверие к пользовательским данным и создали уязвимость.</p>
15 <p>Здесь мы выводим слаг без какой-либо предварительной обработки. В таком случае браузер пытается интерпретировать как HTML все, что похоже на HTML. Любой пользователь может внедрить на сайт исполняемый JavaScript-код без нашего ведома. Другими словами, мы проявили доверие к пользовательским данным и создали уязвимость.</p>
16 <p>Чтобы закрыть ее, нужно использовать не сами теги, а HTML-эквиваленты символов. Тогда код выше начнет выглядеть так:</p>
16 <p>Чтобы закрыть ее, нужно использовать не сами теги, а HTML-эквиваленты символов. Тогда код выше начнет выглядеть так:</p>
17 <p>Здесь мы заменили:</p>
17 <p>Здесь мы заменили:</p>
18 <ul><li>&lt; на &amp;lt;</li>
18 <ul><li>&lt; на &amp;lt;</li>
19 <li>&gt; на &amp;gt;</li>
19 <li>&gt; на &amp;gt;</li>
20 </ul><p>Это не экранирование, а именно замена спецсимволов на их HTML-эквиваленты. Если открыть браузер, то там мы увидим правильное отображение:</p>
20 </ul><p>Это не экранирование, а именно замена спецсимволов на их HTML-эквиваленты. Если открыть браузер, то там мы увидим правильное отображение:</p>
21 <p>Замена символов на спецсимволы выполняется с помощью<a>commons-text</a>и других специальных библиотек. Один из вариантов выглядит так:</p>
21 <p>Замена символов на спецсимволы выполняется с помощью<a>commons-text</a>и других специальных библиотек. Один из вариантов выглядит так:</p>
22 <p>Метод StringEscapeUtils.escapeHtml4() принимает на вход HTML и заменяет в нем все спецсимволы на их HTML-эквиваленты. Остальные символы остаются без изменений.</p>
22 <p>Метод StringEscapeUtils.escapeHtml4() принимает на вход HTML и заменяет в нем все спецсимволы на их HTML-эквиваленты. Остальные символы остаются без изменений.</p>
23 <p>Через такую обработку нужно пропускать любые данные, которые мы выводим. Исключение составляют лишь ситуации, в которых мы точно знаем, что в данных есть HTML и мы его хотим отобразить. К таким данным могут относиться статьи в блоге, потому что они содержат HTML-часть. Например, так работает блог Хекслета.</p>
23 <p>Через такую обработку нужно пропускать любые данные, которые мы выводим. Исключение составляют лишь ситуации, в которых мы точно знаем, что в данных есть HTML и мы его хотим отобразить. К таким данным могут относиться статьи в блоге, потому что они содержат HTML-часть. Например, так работает блог Хекслета.</p>
24 <p>Но даже внутрь безопасного HTML можно добавить вредоносный JavaScript-код. Вряд ли подобным будут заниматься сотрудники компании, но это могут сделать внешние авторы. Попробуем устранить эту уязвимость. В этом поможет механизм, который вырезает из HTML все &lt;script&gt; и другие опасные теги.</p>
24 <p>Но даже внутрь безопасного HTML можно добавить вредоносный JavaScript-код. Вряд ли подобным будут заниматься сотрудники компании, но это могут сделать внешние авторы. Попробуем устранить эту уязвимость. В этом поможет механизм, который вырезает из HTML все &lt;script&gt; и другие опасные теги.</p>
25 <p>Рассмотрим пример с библиотекой<a>java-html-sanitizer</a>:</p>
25 <p>Рассмотрим пример с библиотекой<a>java-html-sanitizer</a>:</p>
26 <p>Главная проблема этих подходов в том, что об этом нужно постоянно думать. На практике разработчики часто забывают обрабатывать данные, и мы получаем уязвимые сайты. Автоматическое преобразование решило бы эту проблему.</p>
26 <p>Главная проблема этих подходов в том, что об этом нужно постоянно думать. На практике разработчики часто забывают обрабатывать данные, и мы получаем уязвимые сайты. Автоматическое преобразование решило бы эту проблему.</p>
27 <p>Безопасность по умолчанию - это ключевой подход в создании надежных приложений. Один из способов ее обеспечить - использовать JTE или другие качественные шаблонизаторы. Они обрабатывают все данные внутри своих шаблонов и автоматически защищают от XSS-атак.</p>
27 <p>Безопасность по умолчанию - это ключевой подход в создании надежных приложений. Один из способов ее обеспечить - использовать JTE или другие качественные шаблонизаторы. Они обрабатывают все данные внутри своих шаблонов и автоматически защищают от XSS-атак.</p>