18

Web登录认证类漏洞分析防御总结和安全验证机制设计探讨

 4 years ago
source link: https://www.freebuf.com/articles/web/217052.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

做渗透测试有一段时间了,发现登录方面的问题特别多,想做个比较全面点的总结,我尽量写的全面点又适合新人,这篇文章可能需要点想象力,因为问题比较多我不可能去海找各种例子举出来,不过好在会上网就遇到过各种登录框,所以大家都比较了解

web登录认证方面,从子功能上可以划分为登录框登录、忘记密码(密码重置)、修改密码、验证码、发送手机验证码、发送邮箱验证码、注册账号、登录信息错误提示、账号锁定等等小功能组成(单点登录还要讲原理,本文暂不涉及),每个web站点的登录大约由上面小功能的全部或者一部分组成(这里漏洞缺陷以这些小功能做划分,更有针对性覆盖也全面一点,但还是避免不了交叉)。

先从最基础最常见的开始列举列:

登录框

登录框账号密码服务端持久化:当你打开登录页面发现账号密码已经填好了,点击登录直接进后台哈哈

修复方案:保存账号密码处理的逻辑针对本地,session及时销毁

信息泄露:登录框提供个示例用户名,比如示例邮箱、手机、用户名规则导致黑客掌握规律生成字典

修复方案:不显示示例用户名

sql注入:用户名字段或者密码字段存在sql注入,比较典型的是万能密码登录(大家都知道)

修复方案:使用参数绑定方式查询和预编译语句,如果使用各种框架按照框架安全开发的要求编程

XSS:用户名或密码字段存在XSS,比较典型的是反射XSS打自己

修复方案:使用各种XSS过滤库编码库,详细请百度,本文不是XSS专题

账号密码暴力破解:黑客通过工具或者脚本加载账号密码字典不断尝试登录

修复方案:添加验证码(添加验证码不对可能导致绕过等,不一定能防止,下文详说)

用户枚举:输入不对的用户名提示密码不存在,输入对的用户名提示密码错误,从而枚举用户名

修复方案:使用模糊的错误提示,如用户名或密码不正确

账号锁定:用户爆破的时候错误次数过多锁定账号,然后黑客批量尝试用户名导致大部分用户名被锁

账号详情泄露:提交合法用户名,服务器返回关于用户名相关的账号、身份、密码等详细信息

修复方案:使用验证码方式防爆破,尽量不要使用登录次数太多锁定的方式,或者设置短时锁定

低频撞库爆破:利用脚本以慢频率持久爆破,针对限制频率数字比较大的防御策略

修复方案:使用验证码机制

图片验证码

易识别:验证码杂点太少或者没有杂点导致可以用程序识别出验证码的内容

验证码前端生成:验证码是用js做的,用js生成点随机字符填充到前端dom

单独验证:验证码和需要验证的参数不在同一个http请求,导致验证码认证成功后进行攻击,比如验证码成功后抓到正在的用户名密码的请求进行暴力破解

置空:当验证码的值或者参数置空的时候,可以直接认证,这是服务端逻辑判断少了一个验证码为空的判断

验证码复用:同一个验证码可以不限次数的使用,或者验证码用完没销毁,导致可以爆破或者任意注册

前端显示:服务端生成的验证码不是图片,而是字符串直接返回到前端

任意值:拦截到http请求,对验证码的值设置任意值都能通过验证码验证

优先级低:同一个http请求到服务端以后验证码不是最先验证的,比如先验证用户名,导致用户枚举

打码平台:使用打码平台调用验证码接口获取验证码进行识别,返回验证码

修复方案:验证码必须要在服务端生成添加杂点干扰项并足够扭曲以图片格式返回前端,前端带验证码和需要验证参数在一个请求里发送到服务端,服务端第一优先级先验证验证码的存在性和正确性,一个验证码使用一次后销毁

手机和邮箱验证码

前端显示:服务器生成的验证码返回到页面前端,导致前端可以看到产生验证信息泄露

复杂度低:由4位数字组成的验证码,如果服务端没次数限制可以枚举出来进行登录或者注册

zha_蛋:通过脚本不断向验证手机号或者邮箱发送短信或者邮件,导致接收方接受大量垃圾信息

