漏洞重温之sql注入(四)
sqli-labs通关之旅
Less-16
进入第十六关,首先可以看到网页上有登录选项。猜测跟上一关内容应该一样。
不多废话,直接看源码。
首先,我们注意这几条代码。
$uname='"'.$uname.'"';
$passwd='"'.$passwd.'"';
@$sql="SELECT username, password FROM users WHERE username=($uname) and password=($passwd) LIMIT 0,1";
如果看过我写的前几篇文章,应该明白我注意这三条代码的原因,因为我们的目的是为了闭合原有的sql语句,拼接我们希望系统执行的语句,所以要进行sql注入,我们首先要闭合原有内容。
通过上面三条代码,我们知道,该处闭合,我们需要使用 ") 进行闭合。
又因为网页是使用post请求获取参数的,所以我们可以利用抓包工具在数据包中进行注入,也可以使用hackbar的post data属性直接在网页进行注入。
我使用的是后者。
随后,我们可以查看if代码块里面的内容,我们可以看到,虽然两块代码是有足够区别的,但是却不能直接返回我们希望返回的信息,所以这里我们只能利用盲注。
构造测试payload:
1") or 1=1 --
1") or 1=2 --
如果上面两条代码都成功执行,并且网页返回有明显区别,那么我们就可以直接使用布尔型盲注手法进行注入。
可以看到,区别很明显,所以我们可以使用布尔型盲注手法获取我们想要的数据,这里因为步骤比较繁琐,我之前的文章里有详细步骤,这里就不多赘述。
第十六关,通关。
Less-20
前几关因为我对报错注入的函数的理解个人认为尚且不足,17.18.19三关我会在研究之后总结文章补上,所以先看20关。
进入二十关,首先可以看到,网页和前面几关并没有太大区别。
但是代码的位置我们却可以明显的看到问题。
首先,我们可以看到,网页先封装了一个check_input函数。
在这个函数中,使用了mysql_real_escape_string这个函数对值进行转义。
然后,我们看登录页面代码。
网站在登录页面代码中,调用了这个函数将我们输入的uname和passwd进行转义,所以一般情况来说,我们无法在这种情况下进行注入。
因为我们输入的代码,在转义之后,无法发挥我们希望他发挥的作用。
但是,接着往下看,我们可以发现另外一个问题。
当我们登录成功后,网站利用我们提交的数据生成了一个$cookee参数,而我们访问登录成功后的页面时,我们的个人信息会被网站直接利用$cookee参数从数据库查询。
这也就说明了,虽然在登录页面,我们无法进行sql注入,但是在登录成功后,我们却可以利用$cookee参数完成注入攻击的目的。
同时,我们观察这条代码:
$sql="SELECT * FROM users WHERE username='$cookee' LIMIT 0,1";
这条代码告诉我们,如果想要利用$cookee参数完成注入,我们必须要使用单引号进行闭合。
所以,首先我们先利用Dumb/Dumb账号登录。
可以看到,我们的信息会被网站反馈回来。
因为我们需要利用cookie进行注入,刷新页面,使用burp抓包。
直接在uname参数后面,按照联合查询的方式构造语句。
payload:
' and 1=1 --
' and 1=2 --
可以发现,网站因为我们代码不同,返回的结果也不同,继续注入。
payload:
' order by 3 --
' and 1=2 union select 1,2,3 --
如果对于剩下的操作还不熟悉的话,可以多看看我前面几关通关过程。
第二十关,通关。
Less-21
二十一关页面和20关一致,查看源码。
登录页面代码是一样的,所以这一关也需要在登录之后利用$cookee参数进行注入。
但是这里我们要注意两个代码。
$cookee = base64_decode($cookee);
$sql="SELECT * FROM user WHERE username=('$cookee') LIMIT 0,1";
第一条代码,明确的告诉了我们,这一关的cookee参数使用base64加密了,同时,第二条代码告诉我,这里的闭合,需要使用')。
先登录,然后刷新页面抓包。
我们将uname后面的值复制之后进行解码。
得到了我们之前登录使用的用户名,也就可以确认,如果我们想要利用cookee参数完成注入,那么我们的payload也需要使用base64进行加密。
将加密后的代码复制到uname后面,即可完成注入。
第二十一关,通关。
Less-22
这一关依然只需要关注几行代码。
$cookee = base64_decode($cookee);
$cookee1 = '"'. $cookee. '"';
$sql="SELECT * FROM users WHERE username=$cookee1 LIMIT 0,1";
首先,第一行告诉我们,这里依然使用的是base64加密。第二行和第三行告诉我们,想要完成闭合,需要使用双引号。
登录,抓包,构造payload:
Dumb" and 1=2 union select 1,version(),database() --
二十二关,通关。
Less-23
进入二十三关,页面直接显示输入id参数,直接可以判断该位置是get型注入。
给出参数之后,直接查看源码。
可以看到,网站使用了preg_replace函数将# 和 -- 两个注释符号替换为空,这就导致了我们无法使用注释符号来进行注入,但并非无法注入。
首先我们要清楚,我们使用注释符号的原因是因为我们需要闭合原有的sql语句,需要使用包裹参数值的符号进行闭合,但是我们输入闭合之后,又会导致原本的语句多出一个符号导致代码出错,所以需要使用注释来将多余的符号注释掉。
但是,如果我们构造的代码可以直接利用到闭合的符号,那就不需要注释了。
构造payload:
-1' union select 1,version(),3 or '1' = '1
这里,要注意两点。
首先,我们使用的是union联合查询语句,所以,我们需要让原本的语句执行错误,这里我们可以直接将参数改为负数,或者可以在参数后面跟上 and 1=2来达到目的。
其次,我们需要的是让闭合之后,单引号不再多余,这里我使用的是'1'='1'的方式,之所以使用or连接符,是因为我们需要执行的代码在前,我们知道代码是没有错误的,所以or后面理论上只要可以让闭合符不再多余,拼接什么都可以。
当然,这只是一种方法,也是我在面对问题的时候第一个想到的办法,如果有其他更好的办法,可以联系我,再学习研究之后,我会再次对该关卡进行总结。
第二十三关,通关。