DVWA靶场通关笔记-暴力破解(Impossible级别)

目录

一、查看源码

二、功能分析

三、SQL注入分析

1、使用PDO预处理语句和参数绑定

2、mysqli_real_escape_string转义

3、stripslashes去除反斜杠

四、暴力破解分析

1、token防止暴力破解机制 

2、登录失败随机延迟机制

3、登陆失败报错信息相同

4、登陆失败的账户锁定机制


本系列为通过《DVWA靶场通关笔记》的暴力破解关卡(low,medium,high,impossible共4关)渗透集合,通过对相应关卡源码的代码审计找到讲解渗透原理并进行渗透实践,本文为暴力破解impossible关卡的原理分析部分,讲解相对于low、medium和high级别,为何对其进行渗透测试是Impossible的。

一、查看源码

进入DVWA靶场源目录,找到impossible.php源码,分析其为何能让这一关卡名为不可能实现暴力破解。

打开impossible.php文件,对其进行代码审计,详细注释的impossible.php源码如下所示。

<?php// 检查是否通过 POST 方法提交了名为 'Login' 的表单数据,并且用户名和密码字段均已设置
if( isset( $_POST[ 'Login' ] ) && isset ($_POST['username']) && isset ($_POST['password']) ) {// 检查反跨站请求伪造(CSRF)令牌// $_REQUEST['user_token'] 是从请求中获取的用户令牌// $_SESSION['session_token'] 是存储在会话中的令牌// 'index.php' 是如果令牌验证失败将跳转的页面checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );// 从 POST 请求中获取用户输入的用户名$user = $_POST[ 'username' ];// 去除用户名中的反斜杠(如果有的话)$user = stripslashes( $user );// 使用 mysqli_real_escape_string 函数对用户名进行转义处理,防止 SQL 注入$user = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $user ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));// 从 POST 请求中获取用户输入的密码$pass = $_POST[ 'password' ];// 去除密码中的反斜杠(如果有的话)$pass = stripslashes( $pass );// 使用 mysqli_real_escape_string 函数对密码进行转义处理,防止 SQL 注入$pass = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $pass ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));// 使用 md5 函数对密码进行加密$pass = md5( $pass );// 设置默认值// 允许的最大失败登录次数$total_failed_login = 3;// 账户锁定时间(分钟)$lockout_time       = 15;// 标记账户是否被锁定$account_locked     = false;// 从数据库中查询用户的失败登录次数和最后登录时间$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();// 检查用户是否因多次失败登录而被锁定if( ( $data->rowCount() == 1 ) && ( $row[ 'failed_login' ] >= $total_failed_login ) )  {// 计算用户可以再次登录的时间$last_login = strtotime( $row[ 'last_login' ] );$timeout    = $last_login + ($lockout_time * 60);$timenow    = time();// 检查是否已经过了锁定时间,如果未过则锁定账户if( $timenow < $timeout ) {$account_locked = true;}}// 从数据库中查询用户名和密码匹配的记录$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( ( $data->rowCount() == 1 ) && ( $account_locked == false ) ) {// 获取用户的头像、失败登录次数和最后登录时间$avatar       = $row[ 'avatar' ];$failed_login = $row[ 'failed_login' ];$last_login   = $row[ 'last_login' ];// 登录成功,显示欢迎信息和用户头像$html .= "<p>Welcome to the password protected area <em>{$user}</em></p>";$html .= "<img src=\"{$avatar}\" />";// 如果账户之前被锁定过,给出警告信息if( $failed_login >= $total_failed_login ) {$html .= "<p><em>Warning</em>: Someone might of been brute forcing your account.</p>";$html .= "<p>Number of login attempts: <em>{$failed_login}</em>.<br />Last login attempt was at: <em>${last_login}</em>.</p>";}// 重置失败登录次数$data = $db->prepare( 'UPDATE users SET failed_login = "0" WHERE user = (:user) LIMIT 1;' );$data->bindParam( ':user', $user, PDO::PARAM_STR );$data->execute();} else {// 登录失败,脚本暂停 2 到 4 秒之间的随机时间sleep( rand( 2, 4 ) );// 给出登录失败的反馈信息$html .= "<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>";// 更新失败登录次数$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();}// 设置用户的最后登录时间$data = $db->prepare( 'UPDATE users SET last_login = now() WHERE user = (:user) LIMIT 1;' );$data->bindParam( ':user', $user, PDO::PARAM_STR );$data->execute();
}// 生成反跨站请求伪造(CSRF)令牌
generateSessionToken();?>

