前几天看到sobug的漏洞时间出来了,看到大家都在做一些科普类的文章,且做得也比较细,本章就以弱验证码导致任意用户密码重置来与大家分享一下,弱验证码大家应该都能理解,一些网站会去使用4-6位的纯数字作为验证码。
本次案例就以短信找回密码弱验证码来进行切入,在这里笔者就做了一个php demo,尽可能会模拟真实的应用场景,首先看一下发送验证码的流程图如下:
判断验证码的流程如下:
一个看似很普通的流程,看图表达的已经很清楚了,来看一下发送验证码部分的核心代码:
$phone=$_POST['phone']; $time =$oMySQL->ExecuteSQL("SELECT * FROM repwd WHERE phone = ".$phone); $retime=date('Y-m-d H:i:s',time());//获取当前时间 $rand=rand(1000,9999);//随机的四位数 //检查数据库时间是否为空 if (count($time)== 4) { $hour=(strtotime($time['retime'])-strtotime($retime))%86400/3600;//计算时间差 if ($hour<=-1) {//如果时间超过了时间限制,则更新下验证码 sendsms($rand,$phone);//把四位随机数发送到手机上 $oMySQL->ExecuteSQL("UPDATE repwd SET code = ".$rand.",retime = now() WHERE phone = ".$phone); }else{//如果时间没有超过 sendsms($time['code'],$phone);//发送原来的四位随机数验证码 } }else{//如果不等于空,则说明这个账号没有被找回过 sendsms($rand,$phone);//发送验证码 $oMySQL->ExecuteSQL("INSERT INTO repwd (phone, code,retime) VALUES ('".$phone."', '".$rand."',now())"); }
再来看一下校验验证码部分的核心代码:
$phone=$_POST['mobile']; $code=$_POST['mobilecode']; $password = $_POST['password']; $time =$oMySQL->ExecuteSQL("SELECT * FROM repwd WHERE phone = ".$phone." and code=".$code); $retime=date('Y-m-d H:i:s',time());//获取当前时间 $hour=(strtotime($time['retime'])-strtotime($retime))%86400/3600;//计算时间差 if (count($time)== 4) { if ($hour<=-1) {//超过时间 $result = array ('Start'=>"请重新获取验证码"); echo json_encode($result); }else{//如果时间没有超过 $result = array ('Start'=>true); echo json_encode($result); } }else{ $result = array ('Start'=>'验证码错误!','Count'=>'0'); echo json_encode($result); }
可以看到整个流程下来会凸显几个主要的问题:
4位纯数字,验证码太短,不够复杂;
验证码校验次数没有进行限制,容易造成猜解;
没有对验证码发送次数作出限制,容易造成短信轰炸;
一个小时的验证码有效时间过长。
在实战的环境中,大家可能看不到源码,但是这个漏洞类型的测试方法比较简单,可以看一下具体的步骤,在测试的时候,先注册一个用户并绑定手机号码。直接切换到找回密码的界面:
然后可以看到手机收到短信,一般的验证码短信背后都会去跟有效时间,测试的短信截图如下:
单单看短信就可以得出来两个信息,验证码为4位纯数字、验证码有效期为1个小时,对于4位纯数字的验证码来说,假如进行穷举,3分钟时间内都绰绰有余了,确定下这些信息之后,接下来要确认的是,验证码输入完点击提交的时候,是否有此数限制,笔者通常的测试方法是手工故意先手工输错验证码5-7遍左右,如果没有提醒重新获取验证码或者弹出图片验证码给我们输入的话,一般情况下,可以证明这个验证码是可以进行猜解的,那么这个时候笔者就直接上burp进行测试了,把对应提交验证码的数据包拦截下来:
可以看到拦截的其中包含手机/验证码/密码,这里需要进行穷举的参数是mobilecode,不断的去猜解这个参数猜到对 >.<,将数据包发送intruder进行穷举,将mobilecode设置payload,如图:
在猜解这种纯数字的参数的时候,有很多的新手在设置的时候都会去找一个字典生成器,然后把0000-9999的数字生成到txt当中,然后导入burp中,其实这个功能burp就自带有,无需要再重新生成字典里,切换到payloads 设置如下:
如果嫌慢点话可以设置下线程:
设置完之后可以直接Sart Attack了,结果如下:
Start = true就是重置密码成功了。
本文简单的讲述了一下利用弱验证码的方式来重置任意用户密码,除了这个以外,这种类型还会存在在于某些地方,一些网站的抽奖页面,注册页面等,文章结尾我把测试的demo提供给大家,大家可以在自己的环境中搭建,短信接口的话需要自己去申请了 :)
Demo下载: http://pan.baidu.com/s/1jGCDaq6
[转载请注明来自 SOBUG漏洞时间 ]