oauth20安全案例回顾Word格式文档下载.docx
《oauth20安全案例回顾Word格式文档下载.docx》由会员分享,可在线阅读,更多相关《oauth20安全案例回顾Word格式文档下载.docx(10页珍藏版)》请在冰豆网上搜索。
场景复杂化下增加了攻击点从业务出发点来讲,制定OAuth2.0协议的最大动力之一,是希望用一个协议适应多个业务场景授权,即需要既能满足传统客户端授权场景,又要满足无服务器参与的授权场景,甚至还有手机应用授权场景等等等等。
而这种拉大业务场景的结果,一般也意味着薄弱点的增多,这是因为在场景复杂化的情况下,开发方容易考虑不周、或者对应用方的相关安全指示不足,应用方也容易错误使用应用场合,而协议对这些场景也没有更加深入的指引。
另外它也可能导致场景之间的安全问题产生了交叉,一些本来属于潜在威胁,很容易通过场景转换变成了显性漏洞。
对于擅长“由点到面”的攻击者来说,现在只需要针对常见薄弱点(尤其是授权认证流程中的薄弱点)就有可能攻击成功。
OAuth2.0的rfc定义了几种场景授权模式,并允许平台方自行扩充,本文讨论的有:
(A)AuthorizationCodeGrant(授权code许可)用户在平台方授权页面登录后,跳转的redirect_uri中,参数段(如http:
//cakkback_url/?
code=aaaaa&
amp;
state=ssss)带code参数;
此时应用需要再次向平台方的指定接口(一般为获取AccessToken接口)发起请求,用code参数换取accesstoken。
这是OAuth1.0中几乎唯一定义过的业务场景,主要用于传统客户端和有服务器参与的网站授权。
图:
rfc6749第4.1节AuthorizationCodeGrant流程图
AuthorizationCodeGrant常见的实现模式:
以网站应用为例(B)ImplicitGrant(隐式许可)用户在平台方授权页面登录后,跳转的redirect_uri中,uri片段(如http:
//cakkback_url/#access_token=aaaaaa&
uid=aaaaa)直接带accesstoken。
这种场景不验证应用的有效性,主要用于无应用方服务器参与的纯浏览器javascript/HTML5交互。
rfc6749第4.2节ImplicitGrant流程图
ImplicitGrant常见的实现模式:
以无应用服务器的浏览器插件为例(C)ResourceOwnerPasswordCredentialsGrant(资源所有者密码凭据许可;
XAuth即为此类)应用直接向平台方的指定接口(一般为专用的XAuth登录接口;
或者为获取AccessToken接口)发起请求,直接用用户名和密码获取AccessToken。
rfc6749第4.3节ResourceOwnerPasswordCredentialsGrant流程图图:
ResourceOwnerPasswordCredentialsGrant常见的实现模式:
以传统客户端应用为例
(2)简化和不作强制要求:
落空的开发者保安全愿望从具体技术实现来讲,OAuth2.0为了让平台方可以以最小的业务改造代价整合已有资源,对于许多方面并不作强制要求,这其中一个核心精神,就是将应用层签名流程简化(甚至去除),并依赖传输层加密(TLS)。
在业界的实践中,这种精神被转化为无绑定token(Unboundedtokens)和无记名token(Bearertokens):
OAuth2.0中既不存在Accesstokensecret等签名专用参数,也放弃以请求参数为基础生成一个签名hash值的做法;
整个api通讯过程在表面上和浏览器访问https网站很相像,唯一不同的是cookies换成了accesstoken。
虽然标准有推荐类似OAuth-HTTP-MAC的签名流程提案,但在实践中并不待见。
这种简化和不作强制要求,提高了平台方和应用方的安全编码要求——在没有协议保障安全下(OAuth1.0就是靠强制签名),双方(尤其是应用方)需要自行实施能够相互配合的安全方案,才能保障整个OAuth2.0的使用全过程,均是出于用户自身意愿的授权。
但问题是,开发普遍有匮乏安全意识的客观情况,对“认证”和“授权”之间的区别也难以细究,更遑论平台方和应用方之间的安全不对等和相互推诿,这就使得靠开发保障安全的美好想法落空。
此处以新浪微博api为例给出两个协议的区别:
【HTTP,SinaweiboOAuth1.0a】GET/users/show/123456.json?
oauth_consumer_key=【应用APPKEY】&
oauth_nonce=【OAuth随机值】&
oauth_signature=【查询参数+应用APPSECRET+AccessTokenSecret三者共同进行签名后的值】&
oauth_signature_method=HMAC-SHA1&
oauth_timestamp=【请求时间】&
oauth_token=【AccessToken】&
oauth_version=1.0aHTTP/1.1
Host:
【HTTPS,SinaweiboOAuth2.0】Host:
GET/2/users/show.json?
uid=123456HTTP/1.1
Authorization:
OAuth2【AccessToken】
0x02攻陷应用方的账号体系OAuth2.0的安全实施问题,有非常多是落在攻陷应用方的账号体系上,这是因为应用方的水平参差不齐且不可控,其安全意识更弱,因此攻击者会挑选最薄弱地带攻击。
当授权用于认证时的不当参数选择或无验证机制漏洞频率:
常见责任方:
应用方(主要)、平台方(无或次要)wooyun案例:
2012-08-24WooYun:
淘网址sinaoauth认证登录漏洞2013-01-14WooYun:
啪啪任意进入他人账号(OAuth2.0无绑定token问题)2013-01-19WooYun:
金山快盘手机客户端任意进入他人快盘账号漏洞成因和建议修复方案:
无论是OAuth1.0还是OAuth2.0,应用场景最多的就是第三方登录(账号打通),其中关键步骤,在于当应用方通过平台方的Accesstoken获取接口得到授权信息(AccessToken、uid、expire_time等)后,如何将其作为参数匹配到自己应用方的账号,然后自动登录(或自动注册)。
针对这个流程常见的攻击之一是修改授权信息,如果后续的匹配处理逻辑出现纰漏(比如不当参数选择或无验证机制),那么就有可能导致任意登录到任一应用方账号的严重漏洞。
攻击Accesstoken数据的薄弱点在OAuth1.0还是AuthorizationCodeGrant一统天下的年代,由于主要用于服务器网站应用,这个问题顶多算是潜在问题,毕竟如果要改授权信息,只能操作服务器或者在服务器所在网站arp——都入侵到那种地步了有啥不可能。
不过是世事无绝对,当年已经有开放平台提前实现了ImplicitGrant场景,然后有网站错误使用了这种模式,通过javascript获取里面的uid/accesstoken,然后再提交给网站直接进行登录;
结果由于这些授权信息可以被攻击者轻易地截包修改,造成安全问题——淘网址的漏洞,就是这么来的。
而OAuth2.0在对待手机、平板之类应用的授权的问题上,一般都倾向于返回accesstoken;
然后由应用将accesstoken上报给服务器,以进行应用自身的账号认证登录。
这种场景的变化导致被篡改的难度大大降低(简单的验证方法是使用fiddler2进行截包篡改),但许多手机开发者、乃至手机背后的服务器api开发者并没有意识到,结果错误选择了授权信息作为参数(比如单纯选择uid)、或者没有对授权信息(accesstoken)进行来源验证,从而导致这类漏洞大爆发。
手机开发者引入OAuth2.0后,常犯的任意登录到应用方账号严重漏洞成因解决这类漏洞的关键点主要靠应用方,但平台方也必须要参与:
(1)应用方需要认真考虑在整个自动登录/自动注册的过程中,平台方返回的授权信息(尤其是accesstoken和uid)会否被用户篡改;
如果任一个授权信息都会被篡改,那么在服务器中必须再次使用平台方给出的accesstoken验证接口,验证该accesstoken是否为指定来源应用所颁发,同时使用该accesstoken验证接口给出的uid,而不能使用可能被篡改的原uid值。
如果应用方已经收到该漏洞攻击的影响,则需要对对所有已存入的绑定access_token进行核查,发现access_token中的平台方uid和绑定的平台方uid不一致、非自身客户端应用appkey授权的access_token、过期access_token等异常情况均需要全部撤消,要求这些异常用户重新授权登录。
(2)平台方需要开发accesstoken验证接口,接收参数为accesstoken等,返回结果应包括颁发的应用来源(一般是appkey)、uid、过期时间等。
同时平台方应针对受影响开发者,发布安全公告和指引,说明易受攻击和使用此接口的场景。
针对应用方csrf劫持第三方账号漏洞频率:
应用方(主要)、平台方(如果没有配合应用方的csrf防御,则为主要;
否则无)wooyun案例:
2012-11-10WooYun:
优酷网存在账号被劫持风险2013-01-07WooYun:
大麦网存在帐号被劫持风险2013-03-01WooYun:
美丽说oauth漏洞可劫持账号漏洞成因和建议修复方案:
有关应用方csrf劫持的问题,不得不提2012年11月份的一场大讨论。
那场讨论的漏洞场景主要是使用AuthorizationCodeGrant的应用(网站居多),主要的漏洞原因是redirect_uri中的code参数没有和当前客户端的状态绑定,攻击者可以通过发送预先获取好的code参数到受害者电脑,导致导致受害者当前登录的应用方账号被绑定到攻击者指定的平台方(如微博)帐号上。
当时我写了篇文章《小议OAuth2.0的state参数——从开发角度也说《互联网最大规模帐号劫持漏洞即将引爆》》,详细建议用state参数防御这种csrf攻击,此处不再重复。
针对code参数的AuthorizationCodeGrant攻击;
以及和rfc6749的流程图关系应用方要预防这种csrf劫持账号,加入state参数是比较简单的通行方法。
根据rfc6749章节10.12,该值既不可预测,又必须可以证明应用(client)和和当前第三方网站的登录认证状态存在关联(如果存在过期时间更好)。
一种简单的方法是:
随机算一个字符串,然后保存在session,回调时检查state参数和session里面的值。
而平台方也要在回调时,支持应用方的state参数(当然如果允许redirect_uri参数中带应用方自己的防csrf参数,其实也可以)。
但严格来讲,仅有state参数,其实还不够,还需要结合3.3提到的防御手段。
更猥琐的针对应用方csrf劫持第三方账号:
应用方授权动作本身的csrf+平台方的登录漏洞…...漏洞频率:
应用方(主要)、平台方(主要?
次要?
)wooyun案例:
暂无其它案例:
webstersprodigy,2012-5-9,CommonOAuthissueyoucanusetotakeoveraccounts:
stackexchange(应用方)+csrffacebook(平台方)=绕过state参数+将受害者的stackexchange账号绑定到攻击着指定的facebook账号)漏洞成因和建议修复方案:
加入state参数是否就意味着没有问题?
比如承认,去年我在文章中仅关注仅关注state参数确实很片面,甚至是违反了“安全是一个整体”的原则,人为割裂了整个授权过程的整体分析,掩盖了其它问题乃至攻击角度:
state参数确能有效保护授权过程中是当前用户的唯一真实操作,但是发起授权前呢?
授权后呢?
国外的这个案例给了很好的答案(该案例在zone上有讨论):
(1)facebook(平台方)存在登录漏洞,可以被csrf如果平台方可以被xss、或者没有xss但其登录流程有漏洞可以被csrf(比如登录表单没有referer保护),那么就可以让受害者的电脑登录到攻击者指定的平台方账号。
这个的作用是干啥?
别急,往下看。
webstersprodigycsrffacebook登录的poc
(2)stackexchange(应用方)csrf发起绑定请求回想一下作为一个普通用户,在应用方(stackexchange)绑定平台方(facebook)账号的过程:
用户到stackexchange绑定页面,提示未绑定facebook,此时当然会点击“开始绑定”。
那么有没有想过,“开始绑定”这个动作,其实是没有做csrf保护的?
这正是应用方(包括我自己)长期以来忽视的一个问题——在应用点击发起绑定授权时,并不等于向平台方发起授权请求啊,它必须要做一些逻辑判断(包括生成state参数)后才能跳转到平台方的授权页面……
webstersprodigy展示应用方的绑定页面因此,结合上面提到的facebook(平台方)可以csrf登录,攻击者首先让受害者电脑登录到指定的facebook账号,然后再csrfstackexchange(应用方)绑定请求,那么就可以达到劫持应用方帐号的目的了。
而这两点成因,和state参数所防御的攻击场景有一定区别,所以完全可以bypass掉。
webstersprodigy的csrf应用方绑定请求poc
webstersprodigy的完整攻击流程图@渥村万涛当年的评论,更能说明有关csrf劫持应用方帐号这类问题的本质,只可惜我醒悟得太迟:
“其实,这个漏洞的根本原因,是违反了RFC6749,没有任何CSRF保护,而不是没有使用state参数(state只是实现CSRF保护的一种).根据RFC6749而不是必须(MUST).但CSRF保护是MUST.没有用state,不违反标准,但没有CSRF保护,则违反”(发表于2012-11-1012:
50)而返回到这个漏洞,“安全是一个整体”再一次体现——只有平台方和应用方的共同努力,才可能修补完全。
不过各位都懂的,对于这种有多个责任方问题的漏洞,这几乎不可能…...针对平台方的建议:
(1)检查所有登录页面和登录流程,防止出现登录漏洞。
比如在存在登录入口的页面(尤其是在具有sso登录功能的页面上)上,强制进行referer和一次性token验证,以防止被csrf登录。
又比如检查所有登录相关的流程,防止出现漏洞。
以下是一些例子:
2013-02-19WooYun:
猪八戒网不用账号密码登录任意账号2013-03-18WooYun:
饭统网登录任意账户漏洞
(2)检测会否能够对帐号异地登录有反应并采取措施。
不过如果出现定向攻击,这似乎没啥用。
针对应用方的建议:
(1)做好发起绑定平台方账号(新浪微博、QQ空间、人人网等等)、解除绑定等等等等诸如此类的绑定相关动作的csrf防护。
这是整个开发界一直以来忽视的点。
(2)在绑定页面显示绑定的平台方昵称、uid等信息等,防止用户无法自查绑定信息。
(3)绑定和解绑时,通知用户。
账号体系的固有逻辑缺陷利用漏洞频率:
少见责任方:
应用方(主要)wooyun案例:
2012-03-14WooYun:
借助第三方连接可创建重复昵称账户漏洞成因和建议修复方案:
实际上这类漏洞和OAuth协议(或者说任何一个账号互通登录协议)没有关联,纯粹是应用方设计的帐号体系逻辑存在问题。
将其放在这里主要是希望提醒应用方开发者,仔细审查账号设计体系和实现方式,在使用平台方的账号互通时要留意对方帐号体系的不同点(在OAuth实现中,则主要体现在应用方账号绑定和注册中的代码逻辑),避免出现重复帐号问题。
0x03攻击平台方的账号和资源体系经过OAuth1.0的洗礼,平台方在安全上有了更多的认识,比如强制限定回调地址(较多是验证域名部分)以降低redirect_uri跳转的范围,强制accesstoken有效期(甚至基本不提供refreshtoken之类的东西)以限制应用方的长时间资源占用和滥用等。
但业务场景的多样化,使得攻击者游走在场景之间以点撕面;
而平台方则受制于防御成本处处受困(无论是来自自身还是来自应用方)。
ImplicitGrant场景的无奈(response_type=token)漏洞频率:
应用方(主要或次要)、平台方(主要或次要)wooyun案例:
2012-04-15WooYun:
人人网Oauth2.0授权可导致用户access_token泄露2012-08-27WooYun:
透过[新浪微博]官方来源调用API发表微博.无需client_sec2012-09-20WooYun:
无需client_sec可用QQ登录平台发表空间日志等高权限操作(WooYun-2012-11314衍生)2012-09-25WooYun:
QQ互联开放平台QQ登陆oauth授权接口可以劫持access_token2012-09-25WooYun:
XX开放平台oauth授权接口可以劫持access_token其它案例:
EgorHomakov,HowwehackedFacebookwithOAuth2andChromebugs,2013-2-19:
2.0ImplicitGrant特性+Chromebug获取facebook的accesstoken)漏洞成因和建议修复方案:
有关ImplicitGrant场景的讨论,可见2012年9月撰写的zone文章《从wooyun-2012-11314小议OAuth2.0认证缺陷》。
此处将一些关键点拿出来再讨论。
ImplicitGrant场景的特点是授权验证时只需要client_id和redirect_uri这两个参数作应用标识,返回的时候也就直接在uri片段中返回accesstoken。
这个场景的提出,和客户端(client-side)业务需求有着密不可分的关联,典型例子就是无服务器参与的纯javascript交互的浏览器插件、各种网站挂件。
在这种业务下,客户端难以保密双secret(appsecret,accesstokensecret)也难以加密,因此干脆将这些限制均进行简化。
但ImplicitGrant场景也在安全问题上深深地困扰着平台方:
(1)由于缺失了双secret的签名,api仅凭accesstoken基本难以分辨应用请求来源
(2)绝大多数开放平台通过ImplicitGrant方式认证获取的client-sideaccesstoken,可用于服务器的api通讯中(即权限等同于走AuthorizationCodeGrant方式获取到的server-sideaccesstoken)(3)各开放平台由于要实施诸如网站挂件之类的应用,经常会对自己开放平台的中转页面或者跨域文件大开绿灯。
也就是说redirect_uri会放行两类域名:
应用方自己的域名、平台方自己指定的中转域名。
(4)client_id(即应用appkey)和redirect_uri基本属于公开信息。
以上困扰造就一种最常见且棘手的网站安全问题,那就是只要合作方网站(最常见)、平台方网站甚至是浏览器三者之一有任何一个xss,攻击者无需知道appsecret,就很容易xss获取到accesstoken,然后以此攻击受害者的平台方账号。
另一种困扰则是“当授权用于认证时的不当参数选择或无验证机制”所阐述的,既然api分辨不了应用请求来源,那么只要掌握了A应用中受害者的accesstoken,并且在B应用中的某些关键请求步骤中替换掉,那么就有可能顺利登录到B应用的受害者应用方账号。
第三种则是应用冒充,攻击者只使上述公开参数用就能冒充成其它应用调出授权页面,获取到的accesstoken可以用于控制受害者的平台方账号。
如果是高权限client_id,获取到的accesstoken显然更有破坏力。
解决这个问题,rfc6749第10.16小节就只是语焉不详的说需要额外的安全措施,这也反映了这种场景的防御难处。
从实践来看,有一种方法是必须的:
平台方必须对应用方的应用强制进行分类——即应用方在申请client_id(即应用appkey)时,需要选择属于哪类应用;
平台方再根据分类开放对应权限,并且进行特定的防御和监控措施,以下以手机sso登录sdk进行分析。
ImplicitGrant场景的无奈手机版:
手机SSO登录SDK漏洞频率:
平台方(主要)wooyun案例:
2013-03-27WooYun:
开放平台单点登录SSO方案设计缺陷导致钓鱼风险其它案例:
@囧虎张建伟,新浪微博Android客户端