为什么说你的API并不安全?  必须要看

为什么说你的API并不安全?

2015-12-04 开发者

开发者(KaiFaX)

面向开发者、程序员的专业平台!

0×00 背景介绍

前段时间我向Spree Commerce公司报告了其所有API路径存在JSONP+CSRF漏洞的问题。同样,Instagram的API存在CSRF漏洞。Disqus、Stripe和Shopify的API通过JSONP泄露隐私信息。这一切问题的根源都是没有合理使用混合API认证。

希望所有API开发者都能看一看这篇文章。我将解释API认证的基础和目前业内最好的做法。

0×01 过程详述

首先你的API通过api_key来进行认证:

def load_user

@current_api_user = Spree.user_class.find_by(spree_api_key: api_key.to_s)

end

这时有人让你启用CORS(跨域资源共享,Cross-Origin Resource Sharing),因为他们想通过JS调用你的API:

config.middleware.insert_before 0, "Rack::Cors" do

allow do

origins ‘*‘

resource ‘*‘, :headers => :any, :methods => [:get, :post, :options]

end

end

显然在你的APIController中有skip_before_action :verify_authenticity_token 。那么你会说对于来自比如Android app的API请求为什么还需要CSRF验证呢?

还有一位开发者希望你能加上JSONP(JSON with Padding)的支持因为低版本浏览器不支持CORS。你觉得这当然没问题:

after_filter :set_jsonp_format

def set_jsonp_format

if params[:callback] && request.get?

self.response_body = "#{params[:callback]}(#{response.body})"

headers["Content-Type"] = ‘application/javascript‘

end

end

目前看来一切都没什么问题。最后你的开发者决定追随Backend-As-API的潮流并在客户端使用你的api.example.com。这时有两种选择:

一. 手动增加api_token

比如说Soundcloud的每个API请求头部使用Authorization:OAuth 1-16343-15233329-796b6b695d2c7c1,Foursquare使用oauth_token=YXIAC4Y254HGZBNPQW6S0UFBGGSU57RBP.

这样做的缺点:

1.XSS。OAuth tokens可通过JS访问,攻击者可借此泄露受害者凭证。可以使用HttpOnly flag来防止此类事件发生。但OAuth tokens并没有此类预防措施。

