暴力破解漏洞原理及利用和防范
暴力破解概述
暴力破解”是一攻击具手段,在web攻击中,一般会使用这种手段对应用系统的认证信息进行获取。 其过程就是使用大量的认证信息在认证接口进行尝试登录,直到得到正确的结果。 为了提高效率,暴力破解一般会使用带有字典的工具来进行自动化操作。 理论上来说,大多数系统都是可以被暴力破解的,只要攻击者有足够强大的计算能力和时间,所以断定一个系统是否存在暴力破解漏洞,其条件也不是绝对的。 我们说一个web应用系统存在暴力破解漏洞,一般是指该web应用系统没有采用或者采用了比较弱的认证安全策略,导致其被暴力破解的“可能性”变的比较高。 这里的认证安全策略, 包括: 1.是否要求用户设置复杂的密码; 2.是否每次认证都使用安全的验证码(想想你买火车票时输的验证码~)或者手机otp; 3.是否对尝试登录的行为进行判断和限制(如:连续5次错误登录,进行账号锁定或IP地址锁定等); 4.是否采用了双因素认证; ...等等。 千万不要小看暴力破解漏洞,往往这种简单粗暴的攻击方式带来的效果是超出预期的!
从来没有哪个时代的黑客像今天一样热衷于猜解密码 ---奥斯特洛夫斯基
个人理解
上面是官话版的暴力破解.我个人理解为暴力破解就是瞎猜.瞎试.结合你收集的一切信息利用社工也好,32GB大字典也好.反正就是逐一乱猜...猜对了.就破解成功了.
爆破小技巧
我们在生成破解密码对应的文件的时候, 应该去尝试注册一个账号,看看目标站点要求我们使用什么样的密码.例如目标站要求我们使用6位以上的密码.显然,我们的字典如果存在6位或者6位以下的就是不合理的.可以利用此方法.去除字典中不必要的密码.
如果是爆破的后台,往往最应该尝试的是admin/administrator/root/adminroot/等象征性比较高的用户名,可以重点对这些用户名+密码进行尝试.观看返回结果.确定用户名.
实验演示
测试目标: http://www.php09.cn
测试工具: burp suite
我们密码和用户名使用同一个字典:
我们随便键入用户名和密码, 可以看到发送的为POST请求, username 对应的用户名.password处对应的密码.当然,我们此处登录失败.
我们抓到这次请求之后,使用burp的intruder进行爆破.
我们首先选择bomb模式, 因为这个模式会穷举字典的一切组合,来尝试所有可能出现的用户名,密码. 我们username和password处进行标记,标记的意思就是等会要替换的位置
接下来我们载入字典文件.一般来说,前面设置了几个变量,后面就需要载入几个字典(跟爆破模式相关), 字典可以一直,载入完字典也可以再次进行手动添加,字典也可以根据特定的规则进行自动生成.替换等.
载入完字典 ,我们开始爆破.
破解的时候 我们可以点击某一次请求 来查看具体发送的内容. 下方则显示整体进度条
刚才由于我的字典文件里面没有正确的密码(123456),导致破解不成功, 我手动添加了123456之后,破解完成之后可以看到,响应的长度和众多响应不一样,我们可以点开查看响应.
还有一种快速分辨的技巧.我们通过手工登录得知,如果账号密码为错的情况下.页面会返回我们
username or password is not exists~ ,那我们把 响应包含 username or password is not exists~ 给排除 是不是就是成功的登录信息了呢.?
设置burp 添加规则,从新尝试, 从上次我们已经得知账户为admin,密码为123456,这次我们节省时间,字典少一点..
添加完之后,我们开始爆破. 完了点击排序. 我们很快的发现有一个请求没有打钩,没有打钩就证明没有出现username or password is not exists~,我们点开请求查看,可看到对应的正确的账号密码.
源码解析
# 如果提前的请求submit 和 username 和password 都不为空的时候. 点击登录,submit就默认赋值了,而username和password对应的我们的账号密码.
if(isset($_POST['submit']) && $_POST['username'] && $_POST['password']){ $username = $_POST['username']; # 获取用户名 $password = $_POST['password']; # 获取密码 $sql = "select * from users where username=? and password=md5(?)"; # 组合sql语句查询用户名等于xxx 同时密码等于MD5后的xxx $line_pre = $link->prepare($sql); # 执行查询sql $line_pre->bind_param('ss',$username,$password); if($line_pre->execute()){ $line_pre->store_result(); if($line_pre->num_rows>0){ $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>'; } }
可以看到上述源码没有对登陆失败做任何处理,只是单纯的输出一句话. :username or password is not exists~
没有没有验证码,没有其他控制措施,典型的暴力破解应用场景.
修复方案
建议增加验证码.登陆次数失败过多的情况下锁定账号或ip等一系列手段.