mysql注入在PHP代码层面的防御手段
字数 1217 2025-08-15 21:34:04
MySQL注入在PHP代码层面的防御手段
1. SQL注入基础概念
1.1 什么是SQL注入
SQL注入是指服务端没有对用户提交的参数进行严格的过滤,导致攻击者可以将SQL语句插入到可控参数中,改变原有SQL语义结构,从而执行攻击者预期的操作。
1.2 SQL注入探测方法
-
判断数据库类型:通过端口、报错信息等
- PHP: MySQL
- ASP: SQL Server
- ASPX: SQL Server
- JSP: MySQL或Oracle
-
寻找SQL注入点:
- 与数据库交互的可控参数:GET、POST、COOKIE、HTTP头
- 确定注入点的核心思想是判断插入的数据是否被当做SQL语句执行(可使用简单算术运算测试)
2. SQL注入防御原理
2.1 核心防御机制
-
SQL语句预编译和绑定变量
- Web应用向数据库传递语句模板
- 数据库对模板进行编译(编译后语义不会改变)
- 变量绑定:变量只会被当做数据识别,不会被作为语义结构识别
- 执行SQL语句
-
核心问题:数据和代码的混淆
3. PDO防御机制
3.1 PDO简介
PHP数据对象(PDO)扩展为PHP访问数据库定义了一个轻量级的一致接口,提供了数据访问抽象层。
3.2 PDO安全相关设置
-
PDO::ATTR_EMULATE_PREPARES- 模拟预编译- False:不存在SQL注入
- True:PDO并非真正预编译,而是将输入统一转化为字符型并转义特殊字符(GBK编码下存在宽字节注入风险)
-
PDO::ATTR_ERRMODE- 报错- 设置为True可能会泄露信息
-
PDO::MYSQL_ATTR_MULTI_STATEMENTS- 多语句执行- True且模拟预编译也为True时,存在宽字节+堆叠注入双重漏洞
3.3 PDO安全使用建议
- 合理、安全地使用GBK编码
- 使用PDO时将模拟预编译设置为false
- 可采用Prepare Statement手动预编译防御SQL注入
3.4 PDO代码示例
// 示例1
$dbh = new PDO('mysql:dbname=testdb;host=127.0.0.1', $user, $password);
$stmt = $dbh->prepare('INSERT INTO REGISTRY (name, value) VALUES (:name, :value)');
$stmt->bindParam(':name', $name);
$stmt->bindParam(':value', $value);
// 插入一行
$name = 'one';
$value = 1;
$stmt->execute();
// 示例2
$dbh = new PDO('mysql:dbname=testdb;host=127.0.0.1', $user, $password);
$stmt = $dbh->prepare('UPDATE people SET name = :new_name WHERE id = :id');
$stmt->execute(array('new_name' => $name, 'id' => $id));
4. ODBC防御机制
4.1 ODBC简介
ODBC是一种应用程序编程接口(API),用于连接到数据源(如MS Access数据库)。
4.2 ODBC代码示例
// 示例1
$stmt = odbc_prepare($conn, 'SELECT * FROM users WHERE email = ?');
$success = odbc_execute($stmt, array($email));
// 示例2
$dbh = odbc_exec($conn, 'SELECT * FROM users WHERE email = ?', array($email));
$sth = $dbh->prepare('SELECT * FROM users WHERE email = :email');
$sth->execute(array(':email' => $email));
5. MySQLi防御机制
5.1 MySQLi简介
MySQLi函数允许访问MySQL数据库服务器。
5.2 MySQLi代码示例
$stmt = $db->prepare('update name set name = ? where id = ?');
$stmt->bind_param('si', $name, $id);
$stmt->execute();
6. 框架中的防御机制
6.1 WordPress示例
global $wpdb;
$wpdb->query(
$wpdb->prepare(
'SELECT name FROM people WHERE id = %d OR email = %s',
$person_id, $person_email
)
);
global $wpdb;
$wpdb->insert(
'people',
array(
'person_id' => '123',
'person_email' => 'bobby@tables.com'
),
array(
'%d', '%s'
)
);
7. 关键防御总结
- 优先使用预编译语句:PDO、MySQLi等都支持预编译
- 禁用模拟预编译:PDO中设置
PDO::ATTR_EMULATE_PREPARES为false - 谨慎处理错误信息:避免泄露敏感信息
- 限制多语句执行:除非必要,否则禁用
- 字符编码安全:特别注意GBK等宽字节编码的潜在风险
- 框架安全使用:遵循框架提供的安全API
通过以上措施,可以有效地防御PHP应用中的MySQL注入攻击。