短信验证码暴力突破
考点:短信验证码爆破
首先查看提示:

可以知道是不会真的发送验证码,需要进行前端代码审计来绕过
所以我们可以随便输个手机号试试就行

这里点击发送后抓包

然后输验证码再抓包

为什么会是这个格式呢?我们看看前端代码
send部分:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| function sendCode() { const phone = document.getElementById('phone').value.trim(); if (!validatePhone(phone)) { showMsg('请输入有效的手机号'); shakeInput('phone'); return; } showMsg(''); const btn = document.getElementById('sendCodeBtn'); btn.disabled = true; btn.innerText = '发送中...';
fetch('/send', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ phone }) }) .then(response => response.json()) .then(data => { if (data.success) { showMsg('验证码已发送,请在输入框输入4位验证码'); startCountdown(); } else { showMsg(data.msg || '发送失败'); btn.disabled = false; btn.innerText = '发送'; } }) .catch(() => { showMsg('网络错误'); btn.disabled = false; btn.innerText = '发送'; }); }
|
login部分:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| function login() { const phone = document.getElementById('phone').value.trim(); const code = document.getElementById('code').value.trim(); if (!validatePhone(phone)) { showMsg('请输入有效的手机号'); shakeInput('phone'); return; } if (!/^\d{4}$/.test(code)) { showMsg('请输入4位验证码'); shakeInput('code'); return; } showMsg('登录中...'); fetch('/login', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ phone, code }) }) .then(response => response.json()) .then(data => { if (data.success) { showMsg('登录成功'); setTimeout(() => { showMsg(''); }, 1500); } else { showMsg(data.msg || '登录失败'); } }) .catch(() => { showMsg('网络错误'); }); }
|
可以看到都是post请求相关接口,然后传入json格式的数据。所以就明白了传数据的方式
对code字段进行爆破,从0000-9999,最后爆破出来就能拿到flag

验证码居然会出现这个地方?
考点:短信验证码泄露

依然前端代码审计,找到验证码是六位数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| function login() { const phone = document.getElementById('phone').value.trim(); const code = document.getElementById('code').value.trim(); if (!validatePhone(phone)) { showMsg('请输入有效的手机号'); shakeInput('phone'); return; } if (!/^\d{6}$/.test(code)) { showMsg('请输入6位验证码'); shakeInput('code'); return; } showMsg('登录中...'); fetch('/login', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ phone, code }) }) .then(response => response.json()) .then(data => { if (data.success) { showMsg('登录成功'); // 弹出美化后的flag弹窗 customAlert(data.msg, "登录成功"); } else { showMsg(data.msg || '登录失败'); } }) .catch(() => { showMsg('网络错误'); }); }
|
随便输入手机号,抓包,在响应包里看到code泄露了

直接登录,拿到flag
短信轰炸-好玩但违法
考点:单手机号短信轰炸漏洞

依然是熟悉的登录界面
这次先直接发送验证码,看到是4位数的验证码

抓包也看不到code泄露,于是我们对/send接口进行测试
抓包进行重放,发现可以无限制地重发,于是我们直接对其进行多次重发,在某次响应包中拿到flag

另一种短信轰炸
考点:多手机号短信轰炸

老规矩,输手机号,发验证码,发现是4位数验证码
抓包,响应包没有验证码泄露
进行重放攻击,发现存在短信轰炸,但是看不到flag
我们进行重放时对手机号进行修改,修改后两位就行(遍历00-99),然后就能看到flag
什么你告诉我短信码没有什么用
考点:验证码可以删除绕过造成的任意用户注册漏洞
这次界面有点不同,可以输入密码,但是大差不差,密码先随便输

老流程走一套
发验证码,是6位数的code
看响应包,没有code泄露
抓包进行重放,发现可以进行重放攻击,但是没有flag,两种短信轰炸都测试,还是没有
现在我们测试/login接口,将请求包的code删除,再发包就能登录,拿到flag