从某cmsV4.1.0 sql注入漏洞看程序开发安全隐患
字数 1114 2025-08-27 12:33:49

CMS V4.1.0 SQL注入漏洞分析与安全开发实践

一、CMS防护机制分析

1.1 程序入口过滤机制

set_globals方法

  • 将GET与POST参数赋值到$GLOBALS数组
  • 使用gpc_stripslashes处理传入键值
  • 特殊行为:当MAGIC_QUOTES_GPC开启时,去除其添加的转义符

input方法

  • 对$GLOBALS数组中的值通过sql_replace进行SQL过滤
  • 开发者意图:保持原始输入,按需进行特定过滤

sql_replace方法

str_replace(array("'",'"',"(",")",";"),"",$value)
  • 对特殊字符(', ", (, ), ;)进行置空处理

safe_htm方法

  • 对HTML特殊字符进行转义,防止XSS攻击

1.2 数据库操作类过滤

insert/update方法

  • 对传入数组的值部分进行过滤处理
  • 使用escape_string方法进行转义

二、安全漏洞分析

2.1 第一类安全隐患:过滤方法使用不当

典型漏洞示例

文件:/api/sms_check.php

$code = strip_tags($GLOBALS['param']);  // 错误:直接使用$GLOBALS
// 正确做法应为:
$code = strip_tags(input('param'));

漏洞原理

  1. 直接使用$GLOBALS获取用户输入,绕过input方法过滤
  2. 参数直接拼接SQL语句导致注入

注入Payload

http://example.com/api/sms_check.php?param=1' and updatexml(1,concat(0x7e,(SELECT @@version),0x7e),1)-- 

2.2 第二类安全隐患:键名过滤缺失

典型漏洞示例

文件:/coreframe/app/content/admin/category.php

$formdata = $GLOBALS['form'];  // 直接接收用户输入数组
$this->db->insert($formdata);  // 键名未过滤

漏洞原理

  1. 数据库操作类只过滤数组值,不过滤键名
  2. 通过控制数组键名实现注入

注入Payload

&form[seo_description`)values(updatexml(1,concat(0x7e,version(),0x7e),1))#]=666

三、安全开发实践指南

3.1 输入处理规范

  1. 统一输入入口:所有用户输入必须通过input方法获取
  2. 避免直接使用$_GET$_POST$GLOBALS等原生变量
  3. 二次过滤原则:避免重复过滤导致数据损坏

3.2 SQL注入防护

  1. 参数化查询:优先使用预处理语句
  2. 全面过滤:键名和键值都需要过滤
  3. 转义策略
    function escape_input($input) {
        if(is_array($input)) {
            return array_map('escape_input', $input);
        }
        return str_replace(array("'",'"',"(",")",";","\\"), "", $input);
    }
    

3.3 安全编码检查清单

  1. [ ] 所有SQL查询使用参数化或严格过滤
  2. [ ] 数组类型输入同时过滤键名和键值
  3. [ ] 避免在过滤后执行解码操作(如urldecode)
  4. [ ] 关键操作进行代码审计

3.4 安全函数实现示例

/**
 * 安全获取输入
 * @param string $key 参数名
 * @param string $type 输入类型(get/post)
 * @return mixed
 */
function safe_input($key, $type = 'get') {
    $value = $type == 'get' ? $_GET[$key] : $_POST[$key];
    
    // 去除魔术引号
    if(get_magic_quotes_gpc()) {
        $value = stripslashes($value);
    }
    
    // SQL过滤
    $value = str_replace(array("'",'"',"(",")",";","\\"), "", $value);
    
    // HTML过滤
    $value = htmlspecialchars($value, ENT_QUOTES);
    
    return $value;
}

/**
 * 安全数据库插入
 * @param array $data 数据数组
 */
function safe_insert($table, $data) {
    $fields = array();
    $values = array();
    
    foreach($data as $key => $value) {
        $fields[] = '`'.str_replace('`', '', $key).'`';  // 过滤键名
        $values[] = "'".mysql_real_escape_string($value)."'";  // 过滤键值
    }
    
    $sql = "INSERT INTO {$table} (".implode(',', $fields).") VALUES (".implode(',', $values).")";
    return execute($sql);
}

四、总结与建议

  1. 框架层面:建立统一的输入输出处理机制
  2. 开发层面:制定严格的安全编码规范
  3. 审计层面:重点关注:
    • 直接使用$GLOBALS/$_GET/$_POST的地方
    • 数组键名直接用于SQL拼接的地方
    • 过滤后执行解码操作的地方
  4. 运维层面:关闭magic_quotes_gpc,统一由应用层处理

通过系统化的安全防护策略和严格的编码规范,可以有效避免此类SQL注入漏洞的产生。

CMS V4.1.0 SQL注入漏洞分析与安全开发实践 一、CMS防护机制分析 1.1 程序入口过滤机制 set_ globals方法 将GET与POST参数赋值到$GLOBALS数组 使用 gpc_stripslashes 处理传入键值 特殊行为:当 MAGIC_QUOTES_GPC 开启时, 去除 其添加的转义符 input方法 对$GLOBALS数组中的值通过 sql_replace 进行SQL过滤 开发者意图:保持原始输入,按需进行特定过滤 sql_ replace方法 对特殊字符( ' , " , ( , ) , ; )进行置空处理 safe_ htm方法 对HTML特殊字符进行转义,防止XSS攻击 1.2 数据库操作类过滤 insert/update方法 对传入数组的值部分进行过滤处理 使用 escape_string 方法进行转义 二、安全漏洞分析 2.1 第一类安全隐患:过滤方法使用不当 典型漏洞示例 文件: /api/sms_check.php 漏洞原理 直接使用 $GLOBALS 获取用户输入,绕过 input 方法过滤 参数直接拼接SQL语句导致注入 注入Payload 2.2 第二类安全隐患:键名过滤缺失 典型漏洞示例 文件: /coreframe/app/content/admin/category.php 漏洞原理 数据库操作类只过滤数组值,不过滤键名 通过控制数组键名实现注入 注入Payload 三、安全开发实践指南 3.1 输入处理规范 统一输入入口 :所有用户输入必须通过 input 方法获取 避免直接使用 : $_GET 、 $_POST 、 $GLOBALS 等原生变量 二次过滤原则 :避免重复过滤导致数据损坏 3.2 SQL注入防护 参数化查询 :优先使用预处理语句 全面过滤 :键名和键值都需要过滤 转义策略 : 3.3 安全编码检查清单 [ ] 所有SQL查询使用参数化或严格过滤 [ ] 数组类型输入同时过滤键名和键值 [ ] 避免在过滤后执行解码操作(如urldecode) [ ] 关键操作进行代码审计 3.4 安全函数实现示例 四、总结与建议 框架层面 :建立统一的输入输出处理机制 开发层面 :制定严格的安全编码规范 审计层面 :重点关注: 直接使用 $GLOBALS / $_GET / $_POST 的地方 数组键名直接用于SQL拼接的地方 过滤后执行解码操作的地方 运维层面 :关闭 magic_quotes_gpc ,统一由应用层处理 通过系统化的安全防护策略和严格的编码规范,可以有效避免此类SQL注入漏洞的产生。