Статья Python для пентеста: пишем инструменты для автоматизации разведки, эксплуатации и пост-эксплуатации

Руки на тёмной механической клавиатуре в зелёном свечении терминала. Экран отображает работу Python-сканера субдоменов в ночной тишине.


За последние два года я написал больше сотни Python-скриптов для реальных Red Team-проектов - из них ровно три заменили существующий инструмент. Остальные делали то, чего готовые тулзы не умеют: парсили нестандартный API заказчика, обходили кастомный rate-limiting через ротацию сессий, автоматизировали специфические цепочки атак, которые руками отнимали часы. Python для пентеста - не замена Nmap или Burp Suite. Это клей между ними и кастомный слой автоматизации, закрывающий зазоры в стандартном инструментарии.
Записано со слов нашего тимлида

Место Python в цепочке атаки​

Каждый скрипт существует не в вакууме - он занимает конкретную позицию в kill chain и решает задачу конкретного этапа. Без понимания этого контекста код остаётся учебным упражнением, а не рабочим инструментом. Подробнее - в нашем обзоре разработка red team инструментов.

В терминах MITRE ATT&CK скрипты на Python покрывают несколько тактик:
  • Reconnaissance - сканирование портов, перебор поддоменов, fingerprinting сервисов. Техники Vulnerability Scanning (T1595.002) и Network Service Discovery (T1046)
  • Credential Access - brute-force форм и протоколов, извлечение токенов. Техника Brute Force (T1110)
  • Execution - Python как среда исполнения на захваченном хосте. Техника Python (T1059.006)
  • Discovery - перечисление SMB-шар, сбор системной информации. Техника System Information Discovery (T1082)
  • Post-Exploitation - перечисление сетевых ресурсов, поиск credentials в файлах, lateral movement через impacket. Техники Network Share Discovery (T1135), Credentials In Files (T1552.001), Ingress Tool Transfer (T1105)
Главный вопрос перед написанием любого скрипта: на каком этапе вы находитесь и что должно произойти до и после. Сканер портов бесполезен без списка целей из предыдущего этапа OSINT. Brute-force бесполезен без понимания того, как приложение обрабатывает ошибки аутентификации. Пост-эксплуатационный скрипт бессмыслен без начального доступа.

Когда писать кастомный скрипт, а когда использовать готовый инструмент​

УсловиеРешение
Задача стандартная, инструмент работает из коробкиNmap, Burp, sqlmap - не изобретайте велосипед
Нужна кастомизация под специфику целиPython-обёртка вокруг существующего инструмента
Готовый инструмент не поддерживает нужный протокол или форматКастомный скрипт с нуля
Инструмент детектируется защитой, нужен stealthКастомный скрипт с контролем тайминга и fingerprint
Массовая задача с 1000+ целямиAsync Python с aiohttp и asyncio
Захваченный хост с Python, но без возможности установить бинариСкрипт на стандартной библиотеке (socket, os, subprocess)

Требования к окружению​

Прежде чем писать первую строку - зафиксируйте среду. Без этого половина скриптов сломается на чужой машине или на захваченном хосте.

ПараметрМинимумРекомендуется
ОСKali Linux 2024.x / Ubuntu 22.04+Kali Linux 2025.x
Python3.10+3.12+
RAM2 ГБ (скрипты без scapy)4 ГБ (scapy + async)
СетьДоступ к целевой подсетиVPN или прямое подключение
Праваuser (для requests, socket)root/sudo (для scapy, raw sockets)

Установка базового стека: pip install scapy aiohttp requests beautifulsoup4 impacket paramiko. Настоятельно рекомендую виртуальное окружение через python -m venv pentest-env - изоляция зависимостей спасает от адских конфликтов версий между проектами. Все перечисленные библиотеки работают в offline-режиме после установки - критично для изолированных сетей на внутреннем пентесте, когда выхода в интернет нет.

Ещё один момент, который экономит нервы: создайте requirements.txt с точными версиями (pip freeze > requirements.txt) и храните его в репозитории проекта. При переходе между проектами это экономит десятки минут на восстановление окружения. Казалось бы, мелочь - но когда у тебя три проекта в неделю, мелочь превращается в систему.

