Чем искать уязвимости веб-приложений: сравниваем восемь популярных сканеров

Как защититься от XSS

К нашему огромному счастью, есть простой универсальный инструмент — функция htmlspecialchars() или её иногда применяемый аналог htmlentities().


Как это работает. В HTML есть такая штука как сущности или мнемоники. Это когда я пишу прямо в HTML определённую последовательность символов, например ©, а браузер отображает соответствующий этой мнемонике символ, в данном случае значок копирайта .

Попробуй сам:

Так вот. Когда мы запускаем функцию htmlspecialchars(), она берёт нашу строку и заменяет некоторые символы в ней (кавычки, угловые скобки и т.д.) на мнемоники, чтобы браузер гарантированно вывел нашу строку на экран как строку, не пытаясь выполнять её как код.

Т.е. когда мы введём в нашу форму текст <script>alert(‘hello’)</script>, функция htmlspecialchars() превратит его в &lt;script&gt;alert(‘hello’)&lt;/script&gt;. Разумеется, браузер уже не воспримет такой код как javascript и просто выведет на экран как есть.

Проверим:

Теперь какой бы javascript код мы не пытались подставить, он будет просто выводиться в браузер как строка.

How Cross-site Scripting Works

There are two stages to a typical XSS attack:

  1. To run malicious JavaScript code in a victim’s browser, an attacker must first find a way to inject malicious code (payload) into a web page that the victim visits.
  2. After that, the victim must visit the web page with the malicious code. If the attack is directed at particular victims, the attacker can use social engineering and/or phishing to send a malicious URL to the victim.

For step one to be possible, the vulnerable website needs to directly include user input in its pages. An attacker can then insert a malicious string that will be used within the web page and treated as source code by the victim’s browser. There are also variants of XSS attacks where the attacker lures the user to visit a URL using social engineering and the payload is part of the link that the user clicks.

The following is a snippet of server-side pseudocode that is used to display the most recent comment on a web page:

The above script simply takes the latest comment from a database and includes it in an HTML page. It assumes that the comment printed out consists of only text and contains no HTML tags or other code. It is vulnerable to XSS, because an attacker could submit a comment that contains a malicious payload, for example:

The web server provides the following HTML code to users that visit this web page:

When the page loads in the victim’s browser, the attacker’s malicious script executes. Most often, the victim does not realize it and is unable to prevent such an attack.

Хеширование паролей и авторизация

Для хеширования паролей в PHP существует функция password_hash():

Вторым параметром передаётся алгоритм хеширования. По-умолчанию это указанный нами bcrypt, но я рекомендую указывать его вручную, поскольку базовый алгоритм в будущем может поменяться. Будет грустно, если при очередном обновлении версии PHP на сайте отвалится авторизация.

Для проверки корректности введённого пользователем пароля используется функция password_verify():


Ещё раз. При регистрации пользователя нужно передать пароль в функцию password_hash(), а полученный хеш сохранить в базу данных.

При попытке авторизации получаем пользователя по его логину и проверяем функцией password_verify(), соответствует ли хеш пароля тому паролю, который ввёл пользователь.

Таким образом, хранить исходный пароль больше нет смысла.

Да, разные алгоритмы хеширования генерируют хеш разной длины, поэтому рекомендуется хранить хеш в поле с типом VARCHAR(255).

Эффективная защита

Избегать перезаписи документа на стороне клиента, переадресацию или другие подобные действия, использующие данные на стороне клиента. Большинство этих действий может быть выполнено с использованием динамических страниц (на стороне сервера). Анализ и повышение защищенности кода (Javascript) на стороне клиента. Ссылки на объекты DOM, на которые может влиять пользователь (атакующий), должны быть тщательно проверены

