0


Pikachu漏洞练习平台----验证码绕过(on server) 的深层次理解

在这里插入图片描述
其实这是一道很简单的题,题目中也给了提示:
在这里插入图片描述
提示的意思是验证码不会变,结合网上的一些解析也是对此直接默认了,但是这个验证码是怎么不变的,没有看到有人细说,也许这些思考对于一些人来说已经微不足道了,但是结合一些搭建网站前后端的知识,我想从一个初学者的角度更深层次的解释一下这个问题。
——————————————————————————————

解题方法

在这里插入图片描述
爆破是基于上一题对于用户名密码的简单爆破,这题关键在于有了验证码。
初步的试探一下,如果输错了验证码,不管用户名密码是什么,都会显示“验证码输入错误哦!”,然后验证码会刷新
输入错误验证码
显示相应文字
而把验证码输入正确,用户名密码不正确,就会显示“username or password is not exists~”,然后验证码也会刷新
正确输入了验证码
显示不同的文字
所以总结一下网站的展现的表象,这个验证码在两种情况下会变,第一种情况是刷新页面的时候,第二种情况是点击验证码图片的时候。

然后打开burpsuite按照正常顺序,打开代理,输入用户名、密码、验证码,点击“Login”,然后发的请求就会被burpsuite捕获到。
在这里插入图片描述
发现这个请求是POST,然后一共有四个参数分别是 username password vcode submit
其中submit是前端代码中在“Login”按钮里写死的

<inputclass="submit"name="submit"type="submit"value="Login">

而username与password是需要爆破的,所以想着这个vcode先不让他变,把这个请求送到Repeater里面去,先改变用户名和密码看一看响应的回来代码的变化,尤其是“Login”按钮下面那一行小字,看看是返回的文字是验证码不对还是用户名密码不对。
于是在Repeater中如下操作:
在这里插入图片描述
在左面的请求中,用户名、密码改成222,验证码(vcode)是正确的,只不过刷新了页面不是原来的验证码了。
在右面的响应中,在html代码中找到那个“Login”按钮,下面显示的是用户名密码不对。
如是再更改几次用户名密码,验证码vcode不改变,结果还是显示用户名密码不对,说明验证码一直是对的。
由此就知道了,在burpsuite里面操作这期间,没有碰浏览器,验证码一直是没有变的。
所以此时把请求发送到intruder来进行爆破,由于是用户名和密码两个参数的爆破,需要选择pitchfork模式,将username和password添加进参数。
在这里插入图片描述
分别为用户名和密码选择爆破字典,然后进行爆破。
在这里插入图片描述
在这里插入图片描述
这里字典简单了些,就是为了做题。
结果如下:
在这里插入图片描述
然后发现admin和123456组合的响应报文长度不一样,点进去看发现他是“login success”字样,所以比别的“username or password is not exists~”字样会少一点字。
在这里插入图片描述
到此这道题就做完了。

深度思考

那为啥这个验证码当时在burpsuite里就不变呢?单单的试一试发现他不变有点瞎猫碰死耗子的侥幸,感觉这道题和闹着玩一样。但其实仔细深究的话,这里面知识还是不少的。
这个pikachu平台我是搭建在自己电脑上的,随时可以看源代码,这个问题的答案就是藏在源代码里,所以就先细细的分析一下代码。

首先要知道一个事情,这个网站由php、html、js等代码写成的,php属于后端代码,由服务器来解析运行;html、js是前端代码,在浏览器(客户端)来解析运行。所以在网页中右键,再点击查看网页源代码之后,能看见的只有html和js代码,以及php代码运行过之后对html代码的一些更改、添加等效果。要是想看后端的php代码就要去本地文件夹中去看。
查看浏览器中的验证码图片这个区域的源代码(对应的后端文件是bf_server.php),观察到img标签中的src指向showvcode.php;后面的onclick事件是对于showvcode.php的重新请求,后面用get方法传日期那个没有用,后面代码可以看出来。
在这里插入图片描述
在本地文件中找到这个文件,这是pikachu作者的源文件:
showvcode.php

<?phpsession_start();include_once'function.php';//$_SESSION['vcode']=vcode(100,40,30,4);$_SESSION['vcode']=vcodex();//验证码绕过 on server 这里其实还是有一个问题,就是服务端将验证码字符串以明文COOKIE的方式给了前端,那验证码还有什么鸟意义。。。setcookie('bf[vcode]',$_SESSION['vcode']);?>

发现这个showvcode.php调用了function.php中的vcodex函数,然后执行vcode()函数的返回值赋值给session会话中的’vcode’参数,而onclick事件里面用get方法新传入的参数在这里没用到,效果和直接请求showvcode.php一样。
再去看源代码:
function.php