Автоматизация разведки Python-скриптами

Разведка - первый этап kill chain, где Python даёт максимальную отдачу. Готовые инструменты (Nmap, masscan, Amass) покрывают стандартные задачи, но специфические сценарии требуют кастомного кода.

Сканирование портов: от socket к SYN-scan через scapy​

Базовый TCP connect-scan через модуль socket - самый простой вариант. Создаёте сокет socket.socket(socket.AF_INET, socket.SOCK_STREAM), вызываете connect_ex((target, port)), проверяете код возврата: ноль - порт открыт. Работает без root-прав, на любой ОС с Python. Проблема: медленно. Каждое соединение - полный TCP handshake, на диапазон 1-1024 уходят минуты. Можно обернуть цикл в concurrent.futures.ThreadPoolExecutor с 50-100 потоками, но это порождает шумный трафик с сотнями одновременных SYN-пакетов.

Scapy решает проблему скорости через SYN-scan: шлёт SYN-пакет, ждёт SYN/ACK и сразу закрывает соединение RST-ом. Быстрее в разы, но требует root для работы с raw sockets.
Python:
from scapy.all import IP, TCP, sr1

def syn_scan(host, ports):
    for port in ports:
        pkt = IP(dst=host) / TCP(dport=port, flags='S')
        resp = sr1(pkt, timeout=1, verbose=0)
        if resp and resp.haslayer(TCP) and resp[TCP].flags == 'SA':  # SYN+ACK
            print(f'Port {port}: open')
            # Примечание: ядро Linux отправит RST, т.к. не имеет открытого сокета для SYN/ACK.
            # Для чистого stealth-скана добавьте iptables -A OUTPUT -p tcp --tcp-flags RST RST -j DROP
        elif resp and resp.haslayer(TCP) and resp[TCP].flags & 0x04:  # RST set
            print(f'Port {port}: closed')
        else:
            print(f'Port {port}: filtered')

syn_scan('192.168.1.1', [21, 22, 80, 443, 445, 3389, 8080])
Когда это нужно: внутренний пентест, ситуация когда Nmap недоступен - например, на захваченном хосте с Python, но без возможности притащить бинари. На внешнем пентесте со стабильным каналом берите nmap или masscan - они быстрее и надёжнее. Не надо изобретать велосипед там, где велосипед уже есть.

Что видит защита: SYN-scan через scapy генерирует характерный паттерн трафика. Stateful firewall с DPI (FortiGate, Palo Alto) видит неполные TCP-сессии без завершения handshake и может блокировать или алертить. IDS типа Suricata с включённым правилом ET SCAN поймает серию SYN-пакетов за секунды. Mitigation: time.sleep(random.uniform(0.5, 2)) между портами и рандомизация порядка через random.shuffle(ports). Не панацея, но разницу между «алерт через 3 секунды» и «алерт через 3 минуты» иногда достаточно.

Асинхронный перебор поддоменов​

Перебор поддоменов через requests с синхронным циклом - 1-2 запроса в секунду. При словаре в 10000 записей потратите больше часа. Async через aiohttp ускоряет задачу до нескольких минут за счёт конкурентных соединений.
Python:
import aiohttp, asyncio

async def check(session, target, sub, sem):
    async with sem:
        try:
            async with session.get(f"http://{sub}.{target}",
                timeout=aiohttp.ClientTimeout(total=3)) as r:
                print(f"[+] {sub}.{target} -> {r.status}")
        except aiohttp.ClientError: pass

async def main(target, wordlist_path):
    subs = open(wordlist_path).read().splitlines()
    sem = asyncio.Semaphore(100)
    async with aiohttp.ClientSession() as s:
        await asyncio.gather(*[check(s, target, w, sem) for w in subs])
Запуск: asyncio.run(main('target.com', 'subdomains-10k.txt')). Semaphore на 100 конкурентных запросов - разумный предел, который не вызовет мгновенный бан. Но есть подвох: стандартный getaddrinfo блокирующий и не параллелится - Semaphore(100) не даст 100 параллельных DNS-резолвов. Для реальной конкурентности добавьте aiodns: connector = aiohttp.TCPConnector(resolver=aiohttp.AsyncResolver(nameservers=['8.8.8.8'])) и передайте в ClientSession(connector=connector). Без этого на словаре в 10000 записей всё будет работать заметно дольше, чем хотелось бы.