二、功能分析

此 PHP 代码实现了一个具备反 CSRF 保护、防暴力破解机制的用户登录验证系统。当用户通过 POST 方法提交登录表单时,代码会先检查 CSRF 令牌的有效性,接着对用户名和密码进行处理,包括去除反斜杠和转义处理,再对密码进行 MD5 加密。之后会从数据库中查询用户的失败登录次数和最后登录时间,判断账户是否被锁定。若账户未锁定且用户名和密码匹配,则登录成功,显示欢迎信息和用户头像,同时重置失败登录次数;若登录失败,会暂停一段时间并给出反馈信息,同时更新失败登录次数。无论登录结果如何,都会更新用户的最后登录时间。最后,会生成一个新的反 CSRF 令牌。

三、SQL注入分析

代码中使用了如下三种方法进行防御,具体如下所示。

  • 使用PDO预处理语句和参数绑定
  • 对用户名和密码输入进行了mysqli_real_escape_string转义
  • 使用了stripslashes去除反斜杠

1、使用PDO预处理语句和参数绑定

PDO预处理语句是SQL注入防护的黄金标准。通过参数绑定,用户输入的数据不会被解释为SQL代码的一部分,而是作为纯数据处理。这种方式完全隔离了代码和数据,即使输入中包含SQL特殊字符(如单引号、分号等),也不会改变SQL语句的结构。这是最有效的SQL注入防护措施,从根本上消除了SQL注入风险的可能性。

$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();

2、mysqli_real_escape_string转义

mysqli_real_escape_string对特殊字符进行转义,特别是在字符串上下文中。它会转义单引号(')、双引号(")、反斜杠()和NULL字符等,防止这些字符破坏SQL语句结构。虽然这在PDO预处理的基础上是冗余的,但提供了额外的防御层。这种深度防御策略确保了即使预处理机制出现问题,转义功能仍然能提供保护。

$user = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $user ) : "");
$pass = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $pass ) : "");

3、stripslashes去除反斜杠

stripslashes函数去除输入中的反斜杠,主要用于处理Magic Quotes功能开启时自动添加的转义字符。虽然现代PHP版本默认关闭Magic Quotes,但这个处理确保了向后兼容性。它防止了双重转义问题,确保数据在进入数据库前保持正确的格式。这是防御深度策略的一部分,处理各种可能的输入场景。

$user = stripslashes( $user );
$pass = stripslashes( $pass );

综上,代码在处理用户输入时,使用了stripslashes和mysqli_real_escape_string对用户名和密码进行处理,并且在后续的数据库查询中使用了 PDO 预处理语句。PDO 预处理语句本身能够有效防止 SQL 注入,因为它将 SQL 语句和用户输入分开处理,数据库会自动对输入进行正确的转义。但stripslashes的使用可能会破坏mysqli_real_escape_string的转义效果,不过由于后续使用了 PDO 预处理语句,整体上 SQL 注入的风险相对较低。

四、暴力破解分析

代码中使用了如下三种方法进行防御暴力破解,具体如下所示。

  • 基于token防暴力破解验证机制
  • 失败登录后有随机延迟(2-4秒)
  • 所有登录失败都打印同一错误信息,不利于攻击者枚举有效用户名
  • 登陆失败后的账户锁定机制

