
1) 【一句话结论】
实现一个Python SSRF检测工具,通过构造包含内部网络地址的HTTP请求,结合响应状态码、重定向跟踪、认证处理(如登录表单解析),判断目标系统是否允许访问内部网络资源。
2) 【原理/概念讲解】
SSRF(服务器端请求伪造)是指Web应用将用户输入作为URL或参数,服务器以自身身份发起请求,从而访问内部资源(如内部IP、数据库端口等)。检测工具的核心逻辑是:
http://10.0.0.1或http://internal-db:3306),用HTTP客户端发送请求;200可能表示允许访问(漏洞存在),404表示内部资源不存在,401/403表示认证失败,其他状态码或异常(如超时、连接错误)需进一步分析;Location头,循环重定向直到无重定向或达到最大次数);类比:就像服务器自己发送一封“假”的邮件,假装是用户输入的URL,看服务器是否会响应,从而暴露内部网络。
3) 【对比与适用场景】
| 方法 | 定义 | 特性 | 使用场景 | 注意点 |
|---|---|---|---|---|
| 直接请求(GET/POST) | 直接向目标URL发送HTTP请求,参数为内部URL | 速度快,无需代理 | 测试简单场景,目标允许直接访问 | 可能被防火墙拦截,或目标有访问控制 |
| 代理方式(Socks5/HTTP代理) | 通过代理服务器转发请求 | 更灵活,可绕过防火墙/访问限制 | 测试复杂网络环境,或目标有访问限制 | 需要配置代理,可能增加延迟 |
| GET vs POST | GET用于参数传递(如查询内部资源),POST用于提交数据(如登录表单) | GET传递数据,POST提交数据 | 根据目标系统对参数的处理方式选择 | GET可能被过滤,POST更隐蔽 |
4) 【示例】
伪代码(包含重定向跟踪、循环检测多个内部服务、动态解析登录表单):
import requests
from bs4 import BeautifulSoup
from requests.exceptions import RequestException
def ssrf_detector(target_url, internal_urls, use_proxy=False, proxy_url=None):
headers = {'User-Agent': 'Mozilla/5.0'}
proxies = {} if use_proxy else None
if use_proxy and proxy_url:
proxies = {'http': proxy_url, 'https': proxy_url}
max_redirects = 5
for internal_url in internal_urls:
try:
# 重定向跟踪
response = requests.get(f"{target_url}?url={internal_url}", headers=headers, proxies=proxies, timeout=5, allow_redirects=False)
# 跟踪重定向
while response.status_code in (301, 302, 303, 307, 308):
if 'Location' in response.headers:
redirect_url = response.headers['Location']
response = requests.get(redirect_url, headers=headers, proxies=proxies, timeout=5, allow_redirects=False)
else:
break
if response.status_code == 200:
print(f"检测到SSRF漏洞,访问 {internal_url} 成功,响应: {response.text[:100]}")
return True
elif response.status_code == 404:
print(f"内部资源 {internal_url} 不存在")
elif response.status_code in (401, 403):
print(f"认证失败,尝试处理登录")
# 动态解析登录页面
login_page = requests.get(f"{target_url}?url={internal_url}", headers=headers, proxies=proxies, timeout=5)
soup = BeautifulSoup(login_page.text, 'html.parser')
# 解析表单字段
form = soup.find('form', {'action': f"{target_url}?url={internal_url}"})
if form:
inputs = form.find_all('input')
login_data = {}
for inp in inputs:
if 'name' in inp.attrs:
login_data[inp['name']] = 'testuser' # 假设用户名
# 构造POST请求
login_response = requests.post(f"{target_url}?url={internal_url}", data=login_data, headers=headers, proxies=proxies, timeout=5)
if login_response.status_code == 200 and 'login success' in login_response.text:
# 认证成功后再次测试
final_response = requests.get(f"{target_url}?url={internal_url}", headers=headers, proxies=proxies, timeout=5)
if final_response.status_code == 200:
print(f"认证后成功访问 {internal_url}")
return True
else:
print(f"认证后仍无法访问 {internal_url}")
else:
print(f"登录失败,无法处理认证")
else:
print(f"未找到登录表单")
else:
print(f"其他状态码: {response.status_code}")
except RequestException as e:
print(f"请求异常: {e}")
return False
# 测试示例
target = "http://example.com/vuln"
internal_services = [
"http://10.0.0.1",
"http://internal-db:3306",
"http://10.0.0.1:8080",
"http://web-server:80"
]
ssrf_detector(target, internal_services, use_proxy=True, proxy_url="http://proxy:8080")
5) 【面试口播版答案】
面试官您好,我来解释如何用Python实现一个简单的SSRF检测工具。首先,SSRF是服务器端请求伪造,核心是让服务器访问内部资源。工具通过构造一个包含内部URL的请求(比如目标URL加上参数,指向内部IP或服务),用requests库发送。然后检查响应状态码:200可能表示允许访问,404表示内部资源不存在,401/403表示认证失败。异常处理方面,比如网络超时或连接错误,会捕获并提示。具体来说,代码会发送GET请求,参数是内部URL,然后根据状态码判断漏洞。比如测试内部服务是否可访问,如果返回200,说明可能存在SSRF漏洞。处理异常时,比如404就说明内部资源不存在,401需要构造登录请求(POST方法提交用户名密码),认证成功后再测试内部资源,若能访问则确认漏洞。另外,工具还处理了重定向(跟踪Location头),避免漏检,并且循环测试多个内部URL(如不同端口、服务),提高检测全面性。这样就能检测是否允许内部网络访问了。
6) 【追问清单】
7) 【常见坑/雷区】