分享web开发知识

注册/登录|最近发布|今日推荐

主页 IT知识网页技术软件开发前端开发代码编程运营维护技术分享教程案例
当前位置:首页 > 前端开发

【笔记】网易微专业-Web安全工程师-04.WEB安全实战-2.暴力破解

发布时间:2023-09-06 01:43责任编辑:彭小芳关键词:Web

KP君之前买了一个拉杆箱,在初始设置密码时不熟悉步骤,一时手抖,密码已经设好,但不知道设置了什么密码,欲哭无泪。想要找回密码,只能一个个试验,拉杠箱的密码锁有3位,对应000~999,那么最多需要1000次就能打开密码,这就是简单的“暴力破解”。

暴力破解(Brute Force):核心就是“穷举法”,猜出用户的密码。看起来似乎工程量很大,但是通常用户设置密码都不太复杂,因此利用常用的密码字典,就能破获大部分的密码。理论上来说,只要给定足够的时间,暴力破解就一定能破译密码。

在实战前,先介绍一款渗透工具OWASP ZAP (Zed Attack Proxy),可点击下方链接了解和下载安装。

https://www.owasp.org/index.php/OWASP_Zed_Attack_Proxy_Project

这款工具功能强大,包含抓包,爬虫,端口扫描,主动扫描等等。我们在暴力破解这一章节中要利用的是它的抓包以及Fuzzy功能。

DVWA实战:

1. 打开phpStudy或xampp,运行Apach和MySQL;

2. 打开ZAP软件,默认代理端口是8080;因此,需要我们在Firefox设置同样的代理端口,可以使用之前提到的Proxy Switcher插件实现,也可直接配置浏览器的网络代理。

3. 浏览器进入DVWA主界面,在左侧栏选择DVWA Security安全等级为Low,然后进入Brute Force;

 4. 随便输入一个用户名和密码:kplayer/password,收到报错提示:

通过ZAP抓包,我们看到登录时采用GET方法,带上username和password参数:

因此,我们采用暴力破解的一个思路就是构造多条URL请求,替换其中的username和password,不过要是人工构造,那跟在输入框里一个个输有什么两样?好在ZAP提供了Fuzz方法,让我们可以配置需要替换的域,一个个尝试,节省劳动力。

5. 选中kplayer,右键Fuzz,选中Payloads,点击Add,增加我们的用户名字典:admin,root,guest,Test;同样的方法,对password增加字典:admin,123456,111111,666666,root,password; 然后点击右下角Start Fuzzer,ZAP就会替我们自动组合发送请求。

6. 查看底部Fuzzer的任务,发现ZAP已经完成了所有的组合请求。那么问题来了,怎么知道哪一个是正确的用户名/密码响应?通常来说,登录成功和登录失败的响应报文大小会有差异,我们按响应报文大小排序,那个不一样的一般就是正确的用户名/密码,也就是我们的默认密码admin/password。

至此,我们完成了一个low等级的暴力破解,接下去我们看看medium等级的暴力破解。

7. 进入DVWA主界面,在左侧栏选择DVWA Security安全等级为medium,使用上述同样的方法,我们发现同样能够破解,只是需要花费的时间变长了,查看右下角View Source,我们发现代码中多了失败登录sleep两秒的控制:

else { ???// Login failed ???sleep( 2 ); ???echo "<pre><br />Username and/or password incorrect.</pre>";}

8. 接下去我们看看high等级的破解,采用同样的方法,这次失败了,我们查看请求报文,发现在原来的参数username和password后面,多了一个token:

查看页面源码,发现多了一个隐藏的token框:

<form action="#" method="GET"> ???Username:<br /> ???<input type="text" name="username"><br /> ???Password:<br /> ???<input type="password" AUTOCOMPLETE="off" name="password"><br /> ???<br /> ???<input type="submit" value="Login" name="Login"> ???<input type=‘hidden‘ name=‘user_token‘ value=‘ac9dabf93f796a0b905e64e5326e579c‘ /></form>

查看后台源码,发现登录中多了token的生成和校验。

<?phpif( isset( $_GET[ ‘Login‘ ] ) ) { ???// Check Anti-CSRF token ???checkToken( $_REQUEST[ ‘user_token‘ ], $_SESSION[ ‘session_token‘ ], ‘index.php‘ );......// Generate Anti-CSRF tokengenerateSessionToken();?>

Token,也叫令牌,是随机生成的一组序列,一般用在两个地方: 1) 防止表单重复提交, 2) Anti-CSRF攻击。原理上都是通过session token来实现的:当客户端请求页面时,服务器会生成一个随机数Token,并且将Token放置到session当中,然后将Token发给客户端(一般通过构造hidden表单)。下次客户端提交请求时,Token会随着表单一起提交到服务器端。 

在Anti-CSRF攻击中:服务器端会对Token值进行验证,判断是否和session中的Token值相等,若相等,则可以证明请求有效,不是伪造的。 

在“防止表单重复提交",服务器端第一次验证相同过后,会将session中的Token值更新下,若用户重复提交,第二次的验证判断将失败,因为用户提交的表单中的Token没变,但服务器端session中Token已经改变。 

那么是不是就无懈可击了呢?只要能拿到每次的token,就能像之前一样拼接请求,完成自动发送,所以一种方法就是用Python写个脚本,每次都取返回报文里的token value值再拼接。另外一个思路是,既然只有在第一次请求后,服务器会生成一个token返给客户端,之后才需要校验,那么如果我们每次的请求都伪装成第一次,就不用进行token检测了。