Особое внимание нужно уделять следующим объектам (но не ограничиваться ими): document.URL document.URLUnencoded document.location (и его свойства) document.referrer window.location (и его свойства) Обратите внимание: на свойства объектов document и window можно сослаться несколькими способами: явно (пример — window.location), неявно (пример — location) или через получения дескриптора и использования его (пример — handle_to_some_window.location). Особое внимание нужно уделить коду, где модифицируется DOM, явно или есть потенциальная возможность, а также через прямой доступ к HTML или через доступ непосредственно к DOM. Примеры (это ни в коем случае не исчерпывающий список): Запись в HTML код страницы: document.write(…) document.writeln(…) document.body.innerHtml=… Изменение DOM напрямую (включая события DHTML): document.forms.action=… (и другие вариации) document.attachEvent(…) document.create…(…) document.execCommand(…) document.body

… (доступ к DOM через объект body) window.attachEvent(…) Изменение URL документа: document.location=… (а также присвоение значений href, host и hostname объекта location) document.location.hostname=… document.location.replace(…) document.location.assign(…) document.URL=… window.navigate(…) Открытие/модификация объекта window: document.open(…) window.open(…) window.location.href=… (а также присвоение значения host и hostname объекта location) Выполнение скрипта напрямую: eval(…) window.execScript(…) window.setInterval(…) window.setTimeout(…) В продолжение вышеупомянутого примера, для эффективной защиты оригинальный скрипт может быть заменен следующим кодом, который проверяет строку, записываемую в HTML страницу на наличие только алфавитно-цифровых символов.   Такая функциональности может быть (и, наверное, должна быть) реализована через универсальную библиотеку контроля данных (т.е. через набор функций Javascript, осуществляющий проверку/модификацию входных данных). Минусом этого способа является то, что принцип работы защиты доступен атакующим, т.к. защита реализована в HTML коде. Это упрощает анализ и планирование атаки. В примере выше ситуация достаточно простая, тогда как проверки защиты в более сложных скриптах далеки от совершенства, что дает возможность поиска путей обхода защиты. Использовать строгие правила IPS, в которых, к примеру, странице welcome.html разрешено получать один единственный параметр, имеющий имя “name”, значение которого проверяется, и любое несоответствие (включая избыточные параметры или отсутствие параметров) приводит к отказу в обслуживании оригинальной страницы, также как и любое другой нарушение (например, заголовки Authorization или Referer, содержащие проблематичные данные). Хотя в некоторых случаях даже такие меры не гарантируют полную защиту от атаки.

Sometimes the XSS payload can persist

In the attack we described above, the web server echoes back the XSS payload to the victim right away. But it is also possible for the server to store the attacker-supplied input (the XSS payload) and serve it to the victim at a later time. This is called a «stored XSS».

Below we illustrate a basic example using a demo social networking site. Go ahead, enter some text and share your status in the demo application below.

Demo application 2:

Next, try this:

  1. Enter
  2. Share your status.
  3. You should see a pop-up alert! You’ll see the alert again if you refresh the page or share another status message.

Now, enter and hit ‘Share status!’.

The session ID for this application (a contrived one that is probably ‘123412341234’) will pop up! An attacker could use XSS exploit code to collect this session ID, and try to impersonate the owner of the account.

Note: To reset the application and get rid of the annoying pop-ups, click the «Clear all posts» button.

What else can you do besides popping up alerts or stealing session IDs? You can pretty much do anything JavaScript allows. Try entering the following:

Spooky, huh? In this example, an evil JavaScript file was retrieved and embedded via XSS.

DDOS

Ситуация та же. Любой пользователь любым образом имеет возможность добавить в текст сообщения изображение со стороннего сайта, которое будет доступно всем, открывающим эту html страницу

Теперь, допустим, в третьем сайте, имеется любая уязвимость – некоторый документ при некоторых параметронах потребляет слишком много системных ресурсов.

В первую очередь я имею ввиду SQL инъекцию, с возможностью внедрения benchmark() функции, таким образом, что один запрос сильно нагрузит уязвимый сервер.

Об уязвимости типа SQL инъекция и в том числе об использовании фунункции benchmark в SQL запросе для проведения DOS атаки, рассказано в этой статье http://www.securitylab.ru/45438.html

