今天上線測試發現了一個只有前端驗證的修改密碼邏輯漏洞,但是該應用根本沒有對驗證碼進行驗證。
訪問測試地址http://xxx.xxx.xxx.xxx:xxx/dss,查看頁面功能,發現存在找回密碼功能。
登陸頁面
點擊找回密碼功能,輸入內容後發現前端驗證,未向後端發送數據包
找回密碼
從驗證碼入手,看看發送驗證碼的情況
獲取驗證碼
發現點擊發送沒有時間限制,但是不能指定電話號碼,所以不知道是否真的有短信發送
點擊確定,向服務器發起獲取驗證碼請求
POST /dss/findPwd.e HTTP/1.1
Host: xxx.xxx.xxx.xxx:xxx
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:65.0) Gecko/20100101 Firefox/65.0
Accept: */*
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Referer: http://xxx.xxx.xxx.xxx:xxx/dss/findPwd.jsp
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
X-Requested-With: XMLHttpRequest
Content-Length: 7
Connection: close
Cookie: JSESSIONID=14CEE8646A9BF274394F948BE24D5ED5
id=test
放過請求找回test賬號,返回200,沒有數據內容
正確用戶名返回數據包
再嘗試請求一個錯誤的賬號,返回內容中疑似存在驗證碼,但是該驗證碼不能成功重置密碼
錯誤用戶名返回數據包
上面數據包根據返回內容不同,也可用來爆破存在的用戶名
既然是前端驗證,我們通過使用開發者工具箱找到前端驗證的函數
更新密碼調用的js函數
查看找到的函數內容
function checkform() {
$("#checkResult").html('');
var checkResultMes = '請輸入的用戶賬號!';
var findPwdNumber = $('#findPwdNumber').val();
if(!findPwdNumber||$.trim(findPwdNumber)=='') {
//驗證手機號爲11位
$("#checkResult").html(checkResultMes);
return false;
}
return true;
}
//驗證輸入的手機號是否存在
function getRand(){
if(checkform()){
var findPwdNumber = $('#findPwdNumber').val();
if(confirm('是否確認執行找回工號[' + findPwdNumber + ']的密碼操作?')){
$.post('/dss/findPwd.e',{id:findPwdNumber},function(data){
var result = eval(data);
$("#findPwdRand_hidden").val(result[0].findPwdRand);
$("#checkResult").html(result[0].Msg);
});
}
}
}
//重置密碼
function forwordcxc(){
var info = {};
info.findPwdNumber = $("#findPwdNumber").val();
info.findPwdRand = $("#findPwdRand").val();
info.findPwdRand_hidden = $("#findPwdRand_hidden").val();
info.findPwdNew = $("#findPwdNew").val();
info.findPwdNewRepeat = $("#findPwdNewRepeat").val();
if(info.findPwdNew==""||info.findPwdNewRepeat==""){
$("#checkResult").html('請輸入兩次新密碼!');
return;
}
if(info.findPwdNew != info.findPwdNewRepeat){
$("#checkResult").html('兩次輸入的密碼不一致,請重新輸入!');
return;
}
var numExp = new RegExp(/([0-9])/);
var strExp = new RegExp(/([a-zA-Z])/);
var strnumExp = new RegExp(/([!,@,#,$,%,^,&,*,?,_,~])/);
if(!(strnumExp.test(info.findPwdNew)&& strExp.test(info.findPwdNew)&&numExp.test(info.findPwdNew)&&info.findPwdNew.length>=8)){
$("#checkResult").html('新密碼必需包括特殊字符(! @ # $ % ^ & * ? _ ~), 字母, 數字且長度大於7!');
return;
}
if(info.findPwdRand==""){
$("#checkResult").html('請輸入接收到的驗證碼!');
return;
}
if(info.findPwdRand != info.findPwdRand_hidden){
$("#checkResult").html('驗證碼輸入錯誤,請重新輸入!');
return;
}
info.findPwdNew = aesEncrypt(info.findPwdNew);
info.findPwdNewRepeat = aesEncrypt(info.findPwdNewRepeat);
$.post('/dss/updatePwd.e',info,function(data){
var value = eval(data);
if(value[0].result == '1'){
$("#checkResult").html("密碼更新成功,此頁面3秒後關閉,請用新密碼登錄!");
setTimeout(rollBack, 3000);
}else{
$("#checkResult").html("修改密碼錯誤,請聯繫管理員!");
}
});
}
function rollBack(){
window.location.href = "/dss/index.jsp";
}
查看js代碼發現驗證碼是否正確只通過提交字段和隱藏字段是否相等
驗證碼驗證代碼
使用開發者工具箱的控制檯執行js代碼
執行js代碼
獲取id爲findPwdRand和findPwdRand_hidden的值,發現findPwdRand_hidden內容爲空,爲findPwdRand_hidden賦值與findPwdRand相同的值,點擊更新密碼,然後發起修改請求
修改密碼數據包
放過攔截的數據包
修改成功
密碼更新成功,驗證可登陸。