允许TRACE方法漏洞
漏洞定义
TRACE方法是HTTP协议中定义的一种调试方法,主要用于测试或诊断Web服务器连接。Web服务器在配置时未正确禁用HTTP TRACE方法,从而允许客户端向服务器发送TRACE请求,并导致服务器返回可能包含敏感信息的响应。
漏洞危害
这种配置不当可能构成安全风险,因为TRACE请求可以使服务器原样返回请求头信息,包括Session Token、Cookies或其他认证信息,这些信息若被恶意攻击者获取,则可能被用于进一步攻击,如跨站脚本攻击(XSS)、会话劫持等。
漏洞检测
若回显如下,则漏洞存在
< HTTP/1.1 200 OKHTTP/1.1 200 OK
< Content-Type: message/httpContent-Type: message/http
若回显如下,则漏洞不存在
< HTTP/1.1 403 Forbidden
< Content-Type: text/html; charset=iso-8859-1
或者
< HTTP/1.1 405 Method Not Allowed
< Content-Type: text/html; charset=iso-8859-1
检测脚本
原理
使用OPTIONS请求查看服务器声明的支持方法
curl -I -X OPTIONS http://www.test.com通过实际的TRACE请求验证服务器是否按照声明执行了TRACE方法
curl -v -X TRACE http://www.test.com
用法
python scanner.py urls.txt的文件路径
注意:检测结果不可避免的存在一些误报,需要人工对检测结果进行最终的验证
代码
scanner.py
import subprocess
import sys
import requests
import pandas as pddef read_urls_from_file(file_path):try:with open(file_path, 'r', encoding='utf-8') as file: # 指定编码为utf-8urls = file.readlines()# 去除每行末尾的换行符和空行urls = [url.strip() for url in urls if url.strip()]return urlsexcept FileNotFoundError:print(f"错误: {file_path} 文件不存在!")sys.exit(1) # 退出程序并返回错误码1except IOError:print(f"错误: {file_path} 文件读取失败!")sys.exit(1) # 退出程序并返回错误码1def export_to_excel(data, file_name):df = pd.DataFrame(data)try:# 将DataFrame写入Excel文件,不包括索引df.to_excel(file_name, index=False)print(f"结果已写入文件: {file_name}")except IOError:print(f"结果写入出错: {file_name}.")def check_trace_first(url):try:# 使用 curl -I -X OPTIONS 请求来获取支持的 HTTP 方法result = subprocess.run(['curl', '-I', '-X', 'OPTIONS', url],stdout=subprocess.PIPE,stderr=subprocess.PIPE,# 5秒未响应返回falsetimeout=5)# 尝试 UTF-8 解码try:stdout_text = result.stdout.decode('utf-8')except UnicodeDecodeError:# 如果 UTF-8 解码失败,尝试 GBK 解码try:stdout_text = result.stdout.decode('gbk')except UnicodeDecodeError:# 如果两种编码都失败,可以选择忽略错误、使用替换字符等stdout_text = result.stdout.decode('utf-8', errors='replace')# 检查响应是否包含 'TRACE' 字段if 'TRACE' in stdout_text:print("OPTIONS:true")return Trueelse:print("OPTIONS:false")return Falseexcept subprocess.TimeoutExpired:print("OPTIONS: timeout")return Falseexcept Exception as e:print("OPTIONS:",e)return Falsedef check_trace_second(url):try:result = subprocess.run(['curl', '-v', '-X', 'TRACE', url],stdout=subprocess.PIPE,stderr=subprocess.PIPE,# 5秒未响应返回falsetimeout=5)# 尝试 UTF-8 解码try:stderr_text = result.stderr.decode('utf-8')except UnicodeDecodeError:# 如果 UTF-8 解码失败,尝试 GBK 解码try:stderr_text = result.stderr.decode('gbk')except UnicodeDecodeError:# 如果两种编码都失败,可以选择忽略错误、使用替换字符等stderr_text = result.stderr.decode('utf-8', errors='replace')# 判断 TRACE 是否被允许,通常响应会包含 "405 Method Not Allowed" 或类似的内容if "200 OK" in stderr_text:print("TRACE:true")return Trueelse:print("TRACE:False")return Falseexcept subprocess.TimeoutExpired:print("TRACE: timeout")return Falseexcept Exception as e:print("TRACE:",e)return Falseif __name__ == "__main__":# 如果提供了命令行参数,则使用它作为文件路径,否则使用默认路径if len(sys.argv) > 1:file_path = sys.argv[1]else:# 默认文件路径,假设它与脚本在同一目录中file_path = 'urls.txt'# 从urls.txt文件中读取需要扫描的所有urlurls = read_urls_from_file(file_path)# 定义用于存放扫描结果的切片scan_results = []# 依次遍历需要扫描的urlfor url in urls:print("检测:",url)# 第一次检测trace_first = check_trace_first(url)if not trace_first:scan_result = {'url': url, '允许TRACE方法': False}scan_results.append(scan_result)# 第一次检测为false直接跳过第二次检测continue# 第二次检测,两次检测都必须为true才能算是检测到了漏洞trace_second = check_trace_second(url)if trace_second:scan_result = {'url': url, '允许TRACE方法': True}else:scan_result = {'url': url, '允许TRACE方法': False}# 将本次检测结果放入结果集scan_results.append(scan_result)# 将检测结果集导出为xlsx文档export_to_excel(scan_results, 'result.xlsx')