随着微服务的发展,微服务越来越多,为每一个服务写一套认证服务会浪费很多人力,所以越来越多的公司开始使用统一认证了。统一认证给大家带来便利的同时,也带来了新的安全风险。仅以此文与大家…
随着微服务的发展,微服务越来越多,为每一个服务写一套认证服务会浪费很多人力,所以越来越多的公司开始使用统一认证了。统一认证给大家带来便利的同时,也带来了新的安全风险。仅以此文与大家探讨一下几年内遇到过的统一认证相关安全风险及新的测试思路。
1.ApereoCAS
CAS是Central Authentication Service的首字母缩写,Apereo CAS 是由耶鲁大学实验室2002年出的一个开源的统一认证服务。该服务在低版本中存在RCE漏洞。
直接用网上的exploit打就行:https://github.com/j1anFen/ysoserial_ApereoCAS
遇到了可以直接RCE。
2.可伪造的token
在大厂商中很多都是自己研发的统一认证流程,在大部分的认证过程中,过程基本上是这样的:
可以看到当统一认证平台(passport)校验用户账号密码正确后,会返回一个统一认证的字符串token,然后调用微服务的setcookie接口,将token置换为可以访问该服务(业务)的合法cookie,这一步,很多时候token可能未进行强加密等等方式,导致token可以被伪造。看下面的数据包可以帮助理解。
2.1 案例1:token为明文手机号
setcookie过程的数据包如下:
GET /settoken?id=1001&redir=%2fredirect.html&token=13312341234 HTTP/1.1
Host: 127.0.0.1
Connection: close
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3
Referer: http://127.0.0.1/
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
返回包:
HTTP/1.1 302 Found
Server: openresty
Date: Fri, 12 Nov 2021 02:41:37 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 59
Connection: close
Vary: Accept-Encoding
Set-Cookie: token=uq4Vp4jdN54%2BUVy3FegBRg%3D%3D;httpOnly;secure;sameSite=none;path=/
Location: /redirect.html
Redirecting to <a href="/redirect.html">/redirect.html</a>.
可以看到请求包里面的token直接就是用户的手机号可以修改成任意用户的手机号,从而造成任意用户登录。
2.2 案例2:token可解密
还用以上模型,进行介绍
setcookie过程的数据包如下:
GET /settoken?redir=%2fredirect.html&token=XyfmnaHvdkpKgII4Dgs0NA%3D%3D HTTP/1.1
Host: 127.0.0.1
Connection: close
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3
Referer: http://127.0.0.1/
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
然后,因为是小程序,翻了翻竟然看到了加密方式及AES的密码:
可以成功揭秘token:
根据我对其了解,这是用户id号(跟qq号一样,每个号都有唯一的),然后换成其他人的用户id,重新加密后可以登录到任意用户的账号中。
3.绕过风控(验证码)
在很多场景中,都会多多少少遇到一些风控策略,比如异地登录/新设备登录情况下的验证码。如第二节中所做的流程图,风控策略的验证一般在passport进行验证。不同的微服务触发的登录会有不同的风控策略,有些刚开发或者流量没那么大的业务当中,可能风控策略较为薄弱或者没做策略,从而可以绕过风控直接登录到防护策略严格的业务中。
举个例子:当我们登录到A服务时,调用的passport链接如下:
https://passport.admintony.com/login?service=1001&target=http%3A%2F%2Fservice-a.admintony.com%2fsetcookie%2f
可以看到在service参数中标注了一个id,代表A服务登录。而在登录B服务时,调用的passport链接为:
https://passport.admintony.com/login?service=1002&target=http%3A%2F%2Fservice-b.admintony.com%2fsetcookie%2f
而A服务属于该公司主打业务,登录时会触发短信验证码的校验。
在B服务中校验不严格,可以不用验证码就登录到系统中了。那么利用过程来了:
第一步:在B服务中登录需要短信验证码校验的账号,获取到其关键认证字符串ticket
登录:
POST /login/?service=1001&target=http%3A%2F%2Fservice-a.admintony.com%2fsetcookie%2f HTTP/1.1
Host: passport.admintony.com
Content-Type: application/x-www-form-urlencoded
登录跳转:
HTTP/1.1 302 Found
Server: openresty
Date: Thu, 11 Nov 2021 09:17:13 GMT
Content-Length: 0
Connection: close
M-TraceId: -3963864348522592536
Access-Control-Allow-Methods: POST,GET,PUT,PATCH,DELETE,OPTIONS
Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, source
Access-Control-Allow-Credentials: true
Location: https://service-a.admintony.com/setcookie/?ticket=xx-xxx-xxx-xxx
第二步:在A服务中登录自己的账号,抓取其调用setcookie的过程:(因为可能还存在部分其他跳转相关参数)
登录:
POST /login/?service=1002&target=http%3A%2F%2Fservice-b.admintony.com%2fsetcookie%2f HTTP/1.1
Host: passport.admintony.com
Content-Type: application/x-www-form-urlencoded
登录跳转:
HTTP/1.1 302 Found
Server: openresty
Date: Thu, 11 Nov 2021 09:17:13 GMT
Content-Length: 0
Connection: close
M-TraceId: -3963864348522592536
Access-Control-Allow-Methods: POST,GET,PUT,PATCH,DELETE,OPTIONS
Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, source
Access-Control-Allow-Credentials: true
Location: https://service-b.admintony.com/setcookie/?ticket=xx-xxx-xxx-xxx&service=b
然后提炼核心的setcookie跳转是:https://service-b.admintony.com/setcookie/?ticket=xx-xxx-xxx-xxx&service=b 。
第三步:从第一步中,把核心认证字符串ticket放入到到第二步提取的链接当中,然后浏览器访问,即可绕过短信验证码校验,直接登录到系统当中。
适用场景:找到泄漏账号后,登录业务。(GitHub记得翻一翻哦)。
4.未授权账号使用特权业务
业务本身需要一定的权限才能够访问,比如运维、比如认证后的商家、外卖商家、酒店商家等,但是由于使用了同一套统一认证,也就意味着外卖商家的账号也可以在酒店商家系统登录,只不过看不到功能罢了,这时也会产生该业务的cookie。有时候,开发在做程序的时候,只在setcookie流程中判断了token是否拥有业务的访问权限,而业务正常接口会忽视校验用户是否拥有调用权限,从而造成未授权访问。
4.1 拼凑接口找到未授权访问点
之前在测试的时候,找到一个小程序,直接用自己账号登录,发现:
所以我们账号并没有该小程序的一个使用权限,但是如大家所知,小程序的接口都是可以通过dump小程序前端的代码获取到的,于是经过dump代码分析,发现了接口:
然后往前阅读,找到t.API_HOST()拼凑成完整的业务URL,此时我们有了完整的URL和POST的数据包了,如果直接这样调用,必然会出现一个问题就是没有登录。
那么我们可以通过刷新小程序,然后抓取它的一个包(校验用户是否有权限的),把里面的cookie抓出来,然后放到我们拼出来的接口中,即可发现越权/未授权访问:
4.2 拥有特权账号时越权的测试技巧
在漏洞挖掘过程中,大家都会或多或少的拥有一些特权账号,有些可能是自己开店的,有些可能是自己找朋友、亲戚借用的,还有些SRC会定时推送专测活动,官方直接给出特权账号。无论是通过哪种方式获取到特权账号都是不容易的,也很少能够一个人拥有同一个系统的多个账号。那么在测试越权的时候,难免会遇到因id的复杂而无法测试的情况。
本节的技巧也是主要解决这个问题的,还是如4.1所说,很多时候,业务的权限校验一般在登录或者setcookie过程。而这时候我们可以使用自己的账号(未认证商家账号),在该微服务登录,然后获取到自己账号在该微服务中的cookie,然后通过正常账号抓取的功能数据包,直接替换cookie测试越权。
看一个案例:
业务A在做专测活动,提供了一个账号,而且有且只有一个账号。进去以后看到一个删除功能。
于是心生一念,想测试这个删除功能是否有越权呢,于是抓到数据包:
POST /manager/DeleteDishInfo HTTP/1.1
Host: fish.admintony.com
Token: xx-xxx-xxx-xxx-xxx-xx
{"productId":308,"poiIds":[10880123]}
此时越权测试有两个问题,比如上面的是双参数控制的,另外就是删除以后,我们需要确认这个商品被删掉了。于是我使用自己的账号(无该系统权限)在该系统登录,然后抓到cookie,替换尝试删除:
然好poiIds可能和账号的Token绑定了,所以这时候想到,我账号在该系统未注册,所以,poiIds置空试试。
删除成功,然后上给出的测试账号查看,也确实商品被删除掉了。
总结:
(1)这个Id还比较简单,当然遇到复杂ID也是同一套操作流程,这样不需要两个特权账号就可以证明越权了。
(2)这里同样引出了一个越权的测试方法,就是直接替换cookie/token等认证字符串,这样即使多参数共同影响的越权也可以被测出来。(example:退款场景下orderid和refundId共同确定一个退款情况,需要两者才能共同查询,这时候如果只是改refundId就会漏掉这处越权)。
5.URL跳转漏洞
大家也肯定都想关注些价值比较高的漏洞,所以把统一认证场景下的URL跳转漏洞放在最后讲讲。
在统一认证下,经常会触发URL跳转的地方有三处:(1)passport返回给微服务token时候(2)setcookie接口(3)退出登录的时候。
大概的一个模型是:
http://passport.admintony.com/login?target=http://s-a.admintony.com&token=xx-xx-xx
常规的绕过方法咱就不说了,主要讲一下这两年遇到过新奇的方法:
1、@符号直接截断
http://passport.admintony.com/login?target=http://baidu.com@s-a.admintony.com&token=xx-xx-xx
Location:http://baidu.com
原理:@后面直接截断了。
2、\@ /@ #@ ?@等组合
http://passport.admintony.com/login?target=http://baidu.com\@s-a.admintony.com&token=xx-xx-xx
Location:http://baidu.com\@s-a.admintony.com
原理:程序在判断存在@的时候,只判断@后面的域名是否合法,而忘记判断前面是否存在\/#?等内容
3、中文域名绕过waf
遇到过一次这样的情况,target参数直接输入http://aaa可以跳转,[http://aaaa跳出了waf](http://xn--aaaawaf-vp4kt0xtm6n)。
=== 请求1
http://passport.admintony.com/login?target=http://aaa&token=xx-xx-xx
Location:http://aaa
=== 请求2
http://passport.admintony.com/login?target=http://aaa%21&token=xx-xx-xx
Location:http://aaa!
=== 请求3(%65 == s)
http://passport.admintony.com/login?target=http://aaa%65&token=xx-xx-xx
waf拦截
=== 请求4(a.中国)
http://passport.admintony.com/login?target=http://a.%2d%fd&token=xx-xx-xx
Location:http://a.%2d%fd
造成URL跳转。
4、目标中不能出现小数点
target里面不能出现小数点,如果出现则被程序拦,但直接 http://a 就可以跳转,此时可以使用数字地址进行绕过:
target改为 http: //1920103026 跳转成功,完成绕过。
- 本文作者: Alivin
- 本文来源: 奇安信攻防社区
- 原文链接: https://forum.butian.net/share/898
- 版权声明: 除特别声明外,本文各项权利归原文作者和发表平台所有。转载请注明出处!