1. 为什么需要自己写漏洞扫描脚本
在网络安全领域,漏洞扫描是最基础也是最重要的防御手段之一。市面上虽然有很多成熟的商业扫描工具,但自己动手写扫描脚本的价值在于:
-
定制化需求:商业工具往往针对通用场景,而实际业务中我们经常需要针对特定应用、特定协议或特定漏洞进行检测。比如专门扫描公司内部使用的CMS系统,或者检测某个API接口的特定参数。
-
学习价值:通过编写扫描脚本,可以深入理解漏洞原理。比如SQL注入漏洞,只有亲手实现过注入检测逻辑,才能真正理解各种过滤绕过手法的本质。
-
轻量快速:商业工具启动慢、报告冗长,而自研脚本可以只关注关键风险点。在应急响应时,一个几十行的Python脚本可能比运行全套Nessus扫描更高效。
我最近在一次内部渗透测试中就遇到了这种情况:需要快速检测200多个Web服务是否暴露了Swagger文档接口。用现成工具需要配置太多参数,而用Python写个简单脚本只用了不到30分钟就完成了任务。
2. 基础环境准备
2.1 Python版本选择
推荐使用Python 3.6+版本,原因如下:
- 3.6引入的f-string让字符串格式化更直观
- 3.7+对异步IO的支持更完善
- 避免使用Python 2.x,因为其已停止维护且许多安全库不再支持
验证Python版本的命令:
bash复制python --version
# 或
python3 --version
2.2 必要库安装
核心需要以下几个库:
bash复制pip install requests beautifulsoup4 python-nmap
requests:比标准库urllib更友好的HTTP客户端beautifulsoup4:HTML解析,用于分析网页内容python-nmap:nmap的Python接口,用于端口扫描
注意:在Kali Linux等安全发行版中,这些库可能已预装。建议使用虚拟环境避免污染系统Python环境:
bash复制python -m venv scanenv source scanenv/bin/activate # Linux/Mac scanenv\Scripts\activate # Windows
3. 实现基础端口扫描功能
3.1 使用python-nmap进行端口发现
端口扫描是漏洞扫描的第一步,以下是一个基础的扫描实现:
python复制import nmap
def port_scan(target, ports='1-1024'):
scanner = nmap.PortScanner()
scanner.scan(target, ports)
for host in scanner.all_hosts():
print(f"扫描结果 {host}:")
for proto in scanner[host].all_protocols():
print(f"协议: {proto}")
ports = scanner[host][proto].keys()
for port in sorted(ports):
print(f"端口 {port}: 状态 {scanner[host][proto][port]['state']}")
典型输出示例:
code复制扫描结果 192.168.1.1:
协议: tcp
端口 22: 状态 open
端口 80: 状态 open
端口 443: 状态 open
3.2 扫描优化技巧
实际使用中有几个注意事项:
- 速率控制:添加
--max-rate 100参数限制每秒包数,避免触发防火墙 - 结果过滤:只关注
open状态的端口 - 常见端口:优先扫描80,443,22,21,3389等高危端口
改进后的扫描函数:
python复制def safe_port_scan(target, ports='80,443,22,21,3389'):
scanner = nmap.PortScanner()
scanner.scan(target, ports, arguments='-n -T4 --max-rate 100')
open_ports = []
for host in scanner.all_hosts():
for proto in scanner[host].all_protocols():
for port, info in scanner[host][proto].items():
if info['state'] == 'open':
open_ports.append((proto, port))
return open_ports
4. Web漏洞扫描实现
4.1 目录遍历检测
许多网站存在目录遍历漏洞,可以通过尝试访问常见敏感路径来检测:
python复制import requests
def check_directory_traversal(url):
test_paths = [
'/etc/passwd',
'/proc/self/environ',
'../../../../etc/passwd',
'WEB-INF/web.xml'
]
vulnerabilities = []
for path in test_paths:
try:
r = requests.get(f"{url.rstrip('/')}/{path}")
if 'root:x:' in r.text or '<web-app>' in r.text:
vulnerabilities.append(path)
except:
continue
return vulnerabilities
4.2 SQL注入检测初探
基础的SQL注入检测可以通过发送特定payload并分析响应实现:
python复制def check_sql_injection(url, params):
payloads = [
"'",
'"',
"' OR '1'='1",
'" OR "1"="1',
'1 AND 1=1',
'1 AND 1=2'
]
injection_points = []
for param, value in params.items():
for payload in payloads:
test_params = params.copy()
test_params[param] = value + payload
r = requests.get(url, params=test_params)
if 'error in your SQL syntax' in r.text:
injection_points.append(param)
break
elif 'MySQL server version' in r.text:
injection_points.append(param)
break
return injection_points
重要提示:在实际测试中务必先获得授权,未经授权的扫描可能违法。添加User-Agent标识是个好习惯:
python复制headers = {'User-Agent': 'MySecurityScanner/1.0'} requests.get(url, headers=headers)
5. 漏洞扫描脚本进阶技巧
5.1 多线程加速扫描
Python的concurrent.futures可以轻松实现并行扫描:
python复制from concurrent.futures import ThreadPoolExecutor
def scan_targets(targets, scan_func, max_workers=10):
with ThreadPoolExecutor(max_workers=max_workers) as executor:
results = list(executor.map(scan_func, targets))
return results
# 使用示例
targets = ['192.168.1.{}'.format(i) for i in range(1, 255)]
open_ports_list = scan_targets(targets, safe_port_scan)
5.2 结果保存与报告生成
将扫描结果保存为结构化的JSON文件:
python复制import json
from datetime import datetime
def save_scan_results(results, filename=None):
if not filename:
filename = f"scan_result_{datetime.now().strftime('%Y%m%d_%H%M%S')}.json"
with open(filename, 'w') as f:
json.dump({
'timestamp': datetime.now().isoformat(),
'results': results
}, f, indent=2)
return filename
5.3 添加日志记录
使用Python标准库的logging模块记录扫描过程:
python复制import logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s',
handlers=[
logging.FileHandler('scanner.log'),
logging.StreamHandler()
]
)
def port_scan_with_logging(target):
logging.info(f"开始扫描 {target}")
try:
results = safe_port_scan(target)
logging.info(f"扫描完成,发现 {len(results)} 个开放端口")
return results
except Exception as e:
logging.error(f"扫描 {target} 时出错: {str(e)}")
return []
6. 实际案例:扫描暴露的API文档
假设我们需要扫描内网中暴露的Swagger UI接口(常见于开发测试环境):
python复制def find_swagger_interfaces(base_urls):
endpoints = [
'/swagger-ui.html',
'/api-docs',
'/v2/api-docs',
'/swagger.json'
]
exposed_interfaces = []
for url in base_urls:
for endpoint in endpoints:
try:
full_url = f"{url.rstrip('/')}{endpoint}"
r = requests.get(full_url, timeout=3)
if 'swagger' in r.text or 'API Documentation' in r.text:
exposed_interfaces.append(full_url)
break
except:
continue
return exposed_interfaces
使用示例:
python复制internal_ips = ['http://192.168.1.{}'.format(i) for i in range(1, 50)]
exposed_apis = find_swagger_interfaces(internal_ips)
print(f"发现 {len(exposed_apis)} 个暴露的API接口")
7. 安全与法律注意事项
- 授权扫描:确保你有权扫描目标系统,未经授权的扫描可能违反《计算机犯罪法》
- 速率限制:避免对目标系统造成拒绝服务(DoS)
- 敏感数据处理:扫描结果可能包含敏感信息,需妥善保管
- 规避防御:添加随机延迟、使用代理池等技术避免被屏蔽
合法的扫描请求头示例:
python复制headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)',
'X-Scanner': 'InternalSecurityAudit/1.0',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8'
}
8. 扩展思路与改进方向
-
集成更多漏洞检测:
- 添加CVE已知漏洞检测(可通过https://cve.mitre.org/获取数据)
- 实现OWASP Top 10中的其他漏洞检测(如XSS、CSRF等)
-
可视化展示:
- 使用Matplotlib生成扫描结果图表
- 集成Flask创建简单的Web报告界面
-
分布式扫描:
- 使用Celery实现任务队列
- 支持多台机器协同扫描大型网络
-
智能识别:
- 使用机器学习模型分析响应内容,提高漏洞识别准确率
- 实现WAF指纹识别和绕过技术
一个简单的改进示例(添加超时和重试机制):
python复制from requests.adapters import HTTPAdapter
from requests.packages.urllib3.util.retry import Retry
def create_safe_session():
session = requests.Session()
retries = Retry(
total=3,
backoff_factor=1,
status_forcelist=[500, 502, 503, 504]
)
session.mount('http://', HTTPAdapter(max_retries=retries))
session.mount('https://', HTTPAdapter(max_retries=retries))
return session
在实际项目中,我通常会先针对特定需求开发小型扫描脚本,验证可行性后再逐步扩展功能。比如先实现一个专门检测Spring Boot Actuator接口的脚本,再慢慢添加其他框架的检测逻辑。这种渐进式开发方式可以快速获得可用工具,同时避免一开始就陷入复杂架构的设计困境。
