Основы анализа безопасности веб-проектов
Совсем недавно прошел на платформе Stepik курс "Анализ безопасности веб-проектов", от mail.ru. Этот пост представляет собой что-то вроде конспекта курса, который писался по мере прохождения, для того, чтобы проще было систематизировать информацию и обращаться к ней спустя какое-то время. Помимо содержимого курса, старался дополнять материал ссылками на показавшиеся интересными и полезными статьи/ресурсы для более глубокого знакомства с темой.
Общий подход курса - посмотреть на целевую систему со стороны злоумышленника. Для этого выделена определенная последовательность шагов - сбор информации, обзор возможных точек входа в целевую систему, поиск веб-уязвимостей, поиск уязвимостей со стороны клиента, пост-эксплуатация найденных уязвимостей.
В курсе освещаются (поверхностно, но достаточно, для общего понимания принципов и возможности углубиться самостоятельно) такие уязвимости и направления атаки, как локальное включение данных, инъекция команд, SQL-инъекции, CSRF, XSS и другие.
Перед тем, как перейти к основной части конспекта - хотелось бы оговорить две вещи:
- чтение данного поста не заменит прохождение самого курса, т.к. в нем есть весьма и весьма интересные задачи.
- если вы - автор/правообладатель курса и вы против публикации такого рода конспекта - напишите сюда.
Сбор информации
Для любой системы есть некая точка входа. Такой точкой может быть url-адрес, ip-адрес компьютера и т.п. Изначально мы должны постараться максимально расширить поверхность атаки, т.е. если точка входа - некое доменное имя - стоит узнать об имеющихся поддоменах, других доменах, принадлежащих той же организации и т.п. И если у первоначальной точки входа не было уязвимостей, возможно их удастся найти в других точках, входящих в поверхность атаки.
Для получения первоначальной информации о цели есть две группы методов: пассивный анализ и активный анализ.
- При пассивном анализе используются только общедоступные методы, "никто ничего не нарушает".
- Активный анализ может в том или ином виде спровоцировать реакцию системы безопасности целевой системы.
В пассивном анализе рассматриваются:
- Использование данных, получаемых через систему доменных имен (DNS, WhoIs)
- Поисковые системы
- Код клиентской части
- Содержимое robots.txt
- Используемые компоненты
- Социальные сети
Все это может дать некоторую информацию о цели
В ходе активного анализа рассматриваются:
- Подбор DNS-записей
- Подбор файловых путей
- Подбор пользователей
- Сканирование портов
DNS и Zonetransfer
Каждый компьютер, подключенный к сети обладает неким IP-адресом. Для того, чтобы при обращении клиента к серверу не пришлось указывать ip-адрес, существует система доменных имен. При обращении клиента к доменному имени сначала идет обращение к DNS-серверу, получение ответа от него, содержащего IP-адрес целевого сервера, затем идет обращение по полученному IP-адресу.
Для формирования запросов к DNS-серверу есть несколько полезных утилит:
nslookup [-q=ns|mx|afxr|txt] [name] [server]
-q - тип запроса
name - имя, которое хотим отрезолвить
server - DNS-сервер, через который хотим отправить запрос, необязательный параметр,
по умолчанию будут использованы указанные в настройках клиентской машины сервера
Также можно использовать другие утилиты:
dig [@server] [name] [type]
host [name] [server]
Для получения информации о других доменных именах, связанных с целевой системой (и включения их в поверхность атаки) можно получить список поддоменов данной доменной зоны. Такая задача называется zonetransfer. В большинстве случаев zonetransfer запрещают, но далеко не всегда.
Запрос может быть выполнен следующим образом (используется проект zonetransfer.me, созданный как раз для демонстрации этой возможности):
nslookup -q=ns zonetransfer.me - выдергиваем "авторитетные" dns-сервера для этой зоны
dig zonetransfer.me @dnsserver axfr - в качестве dnsserver указываем сервер, полученный на первом шаге.
Также можно использовать следующие команды под windows:
В командной строке (cmd):
nslookup
set type=ns (указываем, чтохотим увидеть только записи типа ns - DNS-сервера, поддерживающие зону)
zonetransfer.me <Enter> (получаем список DNS-серверов данной зоны)
server <имя первого DNS-сервера> (указываем, что теперь любые запросы программа отсылает ему)
ls -d zonetransfer.me (получаем вывод всего, что содержится в домене zonetransfer.me)
Как третий вариант - можно использовать веб-сервисы, например: http://www.digwebinterface.com/
WhoIs
Whois - предназначен для получения информации об определенном доменном имени.
Стандартная практика использования следующая:
nslookup <domain.com> - резолвим домен, получая IP-адрес
whois <ip из шага 1> - получаем сеть, к которой принадлежит этот ip-адрес, выявленные адреса можно включать в поверхность атаки
Если выполнить:
whois domain.com
то мы получим данные из базы регистратора доменных имен. Для российских доменных имен информация о владельце доменных имен на данный момент не отображается, но для старых доменных имен вполне можно найти исторические данные в интернете. В зоне .com такого ограничения нет.
Поисковые движки
Содержат массу полезной информации. У поисковых движков есть свой язык запросов, который можно использовать.
inurl: - позволяет задать паттерн, который должен встречаться в url
site: - позволяет искать все, относящееся к конкретному сайту
filetype: - позволяет определять типы документов по расширению (например можно искать все pdf на сайте)
cache: - в качестве параметр применяются url, поисковая машина вернет закешированную копию
Robots.txt
Содержит информацию о каталогах, которые должны/не должны быть индексированы поисковыми системами.
Среди запрещенных для поисковой машины каталогов часто можно найти специфические для безопасности каталоги (содержащие, например, адрес интерфейса администратора).
HTML-код
Может содержать массу интересной информации. В целом стоит обращать внимание на следующие моменты:
- комментарии - могут содержать массу интересной информации, например закомментированный код серверной части системы
- версии распространенных продуктов - позволяют понять "на чем" работает целевая система
- параметры - GET и POST-параметры, которые не используются по каким-либо причинам
- файлы и пути - расположение относительно корневой веб-директории
Сканирование портов
Цель - понять что еще находится на целевом сервере, помимо интересущей нас системы.
Для сканирования портов используем стандартную утилиту nmap:
nmap -sS -T4 -n <target>
-sS - посылать только syn и считать порт открытым если получен syn_ack
-n - не делать DNS-резолв, влияет на скорость работы
-T4 - тайминг между запросами, от этого зависит скорость сканирования
-vvv - вывод информации о найденных портах по ходу сканирования а не после его окончания
-p - сканировать все 65000 портов, а не только самые популярные
--reason - отображает причину, почему было принято решение о состоянии порта
По ссылке также есть довольно много примеров использования команды с разным набором параметров.
Точки входа в систему
Веб - приложение может принимать данные через:
- GET / POST методы
- Cookies
- Headers
- Hosts
- Data sources
Все эти входные данные могут быть модифицированы пользователем, при разработке это нужно всегда осознавать.
HTTP - протокол открытый, т.е. данные передаются без кодирования, любой запрос может быть без особых проблем воспроизведен вручную.
В ходе анализа как правило воспроизводится следующий цикл:
Для каждого параметра можно проверить состояние системы в трех ситуациях: когда есть данные, когда нет данных и ошибочное состояние (например, параметр неверного типа).
Интересные Header-ы
HTTP 1.1 отличает от HTTP 1.0 наличие header-а "Host". Это было введено для того, чтобы была возможность хостить несколько веб-серверов на одном физическом IP-адресе. Заголовок Host как и все остальные формируется клиентом.
Cookie - передаются в заголовку для сохранения состояния между сессиями.
Для того, чтобы определять IP-адрес пользователя, находящегося за прокси-сервером, был придуман служебный заголовок, который прокси-сервер дописывает: X-Forwarded-For. Некоторые разработчики надеются таким образом распознать реальный адрес клиента и отдают значению этого заголовка приоритет в обработке. Делают тем самым хуже себе, т.к. заголовок легко подделывается.
GET / POST запросы, их перехват и создание в консоли
Для анализа (и подмены "на лету") GET / POST запросов к серверу можно использовать т.н. перехватывающие прокси-сервера. Наиболее распространенные программы такого типа: OWASP ZAP, Burp Suite, Fiddler.
Для выполнения запросов можно подсоединиться к целевому веб-серверу, например так:
telnet ya.ru 80
GET / HTTP/1.1
Host: ya.ru
Для организации HTTPS-соединения можно сделать так:
openssl s_client -connect e.mail.ru:443
GET / HTTP/1.1
Host: e.mail.ru
В качестве более-удобных инструментов для общения с веб-сервером из консоли можно использовать wget (русскоязычная справка) и curl (русскоязычная справка).
Версия curl для windows: http://curl.haxx.se/download.html
Версия wget для windows: https://eternallybored.org/misc/wget/
wget -O - --header "headername:value" http://target.com
curl -H "headername:value" http://target.com
Неожиданно, но, используя curl через GET-метод также можно передавать тело запроса (не средствами браузера). Например, так:
curl -X GET -H "Content-Type: application/json" -d '{"the": "body"}' 'http://localhost/test/get.php'
Подробное обсуждение здесь.
Стоит помнить, что параметры в запросах часто передаются не в открытом виде, а , например закодированные в base64. В таком случае для их подмены нужно их расшифровать, подменить и зашифровать обратно по тому же алгоритму.
Уязвимости веб-приложений
Раскрытие служебных данных
Раскрытие данных - это ошибка системы, позволяющая злоумышленнику получить информацию относительно логики работы атакуемой системы, её настроек, внутренней архитектуры, имеющихся пользователей, текущего состояния - всего того, что само по себе не является целью злоумышленника, однако может привести к взлому в совокупности с другой уязвимостью.
Возможные данные:
- структура файловой системы
- пользователи
- исходный код
- внутренняя архитектура
- настройки
Причины раскрытия данных:
- ошибки приложения
- ошибки конфигурации
- системы контроля версий
- html-код
- "мусорные" файлы
Локальное включение файлов (LFI)
Локальное включение данных довольно часто используется веб-системами , представляет собой передачу через параметры имен локально существующих файлов и их отображение пользователю.
Например, так:
http://target.com/getpage.php?page=contacts.txt
Код такого рода часто используется для навигации по страницам сайта.
Зная структуру каталогов веб-сервера можно "попросить" его отобразить содержимое других файлов, например, содержащих пароли (/etc/password), примерно так:
http://target.com/getpage.php?page=../../../../../../etc/passwd
Если кроме загрузки файла и отображения его содержимого происходит еще и их интерпретация, можно заставить сервер рекурсивно включать файл и посмотреть что из этого получится :)
http://target.com/getpage.php?page=../getpage.php
Если разработчик добавляет расширение к файлу, т.е. при вызове
http://target.com/getpage.php?page=contacts
в коде будет добавлено расширение и отображено содержимое файла contacts.txt, то можно использовать null-byte - символ, обозначающий конец строки, чтобы обрезать расширение.
http://target.com/getpage.php?page=../../../../../../etc/passwd%00
Инъекция команд
Инъекция команд - это уязвимость, позволяющая выполнить непредусмотренную разработчиком (или даже любую системную) команду на сервере. Может быть выполнена, если в системе делается вызов какой-либо команды на базе параметров, пришедших от пользователя.
Пример:
http://hosttool.com/tools.php?host=1.2.3.4;pwd
Точка с запятой в данном случае будет разделителем и выполнится команда вида:
ping 1.2.3.4; pwd
В результате мы увидим не только результат команды ping, но и текущий каталог в системе.
http://hosttool.com/tools.php?host=1.2.3.4|pwd
Используя вертикальную черту, можно передавать stdout одной команды на stdin следующей команды, организуя "цепочку".
SQL инъекция
Представляет собой атаку, цель которой - модификация sql-запроса, выполняющегося на сервере базы данных. При успешном выполнении злоумышленник сможет выполнить на сервере команды.
Примером может быть запрос такого типа:
http://target.com/login.php?user=alex' OR 1=1
Основные подходы:
- сворачивание условия WHERE к истиностному результату при любых значениях параметров (' OR 1=1).
- присоединение к запросу результатов другого запроса (' UNION select ...)
- закомментирование части запроса (' --)
Клиентские атаки
В отличие от атак серверной части, для выполнения клиентских атак может быть нужно заставить пользователя совершить определенное действие, например, перейти по какой-то ссылке.
Same-origin policy - это механизм для защиты данных и методов, пришедших из разных источников.
"Одинаковость" источника определяется по трем признакам: протокол, домен, порт.
Одинаковыми считаются: http://example.com/ http://example.com/folder/ |
Разными считаются:
http://example.com/ https://example.com/ http://test.example.com/ http://example.com:8080/ http://otherexample.com/ |
Задача клиентских атак как раз сводится к тому, чтобы каким-либо образом обойти Same-origin policy.
CSRF (cross-site request forgery)
Основывается на идее, что страницы могут включать в себя данные из разных источников.
На контролируемом злоумышленником домене размещается ссылка, осуществляющая переход на сторонний сайт. При этом пользователь сайта-злоумышленника может быть авторизован на этом стороннем сайте.
Например, включив в код сайта-злоумышленника следующую строку, в случае, если пользователь авторизован на target.com, он может сам того не зная оставлять комментарии со спамом:
<img src="http://target.com/post_comment.php?text="spam"/>
Переделка GET запроса на POST-запрос на target.com не поможет, тогда злоумышленник добавит код вида:
<form action ='http://target.com/form.php'>
<input type=hidden name='id' value=1>
</form>
<script>submitForm()</script>
Для защиты следует использовать CSRF-токены - механизм "подписывания" форм по алгоритму, неизвестному злоумышленнику .При создании защиты от csrf распространенная ошибка - генерация предсказуемых security-токенов. Токены должны всегда создаваться на основе недоступной злоумышленнику информации (зашифровать имя пользователя в md5 - плохая идея!).
XSS (cross-site scripting)
Одна из наиболее часто используемых атак веб-приложений. Основывается на факте, что злоумышленник может вставлять свой код в ответ от веб-сервера пользователю. Основная задача атаки - обойти Same Origin Policy и получить доступ к данным и функционалу клиентской части веб-приложения в рамках пользовательской сессии и с правами ее пользователя.
Существует несколько основных подходов к осуществлению XSS - атак.
Reflected XSS -злоумышленник создает ссылку, которая использует найденную уязвимость, передает ее пользователю. Пользователь переходит на целевой веб-сервер и получает ответ, подконтрольный злоумышленнику. Таким образом браузер пользователя можно заставить выполнять какие-либо действия.
Выполняемый код может быть в составе ссылки, отправленной пользователю:
www.target.com/script.php?lang=en<script>alert(1)</script>
Чтобы пользователю не был виден активный элемент - ссылка может быть закодирована механизмом кодирования узлов (goo.gl и т.п.), шифровка параметров в base64 и т.п. Такие ссылки уже вызовут меньше подозрений у пользователя.
Stored XSS - способ реализации атаки, когда код размещается на ресурсе (например, пост с неотфильтрованным js-кодом в гостевой книге), после чего каждый пользователь, зашедший на страницу невольно выполняет этот код.
DOM-based XSS - не требует никаких обращений на сервер со стороны пользователя. Все предпосылки для создания XSS находится в самом браузере. Основывается на том, что в контексте самого браузера есть код, обрабатывающий параметры и содержащий ошибку. К примеру, если участок JS- кода имеет доступ к параметру url и на его основе формирует некий html-код на странице.
Стоит проверить наличие в коде страницы таких конструкций, как:
document.write()
document.writeln()
eval()
.innerHTML
Еще один важный момент - если на странице есть flash (.swf), то все, что приходит от swf также подлежит строгой валидации, о чем часто забывают
Основной способ защиты - правильная обработка всех входных и выходных данных. Множество векторов атаки описано здесь: http://html5sec.org/, стоит об этом помнить. Много полезного про XSS и то, как правильно строить защиту от него также описано в годной статье на хабре.
Инъекция заголовков (header injection)
В рамках HTTP-протокола заголовки разделяются друг от друга символом перевода каретки (%0d%0a). Если на сайте есть метод, позволяющий сгенерировать заголовок, содержащий символ перевода каретки, после этих символов можно поставить новый header.
Например, если есть некая страница: http://target.com?jump=<user input> при переходе на нее, генерирующая в ответе заголовок
...
Location: <user input>
то передав запрос вида:
http://target.com?jump=hell%0d%0aSet-Cookie: gotohell%3d1 получим в ответе:
...
Location: hell
Set-Cookie: gotohell = 1
...
Таким образом можно будет внедряя заголовки / куки осуществлять XSS-атаку в любом месте страницы.
Фиксация сессии (Session Fixation)
На данный момент эта уязвимость встречается достаточно редко. Эта уязвимость связана не с ошибками фильтрации данных, а носит архитектурный характер. Реализуется таким образом: есть сервер, который раздает полномочия на базе сессий. При первом заходе, когда пользователь еще не залогинился - ему уже выдается некая сессия. После того, как он вводит корректные логин и пароль, идентификатор сессии остается прежним, а сервер запоминает, что эта сессия теперь относится к этому пользователю.
Злоумышленник в таком сценарии создает сессию (просто зайдя на сайт и получив sessionid). Далее он передает в рамках какого-то запроса передает сессионный идентификатор пользователю. Пользователь заходит по этой ссылке, вводит свой логин и пароль, сессия при этом остается той же самой. Теперь злоумышленник, используя тот же sessionid имеет права доступа, как у пользователя.
На практике сессии обычно хранятся в cookies-переменных. Таким образом злоумышленнику надо найти уязвимость, которая позволит пользователю добавить некое cookies-значение, например описанную выше header injection. Как вариант можно попробовать передать значение сессии через GET / POST параметр в надежде, что код на стороне сервера не анализирует источник, а работает с неким глобальным массивом, содержащим GET, POST, COOKIE параметры.
Пост-эксплуатация
Пост-эксплуатация - это то, что можно сделать с целевой системой после того, как удалось найти уязвимость и выполнить какой-то участок кода на целевой системе.
Основные паттерны, по которым работают злоумышленники предполагают:
- получить доступ на выполнение (желательно в реальном времени)
- изучение данных, хранящихся на сервере
- перехват данных, которых нет на системе сейчас, но они могут появиться в будущем
- организация перманентного доступа к целевой системе
Злоумышленник может получать информацию о скомпрометированной системе, анализируя:
- конфигурацию системы (логин и пароль к БД в исходных кодах)
- конфигурацию веб-сервера (например httpd.conf, .htaccess)
- исходные коды приложения (ищем уязвимости, анализируя логику приложения)
- доступы к окружению (находясь внутри сети может быть проще попасть на соседние сервера)
- базы данных (и аутентификационная информация,к другим системам, хранящаяся в них)
Получение паролей из хеша
Чаще всего пароли хранят в виде хешей. Но есть способы получить пароль, имея его хеш.
Один из самых известных онлайн-брутфорсеров паролей: John the Ripper.
Может быть использован, например, так:
john <passwd file>
john --wordlist=<dictionary pass> <passwd file>
john --format=<formatname> passfile (список форматов: john --list=formats)
Организация перманентного доступа
Самый простой способ - создать своего пользователя (желательно замаскировав его под системного).
Другой вариант - бинарные бекдоры, которые кладутся на систему и организуется их периодическое выпролнение (через cron или при каждом вызове любой частой команды, например ls).
Если удалось получить доступ под пользователем веб-сервера, можно сделать веб-бекдор, например положив куда-либо на вебсервере скрипт, позволяющий выполнять произвольные действия.
Самый жесткий вариант - патч ядра операционной системы, включение бекдора туда.
Полезные ссылки
Классификация угроз от Web App Security Consorcium
Cheatsheet по угрозам безопасности HTML и не только
SQL Injeciton от А до Я в pdf от Positive Technologies
База раскрытых уязвимостей Exploit DB
Поисковик по уязвимостям vulners.com ( и еще есть статья о нем на хабре)
Лекции от того же автора на YouTube (во многом похожи, но есть часть тем, не раскрытых в курсе, например раздел про CMS)