Размещая в рассматриваемом форуме (предполагаем, что он имеет большую посещаемость), большое количество сообщений, содержащих изображения с URL-ом на самом деле эксплуатирующую уязвимость в третьем сайте.

Этот метод атаки, на первый взгляд кажется не эффективным по нескольким причинам.

Не во всех случаях удастся поставить такой URL в качестве ссылки на изображение по той причине, что различные фильтры не сервере могут заблокировать сложный URL.

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

Однако, используя следующий прием, можно свести к нулю оба этих замечания.

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

Лучше всего для таких целей подходит ссылка на аватар.

После того, как накоплена значительная база таких сообщений, скрипт, ранее, возвращающий содержимое изображения, станет возвращать заголовок HTTP ответа 301 – moved, с указанным в Location заголовке URL, эксплуатирующим уязвимость в третьем сайте.

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

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

Когда htmlspecialchars() не помигает

Теперь рассмотрим другую ситуацию. К примеру, в некоторой системе (форуме), некоторыми методами в каждом сообщении можно оставить ссылку (

 <a href=…>…</a>

Так, например, может использоваться слеующие конструкции ….

Значение URL находится в двойных кавычках, все опасные символы, такие, как кавычки, знаки больше меньше, фильтруются любым образом, перед вставкой значения в качестве URL.

Например, для вывода собственно URL ссылки и текста ссылки используется функция наподобие функции PHP htmlspecialchars().

Таким образом, выбраться за пределы атрибута href, невозможно. И невозможно изменить реакции на события OnMouseClick или OnMouseOver.

Другими словами, казалось бы, уязвимость отсутствует.

Однако, что если сделать вот так?

 
click me
<a href=”javascript:alert(document.cooke)”>click me</a>

В частности, это может использоваться для кражи COKIE целевого пользователя.

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

Например, пробелы в JavaScript коде, могут замениться на последовательности /**/.

А от использования кавычек спасет функция string.fromCharCode(), которая принимает коды символов и возвращает строку.

Для исключения этой уязвимости достаточно фильтровать слово script в URL ссылки.

Is Your Website or Web Application Vulnerable to Cross-site Scripting

Cross-site Scripting vulnerabilities are one of the most common web application vulnerabilities. The OWASP organization (Open Web Application Security Project) lists XSS vulnerabilities in their OWASP Top 10 2017 document as the second most prevalent issue.

Fortunately, it’s easy to test if your website or web application is vulnerable to XSS and other vulnerabilities by running an automated web scan using the Acunetix vulnerability scanner, which includes a specialized XSS scanner module. Take a demo and find out more about running XSS scans against your website or web application. An example of how you can detect blind XSS vulnerabilities with Acunetix is available in the following article: How to Detect Blind XSS Vulnerabilities.

Сбор статистики

Представим себе систему, например, форум, в котором возможно в сообщения каким либо образом можно вставлять изображения со сторонних сайтов.

Так, например, на многих форумах, вставить изображение можно используя конструкцию http://site/image

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

Теперь представим себе, что вместо изображение находиться некоторый скрипт http://site/image.php, который делает следующее

  1. охраняет информацию о запросе
  2. выводит заголовок: Content-type: image/jpeg (для PJEG изображения)
  3. выводит собственно, содержание изображения.

Теперь, учитывая, что в большинстве случаев в качестве поля HTTP-REFERER, HTTP запроса при запросе картинок, броузер отсылает URL документа, на котором вставлена картинка, то при помощи скрипта можно собрать следующие данные

  1. IP адрес (включая заголовки X-FORWARDED_FOR и тп.)
  2. Каждую страницу, посещенную каждым пользователем (при условии, что на ней имеется ссылка на данное изображение)
  3. Поле User-Agent пользователя

Наверное, результативнее всего для сбора статистики в большинстве форумов, такой URL изображения, следует задать в качестве URL-а аватара. Можно бы было предположить, что для того, чтобы исключить такую возможность, на сервере можно разрешить размещение только изображений, имеющих соответствующее расширение файла — .jpg или только .gif Однако, излишне любопытный пользователь сможет настроить HTTP сервер таки образом, чтобы файлы .jpg к примеру, тоже считались и обрабатывались как PHP скрипты.

Более того, PHP может быть сконфигурирован таким образом, что никакая информация об интерпретаторе PHP не посылалась в заголовке HTTP ответа. Таким образом, подобный сбор статистики может быть реализован абсолютно прозрачно для сервера и клиентов.

Никакими методами невозможно узнать, имеет место подобный сбор статистики или нет.

Конечно, всю эту информация можно собрат и из логов HTTP сервера, на котором находится такое “изображение”, но ведение логов в скрипте кажется мне более избирательным.

Cross-site Scripting Attack Vectors

The following is a list of common XSS attack vectors that an attacker could use to compromise the security of a website or web application through an XSS attack. A more extensive list of XSS payload examples is maintained by the OWASP organization: XSS Filter Evasion Cheat Sheet.

<script> tag

The tag is the most straightforward XSS payload. A tag can reference external JavaScript code or you can embed the code within the tag itself.

<body> tag


An XSS payload can be delivered inside the by using event attributes (see above) or other more obscure attributes such as the attribute.

<img> tag

<iframe> tag

The tag lets you embed another HTML page in the current page. An IFrame may contain JavaScript but JavaScript in the IFrame does not have access to the DOM of the parent page due to the Content Security Policy (CSP) of the browser. However, IFrames are still very effective for pulling off phishing attacks.

<input> tag

<link> tag

<table> tag

<div> tag

<object> tag

Общая классификация XSS

Четкой классификации для межсайтового скриптинга не существует, но экспертами по всему миру выделено три основных типа.

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

Отраженные XSS (непостоянные). В этом случае вредоносная строчка выступает в роли запроса жертвы к зараженному веб-сайту. Работает этот принцип по следующей схеме:

DOM-модели. В этом варианте возможно использование как хранимых XSS, так и отраженных. Суть заключается в следующем:

  1. Злоумышленник создает URL-адрес, который заранее содержит вредоносный код, и отправляет его по электронной почте или любым другим способом пользователю.
  2. Человек переходит по этой ссылке, зараженный сайт принимает запрос, исключая вредоносную строку.
  3. На странице у пользователя выполняется сценарий, в результате чего загружается вредоносный скрипт и злоумышленник получает cookies.

Use a template system with context-aware auto-escaping

The simplest and best means to protect your application and your users from XSS bugs is to use a web template system or web application development framework that auto-escapes output and is context-aware.

«Auto-escaping» refers to the ability of a template system or web development framework to automatically escape user input in order to prevent any scripts embedded in the input from executing. If you wanted to prevent XSS without auto-escaping, you would have to manually escape input; this means writing your own custom code (or call an escape function) everywhere your application includes user-controlled data. In most cases, manually escaping input is not recommended; we’ll discuss manual escaping in the next section.

«Context-aware» refers to the ability to apply different forms of escaping based on the appropriate context. Because CSS, HTML, URLs, and JavaScript all use different syntax, different forms of escaping are required for each context. The following example HTML template uses variables in all of these different contexts:

As you can see, trying to manually escape input for various contexts can be very difficult. You can read more about context-aware auto-escaping here. Go Templates, Google Web Toolkit (GWT) with SafeHtml, Closure Templates, and CTemplate all provide context-aware auto-escaping so that variables are correctly escaped for the page context in which they appear. If you are using templates to generate HTML within JavaScript (a good idea!) Closure Templates and Angular provide built-in escaping capabilities.

Learn the best practices for your technology

The following best practices can help you reduce XSS vulnerabilities in your code for specific technologies.

  • JavaScript: Many XSS vulnerabilities are caused by passing user data to Javascript execution sinks; browser mechanisms that will execute scripts from their input. Such APIs include , and . When user-controlled data (in the form of , or JavaScript variables containing user data) is returned by the server, calling such functions can lead to XSS.
  • JSON: Make sure you apply proper escaping (including HTML-escaping of characters such as and ). Do not allow user-supplied data to be returned as the first part of the response (as often happens in JSONP). Do not use to parse the data.
  • Flash: Consider hosting SWF files in a separate domain.
  • GWT: Follow the guidelines in the GWT Developer’s Guide on SafeHtml. In particular, avoid the use of APIs that interpret plain String-typed values as HTML and prefer the SafeHtml-variants where available. For example, prefer over .
  • HTML sanitization: If you need to support user-supplied markup such as images or links, look for technologies that support HTML sanitization. For example, Caja includes an html-sanitizer written in Javascript that can be used to remove potentially executable Javascript from a snippet of HTML.

Примечания[править | править код]

  1. ↑  (недоступная ссылка)
  2.  (англ.). The Open Web Application Security Project (OWASP). Дата обращения 26 декабря 2014.
  3. , p. 290, 379.
  4.  (англ.). W3C. Дата обращения 18 декабря 2014.
  5. Grossman, Jeremiah. . (англ.)
  6. , p. 3.
  7. Mirkov, Denis. . Хакер (21 сентября 2010). Дата обращения 18 декабря 2014.
  8. Mirkov, Denis. . Хакер (10 марта 2011). Дата обращения 18 декабря 2014.
  9. Mirkov, Denis. . Хакер (25 сентября 2006). Дата обращения 18 декабря 2014.
  10. Mirkov, Denis. . Хакер (23 июля 2008). Дата обращения 18 декабря 2014.
  11. Mirkov, Denis. . Хакер (26 мая 2008). Дата обращения 18 декабря 2014.
  12. , p. 128.
  13.  (англ.). Web Application Security Consortium (2005). Дата обращения 18 декабря 2014.
  14.  (англ.). JQuery. Дата обращения 18 декабря 2014.
  15.  (англ.). The Open Web Application Security Project (OWASP). Дата обращения 18 декабря 2014.
  16.  (англ.). AngularJS. Дата обращения 18 декабря 2014.
  17. ↑  (англ.). The Open Web Application Security Project (OWASP). Дата обращения 18 декабря 2014.
  18.  (англ.). Bugzilla@Mozilla. Дата обращения 18 декабря 2014.
  19. Boerwinkel, Martijn.  (англ.). seclists.org (26 May 2002). Дата обращения 18 декабря 2014.
  20. Стандартная функция PHP по умолчанию не экранирует апостроф, и в сочетании с кодом получается уязвимость.
  21. . Веб-разработка. Дата обращения 18 декабря 2014.
  22.  (англ.). Web Hypertext Application Technology Working Group (WHATWG). Дата обращения 18 декабря 2014.
  23. Например, движок MediaWiki кэширует HTML-код страниц.
  24. Kochetkov, Vladimir. . SecurityLab (8 августа 2012). Дата обращения 18 декабря 2014.
  25. . PHP. Дата обращения 18 декабря 2014.
  26.  (англ.). PHP. Дата обращения 18 декабря 2014.
  27. . The Open Web Application Security Project (OWASP). Дата обращения 18 декабря 2014.
  28.  (англ.). The Open Web Application Security Project (OWASP). Дата обращения 18 декабря 2014.

Frequently asked questions

How does Cross-site Scripting work?

In a Cross-site Scripting attack (XSS), the attacker uses your vulnerable web page to deliver malicious JavaScript to your user. The user’s browser executes this malicious JavaScript on the user’s computer. Note that about one in three websites is vulnerable to Cross-site scripting.

Why is Cross-site Scripting dangerous?

Even though a Cross-site Scripting attack happens in the user’s browser, it may affect your website or web application. For example, an attacker may use it to steal user credentials and log in to your website as that user. If that user is an administrator, the attacker gains control over your website.

How to discover Cross-site Scripting?

To discover Cross-site Scripting, you may either perform manual penetration testing or first use a vulnerability scanner. If you use a vulnerability scanner, it will save you a lot of time and money because your penetration testers can then focus on more challenging vulnerabilities.

How to protect against Cross-site Scripting?

To protect against Cross-site Scripting, you must scan your website or web application regularly or at least after every chance in the code. Then, your developers must correct the code to eliminate the vulnerability. Contrary to popular opinions, web application firewalls do not protect against Cross-site Scripting, they just make the attack more difficult – the vulnerability is still there.

Справочная информация

Безопасность в Интернете обеспечивается с помощью многих механизмов, в том числе важной концепцией, известной как правило ограничения домена. Это правило разрешает сценариям, находящимся на страницах одного сайта (https://mybank.example.com), доступ к методам и свойствам друг друга без ограничений, но предотвращает доступ к большинству методов и свойств для страниц другого сайта (https://othersite.example.com) (недоступная ссылка).. Межсайтовый скриптинг использует известные уязвимости в web-приложениях, серверах (или в системных плагинах, относящихся к ним)

Используя одну из них, злоумышленник встраивает вредоносный контент в содержание уже взломанного сайта. В результате пользователь получает объединенный контент в веб-браузере, который был доставлен из надежного источника, и, таким образом, действует в соответствии с разрешениями, предоставленными для этой системы. Сумев внедрить необходимый скрипт в веб-страницу, злоумышленник может получить повышенные привилегии в отношении работы с веб-страницами, cookies и другой информацией, хранящейся в браузере для данного пользователя.

Межсайтовый скриптинг использует известные уязвимости в web-приложениях, серверах (или в системных плагинах, относящихся к ним). Используя одну из них, злоумышленник встраивает вредоносный контент в содержание уже взломанного сайта. В результате пользователь получает объединенный контент в веб-браузере, который был доставлен из надежного источника, и, таким образом, действует в соответствии с разрешениями, предоставленными для этой системы. Сумев внедрить необходимый скрипт в веб-страницу, злоумышленник может получить повышенные привилегии в отношении работы с веб-страницами, cookies и другой информацией, хранящейся в браузере для данного пользователя.

Выражение «межсайтинговый скриптинг» первоначально означало взаимодействие уязвимого веб-приложения с сайтом злоумышленника таким образом, чтобы в контексте атакуемого домена был выполнен JavaScript-код, подготовленный злоумышленником (отражённая или хранимая XSS уязвимость). Постепенно определение стало включать в себя и другие способы внедрения кода, включая использование устойчивых и не относящихся к JavaScript языков (например, ActiveX, Java, VBScript, Flash и даже HTML), создавая путаницу среди новичков в сфере информационной безопасности.

XSS уязвимости зарегистрированы и используются с середины 1990-x годов. Известные сайты, пострадавшие в прошлом, включают такие сайты социальных сетей, как , , MySpace, YouTube, и др.

What can I do to prevent XSS?

A common technique for preventing XSS vulnerabilities is «escaping». The purpose of character and string escaping is to make sure that every part of a string is interpreted as a string primitive, not as a control character or code.

For example, » is the HTML encoding for the » character. If you include:

in the HTML of a page, the script will execute. But if you include:

in the HTML of a page, it will print out the text «<script>alert(‘testing’)</script>», but it will not actually execute the script. By escaping the tags, we prevented the script from executing. Technically, what we did here is «encoding» not «escaping», but «escaping» conveys the basic concept (and we’ll see later that in the case of JavaScript, «escaping» actually is the correct term).

The following can help minimize the chances that your website will contain XSS vulnerabilities:

  • Using a template system with context-aware auto-escaping
  • Manually escaping user input (if it’s not possible to use a template system with context-aware auto-escaping)
  • Understanding common browser behaviors that lead to XSS
  • Learning the best practices for your technology

The rest of this section describes these measures in detail.


С этим читают