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


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

    解题方法

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

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

    <input class="submit" name="submit" type="submit" value="Login">
    
    • 1

    而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

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

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

    function vcodex(){
    	
    	$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;
    	
    }
    
    • 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
    • 36
    • 37

    这一段代码主要功能很简单,先从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 .= "

    用户名不能为空

    "
    ; } else { if (empty($_POST['password'])) { $html .= "

    密码不能为空

    "
    ; } else { if (empty($_POST['vcode'])) { $html .= "

    验证码不能为空哦!

    "
    ; } else { // 验证验证码是否正确 if (strtolower($_POST['vcode']) != strtolower($_SESSION['vcode'])) { $html .= "

    验证码输入错误哦!

    "
    ; //应该在验证完成后,销毁该$_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.='

    login success

    '
    ; }else{ $html.= '

    username or password is not exists~

    '
    ; } }else{ $html.= '

    执行错误:'.$line_pre->errno.'错误信息:'.$line_pre->error.'

    '
    ; } } } } } }
    • 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
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48

    这一段重点代码从上到下分析,首先接收了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有帮助。

  • 相关阅读:
    C#,数值计算——插值和外推,Base_interp的计算方法与源程序
    MacOS - ToDesk 无法远程操控鼠标键盘解决方案
    Java内部类分类
    java中的原子操作类
    vue3使用v-model控制子组件进行双向数据绑定
    【软考】敏捷方法
    超详细教程:在Blender中打造毛毡风格角色
    论坛议程|COSCon'23开源商业(V)
    QT中Shader类与多VAO、VBO的使用
    小红书种草步骤:小红书种草怎么做?
  • 原文地址:https://blog.csdn.net/BengDouLove/article/details/126320814