AIGC标识 Streamlit路径遍历漏洞(CVE-2022-35918)

import requests
import sys
import urllib3

# 禁用不安全请求警告
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

def check_cve_2022_35918(target_url):
    """
    检测目标 Streamlit 应用是否存在 CVE-2022-35918 路径遍历漏洞
    :param target_url: 目标 Streamlit 应用的基础 URL (例如: http://localhost:8501)
    :return: 检测结果字符串
    """
    if not target_url.startswith(('http://', 'https://')):
        return "[-] 错误: URL 必须以 http:// 或 https:// 开头"

    # 确保 URL 末尾没有斜杠
    base_url = target_url.rstrip('/')
    
    # 构造测试 payload
    # 该漏洞通常涉及对静态资源路径的遍历尝试
    # 常见的测试路径是尝试访问 /static/ 之外的文件
    # 注意:实际漏洞利用可能涉及更复杂的路径构造,此处仅做基础连通性和版本指纹检查建议
    
    print(f"[*] 正在检测目标: {base_url}")
    
    try:
        # 1. 检查 Streamlit 是否正在运行
        resp = requests.get(f"{base_url}/", timeout=5, verify=False)
        if resp.status_code != 200:
            return f"[-] 目标不可达或返回状态码: {resp.status_code}"
        
        # 2. 尝试获取版本信息 (如果暴露)
        # Streamlit 通常在页面源码或特定接口中泄露版本
        # 这里我们主要依赖版本比对作为最安全的判断方式
        
        # 3. 模拟漏洞检测逻辑 (非破坏性)
        # 真正的 PoC 会尝试读取 /etc/passwd 或类似文件
        # 为了安全,我们只检查是否存在已修复版本的特征或已知漏洞版本的特征
        
        # 由于直接请求敏感文件可能被 WAF 拦截或产生日志,
        # 最佳实践是检查 Server 头或页面中的版本标识
        
        version = extract_version(resp.text)
        
        if version:
            print(f"[*] 检测到 Streamlit 版本: {version}")
            if is_vulnerable(version):
                return f"[!] 危险: 版本 {version} 存在 CVE-2022-35918 漏洞,建议立即升级到 1.11.1 或更高版本"
            else:
                return f"[+] 安全: 版本 {version} 已修复该漏洞或不受影响"
        else:
            # 如果无法获取版本,尝试发送一个无害的探测请求
            # 注意:以下路径仅为示例,实际漏洞利用路径可能不同
            probe_url = f"{base_url}/static/../README.md"
            resp_probe = requests.get(probe_url, timeout=5, verify=False, allow_redirects=False)
            
            # 如果返回 200 且内容包含 README 特征,可能存在遍历
            if resp_probe.status_code == 200 and "readme" in resp_probe.text.lower():
                 return "[!] 危险: 疑似存在路径遍历漏洞,请手动核查并升级"
            else:
                 return "[?] 未知: 无法确定版本,但未发现明显的简单遍历特征。建议强制升级到最新版。"

    except requests.exceptions.RequestException as e:
        return f"[-] 请求失败: {str(e)}"

def extract_version(html_content):
    """
    从 HTML 内容中提取 Streamlit 版本号
    """
    import re
    # 尝试匹配常见的版本标识模式
    match = re.search(r'Streamlit v(\d+\.\d+\.\d+)', html_content)
    if match:
        return match.group(1)
    return None

def is_vulnerable(version_str):
    """
    判断版本是否在受影响范围内 [0.63.0, 1.11.1)
    """
    try:
        parts = list(map(int, version_str.split('.')))
        if len(parts) < 3:
            return False
            
        major, minor, patch = parts, parts, parts
        
        # 受影响范围: >= 0.63.0 且 < 1.11.1
        if major == 0:
            if minor > 63:
                return True
            elif minor == 63:
                return True # 0.63.0 及以上
            else:
                return False # < 0.63.0
        elif major == 1:
            if minor < 11:
                return True
            elif minor == 11:
                if patch < 1:
                    return True
                else:
                    return False # >= 1.11.1
            else:
                return False # > 1.11.x
        else:
            return False # > 1.x.x
            
    except Exception:
        return False

if __name__ == "__main__":
    if len(sys.argv) != 2:
        print("用法: python cve_check.py <target_url>")
        print("示例: python cve_check.py http://localhost:8501")
        sys.exit(1)
        
    target = sys.argv[1]
    result = check_cve_2022_35918(target)
    print(result)

 

posted @ 2026-09-10 09:57  LalaTina  阅读(4)  评论(0)    收藏  举报