实验环境
-
Firefox+Burp suite
-
测试web应用:pikachu系统(https://github。com/zhuifengshaonianhanlu/pikachu):php开发,后台数据库为mysql,只需要安装好PHP,web中间件(Apache等)就可以运行
集成环境部署软件,如PHPstudio或xampp
暴力破解攻击&暴力破解漏洞概述
- 在不知道密码的情况下:连续性尝试+字典+自动化,从而碰撞出有效的密码。简单来说就是瞎猜。
- 字典:
- 常用的账号密码,比如在网上搜索常用用户名/密码Top 500等
- 互联网上被脱库后账号密码(社工库),比如CSDN当年泄露的约600w用户信息
- 根据特点目标的信息,使用指定的字符使用工具按照指定的规则进行排列组合算法生成的密码
- 如果一个网站没有对登录接口实施防暴力破解的措施,或者实施了不合理的措施,则称该网站存在暴力破解漏洞。这些措施有:
- 是否设置复杂密码
- 认证时是否使用安全地验证码
- 是否对尝试登录的行为进行判断和限制
- 是否存在必要的情况下采用双因素认证
等等
暴力破解漏洞测试流程
字典优化技巧:
基于表单的暴力破解攻击(基于burp suite)
Grep Match:根据报文返回的一些特殊字符串和报文长度可以区分出请求成功和请求失败.
利用Burpsuite的重放功能,将表单项设为变量,用设置好的字典进行匹配,碰撞出正确的账号密码。
暴力破解之不安全的验证码分析
- ---on client
on client 常见问题
- 当验证码是利用前端脚本生成且只由由前端验证的时候,验证码是不安全的,利用burpsuite的proxy、inturder和repeater功能可以完成绕过。
- 如果验证码放在cookie,攻击者可利用脚本提前获取验证码。
- 如果在前端代码里,则更容易被获取。
【小技巧】
如何简单判断验证机制设置在前端?
1. burpsuite的proxy处于打开截取状态
2. 随便输入账号密码,第一次不填验证码;第二次填写错误的验证码;第三次填写正确的验证码。
3. 如果只有第三次在burpsuite产生了拦截消息,则说明该验证机制是在前端进行的。原因是,当验证机制设在前端时,只有验证码正确才会发起请求,才会被burpsuite拦截到。
- ---on server
on server常见问题:
-
如何判断验证码是否会过期?
方法一:
刷新页面获取新的验证码,记下验证码,不提交。
放入重放请求表单里。若无提示验证码错误,则说明验证码是不会过期的。方法二:
随便填入账号密码,不填验证码,但记下验证码p3zdc8
,点击login,burpsuite开始抓包
不停forward,直到看到响应的cookie信息,把该包丢掉(可猜测/inc/showvcode.php是验证脚本)
无法正常返回验证码,这时我们试试刚才那个验证码`p3zdc8`
显然该验证码还可用
注意几点:
- 如果我们不把那个包Drop掉,正常来说应该返回新的验证码的,但是这没有
- 从刚才被Drop掉的包可以猜测验证脚本为/inc/showvcode.php
点击Forward————
两个重要PHP文件代码分析
bf_server.php:作用是执行验证过程
··skip··
$html="";
if(isset($_POST['submit'])) {
if (empty($_POST['username'])) { //用户名是否为空
$html .= "<p class='notice'>用户名不能为空</p>";
} else {
if (empty($_POST['password'])) { //密码是否为空
$html .= "<p class='notice'>密码不能为空</p>";
} else {
if (empty($_POST['vcode'])) { //验证码是否为空
$html .= "<p class='notice'>验证码不能为空哦!</p>";
} else {
// 验证验证码是否正确
if (strtolower($_POST['vcode']) != strtolower($_SESSION['vcode'])) { //验证码是否和session中的匹配
$html .= "<p class='notice'>验证码输入错误哦!</p>";
//应该在验证完成后,销毁该$_SESSION['vcode'],应该只用一次
}else{ //账号密码以及验证码都正确的话就开始向数据库查询用户
$username = $_POST['username'];
$password = $_POST['password'];
$vcode = $_POST['vcode'];
$sql = "select * from users where username=? and password=md5(?)";
$line_pre = $link->prepare($sql);
$line_pre->bind_param('ss',$username,$password);
// && (strtolower($vcode) == strtolower($_SESSION['vcode'])) 仅在这里增加了对验证码的验证也没用,问题在于验证码不过期
if($line_pre->execute()){
$line_pre->store_result();
//虽然前面做了为空判断,但最后,却没有验证验证码!!!
if($line_pre->num_rows()==1){
$html.='<p> login success</p>';
}else{
$html.= '<p> username or password is not exists~</p>';
}
}else{
$html.= '<p>执行错误:'.$line_pre->errno.'错误信息:'.$line_pre->error.'</p>';
}
}
}
}
}
}
··skip··
showvcode.php
<?php
session_start();
include_once 'function.php';
//$_SESSION['vcode']=vcode(100,40,30,4);
$_SESSION['vcode']=vcodex();
//验证码绕过 on server 这里其实还是有一个问题,就是服务端将验证码字符串以明文COOKIE的方式给了前端,那验证码还有什么鸟意义。。。
setcookie('bf[vcode]',$_SESSION['vcode']);
?>
当前验证码存放在cookie里,而且http-only属性是false,也就是说,我们可以直接拿到验证码,通过脚本填入表单。
document.cookie只能读取会话信息,另一个参数只是将验证码存在了cookie中,不属于会话信息,所以通过这个方法读取不到
Token可以防暴力破解吗?
不能,因为token值明文放到表单里,攻击者可以写个脚本获取这个token值就可以了,所以token不能抵御暴力破解。
暴力破解常见的防范措施
总结
- 暴力破解是因为允许攻击者“不断试错”而存在的漏洞。
- 本次学习中提到的有三种类型的暴力破解。
1. 无验证码:利用burpsuite的Proxy功能进行抓包,利用intruder进行字典破解。这里的intruder有四种爆破模式:分别是一套字典爆破一个变量;一个字典爆破两个变量;两个字典一对一爆破两个变量;两套字典相互组合爆破两个变量。
2. 有验证码,但仅在前端利用js脚本验证:只需要输入一次正确的验证码,通过js脚本的验证,将此时抓取的数据包送到intruder即可爆破。因为只在前端验证,当前端验证通过时请求才会被发出,而此时正好可以被burpsuite抓取到,而抓取到的包是被服务器认为是通过验证的,之后也不会有任何验证,于是不需要在意验证码就可以去爆破了。
3. 有验证码,但仅在后端验证且验证码不存在有效期,即服务端没有在验证过后删除session中的旧验证码。只需要刷新一个验证码,又不提交,然后利用之前抓取的包,在请求包里填写最新刷新出来的验证码,将账号密码设为变量即可进行爆破。防范措施:既要在验证之后立即将验证码从session中删除,又要保证不将验证码明文泄露在HTML代码或cookie中。
4. 利用token防御:实则是无效的,因为token是以隐藏表单的形式存放在HTML代码中,也就是说,攻击者时可能获取到该token的。 - 暴力破解需要好的字典。比如常用密码top100等。
- 根据表单值长度的限制可以筛选一部分碰撞字段,提高效率。
- 抵御暴力破解的时候既要考虑易用性也要考虑安全性,不能因为安全而过分影响用户体验,当然一些涉及金钱等应用可以适当牺牲易用性。
感谢阅读!