验证码安全 - Pikachu简单学习测试
简述
验证码(CAPTCHA)是Completely Automated Public Turing test to tell Computers and Humans Apart(全自动区分计算机和人类的图灵测试)的缩写
分类:
- 图片(易被OCR技术破解)
- 手机短信(基本是最有效的)
- 行为式
- 滑动式
- 点触式
- 语音
- 视频(验证码嵌入到视频中)动态变换,有效防范字典、穷举
常见缺陷:
- 验证码无效
- 验证码由客户端生成验证
- 验证码回显
- 验证码固定(重用)
- 验证码可猜测
- 验证码可绕过
- 删除cookie
- 验证码为空
- 删除验证码参数
测试:Pikachu
下载:
https://github.com/zhuifengshaonianhanlu/pikachu
注意:要抓包的时候如果初始地址是localhost 可能抓不到,要改一下地址
用192的那个地址
验证码绕过(on server)
步骤1:
先随便填个账号密码和正确的验证码

再填个错误的验证码(刚刚正确的 sgdtj0先记着)

结合这两图,发现应该是先检查验证码,在检查用户名密码
步骤2:
尝试判断是否有验证码固定的漏洞(验证码重用)

这里之前用过的正确的验证码,密码随便填一个,发现验证码刷新后,刚刚使用的验证码还能用,存在验证码固定的漏洞!
步骤3:
尝试爆破


嘻嘻这里账号密码我看网上的这里只是作演示账号用的BP里面的username list,密码直接用的123456
这里遇到点小问题,如果爆破久了,网站会报错

步骤4:
这里在看看源码吧
1 if(isset($_POST['submit'])) { 2 if (empty($_POST['username'])) { 3 $html .= "<p class='notice'>用户名不能为空</p>"; 4 } else { 5 if (empty($_POST['password'])) { 6 $html .= "<p class='notice'>密码不能为空</p>"; 7 } else { 8 if (empty($_POST['vcode'])) { 9 $html .= "<p class='notice'>验证码不能为空哦!</p>"; 10 } else { 11 // 验证验证码是否正确 12 if (strtolower($_POST['vcode']) != strtolower($_SESSION['vcode'])) { 13 $html .= "<p class='notice'>验证码输入错误哦!</p>"; 14 //应该在验证完成后,销毁该$_SESSION['vcode'] 15 }else{ 16 17 $username = $_POST['username']; 18 $password = $_POST['password']; 19 $vcode = $_POST['vcode']; 20 21 $sql = "select * from users where username=? and password=md5(?)"; 22 $line_pre = $link->prepare($sql); 23 24 $line_pre->bind_param('ss',$username,$password); 25 26 if($line_pre->execute()){ 27 $line_pre->store_result(); 28 //虽然前面做了为空判断,但最后,却没有验证验证码!!! 29 if($line_pre->num_rows()==1){ 30 $html.='<p> login success</p>'; 31 }else{ 32 $html.= '<p> username or password is not exists~</p>'; 33 } 34 }else{ 35 $html.= '<p>执行错误:'.$line_pre->errno.'错误信息:'.$line_pre->error.'</p>'; 36 } 37 } 38 } 39 } 40 } 41 }
先用户名和密码判空,再是验证码判空,这里代码也注释了,应该销毁$_SESSION
如果没销毁,就会被重复利用,导致存在爆破的风险
验证码(on client)
主要漏洞:在客户端生成验证码并在前端检查

直接抓包分析


由两图可知,这里已经不需要验证码了,这里验证码是客户端生成验证的,所以后面爆破就不啰嗦了

浙公网安备 33010602011771号