什么是跨域,有什么攻击,如何防止跨域攻击攻击

权限不足 - SegmentFault
该内容处于隐藏状态,只有作者自己能看到哦51CTO旗下网站
HTML5安全风险详析之一:CORS攻击
CORS-CrossOrigin Resources Sharing,也即跨源资源共享,它定义了一种浏览器和服务器交互的方式来确定是否允许跨域请求。它是一个妥协,有更大的灵活性,但比起简单地允许所有这些的要求来说更加安全。简言之,CORS就是为了让AJAX可以实现可控的跨域访问而生的。
作者:蒋宇捷来源:博客| 11:22
一、从SOP到CORS
SOP就是Same Origin Policy同源策略,指一个域的文档或脚本,不能获取或修改另一个域的文档的属性。也就是Ajax不能跨域访问,我们之前的Web资源访问的根本策略都是建立在SOP上的。它导致很多web开发者很痛苦,后来搞出很多跨域方案,比如JSONP和flash socket。如下图所示:
后来出现了CORS-CrossOrigin Resources Sharing,也即跨源资源共享,它定义了一种浏览器和服务器交互的方式来确定是否允许跨域请求。它是一个妥协,有更大的灵活性,但比起简单地允许所有这些的要求来说更加安全。简言之,CORS就是为了让AJAX可以实现可控的跨域访问而生的。具体可以参见我的这篇文章《HTML5安全:CORS(跨域资源共享)简介》。示意如下图所示:
现在W3C的官方文档目前还是工作草案,但是正在朝着W3C推荐的方向前进。不过目前许多现代浏览器都提供了对它的支持。
服务器端对于CORS的支持,主要就是通过设置Access-Control-Allow-Origin来进行的。如果浏览器检测到相应的设置,就可以允许Ajax进行跨域的访问。例如:
Access&Control-Allow-Origin: http://blog.csdn.net
应用CORS的系统目前包括Face.com、GoogleCloudStorage API等,主要是为开放平台向第三方提供访问的能力。
二、CORS带来的风险
CORS非常有用,可以共享许多内容,不过这里存在风险。因为它完全是一个盲目的协议,只是通过HTTP头来控制。
它的风险包括:
1、HTTP头只能说明请求来自一个特定的域,但是并不能保证这个事实。因为HTTP头可以被伪造。
所以未经身份验证的跨域请求应该永远不会被信任。如果一些重要的功能需要暴露或者返回敏感信息,应该需要验证Session ID。
2、第三方有可能被入侵
举一个场景,FriendFeed通过跨域请求访问Twitter,FriendFeed请求tweets、提交tweets并且执行一些用户操作,Twitter提供响应。两者都互相相信对方,所以FriendFeed并不验证获取数据的有效性,Twitter也针对Twitter开放了大部分的功能。
但是当如果Twitter被入侵后:
FriendFeed总是从Twitter获取数据,没有经过编码或者验证就在页面上显示这些信息。但是Twitter被入侵后,这些数据就可能是有害的。
或者FriendFeed被入侵时:
Twitter响应FriendFeed的请求,例如发表Tweets、更换用户名甚至删除账户。当FriendFeed被入侵后,攻击者可以利用这些请求来篡改用户数据。
所以对于请求方来说验证接收的数据有效性和服务方仅暴露最少最必须的功能是非常重要的。
3、恶意跨域请求
即便页面只允许来自某个信任网站的请求,但是它也会收到大量来自其他域的跨域请求。.这些请求有时可能会被用于执行应用层面的DDOS攻击,并不应该被应用来处理。
例如,考虑一个搜索页面。当通过'%'参数请求时搜索服务器会返回所有的记录,这可能是一个计算繁重的要求。要击垮这个网站,攻击者可以利用XSS漏洞将Javascript脚本注入某个公共论坛中,当用户访问这个论坛时,使用它的浏览器重复执行这个到服务器的搜索请求。或者即使不采用跨域请求,使用一个目标地址包含请求参数的图像元素也可以达到同样的目的。如果可能的话,攻击者甚至可以创建一个WebWorker执行这种攻击。这会消耗服务器大量的资源。
有效的解决办法是通过多种条件屏蔽掉非法的请求,例如HTTP头、参数等。
4、内部信息泄漏
假定一个内部站点开启了CORS,如果内部网络的用户访问了恶意网站,恶意网站可以通过COR(跨域请求)来获取到内部站点的内容。
5、针对用户的攻击
上面都是针对服务器的攻击,风险5则针对用户。比方说,攻击者已经确定了你可以全域访问的productsearch.php页面上存在SQL注入漏洞。 攻击者并不是直接从它们的系统数据库中获取数据,他们可能会编写一个JavaScript数据采集脚本,并在自己的网站或者存在XSS问题的网站上插入这段脚本。当受害者访问含有这种恶意JavaScript脚本的网站时,它的浏览器将执行针对&productsearch.php&的SQL注入攻击,采集所有的数据并发送给攻击者。检查服务器日志显示是受害人执行了攻击,因为除了来自Referrer的HTTP头一般没有其他日志记录。受害者并不能说他的系统被攻破,因为没有任何任何恶意软件或系统泄漏的痕迹。
三、攻击工具
Shell of the Future是一个反向WebShell处理器,它利用HTML5的跨站请求来劫持会话。
四、防御之道
1、不信任未经身份验证的跨域请求,应该首先验证Session ID或者Cookie。
2、对于请求方来说验证接收的数据有效性,服务方仅暴露最少最必须的功能。
3、通过多种条件屏蔽掉非法的请求,例如HTTP头、参数等。
【编辑推荐】
【责任编辑: TEL:(010)】
大家都在看猜你喜欢
热点聚焦头条聚焦头条
24H热文一周话题本月最赞
讲师:1825人学习过
讲师:869人学习过
讲师:2722人学习过
精选博文论坛热帖下载排行
本书是在《网管员必读―网络安全》第1版的基础上修改而成的。新版在保留第1版实用内容的基础上增加了大量新的实用内容,同时删除了一些过时...
订阅51CTO邮刊这几天遇到这三个问题,现在简单的记录下来。
& & 如我服务器的域名是www.test1.com,我在另一个服务器www.test2.com通过ajax访问www.test1.com的数据时,就引起跨域的问题,提示错误&No 'Access-Control-Allow-Origin' header is present on the...
& & 网上有很多文章,可以搜索下。http://blog.csdn.net/liruxing1715/article/details/ &&http://twlidong.github.io/blog//kua-yuan-zi-yuan-gong-xiang-cross-origin-resource-sharing-cors/
& & jquery已经考虑到了这个问题,在ajax中封装了应对跨域的方法。参考上面黏出的第一个链接,我解决了问题。
2、xxs攻击 &xss表示Cross Site Scripting(跨站脚本攻击),通过插入恶意脚本,实现对用户游览器的控制
& &假如用户提交的数据含有js代码,不做任何处理就保存到了数据库,读出来的时候这段js代码就变成了可执行的代码,将会产生意向不到的效果。一般用户提交的数据永远被认为是不安全的,在保存之前要做对应的处理。这次我就遇到了这个问题,
& &我提交的内容&script&alert(1111)&/script&,或者&a href="www.baidu.com"&百度&/a&,读出来的时候,将直接弹出1111,或者百度是有效的超链接,这个显然是不行的。
& &提交的数据用下面的这个方法过滤一下,可以有效的防范xxs的攻击:
过滤用户代码
function security($str){
$str = trim($str);
//清理空格
$str = strip_tags($str);
//过滤html标签
$str = htmlspecialchars($str);
//将字符内容转化为html实体
$str = addslashes($str);
3、sql注入攻击 & &SQL注入攻击中以SQL语句作为用户输入,从而达到查询/修改/删除数据的目的
& & 我用的PDO连接,但是如果不用参数绑定的话,是依然可以sql注入的。应该多注意使用绑定参数!
阅读(...) 评论()跨域post 及 使用token防止csrf 攻击
我的图书馆
跨域post 及 使用token防止csrf 攻击
后台使用的python - flask
前台使用angular框架
1.一个跨域post的样例:
跨域post有多种实现方式:
2.利用iframe
3.server proxy:
样例使用的为iframe,想要证明,在没有进行csrf防御时,随意攻击者能够利用javascript发送 post 请求。从而简单的提交或获取数据资料;
1.本地test.html页面
&title&POST&/title&
&script type="text/javascript" src="jquery-2.1.4.min.js"&&/script&
&input type="button" onclick="test();" value="test"/&
&script type="text/javascript"&
function test() {
crossDomainPost({
url: 'http://localhost:5000/test',
param: {a: '1', b: '2'},
onSubmit: function (e) {
console.log(e);
function crossDomainPost(config) {
var def = {
//提交的地址
//提交的參数
//延迟获取參数的时间。单位为毫秒
: function (i) {}
//提交成功后的回调函数,參数为跳转的IFRAME
= $.extend({}, def, config);
if (!config.url) {
config.onSubmit({error: 'URL is Empty!'});
/****baseMethod****/
* 生成随机的10位字符,且唯一
* @returns {string}
var createGuid
= function () {
var guid = "";
for (var i = 1; i &= 10; i++) {
guid += Math.floor(Math.random() * 16.0).toString(16);
* 删除指定的节点
* @param _element 要删除的节点
removeElement = function (_element) {
var _parentElement = _element.parentN
if (_parentElement) {
_parentElement.removeChild(_element);
// Add the iframe with a unique name
var iframe
= document.createElement("iframe");
var uniqueString
= createGuid();
document.body.appendChild(iframe);
iframe.style.display
iframe.contentWindow.name = uniqueS
// construct a form with hidden inputs, targeting the iframe
= document.createElement("form");
form.target = uniqueS
form.action = config.
form.method = "POST";
// repeat for each parameter
for (var item in config.param) {
= document.createElement("input");
input.type
= "hidden";
input.name
input.value = config.param[ item ];
form.appendChild(input);
document.body.appendChild(form);
form.submit();
}catch(e){
console.log('error');
consoel.log(e);
setTimeout(function () {
config.onSubmit(iframe);
removeElement(form);
//移除form
}, config.delay);
&/html&12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
2.后台接收代码
这里仅接收POST的请求
@app.route('/test' ,methods=['POST'])
def test():
print 'param is :';
print request.form
return jsonify(data='2222')12345
3.控制台输出:
服务端处理了非站内的请求
4.浏览器输出:
本地test.html获取到返回信息
跨站请求攻击。简单地说,是攻击者通过一些技术手段欺骗用户的浏览器去訪问一个自己以前认证过的站点并运行一些操作(如发邮件,发消息,甚至財产操作如转账和购买商品)。因为浏览器以前认证过。所以被訪问的站点会觉得是真正的用户操作而去运行。这利用了web中用户身份验证的一个漏洞:简单的身份验证仅仅能保证请求发自某个用户的浏览器,却不能保证请求本身是用户自愿发出的。
你这能够这么理解CSRF攻击:攻击者盗用了你的身份,以你的名义发送恶意请求。CSRF能够做的事情包含:以你名义发送邮件。发消息,盗取你的账号。甚至于购买商品,虚拟货币转账……造成的问题包含:个人隐私泄露以及財产安全。
从上图能够看出,要完毕一次CSRF攻击,受害者必须依次完毕两个步骤:
登录受信任站点A,并在本地生成Cookie。
在不登出A的情况下,訪问危急站点B。
看到这里。你或许会说:“假设我不满足以上两个条件中的一个,我就不会受到CSRF的攻击”。是的,确实如此。但你不能保证下面情况不会发生:
1.你不能保证你登录了一个站点后,不再打开一个tab页面并訪问另外的站点。
2.你不能保证你关闭浏览器了后,你本地的Cookie立马过期,你上次的会话已经结束。
3.上图中所谓的攻击站点。可能是一个存在其它漏洞的可信任的常常被人訪问的站点。
原理具体:
2.常见的攻击类型:
1.GET类型的CSRF
仅仅须要一个HTTP请求。就能够构造一次简单的CSRF。
银行站点A:它以GET请求来完毕银行转账的操作,如:
危急站点B:它里面有一段HTML的代码例如以下:
&img src=http://www.mybank.com/Transfer.php?toBankId=11&money=1000&1
首先。你登录了银行站点A,然后訪问危急站点B,噢,这时你会发现你的银行账户少了1000块
为什么会这样呢?原因是银行站点A违反了HTTP规范,使用GET请求更新资源。在訪问危急站点B的之前。你已经登录了银行站点A,而B中的以GET的方式请求第三方资源(这里的第三方就是指银行站点了,原本这是一个合法的请求,但这里被不法分子利用了)。所以你的浏览器会带上你的银行站点A的Cookie发出Get请求,去获取资源 ,结果银行站点服务器收到请求后,觉得这是一个更新资源操作(转账操作),所以就立马进行转账操作
2.POST类型的CSRF
如上边的跨域POST样例
3.怎样防御CSRF
1.提交验证码
在表单中添加一个随机的数字或字母验证码。通过强制用户和应用进行交互。来有效地遏制CSRF攻击。
2.Referer Check
检查假设是非正常页面过来的请求,则极有可能是CSRF攻击。
3.token验证
在 HTTP 请求中以參数的形式添加一个随机产生的 token,并在服务器端建立一个拦截器来验证这个 token,假设请求中没有
token 或者 token 内容不对,则觉得可能是 CSRF 攻击而拒绝该请求。
token须要足够随机
敏感的操作应该使用POST。而不是GET,以form表单的形式提交。能够避免token泄露。
4.在 HTTP 头中自己定义属性并验证
这样的方法也是使用 token 并进行验证。这里并非把 token 以參数的形式置于 HTTP 请求之中,而是把它放到 HTTP 头中自己定义的属性里。通过 XMLHttpRequest 这个类,能够一次性给全部该类请求加上 csrftoken 这个 HTTP 头属性。并把 token 值放入当中。这样攻克了上种方法在请求中添加 token 的不便。同一时候,通过 XMLHttpRequest 请求的地址不会被记录到浏览器的地址栏,也不用操心 token 会透过 Referer 泄露到其它站点中去。
4.关于token
Token 应该被保存起来(放到 )
Tokens 除了像 cookie 一样有有效期。而且你能够有很多其它的操作方法。一旦 token 过期,仅仅须要又一次获取一个。你能够使用一个接口去刷新 token。你甚至能够把 token 原来的公布时间也保存起来。而且强制在两星期后又一次登录什么的。假设你须要撤回 tokens(当 token 的生存期比較长的时候这非常有必要)那么你须要一个 token 的生成管理器去作检查。
Local / session storage 不会跨域工作,请使用一个标记 cookie
有须要的话,要加密而且签名 token
将 JSON Web Tokens 应用到 OAuth 2
1.引入csrf
from flask_wtf.csrf import CsrfProtect
csrf = CsrfProtect()
app = Flask(__name__)
csrf.init_app(app)
app.config['SECRET_KEY']='myblog'1234567
2.在站内页面上head中,添加token
&meta name="csrf-token" content="{{ csrf_token() }}"&1
3.配置angular提交表头
app.config(function ($httpProvider) {
$httpProvider.defaults.headers.common['X-CSRF-Token'] = $('meta[name=csrf-token]').attr('content');
4.再次測试跨域post
后台输出:
前台输出:
关于webapp跨域Post使用token思路:
移动端登录时,服务端验证表单信息。登陆成功,生成token,返回给client;
client将token存在localstorage/sessionstorage中。每次提交表单。都须要携带token;
服务端获取请求。假设没有token,则忽略请求;
出现的问题:
服务端须要限制登陆次数
解决方法:
client添加登陆间隔。请求一次后,等待x秒才干再次请求
服务端做cas验证
服务端须要保存用户的token,及过期时间;
解决方法:
能够将token 保存在Memcache,数据库中,redis
client存token时。须要对token加密
解决方法:
在存储的时候把token进行对称加密存储,用时解开
将请求URL、时间戳、token三者进行合并加盐签名。服务端校验有效性
当然。以上仅仅防君子,不防小人
跨域post请求:
跨站请求伪造:
[转]&[转]&[转]&[转]&
喜欢该文的人也喜欢NodeJS的CSRF跨域访问攻击的解决方案原创
CSRF跨域访问攻击是什么呢?
一个网页通常会通过POST/PUT/DELETE请求更改对应用户账户的信息。但是浏览器并不会限制其它网站对你网站的访问。如果在其它网站中有一个链接叫“抽奖”,用户点了,该链接正是调用你网站的支付接口,那么用户就会莫名奇妙的损失了钱财。
CSRF的解决方案是什么呢?
关键是保证后端只能接受自己的前端放送过来的POST/PUT/DELET这些增删改的接口。为什么不屏蔽GET呢。嘿嘿,当然我们需要通过别的网站的链接也能访问到自己的网站啦。屏蔽了外网站的GET也就屏蔽了网站外链接,那么用户也没发通过搜索或者导航网站网站了呀,得不偿失。
如果保证呢后端只接受本网站前端发出的请求呢?
其中一个有效的策略就是由后端生成一个随即字符串,保存在session,我们根据用途给这个随即字符串起个名字叫csrf_token。并在用户第一个访问网页的时候,保存在HTML/JS中,以后前端发送POST/PUT/DELETE的时候,都要加上csrf_token,否则后端接口会拒绝响应,抛出异常。
后端NodeJS中生成csrf_token随即字符串:
1.后端NodeJS安装csurf包和ejs包
npm install csurf --save
npm install ejs --save
2.后端NodeJS中使用csurf生成csrf_token, 使用ejs在index.html注入token
在NodeJS的入口文件中加入下面的代码
var csrf = require('csurf');
//指定ejs模版文件的名字仍然为.html
//请求过来,仍然默认返回index.html,nodejs可以往index.html写变量拉
app.engine('.html', require('ejs').__express);
app.set('views', path.resolve(publicDir));
app.set('view engine', 'html');
var csrfProtection = csrf({ cookie: true });
app.get(appPath, csrfProtection,
function (req, res){
// 把生成的csrfToken写入到index.html中去
res.render('index', { csrfToken: req.csrfToken() })
index.html
&!doctype html&
&html class="bootstrap3 legacyfalse chrometwo"&
&meta content="&%= csrfToken %&" name="csrf-token"&
3.前端发送POST中加入csrf_token
在前端中取出csrf_token的值,我是在angular中,利用jQuery取值
$scope.csrfToken = $('meta[name=csrf-token]').attr('content');
在表单请求中加入csrf_token
&form method="post" action="/changevalue" class="ng-pristine ng-valid"&
&input value="value" name="input1"&
&input value="value2" name="input2"&
&input type="hidden" value="{{ csrfToken }}" name="_csrf"&
&button type="submit"&submit&/button&
4.在后端NodeJS接口中验证csrf_token
app.post("changevalue" , parseForm, csrfProtection, function (req, res) {
res.send("response");
随时随地看视频

我要回帖

更多关于 跨域脚本攻击的原理 的文章

 

随机推荐