账号锁定:单个手机或邮箱一定时间超过某次数锁定一定时间,自动化批量锁定账号

不匹配:比如同请求用户名和手机不匹配但依旧发送验证码,导致可以向任意号码发短信

资费消耗:有单个手机号次数限制,使用大量不同手机号短时间内发送数万级短信

修复方案:验证码要有一定的复杂度,至少6位,不能返回前端,基于基于客户端session进行次数限制,制定合适的锁定策略,对比账号和绑定的手机邮箱是否匹配

忘记密码

账号枚举:你输入用户名提交以后系统提示用户不存在等

认证方式篡改:输入合法用户名以后输入其他邮箱或者手机可以接受到验证码

密码重置

验证码绕过:图片验证码或手机验证码和被重置的账号不在同一请求或者利用文中技术绕过

用户枚举:通过重置接口判断用户是否存在,获取用户名

任意账号重置:系统通过用户名和密码俩参数进行密码重置,导致任意账号密码都能重置

认证方式篡改:输入合法用户名,使用黑客的邮箱或者手机接收到系统重置的密码

修复方案:判断账号和绑定验证方式的合法关系,重要请求中要带有验证码机制,对不存在或者不正确的账号采用模糊的报错提示信息

任意注册

用户枚举:注册时系统提示用户名已注册,批量枚举用户

验证码绕过:使用正确的图像验证码或者手机邮箱验证码后,再提交注册信息,其他绕过方式见上文

sql注入:注册字段没有预编译参数绑定,导致注入

手机验证码爆破:手机或者邮箱的验证码太短,不强壮被暴力破解

修复方案:把验证码和注册信息在同一请求提交,服务端优先验证验证码是否正确,验证码机制见上文

组合绕过

通过上文各种安全绕过技术,我们可以尝试一种或多种手段绕过验证码、手机验证等等,总会有各种各样的小漏洞被组合绕过进而进行攻击,具体的看认证机制使用了哪些防御措施,比如是否使用图片验证码、手机验证码、用户枚举、等等吧

安全的认证机制

上文中,关于认证的攻击绕过那么多,那么样的认证机制是安全的?上面重放攻击那么多,什么是对抗重放攻击最有效的手段?

对于可以使用脚本或者程序自动化攻击的,最有效的防御手段就是验证码!!

防御手段有哪些关键点呢?

如何尽可能的避免各种逻辑绕过的漏洞?最好减少人造石步骤,甚至把需要认证的参数全放一个http请求中!

对于参数过滤,可以使用正则匹配就使用正则,比如邮箱、手机、***使用正则验证,完全可以避免sql注入XSS这些

对于不能使用正则匹配的,对参数使用owasp等组织开源的过滤库防止XSS

对于同一个http请求的参数,验证码拥有最高优先级验证,验证码验证时要验证其存在性、参数的存在性、一次性

尽量不要使用接口,因为接口一般不能使用验证码

往前端返回信息,使用最小信息原则,只返回必要的信息

一个安全的认证机制的设计

登录功能:把用户名密码和其他需要的字段(如验证码,验证码只有一次,并足够杂点和复杂度)放前端让客户一起填写,然后放到同一个http请求提交给后端,后端判断是否有验证码参数,然后判断验证码是否正确,再然后正则判断部分字段,不能正则的对参数进行过滤转码,然后使用参数绑定和预编译查询数据库,出错或者不存在的提示前端用户名或者密码错误,这样就防止了自动化攻击和SQL注入信息泄露等等

密码重置功能:把验证码、用户名、认证因子(邮箱、手机等)放到同一个http请求中,优先验证验证码的存在性、正确性、一次性,其次对参数进行正则格式验证、之后对不能验证参数进行过滤编码、验证用户名和认证因子的匹配性、最后再触发相关功能

上面两种情况,即使攻击者想撞库、锁定账号、批量重置等操作,也会因为验证码而只能影响个位数的账号,对系统整体影响不大。

其他功能同理,要结合实际的场景进行设计,即可把风险控制到最小!

*本文原创作者:少帅力,本文属于FreeBuf原创奖励计划,未经许可禁止转载


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK