51mee - AI智能招聘平台Logo
模拟面试题目大全招聘中心会员专区

编写一段Python代码,实现一个简单的SSRF漏洞检测工具,能够通过HTTP请求检测目标系统是否允许内部网络访问。请解释代码逻辑,并说明如何处理异常情况(如404、认证失败)。

360助理安全研究员(漏洞挖掘与利用)难度:中等

答案

1) 【一句话结论】
实现一个Python SSRF检测工具,通过构造包含内部网络地址的HTTP请求,结合响应状态码、重定向跟踪、认证处理(如登录表单解析),判断目标系统是否允许访问内部网络资源。

2) 【原理/概念讲解】
SSRF(服务器端请求伪造)是指Web应用将用户输入作为URL或参数,服务器以自身身份发起请求,从而访问内部资源(如内部IP、数据库端口等)。检测工具的核心逻辑是:

  • 构造一个包含内部网络地址的请求(如http://10.0.0.1或http://internal-db:3306),用HTTP客户端发送请求;
  • 根据响应状态码判断漏洞:200可能表示允许访问(漏洞存在),404表示内部资源不存在,401/403表示认证失败,其他状态码或异常(如超时、连接错误)需进一步分析;
  • 处理重定向(跟踪响应的Location头,循环重定向直到无重定向或达到最大次数);
  • 处理认证失败(动态解析登录页面,提取表单字段构造POST请求,认证成功后再次测试内部资源)。

类比:就像服务器自己发送一封“假”的邮件,假装是用户输入的URL,看服务器是否会响应,从而暴露内部网络。

3) 【对比与适用场景】

方法定义特性使用场景注意点
直接请求(GET/POST)直接向目标URL发送HTTP请求,参数为内部URL速度快,无需代理测试简单场景,目标允许直接访问可能被防火墙拦截,或目标有访问控制
代理方式(Socks5/HTTP代理)通过代理服务器转发请求更灵活,可绕过防火墙/访问限制测试复杂网络环境,或目标有访问限制需要配置代理,可能增加延迟
GET vs POSTGET用于参数传递(如查询内部资源),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) 【追问清单】

  • 问:如何处理认证失败的情况?比如目标需要登录?
    回答要点:动态解析登录页面,提取表单字段(如用户名、密码输入框的name属性),构造POST请求提交登录数据,认证成功后再次测试内部资源。
  • 问:如何避免被防火墙或WAF拦截?
    回答要点:使用代理服务器(如Socks5)转发请求,绕过目标IP或端口限制;或构造更复杂的请求(如POST方法、携带数据),增加隐蔽性。
  • 问:如何扩展检测范围,比如检测更多内部服务?
    回答要点:循环测试不同内部URL(如不同端口、服务,或使用字典文件包含常见内部服务地址),提高检测效率。
  • 问:工具是否考虑了重定向(302)的情况?
    回答要点:检查响应的Location头,若重定向到内部资源,则跟踪重定向后的URL继续检测,避免漏检。
  • 问:GET和POST请求在检测中有什么区别?
    回答要点:GET用于传递参数(如查询内部资源),POST用于提交数据(如登录表单),根据目标系统对参数的处理方式选择请求方法,比如登录需要POST。

7) 【常见坑/雷区】

  • 忽略重定向跟踪:响应重定向到内部资源,但未跟踪,导致漏检。
  • 测试URL选择不当:只测试一个内部IP,可能遗漏其他内部服务,或测试的URL不存在,导致误报。
  • 未处理认证:如果目标需要登录,直接测试内部URL会返回401,误判为无漏洞。
  • 忽略代理配置:直接请求可能被拦截,而代理方式需要正确配置,否则请求失败。
  • 未考虑请求方法:使用GET传递登录数据可能被过滤,而POST更隐蔽,需根据目标系统处理方式选择。
51mee.com致力于为招聘者提供最新、最全的招聘信息。AI智能解析岗位要求,聚合全网优质机会。
产品招聘中心面经会员专区简历解析Resume API
联系我们南京浅度求索科技有限公司admin@51mee.com
联系客服
51mee客服微信二维码 - 扫码添加客服获取帮助
© 2025 南京浅度求索科技有限公司. All rights reserved.
公安备案图标苏公网安备32010602012192号苏ICP备2025178433号-1