![image](https://habrastorage.org/webt/7r/-h/k_/7r-hk_k6qgbyxi7norin7vkmfzi.jpeg)
С тех пор как я написал предисловие к первому чрезвычайно успешному изданию Black Hat Python, прошло шесть лет. За это время в мире многое изменилось, но я по-прежнему пишу чертовски много кода на Python. В сфере компьютерной безопасности все еще встречаются инструменты, написанные на разных языках, в зависимости от назначения. Эксплойты для ядра создают на C, средства фаззинга для веб-страниц — на JavaScript, а прокси-серверы могут быть написаны на таком новомодном языке, как Rust. Однако Python остается главной рабочей лошадкой в этой отрасли. Я считаю, что это все еще самый простой язык для начинающих и лучший выбор для быстрой разработки инструментов, решающих сложные задачи простым способом, учитывая большое количество доступных библиотек. Большая часть средств компьютерной безопасности и эксплойтов, как и раньше, написана на Python. Это касается фреймворков создания эксплойтов наподобие CANVAS, классических фаззеров, таких как Sulley, и всего остального.
Веб-хакерство
Навыки анализа веб-приложений совершенно необходимы любому хакеру или пентестеру. В большинстве современных сетей веб-приложения имеют самый высокий потенциал для взлома, поэтому несанкционированный доступ к ним чаще всего получают через них самих.
На Python написано множество отличных веб-инструментов, включая w3af и sqlmap. Если честно, то такие темы, как внедрение SQL-кода, являются крайне заезженными, а готовый инструментарий достаточно развитой для того, чтобы не изобретать велосипед. Поэтому сосредоточимся на основах работы с сетью при помощи Python и затем, опираясь на эти знания, разработаем собственные инструменты для сбора полезных сведений и анализа веб-приложения методом перебора. Это позволит вам приобрести фундаментальные навыки и умения, необходимые для создания любого рода средств анализа веб-приложений, уместных в конкретной атаке.
В этой главе мы рассмотрим три сценария атаки. В первом из них вам известно, какой каркас веб-приложений применяет жертва, и так сложилось, что он имеет открытый исходный код. Каркас веб-приложений содержит множество файлов и вложенных каталогов. Мы сгенерируем локальную карту иерархии веб-приложения и воспользуемся ею для поиска реальных файлов и каталогов на компьютере жертвы.
Во втором сценарии вам известен только URL-адрес жертвы, поэтому придется прибегнуть к методу перебора, чтобы получить ту же структуру каталогов. Мы возьмем словарь и сгенерируем на его основе набор путей и названий каталогов, которые могут присутствовать на атакуемом компьютере. Затем попытаемся отобрать из полученного списка потенциальных путей те, которые действительно существуют.
В третьем сценарии вам известны базовый URL-адрес жертвы и страница для входа. Мы проанализируем эту страницу и попробуем подобрать учетные данные по словарю.
Использование веб-библиотек
Для начала сделаем краткий обзор библиотек, которые можно применять для взаимодействия с веб-сервисами. При выполнении сетевых атак вы можете пользоваться либо своим компьютером, либо устройством внутри атакуемой сети. Если вы пробрались на взломанный компьютер, то придется работать с тем, что под рукой, — это может быть базовая версия Python 2.х или Python 3.х. Мы поговорим о том, что можно сделать в такой ситуации, обходясь стандартной библиотекой. Однако в остальных разделах этой главы предполагается, что на компьютере, с которого проводится атака, установлены самые свежие пакеты.
Библиотека urllib2 для Python 2.х
В коде, написанном на Python 2.х, можно встретить пакет urllib2, встроенный в стандартную библиотеку. Если пакет socket применяется для написания сетевого инструментария, то с помощью urllib2 создают средства взаимодействия с веб-сервисами. Рассмотрим код, который выполняет очень простой GET-запрос к веб-сайту No Starch Press:
import urllib2
url = 'https://www.nostarch.com'
response = urllib2.urlopen(url) # GET
print(response.read())
response.close()
Это простейший пример того, как выполнить GET-запрос к веб-сайту. Мы передаем URL-адрес функции urlopen, которая возвращает объект, похожий на дескриптор, с его помощью можем прочитать тело того, что нам возвращает веб-сервер. Поскольку мы получаем всего лишь код страницы с веб-сайта No Starch, никакие клиентские скрипты, написанные на JavaScript или другом языке, выполняться не будут.
Однако в большинстве случаев требуется более гибкий подход к выполнению запросов. Например, иногда нужно указывать определенные заголовки, обрабатывать cookie и создавать запросы типа POST. Библиотека urllib2 имеет в своем составе класс Request, способный обеспечить такой уровень гибкости. В следующем примере показано, как с помощью этого класса создать такой же GET-запрос с указанием собственного HTTP-заголовка User-Agent:
import urllib2
url = "https://www.nostarch.com"
headers = {'User-Agent': "Googlebot"}
request = urllib2.Request(url,headers=headers)
response = urllib2.urlopen(request)
print(response.read())
response.close()
Процесс создания объекта Request немного отличается от того, который мы видели в предыдущем примере. Чтобы указать собственные заголовки, добавляем их названия и значения в словарь headers. В данном случае мы сделаем так, чтобы наш скрипт представлялся поисковым роботом Googlebot. Затем создаем объект Request, предоставляя ему url и словарь headers, после чего передаем этот объект функции urlopen. В ответ получаем обычный объект-дескриптор, который можно использовать для чтения данных с удаленного веб-сайта.
Библиотека urllib для Python 3.х
Стандартная библиотека Python 3.х содержит пакет urllib, в котором возможности urllib2 разделены на два подпакета: urllib.request и urllib.error. Также в urllib появились функции разбора URL-адресов, доступные в подпакете urllib.parse.
Для создания HTTP-запроса с помощью urllib можно воспользоваться диспетчером контекста и инструкцией with. Полученный ответ должен содержать байтовую строку. Вот как это выглядит на примере GET-запроса:
import urllib.parse
import urllib.request
url = 'http://boodelyboo.com'
with urllib.request.urlopen(url) as response: # GET
content = response.read()
print(content)
Здесь мы импортируем нужные нам пакеты и определяем целевой URL-адрес. Затем с помощью метода urlopen в качестве диспетчера контекста выполняем запрос и читаем ответ.
Чтобы создать POST-запрос, передайте словарь с данными, закодированными в виде байтов, объекту Request. Этот словарь должен содержать пары «ключ — значение», которые ожидает получить атакуемое вами веб-приложение. В этом примере словарь info содержит учетные данные (user, passwd), необходимые для входа на веб-сайт:
info = {'user': 'tim', 'passwd': '31337'}
data = urllib.parse.urlencode(info).encode()
# теперь данные имеют тип bytes
req = urllib.request.Request(url, data)
with urllib.request.urlopen(req) as response: # POST
content = response.read()
print(content)
Мы кодируем словарь с учетными данными, чтобы превратить его в объект типа bytes, помещаем его в POST-запрос, передающий эти учетные данные, и принимаем ответ на попытку входа в веб-приложение.
Библиотека requests
Даже официальная документация Python рекомендует использовать в качестве высокоуровневого клиентского HTTP-интерфейса пакет requests. Он не входит в стандартную библиотеку, поэтому его нужно устанавливать отдельно. Вот как это сделать с помощью pip:
pip install requests
Пакет requests выгодно отличается тем, что может автоматически обрабатывать cookie, и в этом вы сами сможете убедиться в следующем примере, хотя наиболее наглядно это будет представлено в ходе демонстрационной атаки на веб-сайт WordPress, которую мы проведем в разделе «Взлом HTML-формы аутентификации методом перебора» далее. Для выполнения HTTP-запроса проделайте следующее:
import requests
url = 'http://boodelyboo.com'
response = requests.get(url) # GET
data = {'user': 'tim', 'passwd': '31337'}
response = requests.post(url, data=data) # POST
print(response.text) # response.text = string; response.content = bytestring
Создаем url, request и словарь data с ключами user и passwd. Затем отправляем запрос методом POST и выводим атрибут text (строку). Если вы предпочитаете работать с байтовыми строками, используйте атрибут content, возвращенный вместе с ответом. Пример этого будет показан в разделе «Взлом HTML-формы аутентификации методом перебора».
Пакеты lxml и BeautifulSoup
Для разбора содержимого полученного HTTP-ответа подойдет пакет lxml или BeautifulSoup. За последние несколько лет эти два пакета стали более похожими, вы можете применять синтаксический анализатор lxml в сочетании с BeautifulSoup, равно как и синтаксический анализатор BeautifulSoup в сочетании с lxml. Другие хакеры используют в своем коде и тот, и другой пакет. У lxml синтаксический анализатор чуть быстрее, а у BeautifulSoup предусмотрена логика для автоматического обнаружения кодировки заданной HTML-страницы. Здесь мы будем работать с lxml. Оба пакета можно установить с помощью pip:
pip install lxml
pip install beautifulsoup4
Допустим, вы сохранили HTML-код, возвращенный внутри ответа, в переменную content. С помощью lxml можете извлечь из него ссылки, как показано далее:
from io import BytesIO
from lxml import etree
import requests
url = 'https://nostarch.com
r = requests.get(url) # GET
content = r.content # content имеет тип bytes
parser = etree.HTMLParser()
content = etree.parse(BytesIO(content), parser=parser) # преобразуем в дерево
for link in content.findall('//a'): # находим все ссылки (элементы "a")
print(f"{link.get('href')} -> {link.text}")
Импортируем класс BytesIO из модуля io, он позволит нам использовать байтовую строку в качестве файлового объекта при разборе HTTP-ответа. Затем, как и раньше, выполняем GET-запрос и разбираем ответ с помощью синтаксического HTML-анализатора lxml. Анализатор принимает на вход объект-дескриптор или имя файла. Класс BytesIO превратит возвращенную байтовую строку в объект-дескриптор, который можно будет передать синтаксическому анализатору lxml. Мы применяем простой запрос для поиска всех тегов a (ссылок), содержащихся в возвращенном ответе, и выводим результаты. Каждый тег a определяет ссылку. Его атрибут href содержит URL-адрес этой ссылки.
Обратите внимание на использование f-строки, которая на самом деле выполняет запись. В Python версии 3.6 и выше f-строки можно использовать для создания строк с переменными, заключенными в фигурные скобки. Это, к примеру, позволяет легко включить в строку результат вызова функции (link.get('href')) или обычное значение (link.text).
Такого же рода разбор можно выполнить и с помощью BeautifulSoup, используя следующий код. Как видите, это очень похоже на предыдущий пример на основе lxml:
from bs4 import BeautifulSoup as bs
import requests
url = 'http://bing.com'
r = requests.get(url)
tree = bs(r.text, 'html.parser') # преобразуем в дерево
for link in tree.find_all('a'): # находим все ссылки (элементы "a")
print(f"{link.get('href')} -> {link.text}")
Синтаксис почти идентичен. Мы преобразуем содержимое в дерево, перебираем ссылки (теги a) и выводим соответствующие адреса (атрибут href) и текст (link.text).
Если вы работаете на взломанном компьютере, вам, вероятно, придется отказаться от установки всех этих сторонних пакетов, чтобы не поднимать слишком много шума в сети. Таким образом, вы будете использовать то, что под рукой, — например, минимальные версии Python 2 или Python 3. Это означает, что придется ограничиться стандартной библиотекой (urllib2 или urllib соответственно).
В следующих примерах мы исходим из того, что вы используете для взлома собственный компьютер, следовательно, можете соединяться с веб-серверами с помощью пакета requests и разбирать полученный вывод с применением lxml.
Итак, вы получили базовые средства для взаимодействия с веб-сервисами и веб-сайтами. Теперь создадим инструментарий, который будет полезен для атаки или тестирования на проникновение любого веб-приложения.
Получение структуры каталогов веб-приложений с открытым исходным кодом
Системы управления контентом (content management systems, CMS) и платформы для блогов, такие как Joomla, WordPress и Drupal, делают процесс создания блога или веб-сайта простым. Они пользуются довольно высокой популярностью в средах виртуального хостинга и даже в корпоративных сетях. У любой системы есть свои нюансы в плане установки, конфигурации и управления патчами, и пакеты CMS — не исключение. То, что перегруженный системный администратор или незадачливый разработчик не до конца соблюдает все процедуры обеспечения безопасности и установки ПО, может упростить взломщику получение доступа к веб-серверу.
Мы можем скачать любое веб-приложение с открытым исходным кодом и локально проанализировать его файлы и структуру каталогов. Это позволяет создать специализированный сканер, способный находить все файлы, доступные на удаленном компьютере. Таким образом можно избавиться от файлов, оставшихся после установки, защитить с помощью файлов .htaccess каталоги, требующие этого, и позаботиться о прочих нюансах, которые могут позволить взломщику проникнуть на веб-сервер.
В этом проекте мы также познакомимся с объектом Python Queue, позволяющим создавать большие потокобезопасные очереди, элементы которых обрабатываются разными потоками. Это сделает наш сканер очень быстрым. К тому же не нужно будет волноваться о состояниях гонки, так как очередь, в отличие от списка, будет потокобезопасной.
Более подробно с книгой можно ознакомиться на сайте издательства
» Оглавление
» Отрывок
Для Хаброжителей скидка 25% по купону — Python
По факту оплаты бумажной версии книги на e-mail высылается электронная книга.
- Обратите внимание, сейчас проходит Распродажа «Чёрная Пятница» от издательства «Питер».