1、token防止暴力破解机制 

CSRF令牌验证有效防止自动化暴力破解。攻击者必须首先获取有效的user_token才能提交登录请求,这增加了攻击复杂度。每个会话的令牌唯一且有时效性,阻止了重放攻击和批量自动化请求。Token机制确保了每个登录请求都是来自合法的用户会话,显著提高了暴力破解的门槛,迫使攻击者需要先破解CSRF保护才能进行密码猜测。

// 检查反跨站请求伪造(CSRF)令牌
checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );

2、登录失败随机延迟机制

随机2-4秒延迟极大降低了暴力破解的速度。传统攻击每秒可尝试数十次,现在降至每分钟仅15-30次。对于万级密码字典,攻击时间从几分钟延长到数小时。随机性防止攻击者通过固定时间模式优化攻击节奏,增加了不确定性。这种时间成本策略有效消耗攻击者资源,使得大规模暴力破解在经济和时间上变得不可行,显著提升防御效果。

sleep( rand( 2, 4 ) );

3、登陆失败报错信息相同

统一错误信息有效防止用户名枚举攻击。攻击者无法通过错误消息区分"用户名不存在"和"密码错误",必须同时猜测正确的用户名和密码组合。

$html .= "<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>";

这使得攻击复杂度从O(n+m)增加到O(n×m),显著扩大搜索空间。虽然当前实现仍透露了锁定信息,但基本防止了通过错误信息差异进行用户枚举,迫使攻击者采用更耗时耗力的组合攻击方式。如下所示,如果登录错误,报错信息均如下所示,并不会出现只是用户名错误,密码错误,使攻击者不清楚到底是输入参数中哪个信息是不正确的。

4、登陆失败的账户锁定机制

记录了失败登录次数和最后登录时间,有账户锁定机制(3次失败后锁定15分钟=15*60秒)。

if( ( $data->rowCount() == 1 ) && ( $row[ 'failed_login' ] >= $total_failed_login ) ) {$last_login = strtotime( $row[ 'last_login' ] );$timeout = $last_login + ($lockout_time * 60);if( $timenow < $timeout ) {$account_locked = true;}
}

账户锁定机制针对性地保护每个用户账户。在3次失败登录后锁定15分钟,有效阻止针对特定用户的持续暴力破解。时间基于最后登录时间计算,确保锁定期的准确性。这种机制保护了用户账户免受定向攻击,迫使攻击者要么等待锁定解除,要么转向其他目标,分散了攻击压力。结合全局延迟和令牌验证,形成了多层次的有效防护体系。

综上,代码采取了多种措施来防范暴力破解。包括token防暴力破解,设置了最大失败登录次数限制(3次),当失败次数达到上限时,账户会被锁定一段时间(3次失败后锁定15分钟);登录失败时,脚本会暂停 2 到 4 秒之间的随机时间,增加每次尝试的时间成本。但是本关卡仍然存在一些小问题:

  • 锁定是基于用户名而非IP,允许攻击者针对不同用户尝试
  • 锁定时间较短(仅15分钟)
  • 随机延迟不够长(2-4秒不足以阻止自动化攻击)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/94799.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/94799.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

IAR工程如何生成compile_commands.json文件(能生成但是clangd不能生成“.cache文件”)

最近一直在使用vscodeclangd的方式编写代码&#xff0c;感觉使用clangd查找函数调用、函数声明、类型定义等等都比使用vscode自带的c/c插件好用太多了。现在我有一个功能是IAR版本的&#xff0c;那么有没有办法生成clangd使用的compile_commands.json文件呢&#xff1f;答案是&…

QT5.14.2、CMake 扩展openCV

一、准备工具Qt5.14.2c11cmake3.24.0opencv3.4.16二、使用cmake可扩展opencv 首先解压cmake、opencv 两个下载的压缩包&#xff0c;如下&#xff1a;运行cmake-gui.exe打开后有弹窗选择&#xff0c;然后进入QT的安装路径下找 mingw73_64文件下的 C和C的执行文件这个截图是我扩展…

