Dlaczego Python jest tak użyteczny
Python dobrze sprawdza się wszędzie tam, gdzie trzeba szybko zautomatyzować powtarzalne działania, zebrać dane z kilku źródeł albo przygotować wynik w czytelnej formie. W praktyce oznacza to mniej ręcznego klejenia workflow i więcej czasu na analizę.
Największe zalety w pracy technicznej:
- szybkie prototypowanie skryptów,
- duży ekosystem bibliotek,
- łatwe parsowanie danych i formatów raportowych,
- naturalna droga od małego skryptu do własnego narzędzia.
Przygotowanie środowiska
Warto od początku pracować w wirtualnym środowisku i trzymać zależności w jednym miejscu.
sudo apt update
sudo apt install -y python3 python3-pip python3-venv
python3 -m venv pentest-env
source pentest-env/bin/activate
pip install --upgrade pip wheel setuptools
pip install requests urllib3 python-nmap scapy beautifulsoup4 lxml
pip install jinja2 rich colorama tqdm dnspython python-docx reportlab
requests>=2.31
urllib3>=2.0
python-nmap>=0.7.1
scapy>=2.5.0
beautifulsoup4>=4.12
lxml>=4.9
jinja2>=3.1
rich>=13.0
colorama>=0.4.6
tqdm>=4.66
dnspython>=2.4
python-docx>=1.1
reportlab>=4.0
Przydatne idiomy
CLI i logowanie
import argparse, logging
def setup_logger(level=logging.INFO):
logging.basicConfig(
level=level,
format="%(asctime)s | %(levelname)s | %(message)s",
datefmt="%H:%M:%S"
)
return logging.getLogger("pentest")
def get_args():
p = argparse.ArgumentParser()
p.add_argument("target")
p.add_argument("-v", "--verbose", action="store_true")
return p.parse_args()
Requests Session z retry
import requests
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry
def http_session(proxy=None):
s = requests.Session()
retry = Retry(total=3, backoff_factor=0.8, status_forcelist=[429, 500, 502, 503, 504])
s.mount("http://", HTTPAdapter(max_retries=retry))
s.mount("https://", HTTPAdapter(max_retries=retry))
if proxy:
s.proxies.update({"http": proxy, "https": proxy})
s.verify = False
s.headers.update({"User-Agent": "PentestBot/1.0"})
return s
Równoległość
from concurrent.futures import ThreadPoolExecutor
import asyncio
def work(item):
return item
with ThreadPoolExecutor(max_workers=50) as ex:
results = list(ex.map(work, range(100)))
async def do_io(i):
await asyncio.sleep(0.01)
return i
Mini-labsy
Fingerprinting HTTP
import requests
from urllib.parse import urlparse
def http_fingerprint(url, proxy=None):
s = requests.Session()
if proxy:
s.proxies.update({"http": proxy, "https": proxy})
s.verify = False
r = s.get(url, timeout=8)
return {
"status": r.status_code,
"server": r.headers.get("Server"),
"x_powered_by": r.headers.get("X-Powered-By"),
"url": urlparse(url).geturl()
}
Asynchroniczny skaner portów
import asyncio
async def check_port(host, port, timeout=1.0):
try:
reader, writer = await asyncio.wait_for(asyncio.open_connection(host, port), timeout=timeout)
writer.close()
await writer.wait_closed()
return port
except Exception:
return None
Agregator Nmap XML do JSON
import xml.etree.ElementTree as ET
import json
def parse_nmap_xml(file_path):
root = ET.parse(file_path).getroot()
hosts = []
for host in root.findall("host"):
state = host.find("status").get("state")
addrs = [a.get("addr") for a in host.findall("address")]
hosts.append({"state": state, "addresses": addrs})
return hosts
Raport HTML z Jinja2
from jinja2 import Template
HTML = """
Raport skanowania
Hosty aktywne: {{ summary.hosts_up }}/{{ summary.total_hosts }}
"""
Najlepsze podejście: potraktuj te fragmenty jak klocki. Z czasem złożysz z nich własne CLI z modułami, konfiguracją i wspólnym formatem wyników.
Jak to spiąć w workflow
- recon i DNS do jednego formatu JSON,
- skan top portów jako filtr przed pełnym Nmap,
- parsowanie XML i JSON do wspólnego modelu danych,
- raport HTML albo PDF generowany automatycznie na końcu,
- osobne katalogi na raw, parsed i summary.
Bezpieczeństwo kodu i etyka
Automatyzacja nie zwalnia z odpowiedzialności. Korzystaj z takich skryptów wyłącznie w ramach uzgodnionego zakresu i nie wyłączaj bezpieczeństwa TLS poza środowiskiem laboratoryjnym.
- ustawiaj timeouty i limity concurrency,
- czyść logi z danych wrażliwych,
- trzymaj konfigurację i sekrety poza kodem,
- zapisuj wyniki tak, by dało się je później audytować.
Krótki cheatsheet
sess = http_session(proxy="http://127.0.0.1:8080")
resp = sess.get("https://target.local/login", timeout=10)
print(resp.status_code, resp.headers.get("Server"))
from pathlib import Path
import json
data = {"hosts": ["10.0.0.1"], "meta": {"scope": "demo"}}
Path("out/results.json").parent.mkdir(parents=True, exist_ok=True)
Path("out/results.json").write_text(json.dumps(data, indent=2, ensure_ascii=False), encoding="utf-8")
Co dalej
Jeśli chcesz wejść poziom wyżej, zbuduj jedno własne narzędzie z komendami typu recon, http, scan i report. Taki projekt daje dużo więcej niż zbiór pojedynczych skryptów.