SQL注入入门与防御
admin
2026-10-27 09:40
19人看过
免费
# SQL注入入门与防御(软件设计师/安全审计通用笔记)
> SQL注入(SQLi)CWE-89:**攻击者将SQL代码插入应用输入参数,后端未做安全处理,直接拼接到SQL语句,被数据库执行**。
> 核心本质:**把用户可控输入,当成SQL代码执行;业务混淆了「数据」和「代码」边界**
## 一、简单原理示例
原始业务逻辑:根据id查询用户
```java
// 危险写法:字符串拼接
String sql = "select * from user where id = " + userInput;
```
攻击者传入:`1 or 1=1`
拼接后SQL变成:
```sql
select * from user where id = 1 or 1=1
```
条件永远成立,查出全部用户数据。
字符型注入示例(带单引号闭合)
```java
String sql = "select * from user where name = '" + userInput + "'";
```
输入payload:`' or 1=1 -- `
拼接结果:
```sql
select * from user where name = '' or 1=1 -- '
```
`--` 后面内容作为注释,闭合原有单引号,实现脱库。
## 二、SQL注入常见分类
1. **联合查询注入 Union Select**
`union select 1,version(),database()`,把查询结果和原查询合并,读取库名、版本、表、字段。
> 前提:前后查询列数一致,页面会回显查询结果(回显型注入)
2. **布尔盲注**
页面**不直接返回数据**,但页面内容根据SQL真假变化。
payload:`' and length(database())>5 -- `,通过页面正常/异常判断条件真假,逐字符猜内容。
3. **时间盲注**
页面无回显、无布尔差异;使用`sleep(5)`,通过响应延迟判断语句是否执行。
payload:`' and sleep(5) -- `
4. **报错注入**
利用数据库报错函数(updatexml、extractvalue),报错信息带出查询数据。
适用于页面输出数据库错误信息场景。
5. **二次注入**(进阶,前面笔记讲过)
payload第一次入库被转义,后续读取库中数据直接拼接SQL触发注入。
> 补充:堆叠注入 `;` 分号,执行多条SQL;部分数据库支持。
## 三、注入产生必备2个条件
1. 用户可控参数拼入SQL语句
2. 没有使用**预编译参数化查询**
## 四、识别测试(授权测试场景)
### 基础测试Payload
1. 单引号测试:`'`
页面出现数据库报错、语法错误 → 大概率存在注入
2. 逻辑判断:`' and 1=1--`、`' and 1=2--`
对比两个请求页面返回差异(布尔盲注)
3. 延时测试:`' and sleep(3)--`,观察响应时间(时间盲注)
### 注入点常见位置
GET参数、POST表单、JSON参数、Cookie、HTTP请求头(User-Agent/Referer)
## 五、防御方案(优先级从高到低)
### ✅ 1. 参数化预编译查询(治本,首选)
原理:SQL语句结构预先发送给数据库,参数单独传递;**参数永远被当做纯数据,不会解析为SQL代码**。
MyBatis示例:
```xml
select * from user where id = #{userId}
```
```xml
select * from user where id = ${userId}
```
Java JDBC原生预编译示例:
```java
String sql = "select * from user where name = ?";
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setString(1, userInput); // 参数单独传入,不会执行SQL
```
> 注意:表名、排序字段无法用占位符绑定,这类场景**必须使用白名单**,不能直接拼接用户输入。
### ✅ 2. 输入校验(辅助防护,不能单独依靠)
- 数值类参数:正则仅允许数字
- 字符串业务:白名单,只允许业务规定字符;**黑名单(过滤or/union/select)极易被绕过**
### ✅ 3. 最小权限原则(缩小危害)
数据库账号权限收紧:
- Web业务账号,**禁止drop、alter、create**等高权限
- 只授予业务必需表select/insert/update,禁止访问系统库information_schema
### ✅ 4. 关闭详细数据库报错
不要把原生SQL语法错误、表名、字段信息返回前端,防止攻击者利用报错注入。统一返回自定义错误页。
### ✅ 5. WAF Web应用防火墙(兜底辅助)
拦截union、sleep、单引号等注入特征。
> WAF仅辅助,变形注入容易绕过,**不能替代代码层预编译**
## 六、常见误区
1. ❌ 前端过滤特殊字符就能防注入:前端校验客户端可控,可以抓包修改绕过
2. ❌ 使用ORM就不会注入:MyBatis `${}`、原生raw sql拼接输入,依然会注入
3. ❌ 转义单引号就安全:存在二次注入、编码绕过等场景,转义不是根治方案
4. ❌ 不回显页面就不存在注入:布尔盲注、时间盲注无直接数据回显,依然可脱库
## 七、漏洞笔记模板(和前面漏洞格式统一)
漏洞名称:结构化查询语言注入(SQL Injection CWE-89)
漏洞类型:注入漏洞
风险等级:高危
前置权限:可提交可控请求参数
原理:应用将用户可控输入直接拼接进SQL语句,未使用预编译,攻击者可构造恶意SQL片段,被数据库执行,读取/修改数据库数据。
复现步骤:
1. 在参数位置提交单引号`'`,触发数据库语法报错
2. 构造and 1=1 / and 1=2 payload,观察页面差异
3. 使用union/时间盲注读取数据库信息
缓解方案:临时部署WAF拦截注入特征;关闭详细数据库报错
永久修复:全部SQL使用预编译参数化查询;数据库账号最小权限;输入白名单校验
## 八、蓝队日志/审计要点
- 监控请求参数包含 union, select, sleep, extractvalue, updatexml
- 监控数据库大量异常查询、批量查询information_schema
- 审计代码:搜索代码中字符串拼接SQL、Mybatis `${`
版权声明:倡导尊重与保护知识产权。未经许可,任何人不得复制、转载或以其他方式使用本站原创内容。