【3D入门-指标篇下】 3D重建评估指标对比-附实现代码

3D重建评估指标对比表 每个指标的具体代码位于文章末尾指标计算方法数值范围评估重点优缺点适用场景Chamfer Distance (C1)从预测网格到真实网格的平均距离[0, ∞)几何形状准确性优点&#xff1a;直观、计算高效缺点&#xff1a;对噪声敏感整体形状评估Chamfer Distance (C2)从…

香港电讯创新解决方案,开启企业数字化转型新篇章

在数字化浪潮席卷全球的今天&#xff0c;企业正加速突破传统办公和业务模式的桎梏&#xff0c;力求通过高效协同与业务创新实现跨越式发展。香港电讯作为科技解决方案提供商&#xff0c;持续推动技术创新应用。近期&#xff0c;香港电讯通过多项创新应用、产品升级及战略合作&a…

数据分析编程第六步:大数据运算

6.1 数据介绍直接打开集算器运行 createEventsAndUsers.splx 文件&#xff0c;就可以得到如下两张表&#xff08;也可以根据代码中的注释&#xff0c;修改起止日期以及每天的数据量&#xff09;&#xff1a;电商数据表 events.csv字段名含义eventID事件编号, 从 1 开始流水号us…

vue2+elementui 表格单元格增加背景色,根据每列数据的大小 颜色依次变浅显示2

注意&#xff1a; 正数前5和负数后5的颜色是固定的&#xff0c;剩下5之后的数据颜色是根据第5个颜色依次变浅的&#xff1b; 封装的js方法&#xff1a; /*** 最终版表格颜色处理器* param {Array} data 完整表格数据* param {String} field 当前字段名* param {Object} row 当前…

【AOSP】Android Dump 开发与调试指南

在 Android 系统开发与调试中&#xff0c;dump 是一个不可或缺的强大工具。它能够提供关于系统服务、应用程序状态以及底层硬件信息的详细快照。对于希望深入了解 Android 系统内部工作原理、排查复杂问题或进行性能优化的开发者来说&#xff0c;掌握 dump 的使用至关重要。一、…

Qt数据结构与编码技巧全解析

文章目录Qt中的数据结构QDebugqDebug函数QT的内置类型一般都会重载 << 运算符QT的几何规则QString 字符串编码变长 VS 定长QString 适合中转数据吗&#xff1f;Qstring 的底层使用写时复制QString的具体使用QString 的构造函数格式化构造数值转化为字符串字符串转成数值增…

Ubuntu操作系统下MySQL、MongoDB、Redis

在开发和运维过程中&#xff0c;经常需要从Windows客户端远程连接到Ubuntu服务器上的数据库。本文将详细介绍如何在Ubuntu操作系统下安装和配置MySQL、MongoDB和Redis&#xff0c;以允许从Windows客户端进行远程连接&#xff0c;并提供详细的远程连接命令和配置说明。一、MySQL…

校园勤工俭学微信小程序的设计与实现:基于数字化服务生态的赋能体系构建

在高等教育普及化与数字化校园建设的双重驱动下&#xff0c;传统校园勤工俭学管理模式正面临深刻变革。当前高校勤工俭学工作普遍存在岗位匹配效率低下、过程管理粗放、数据孤岛严重等痛点——根据教育部全国学生资助管理中心2022年统计数据&#xff0c;全国普通高校共有约450万…

Apisix工作流程

是的,你的理解基本正确:当请求到达APISIX时,它会先根据请求的URI、Host、请求方法、 headers等信息匹配最合适的路由,然后执行路由关联的插件逻辑,最后转发到路由配置的上游服务。下面详细讲解APISIX处理请求的全链路及可能的情况。 一、请求全链路流程 APISIX处理请求的…

