![伪造跨站请求 伪造跨站请求]()
跨站请求伪造攻击,Cross-Site Request Forgery(CSRF)。
攻击者在用户浏览网页时,利用页面元素(例如img的src),强迫受害者的浏览器向Web应用服务器发送一个改变用户信息的HTTP请求。
CSRF攻击可以从站外和站内发起。从站内发起CSRF攻击,需要利用网站本身的业务,比如“自定义头像”功能,恶意用户指定自己的头像URL是一个修改用户信息的链接,当其他已登录用户浏览恶意用户头像时,会自动向这个链接发送修改信息请求。从站外发送请求,则需要恶意用户在自己的服务器上,放一个自动提交修改个人信息的htm页面,并把页面地址发给受害者用户,受害者用户打开时,会发起一个请求。
攻击者使用CSRF攻击能够强迫用户向服务器发送请求,导致用户信息被迫修改,甚至可引发蠕虫攻击。如果恶意用户能够知道网站管理后台某项功能的URL,就可以直接攻击管理员,强迫管理员执行恶意用户定义的操作。
1.3. 风险评估
结合社会工程学(如通过电子邮件或聊天发送的链接),攻击者诱骗受害者点击恶意链接,而恶意链接中包含了诸如转账等敏感操作。下图简单阐述了CSRF攻击的思想:
从上图可以看出,完成一次CSRF攻击,受害者必须依次完成两个步骤:
GET类型的CSRF利用非常简单,只需要一个HTTP请求。
攻击者诱骗受害者访问恶意页面,通常这个恶意页面包含标签<img src=http://www.mybank.com/Transfer.jsp?toBankId=hackerID&money=1000 />,受害者一旦访问了恶意页面会向:
http://www.mybank.com/Transfer.jsp?toBankId=hackerID&money=1000
发送HTTP请求,该请求是转账操作,受害者在不知情的情况下向攻击者账户转账了1000元。
为了杜绝上面的问题,银行决定改用POST请求完成转账操作。因此,银行网站A的Web表单如下:
<form action="Transfer.jsp" method="POST">
<p>ToBankId: <input type="text" name="toBankId" /></p>
<p>Money: <input type="text" name="money" /></p>
<p><input type="submit" value="Transfer" /></p>
|
后台处理页面Transfer.jsp的伪代码如下:
public void doPost(HttpServletRequest req, HttpServletResponse res)
HttpSession session = request.getSession(false);
response.sendRedirect("../SessionLogin.htm");
String bankID=request.getParameter(“toBankId”);
String money=request.getParameter(“money”);
BankTools.transferMoney(bankID,double.parse(money));
|
危险网站B的HTML代码如下:
<html>
<head>
<script type="text/javascript">
function steal()
{
iframe = document.frames["steal"];
iframe.document.Submit("transfer");
}
</script>
</head>
<body onload="steal()">
<iframe name="steal" display="none">
<form method="POST" name="transfer" action="http://www.myBank.com/Transfer.jsp">
<input type="hidden" name="toBankId" value="11">
<input type="hidden" name="money" value="1000">
</form>
</iframe>
</body>
</html>
|
从以上代码看出,危险网站B暗地里发送了POST请求到银行,且该POST请求是转账操作,攻击者访问危险网站B时在不知情的情况下向攻击者转账了1000元。
检测方式多种多样:工具常常会扫描得到CSRF的漏洞,但是一般常常为误报,重点还是依靠手工来进行检测,以下来举例说明其中一种检测以及攻击方案:
设置页面test.htm中,页面中有一个表单,和一段脚本,脚本的作用是,当页面加载时,浏览器会自动提交请求。页面代码如下:
<form id="modify" action="http://www.test.com/servlet/modify" method="POST">
document.getElementById("modify").submit();
|
诱使用户在登录目标系统后访问URL链接http://xx.x.xx.xxx /test.htm
用户打开test.htm后,会自动提交表单,发送给www.test.com下的那个存在CSRF漏洞的web应用,用户信息被篡改。
在整个攻击过程中,受害者用户仅看到了一个空白页面(可以伪造成其他无关页面),并且不知道自己的信息已经被修改。
通过referer判断页面来源进行CSRF防护,该方式无法防止站内CSRF攻击及referer字段伪造。
通过token方式进行CSRF防护:
在Session中绑定token。如果不能保存到服务器端Session中,则可以替代为保存到Cookie里。
在form表单中自动填入token字段,比如 <input type=hidden name="anti_csrf_token" value="$token" />。
在服务器端对比POST提交参数的token与Session中绑定的token是否一致,以验证CSRF攻击
|
为每个session创建唯一的随机字符串,并在受理请求时验证:
<form action="/transfer.do" method="post">
<input type="hidden" name="randomStr" value=<%=request.getSession().getAttribute("randomStr")%>>
String randomStr = (String)request.getParameter("randomStr");
if(randomStr == null) randomStr="";
if(randomStr.equals(request.getSession().getAttribute("randomStr")))
|
服务端请求伪造攻击(Server-side Request Forgery): 很多web应用都提供了从其他的服务器上获取数据的功能。使用用户指定的URL,web应用可以获取图片,下载文件,读取文件内容等。这个功能如果被恶意使用,可以利用存在缺陷的web应用作为代理攻击远程和本地的服务器。这种形式的攻击称为服务端请求伪造攻击(Server-side Request Forgery)。
一般情况下, SSRF攻击的目标是从外网无法访问的内部系统 。( 正是因为它是由服务端发起的,所以它能够请求到与它相连而与外网隔离的内部系统 ).SSRF 形成的原因大都是由于 服务端提供了从其他服务器应用获取数据的功能且没有对目标地址做过滤与限制 。
比如从指定URL地址获取网页文本内容,加载指定地址的图片,下载等等。
可以对外网、服务器所在内网、本地进行端口扫描,获取一些服务的banner信息;
对内网web应用进行指纹识别,通过访问默认文件实现;
攻击内外网的web应用,主要是使用get参数就可以实现的攻击(比如struts2,sqli等);
其形成的原因大都是由于服务端提供了从其他服务器应用获取数据的功能,但又没有对目标地址做严格过滤与限制,导致攻击者可以传入任意的地址来让后端服务器对其发起请求,并返回对该目标地址请求的数据
如果应用程序对用户提供的URL和远端服务器返回的信息没有进行合适的验证和过滤,则可能存在服务器端请求伪造攻击。服务器端请求伪造攻击场景如下图所示:
攻击者想要访问主机B上的服务,由于存在防火墙的原因无法直接访问,这时可以借助主机A来发起服务器端请求伪造攻击,通过主机A向主机B发起请求,从而完成攻击。SSRF攻击方式主要有以下5种:
对外网、服务器所在内网、本地进行端口扫描,获取一些服务的banner信息(一般包括服务器的类型、版本,服务器上启动的服务信息);
攻击内外网的Web应用,主要是使用GET参数就可以实现的攻击(比如Struts2,Sqli等);
从WEB功能上寻找:我们从上面的概述可以看出,SSRF是由于服务端获取其他服务器的相关信息的功能中形成的,因此我们大可以列举几种在web 应用中常见的从服务端获取其他服务器信息的的功能。
早期分享应用中,为了更好的提供用户体验,WEB应用在分享功能中,通常会获取目标URL地址网页内容中的<tilte></title>标签或者<meta name="description" content=“”/>标签中content的文本内容作为显示以提供更好的用户体验。
http://widget.renren.com/*****?resourceUrl=https://www.nsfocus.com
通过目标URL地址获取了title标签和相关文本内容。而如果在此功能中没有对目标地址的范围做过滤与限制则就存在着SSRF漏洞.
转码服务:通过URL地址把原地址的网页内容调优使其适合手机屏幕浏览:由于手机屏幕大小的关系,直接浏览网页内容的时候会造成许多不便,因此有些公司提供了转码功能,把网页内容通过相关手段转为适合手机屏幕浏览的样式。例如百度、腾讯、搜狗等公司都有提供在线转码服务。
在线翻译:通过URL地址翻译对应文本的内容。提供此功能的国内公司有百度、有道等。
图片加载与下载,通过URL地址加载或下载图片:图片加载远程图片地址此功能用到的地方很多,但大多都是比较隐秘,比如在有些公司中的加载自家图片服务器上的图片用于展示。(此处可能会有人有疑问,为什么加载图片服务器上的图片也会有问题,直接使用img标签不就好了? ,没错是这样,但是开发者为了有更好的用户体验通常对图片做些微小调整例如加水印、压缩等,所以就可能造成SSRF问题)。
图片、文章收藏功能:此处的图片、文章收藏中的文章收藏就类似于功能一、分享功能中获取URL地址中title以及文本的内容作为显示,目的还是为了更好的用户体验,而图片收藏就类似于功能四、图片加载。
未公开的api实现以及其他调用URL的功能:此处类似的功能有360提供的网站评分,以及有些网站通过api获取远程地址xml文件来加载内容.
提示信息告诉我们,该URL访问的是一个xmlrpc服务,但该服务只接受post请求,通过百度知道这是一个CMS,去网上查了一下这个CMS默认开启XMLRPC。
XML-RPC是一个远程过程调用(远端程序呼叫)(remote procedure call,RPC)的分布式计算协议,通过XML将调用函数封装,并使用HTTP协议作为传送机制。
这个XMLRPC中存在一个叫做Pingback协议(Pingback,通知网志系统文章被引用情况的一种手段),POC如下:
发现88端口长度与其他端口不一样,然后提示给出88端口是内网12388的映射端口。于是访问12388端口。
过滤内网服务器对公网服务器请求的响应。如果Web应用是获取某一类型的文件,在把返回结果展示给用户之前应先验证返回的信息是否符合文件类型标准,比如返回信息应为图片,如果返回信息是HTML,则停止将返回信息返回客户端。
统一错误提示信息,避免用户可以根据错误信息来判断远端服务器的端口状态。
在内网服务器的防火墙上限制公网服务器的请求端口为HTTP等协议常用端口,如:80、443.8080、8090。
若公网服务器的内网IP与内网无业务通信,建议将公网服务器对应的内网IP列入黑名单,避免应用被用来获取内网数据。
内网服务器禁用不必要的协议,仅允许HTTP和HTTPS请求,防止类似于file:///、gopher://、ftp:// 等协议引起的安全问题。
![伪造跨站请求 伪造跨站请求]()
原文始发于微信公众号(LSCteam):伪造跨站请求
评论