9. 最后我们来看看impossible等级,这里我们发现输错密码3次后,提示我们15分钟后才能输入,有效的增加了暴力破解的时间成本。

查看后台源码,看看是如何进行控制的:

<?phpif( isset( $_POST[ ‘Login‘ ] ) ) { ???// Check Anti-CSRF token ???checkToken( $_REQUEST[ ‘user_token‘ ], $_SESSION[ ‘session_token‘ ], ‘index.php‘ ); ???// Sanitise username input ???$user = $_POST[ ‘username‘ ]; ???$user = stripslashes( $user ); ???$user = mysql_real_escape_string( $user ); ???// Sanitise password input ???$pass = $_POST[ ‘password‘ ]; ???$pass = stripslashes( $pass ); ???$pass = mysql_real_escape_string( $pass ); ???$pass = md5( $pass ); ???// Default values ???$total_failed_login = 3; ???$lockout_time ??????= 15; ???$account_locked ????= false; ???// Check the database (Check user information) ???$data = $db->prepare( ‘SELECT failed_login, last_login FROM users WHERE user = (:user) LIMIT 1;‘ ); ???$data->bindParam( ‘:user‘, $user, PDO::PARAM_STR ); ???$data->execute(); ???$row = $data->fetch(); ???// Check to see if the user has been locked out. ???if( ( $data->rowCount() == 1 ) && ( $row[ ‘failed_login‘ ] >= $total_failed_login ) ) ?{ ???????// User locked out. ?Note, using this method would allow for user enumeration! ???????//echo "<pre><br />This account has been locked due to too many incorrect logins.</pre>"; ???????// Calculate when the user would be allowed to login again ???????$last_login = $row[ ‘last_login‘ ]; ???????$last_login = strtotime( $last_login ); ???????$timeout ???= strtotime( "{$last_login} +{$lockout_time} minutes" ); ???????$timenow ???= strtotime( "now" ); ???????// Check to see if enough time has passed, if it hasn‘t locked the account ???????if( $timenow > $timeout ) ???????????$account_locked = true; ???} ???// Check the database (if username matches the password) ???$data = $db->prepare( ‘SELECT * FROM users WHERE user = (:user) AND password = (:password) LIMIT 1;‘ ); ???$data->bindParam( ‘:user‘, $user, PDO::PARAM_STR); ???$data->bindParam( ‘:password‘, $pass, PDO::PARAM_STR ); ???$data->execute(); ???$row = $data->fetch(); ???// If its a valid login... ???if( ( $data->rowCount() == 1 ) && ( $account_locked == false ) ) { ???????// Get users details ???????$avatar ??????= $row[ ‘avatar‘ ]; ???????$failed_login = $row[ ‘failed_login‘ ]; ???????$last_login ??= $row[ ‘last_login‘ ]; ???????// Login successful ???????echo "<p>Welcome to the password protected area <em>{$user}</em></p>"; ???????echo "<img src=\"{$avatar}\" />"; ???????// Had the account been locked out since last login? ???????if( $failed_login >= $total_failed_login ) { ???????????echo "<p><em>Warning</em>: Someone might of been brute forcing your account.</p>"; ???????????echo "<p>Number of login attempts: <em>{$failed_login}</em>.<br />Last login attempt was at: <em>${last_login}</em>.</p>"; ???????} ???????// Reset bad login count ???????$data = $db->prepare( ‘UPDATE users SET failed_login = "0" WHERE user = (:user) LIMIT 1;‘ ); ???????$data->bindParam( ‘:user‘, $user, PDO::PARAM_STR ); ???????$data->execute(); ???} ???else { ???????// Login failed ???????sleep( rand( 2, 4 ) ); ???????// Give the user some feedback ???????echo "<pre><br />Username and/or password incorrect.<br /><br/>Alternative, the account has been locked because of too many failed logins.<br />If this is the case, <em>please try again in {$lockout_time} minutes</em>.</pre>"; ???????// Update bad login count ???????$data = $db->prepare( ‘UPDATE users SET failed_login = (failed_login + 1) WHERE user = (:user) LIMIT 1;‘ ); ???????$data->bindParam( ‘:user‘, $user, PDO::PARAM_STR ); ???????$data->execute(); ???} ???// Set the last login time ???$data = $db->prepare( ‘UPDATE users SET last_login = now() WHERE user = (:user) LIMIT 1;‘ ); ???$data->bindParam( ‘:user‘, $user, PDO::PARAM_STR ); ???$data->execute();}// Generate Anti-CSRF tokengenerateSessionToken();?>

实战心得:

暴力破解的核心是“穷举法”,因此,采用token校验,限制登录错误次数,验证码校验都是有效的防止暴力破解的手段。

【笔记】网易微专业-Web安全工程师-04.WEB安全实战-2.暴力破解

原文地址:https://www.cnblogs.com/kplayer/p/8467572.html

知识推荐

我的编程学习网——分享web前端后端开发技术知识。 垃圾信息处理邮箱 tousu563@163.com 网站地图
icp备案号 闽ICP备2023006418号-8 不良信息举报平台 互联网安全管理备案 Copyright 2023 www.wodecom.cn All Rights Reserved