functionvcodex(){$string="abcdefghijklmnopqrstuvwxyz0123456789";$str="";for($i=0;$i<6;$i++){$pos=rand(0,35);$str.=$string{$pos};}//session_start();//$_SESSION['img_number'] = $str;$img_handle=Imagecreate(80,20);//图片大小80X20$back_color=ImageColorAllocate($img_handle,255,255,255);//背景颜色(白色)$txt_color=ImageColorAllocate($img_handle,0,0,0);//文本颜色(黑色)//加入干扰线for($i=0;$i<3;$i++){$line=ImageColorAllocate($img_handle,rand(0,255),rand(0,255),rand(0,255));Imageline($img_handle,rand(0,15),rand(0,15),rand(100,150),rand(10,50),$line);}//加入干扰象素for($i=0;$i<200;$i++){$randcolor=ImageColorallocate($img_handle,rand(0,255),rand(0,255),rand(0,255));Imagesetpixel($img_handle,rand()%100,rand()%50,$randcolor);}Imagefill($img_handle,0,0,$back_color);//填充图片背景色ImageString($img_handle,28,10,0,$str,$txt_color);//水平填充一行字符串ob_clean();// ob_clean()清空输出缓存区    header("Content-type: image/png");//生成验证码图片    Imagepng($img_handle);//显示图片return$str;}

这一段代码主要功能很简单,先从26个字母以及10个数字中随机产生6个字符,然后开始画图,加一些干扰线和干扰像素,再把这6个字符画进去,最后把图片显示出来。
至此搞明白了这个img标签的运行方式,重新刷新页面的时候会请求一次随机的验证码;点击一下图片也会重新请求一下验证码。
但是到这还是不能解决在burpsuite里,验证码为什么不变的问题。
刚才是在前端看的bf_server.php只有html和js,还没看到后端php代码,所以得去分析一下后端php。

/**
 * Created by runner.han
 * There is nothing new under the sun
 */
······ //不是重点的代码省略掉了//下面是重点代码$html="";if(isset($_POST['submit'])){if(empty($_POST['username'])){$html.="<p class='notice'>用户名不能为空</p>";}else{if(empty($_POST['password'])){$html.="<p class='notice'>密码不能为空</p>";}else{if(empty($_POST['vcode'])){$html.="<p class='notice'>验证码不能为空哦!</p>";}else{//              验证验证码是否正确if(strtolower($_POST['vcode'])!=strtolower($_SESSION['vcode'])){$html.="<p class='notice'>验证码输入错误哦!</p>";//应该在验证完成后,销毁该$_SESSION['vcode']}else{$username=$_POST['username'];$password=$_POST['password'];$vcode=$_POST['vcode'];$sql="select * from users where username=? and password=md5(?)";$line_pre=$link->prepare($sql);$line_pre->bind_param('ss',$username,$password);if($line_pre->execute()){$line_pre->store_result();//虽然前面做了为空判断,但最后,却没有验证验证码!!!if($line_pre->num_rows()==1){$html.='<p> login success</p>';}else{$html.='<p> username or password is not exists~</p>';}}else{$html.='<p>执行错误:'.$line_pre->errno.'错误信息:'.$line_pre->error.'</p>';}}}}}}

这一段重点代码从上到下分析,首先接收了POST表单,三个连续判断username、password、验证码都不能为空,然后判断验证码是否正确:
如果错误,就将返回“输入验证码错误哦!”,但是并没有对验证码进行销毁或更改,作者自己在注释里面也写到了;
如果验证码正确,将进行后续的调取数据库,验证用户名密码等操作,最后成功与否都是用户名密码的正确与否问题,都与验证码无关了。

到此为止bf_server.php中的php代码执行完毕,经过了一系列判断,发现只要验证码通过了第一次判断,后面用户名密码是否正确都不会对验证码进行更改。
但是为什么我们在做题页面,输入正确验证码,填上用户名密码,点击“Login”之后,页面一刷新验证码就变了呢?
别忘了bf_server.php中,紧接着php代码的下面还有html代码和js代码,一旦这些代码作为响应response回传到浏览器,浏览器就会解析,相应的那个验证码的img标签就会又一次对后端的showvcode.php发起请求,从而返回一个新的验证码,也改变了该用户session会话中的’vcode’参数,也就是说此是前后端验证码都改变了。
我按我的理解画了张图:
请添加图片描述
正是因为所有在burpsuite里面测试后得到的响应报文都没有发回到客户端那里,也就没有解析html和js代码,所以验证码一直没有变。我们就可以在burpsuite里随意的更改用户名密码来爆破,因为有这么一个代理的墙挡着,报文发不过去,客户端一直在loading转圈圈。

以上就是我对这道题的理解,知识很基础,不过我感觉是一个容易被忽略的点,希望对xdm有帮助。

标签: 前端 php 安全

本文转载自: https://blog.csdn.net/BengDouLove/article/details/126320814
版权归原作者 Bengd0u 所有, 如有侵权,请联系我们删除。

“Pikachu漏洞练习平台----验证码绕过(on server) 的深层次理解”的评论:

还没有评论