В реальных проектах я добавляю к этому скрипту проверку HTTP-ответов: если сервер возвращает одинаковый Content-Length для несуществующих поддоменов (wildcard DNS), фильтрую такие ответы. Без этой проверки словарь на 10000 записей выдаст 10000 «найденных» поддоменов - и результат летит в мусорку.

Когда это нужно: внешний пентест, этап автоматизации разведки. Перед запуском убедитесь, что scope включает wildcard-домены - иначе рискуете выйти за границы разрешённого тестирования.

Что видит защита: массовые DNS-запросы видны в логах резолвера. Организация с собственными DNS-серверами и мониторингом зафиксирует аномально высокую частоту NXDOMAIN-ответов с одного источника. Для скрытности лучше использовать пассивные источники - crt.sh, Certificate Transparency логи, парсинг через requests.get('https://crt.sh/?q=%.target.com&output=json'). Тише едешь - дальше будешь.

Написание эксплойтов и автоматизация атак на веб-приложения​

Python-скрипты для эксплуатации веб-приложений - второй этап после разведки. Связка requests + BeautifulSoup покрывает большинство задач.

Brute-force форм с обходом CSRF и rate-limiting​

Русскоязычные туториалы показывают brute-force как цикл requests.post() с перебором паролей из списка. В реальном приложении это не сработает: CSRF-токен меняется на каждый запрос, WAF блокирует IP после N неудачных попыток, сервер может вернуть CAPTCHA.

Рабочий подход - сессионный brute-force. Создаёте requests.Session(), на каждой итерации GET-запросом получаете страницу логина, извлекаете CSRF-токен через BeautifulSoup: soup.find('input', {'name': re.compile('csrf|token', re.I)})['value'] - это устойчиво к порядку атрибутов и вариациям имени поля (csrf_token, _token, authenticity_token), отправляете POST с актуальным токеном. Между запросами - time.sleep(random.uniform(1, 3)) чтобы не триггерить rate-limiting. Критерий успеха - анализ response.text на наличие элемента, который появляется только после аутентификации (поле профиля, кнопка logout).

Техника соответствует MITRE ATT&CK T1110 (Brute Force) и напрямую связана с OWASP A07:2021 (Identification and Authentication Failures).

Когда это нужно: внешний пентест веб-приложений с кастомной формой аутентификации. Для стандартных CMS (WordPress, Jira) берите специализированные инструменты - wpscan, hydra с модулем http-post-form. Кастомный скрипт нужен, когда форма нестандартная или защита специфическая. На одном проекте заказчик прикрутил к форме логина двойную проверку: CSRF + подпись timestamp-а в скрытом поле. Ни один готовый инструмент это из коробки не обрабатывал - пришлось писать.

Что видит защита: WAF (ModSecurity, Cloudflare, AWS WAF) блокирует перебор по паттерну множественных неудачных аутентификаций с одного IP. Обход через ротацию прокси добавляет сложности, но не гарантирует результат - современные WAF учитывают TLS fingerprint клиента и заголовки. Cloudflare блокирует requests по дефолтному TLS fingerprint (отличается от браузерного). Так что если видите Cloudflare - готовьтесь к танцам с tls-client или headless-браузером.

Разведка SQL-инъекций перед запуском sqlmap​

Для обнаружения SQL-инъекций Python полезен на этапе предварительной разведки - определить, какие параметры потенциально уязвимы, а потом передать их в sqlmap для полноценной эксплуатации. Согласно OWASP A03:2021 (Injection), инъекции остаются в тройке критичных рисков веб-приложений.

