任意用户密码重置(一)

  泳少    编号: 030201    奖励 50 积分   2015.01.19   web安全 设计缺陷

前言

 

前几天看到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);	
}

 

 

可以看到整个流程下来会凸显几个主要的问题:

 

  1. 4位纯数字,验证码太短,不够复杂;

  2. 验证码校验次数没有进行限制,容易造成猜解;

  3. 没有对验证码发送次数作出限制,容易造成短信轰炸;

  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漏洞时间]

 

 

 


小智解读:

任意重置密码的案例有很多,例如很多程序员都喜欢把userid隐藏到重置密码界面中做用户身份识别,发送到邮箱的key采用可逆算法加密(如:base64),未加密明文是用户id或者其他用户身份标识等等,本文做抛砖引玉作用,如果你还有更多重置密码的奇*技巧,欢迎投稿 :)

全部评论 (10)

登录注册


px1624

无节操啊,竟然分开发。。

2015-01-19 23:21 1楼


泳少

@pxq1624。主要系列吧,你可以把它连载。无所谓。加上这个打算这个遇到加密的怎么搞。现在看看没必要了。不是所有人都是像你这么想的。如果说一个点只是真的一个点那就没必要了。一个点还得注意里面的细节问题。犹如你搞一个站。实际真的是搞站但是包含的技术很多。=_=

2015-01-20 09:47 2楼


double

洞主这核心代码有注入呐,

2015-01-20 11:01 3楼


漫步云端

这就是你写的?

2015-01-23 17:44 4楼


M4sk

黑阔

2015-01-31 17:53 5楼


da^liang

http://drops.wooyun.org/papers/2035 px曾经整理的漏洞利用以及挖掘思路,泳少单举了一例弄到代码层讲了下逻辑

2015-02-10 10:30 6楼


evil_webshell

不错,这个分开事例讲确实很好

2015-03-21 17:25 7楼


evil_webshell

不错,这个分开事例讲确实很好

2015-03-21 17:25 8楼


临天人

感觉这网站真的没人来了

2019-05-26 15:17 9楼


rouzi

如图设置六位payload后提示无效的数字设置该怎么办呢,大佬可以帮帮忙吗。

2019-11-30 23:37 10楼