InnoDB存储引擎底层拆解:从页、事务到锁,如何撑起MySQL数据库高效运转(上)

目录 Page页** B树查询 如何加快记录的查询&#xff1f; 索引** 聚簇索引(主键) 二级索引(非主键) 联合索引——多列 bufferPool* Free链表 flush链表 Flush链表刷新方式有如下两种&#xff1a; LRU链表 针对LRU链表方案缺点的优化 redoLog* redo简单日志类型 redo复杂日志类型…

【人工智能99问】GPT4的原理是什么?(32/99)

【人工智能99问】GPT4的原理是什么&#xff1f;(32/99) 文章目录GPT-4简介一、结构与原理二、使用场景三、优缺点分析四、训练技巧与关键改进五、示例说明六、总结GPT-4简介 一、结构与原理 1. 架构设计 GPT-4基于Transformer解码器架构&#xff0c;核心改进包括&#xff1a;…

//Q是一个队列,S是一个空栈,实现将队列中的元素逆置的算法。

#include<stdio.h> #include<stdbool.h> #include<stdlib.h> #define Size 6 typedef struct SqNode//队列结点 {int data;struct SqNode* next; }LinkNode; typedef struct SqQueue//队列 {LinkNode* front, * rear; //头指针和尾指针 }LinkQueue; typedef …

毕马威 —— 公众对人工智能的信任、态度及使用情况调查

文章目录 前言 一、背景介绍 二、对人工智能的信任与接受度 三、人工智能的使用与认知情况 四、人工智能的益处与风险 五、人工智能的监管与治理 六、工作场所的人工智能应用 七、人工智能对工作的影响 八、学生对人工智能的应用 九、核心启示 1.新兴经济体在公众与员工人工智能…

基于Spring Session + Redis + JWT的单点登录实现

实现思路 用户访问受保护资源时&#xff0c;若未认证则重定向到认证中心认证中心验证用户身份&#xff0c;生成JWT令牌并存储到Redis认证中心重定向回原应用并携带令牌应用验证JWT有效性并从Redis获取会话信息用户在其他应用访问时&#xff0c;通过相同机制实现单点登录 代码…

微服务Eureka组件的介绍、安装、使用

微服务 Eureka 组件的介绍、安装与使用详解 在微服务架构中&#xff0c;服务注册与发现是至关重要的一环&#xff0c;而 Eureka 作为 Netflix 开源的服务注册中心&#xff0c;广泛应用于 Spring Cloud 微服务体系中。本文将带你全面了解 Eureka 的概念、安装及在 Spring Boot …

【PostgreSQL内核学习:通过 ExprState 提升哈希聚合与子计划执行效率(一)】

PostgreSQL内核学习&#xff1a;通过 ExprState 提升哈希聚合与子计划执行效率&#xff08;一&#xff09;引言背景补丁的意义补丁概述JIT & LLVM实际例子&#xff08;以 PostgreSQL 为例&#xff09;提交信息提交描述引入 ExprState 进行哈希计算&#xff1a;支持 JIT 编译…

web端播放flv视频流demo(flv.js的使用)

需求&#xff1a;原本是需要前端播放RTMP视频流的&#xff0c;但是现在的浏览器都不支持flash插件了&#xff0c;让用户安装flash插件也不现实&#xff0c;所以直接让后端将RTMP视频流转换成flv视频流给到前端进行播放。 直接上demo&#xff0c;直接就能播放&#xff0c;如果遇…

【拍摄学习记录】04-拍摄模式/曝光组合

曝光组合全自动半自动光圈优先手动挡【固定物体长时间不变时候、闪光灯时候、】手机上的光学变焦与数码变焦是不同的&#xff0c;使用档位推荐可以提升画质。手机夜景模式长曝光【车流轨迹、星轨】HDR 大光比【日落时候使用】专业模式&#xff0c;【感光度iso、快门可以调节】…