Паттерн работы: собираете все URL с параметрами через BeautifulSoup - извлекаете <form action> и <a href> с query strings. Добавляете базовые payloads (', ", 1 OR 1=1), отправляете через requests.get(), анализируете response.text на наличие SQL-ошибок: строки mysql_fetch, ORA-, SQLSTATE, syntax error near. Найдённые кандидаты передаёте в sqlmap: sqlmap -u "http://target.com/page?id=1" --batch.

Не пытайтесь воспроизвести логику sqlmap на Python с нуля. Этот зверь развивается с 2006 года, поддерживает шесть техник инъекций и работает с десятками СУБД. Ваш скрипт - разведчик, sqlmap - тяжёлая артиллерия.

Когда это нужно: внешний и внутренний пентест веб-приложений. Разведочный скрипт особенно полезен, когда scope содержит десятки endpoint-ов - вручную проверять каждый параметр нецелесообразно. Я обычно прогоняю такой скрипт первым делом и получаю шортлист из 5-10 подозрительных параметров вместо сотни.

Post-exploitation на Python: автоматизация в AD-среде

После получения начального доступа к внутренней сети Python становится основным инструментом автоматизации. Библиотека impacket - де-факто стандарт для работы с протоколами Windows из Linux: SMB, LDAP, Kerberos, DCOM, WMI.

Перечисление ресурсов через impacket​

Первое действие после получения учётных данных в AD - проверить доступные сетевые ресурсы. В shared-папках часто валяются скрипты с захардкоженными паролями, бэкапы баз данных, конфигурационные файлы VPN и документы с учётными записями сервисов. Золотая жила, если повезёт.
Python:
from impacket.smbconnection import SMBConnection

target = "192.168.1.10"
conn = SMBConnection(target, target)
conn.login("user", "P@ssw0rd")
for share in conn.listShares():
    name = share['shi1_netname'].rstrip('\x00')
    print(f"[*] Share: {name}")
    try:
        conn.listPath(name, '*')
        print(f"    -> readable")
    except: print(f"    -> access denied")
На практике после обнаружения читаемой шары я автоматизирую рекурсивный обход через conn.listPath(share_name, '\\*') с фильтрацией по расширениям: .conf, .xml, .ps1, .bat, .txt, .xlsx. Файлы с именами вроде passwords.xlsx или deploy.ps1 - приоритетные цели. На одном проекте именно так нашёлся скрипт деплоя с паролем от сервисной учётки - Domain Admin за полчаса.

Когда это нужно: внутренний пентест, grey box - с выданными учётными данными low-privileged пользователя. Это стандартный сценарий реальных проектов: заказчик выдаёт доменную учётку уровня Domain Users. В black box нужно сначала получить credentials через LLMNR/NBT-NS poisoning или Kerberoasting.

Что видит защита: EDR-решения - CrowdStrike Falcon, SentinelOne, Kaspersky EDR Expert - детектируют impacket по сетевым сигнатурам. SMB-пакеты библиотеки отличаются от стандартного поведения Windows-клиента: характерные значения в полях SecurityBlob и NativeOS. На зрелых инфраструктурах с мониторингом используйте нативные инструменты Windows (PowerShell Get-SmbShare) через SOCKS-прокси или SSH-туннель. Да, дольше. Зато не спалитесь в первые пять минут.

Сетевой перехват и lateral movement​

Scapy позволяет перехватывать трафик в локальной сети. Функция sniff(prn=callback, store=0) принимает callback, обрабатывающий каждый пакет. В callback фильтруете по слоям: packet.haslayer(TCP) для TCP, далее анализируете packet[IP].src, packet[IP].dst и payload. Для MitM-атаки через ARP-спуфинг отправляете поддельные ARP-ответы: send(ARP(op=2, pdst=target_ip, hwdst=target_mac, psrc=gateway_ip), inter=0.1, loop=1).

Когда это нужно: внутренний пентест, legacy-сети без 802.1X и без Dynamic ARP Inspection. В современных сетях с Cisco ISE или HPE ClearPass ARP-спуфинг детектируется и блокируется за секунды. На коммутаторах Cisco Catalyst с включённым DAI поддельные ARP-ответы дропаются на порту. Так что перед тем как запускать - убедитесь, что сеть достаточно «дикая» для этого трюка.

Что касается reverse shell - реализация через socket + subprocess занимает десяток строк, но в реальных проектах Python-based reverse shell детектируется большинством EDR. CrowdStrike Falcon и Elastic Security детектируют subprocess.Popen с перенаправлением stdin/stdout на сокет - в репозитории Elastic detection-rules есть соответствующие правила. Предпочтительнее загрузка C2-агента (Sliver, Havoc) через Python-дроппер с обфускацией или SSH-туннель через paramiko - легитимное SSH-соединение реже триггерит алерты.

Какую Python-библиотеку выбрать под задачу​

БиблиотекаЭтап kill chainКогда использоватьКогда НЕ использоватьКлючевое ограничение
socketRecon (T1046)Нет root-прав, минимальная среда, захваченный хостНужен SYN-scan или UDP-scanТолько TCP connect, медленный перебор
scapyRecon, ExecutionКонтроль на уровне пакетов, SYN-scan, ARP-спуфингWindows без Npcap, нет rootТребует root, шумный трафик
requestsCredential Access (T1110)Синхронные HTTP-запросы, малый объём целей1000+ целей, нужна скоростьБлокируется WAF при массовом переборе
aiohttpRecon, Credential AccessМассовый перебор, конкурентный доступ к 1000+ URLПростые одиночные запросыСложнее отладка, нет retry из коробки
impacketPost-Exploitation (T1135, T1552.001)AD-среда, SMB/LDAP/KerberosВнешний пентест без ADДетектируется EDR по сетевым сигнатурам
paramikoPost-ExploitationSSH-автоматизация на Linux-хостахWindows-среда без SSHНе работает с нестандартными SSH-реализациями
BeautifulSoupReconПарсинг HTML, извлечение форм и ссылокJSON API, бинарные данныеТолько парсинг, не отправка запросов

Как ваши скрипты выглядят со стороны IDS и SIEM​

Каждый Python-скрипт из этой статьи оставляет следы. Понимание того, что видит защита, отличает рабочий инструмент от учебного упражнения.
📚 Часть контента скрыта. Этот материал доступен участникам сообщества с рангом One Level или выше
Получить доступ просто — достаточно зарегистрироваться и проявить активность на форуме


Большинство Python-скриптов для пентеста, которые я встречаю на GitHub и в туториалах, учат одному - переписывать Nmap на сокетах и делать requests.post() в цикле. Реальная ценность Python в другом. Это язык, на котором вы пишете то, чего нет: парсер проприетарного API заказчика, обёртку вокруг Responder с автоматической передачей перехваченных хешей в hashcat, скрипт который за три минуты проверяет 500 SMB-шар на наличие файлов с паролями в именах.

Готовые инструменты покрывают 80% задач пентеста. Python закрывает оставшиеся 20% - и именно в них разница между отчётом «найдены стандартные уязвимости» и отчётом «получен доступ к контроллеру домена за четыре часа».

Мой опыт: пентестер, умеющий написать async-скрипт за полчаса, выигрывает у того, кто тратит полдня на ручной перебор. Но есть нюанс - большинство начинающих тратят время на написание красивого кода вместо того, чтобы быстро получить результат и двигаться дальше по kill chain. Скрипт для пентеста - не продакшн-код. Он живёт один проект, не нуждается в покрытии тестами и рефакторинге. Работает, не палится, экономит время - этого достаточно.

Попробуйте взять любой скрипт из статьи и адаптировать под свою задачу. Поменяйте таймауты, добавьте фильтрацию, прикрутите логирование в файл. Потренировавшись «на кошках», вы поймёте, где кончаются готовые инструменты и начинается ваш Python. На WAPT эту цепочку - от разведки до пост-эксплуатации - проходят в течение нескольких модулей с лабами, так что если хочется отработать в легальной среде - есть где.
 
Мы в соцсетях:

Взломай свой первый сервер и прокачай скилл — Начни игру на HackerLab

Похожие темы

🚀 Первый раз на Codeby?
Гайд для новичков: что делать в первые 15 минут, ключевые разделы, правила
Начать здесь →
🔴 Свежие CVE, 0-day и инциденты
То, о чём ChatGPT ещё не знает — обсуждаем в реальном времени
Threat Intel →
💼 Вакансии и заказы в ИБ
Pentest, SOC, DevSecOps, bug bounty — работа и проекты от проверенных компаний
Карьера в ИБ →

HackerLab