2.对于每个请求都会有OPTIONS请求,增加了潜在风险。对了我还写了一篇 CORS不发送预检请求(http://homakov.blogspot.com/2014/01/how-to-use-cors-without-preflights.html)的技巧。

尽管很多人使用这样的方法但我并不推荐。

二. 通过cookie认证用户

这样一来你想到修复方法很简单:

@current_api_user = (try_spree_current_user || Spree.user_class.find_by(spree_api_key: api_key.to_s))

try_spree_current_user 解析 _spree_session cookie, 得到user_id返回User.find(session[:user_id])。那么这种做法有什么问题呢?

类似“授权(Authorization)”,cookie也是封装在头部,但即使是经验丰富的开发也不一定能真正理解cookie。我称其为“自带凭证(sticky credentials)”,因为它们是自动加上的,即使是来自第三方域的请求(比如evil.com)。

因为绝大多数web开发者并没有理解到这样的概念导致CSRF成为全球最普遍的安全问题。这也是为什么所有基于cookie的认证都需要用额外的csrf_token nonce进行双重认证。这个nonce能使你确定请求来自你的域名。

1.因为你的API请求漏掉了CSRF保护,所有你的API路径都有请求伪造的风险。Spree的修改admin密码的例子(http://securecanvas.com/csrf.html#{"url":"https://majestic-stall-2602.spree.mx/api/users/1","autosubmit":false,"target":"_top","data":"utf8=%E2%9C%93&_method=put&user%5Bemail%5D=spree%40example.com1&user%5Bspree_role_ids%5D%5B%5D=&user%5Bpassword%5D=123123123&user%5Bpassword_confirmation%5D=123123123&button=&sbmbtn=&","method":"POST"})。

2.JSONP通过跨站泄露GET响应:

<script src="http://api.example.com/orders.json?callback=leakMe"></script>

3.CORS就更不可靠了,每种请求都会泄露信息。

0×02 解决方案

那么怎么做才对?混合API认证:

@current_api_user = unless api_key.to_s.empty?

Spree.user_class.find_by(spree_api_key: api_key.to_s)

# Good to go!

else

# Everyone stand back, we are using cookies!

# 1) verify CSRF token for all non-GET requests

# 2) drop JSONP support

# 3) drop CORS support

try_spree_current_user

end

这种混合的方法允许前端(JS/HTML app)和第三方应用使用你的api.example.com,让你的凭证不受XSS(HttpOnly)的困扰,也不会产生并无必要的OPTIONS请求。上述介绍的就是目前业内的最好方法。

*原文地址;sakurity,编译/florence

来源:FreeBuf黑客与极客(FreeBuf.COM)

原文:http://www.freebuf.com/articles/security-management/87522.html

转载文章,向原作者致敬!如有侵权或不周之处,敬请劳烦联系若飞(微信:13511421494)马上删除,谢谢!



1. 回复“m”可以查看历史记录;

2. 回复“h”或者“帮助”,查看帮助;

开发者已开通多个微信群交流学习,请加若飞微信:13511421494 进群

开发者:KaiFaX面向开发者、程序员的专业平台!

微信扫一扫
关注该公众号

时间: 2024-09-29 01:34:24

为什么说你的API并不安全?  必须要看的相关文章

QQ地图api里的 地址解析函数 看不懂 javascript_百度知道

QQ地图api里的 地址解析函数 看不懂 javascript_百度知道 ??? QQ地图api里的 地址解析函数 看不懂 javascript??? 2011-09-18 12:18 ??? 匿名 ??? | ??? 分类:JavaScript ??? | 浏览126次 ??? http://cstar.qq.com/qqmapapi/classdoc/symbols/QGeocoder.html函数 帮忙写函数根据地址返回坐标 x y函数看懂??? QGeocoder比? function(

爬虫API学习-斯必克API调用

JQuery手动触发事件API之:通过代码看清trigger与triggerHandler的差别

本文只讨论JQuery如何手动触发DOM上绑定的事件处理函数,至于如何给DOM绑定事件处理函数,可以参考这篇文章.测试环境是IE11/FF17/Chrome39,JQuery版本是1.11.1和2.1.1都测试过. 下面这段js代码给button绑定了click事件处理函数,第一种是我们最常用的做法:第二种使用了自定义参数. // 绑定事件的时候不自定义参数 $("#button").bind("click",function(event){ alert("

JVM虚拟机面试指南:年薪30W以上高薪岗位需求的JVM,你必须要懂!

JVM的重要性 很多人对于为什么要学JVM这个问题,他们的答案都是:因为面试.无论什么级别的Java从业者,JVM都是进阶时必须迈过的坎.不管是工作还是面试中,JVM都是必考题.如果不懂JVM的话,薪酬会非常吃亏.其实学习JVM并不仅仅可以用于面试,而在于更深入地理解 Java 这门语言,以及为未来排查线上问题打下基础. JVM的优势 想要告别增删改查和简单开发,而是去做Java性能分析和调优工作,那么JVM绝对是一把助力的利剑.对于Java开发者而言,只有熟悉底层虚拟机的运行机制,才能通过JV

解决必须要alert一下,才生效的问题

例如: <span style="font-size:18px;"> if(parseInt(status) == 201){ dhxWins.unload(); } </span> 在这段代码前面加上alert就可以运行了. 可能原因:这种情况一般出现在alert()之后的某个代码需要页面元素进行一定的状态才能使用,加上alert()之后,相当于页面元素有足够的事件进入一定的状态了,也就是说:必须给予alert()之后的代码足够的时间来进入一定的状态. 解决办

简单无符号乘法器(怎么总是有疏漏,神啊!必须要level up了!)

module multiplier( input clk,rst, input [7:0] A,B, output [16:0] C); reg [3:0] cnt; reg [16:0] temp; always@(posedge clk or negedge rst) if(!rst) begin cnt<=0; temp<=0; end else if(cnt==8) cnt<=0; else if(B[cnt]) begin temp<=temp+(A<<cnt

学HTML5必须要学JS吗

学习html5的话,如果你是想作为一个前端人员的话,js是必须要学的,这里我给你一些建议: 1.学习目录:html >> css >> js >> html5 >> css3(书籍的话,我建议你<Head First HTML and CSS>这本书还是蛮不错的, 2.进阶:学js的时候建议视频和书配套,视频主入门,书主细节.深入: 3.学习方法:至于html和css可以看看视频学习,初期学习不一定要求那么高,要精通,有大概的映像就行,在后面学习

C++调用C接口必须要加extern &quot;C&quot;的原因

1.第一层直接原因,如果不加extern "C",C++程序调用C接口会出现如下错误(链接时) undefined reference 以实例演示:1)错误示例在ss.c中有如下代码 #include <stdio.h> void cfun_output(int x) { printf("%d\n", x); } 在ss.h头文件中有如下定义 #ifndef SS_H_ #define SS_H_ void cfun_output(int x); #en

linux下的这些压缩,归档命令---你必须要会

一,常见的压缩/解压缩工具: compress /uncompress     后缀:      .z gzip /gunzip             后缀:      .gz bzip2/bunzip2            后缀:      .bz2 zip/unzip                后缀:      .zip 第一种compress已经不太常见了,后面的三种都是现在比较流行的压缩/解压缩工具 二,具体的使用 gzip #gzip filename