10.6 命令/代码执行
第10章 业务功能安全设计
教学资源
掌握验证码的安全设计
掌握用户登录安全设计
掌握用户注册安全设计
掌握密码找回安全设计
掌握远程地址安全设计
掌握命令代码执行安全设计
打造安全的应用程序,要从业务功能的设计开始,只有功能设计得足够安全,编写代码的时候才会少出现一些漏洞,特别是逻辑漏洞。所以设计一个安全功能尤为重要。下面我们将对功能安全进行分析,这些功能包括验证码、用户登录、用户注册、密码找回、资料操作、投票、积分、抽奖、充值支付、私信反馈、文件管理、数据库管理以及命令执行等,对经常出现的漏洞以及利用方式进行详细的分析,再详细讲解安全设计应该注意的地方。这一部分内容对于项目设计人员和研发人员来说更有价值。
10.1 验证码
验证码可以解决很多业务安全问题,比如撞库、垃圾注册,等等,可谓防御业务风险必备神器。验证码有图片验证码、滑动验证码、短信/邮箱/电话、二维码等分类,保守估计起码有80%以上的验证码是可以暴力破解或简单识别的问题,设计一个有效的验证码尤为重要。
10.1.1 验证码绕过
图片验证码是目前见得比较多的,图片验证码形式也比较多,有中文、英文、字母数字和看图识物等等,简单列举一下,如图10.1到图10.3所示。
图10.1 图形验证码
图10.2 手机号验证
图10.3 稍微复杂一点的图形验证码
一些验证码为了避免机器识别,被设计得让人难以辨认,用户体验与安全是有一点矛盾的,从业务角度考虑,我们还是能找到很多绕过这些验证码的方法,我们来一起看看。
(1)不刷新直接绕过
Web页面登录等操作的验证码能够多次使用的原因是后端程序在接收一次请求后,并没有主动刷新验证码,部分比较大的业务使用了负载均衡,验证码跟Session绑定在一起,为了能够保证验证码能够正常使用,所以会把验证码明文或者加密后放在Cookie或者POST数据包里面,所以每次只要同一个数据包里面的两个验证码对上了即可绕过。
(2)暴力破解
注册或者找回密码等敏感操作时的手机或者邮箱验证码能够爆破,主要是因为程序没有设置验证码错误次数和超时,导致能够不断进行尝试。
(3)机器识别
机器识别验证码对于不同的验证码类型有不同的手段,最常见的是图片验证码的机器识别,这类识别有两种情况:一种是针对不是实时生成的验证码,已经生成了部分的验证
码在服务器端保存,前端直接加载验证。这类是最好绕过的,只要把全部的验证码文件保存回来,做一个图片MD5库,然后利用的时候直接匹配服务器端返回的图片MD5即可识别。另外一种是动态生成的验证码,这类需要做一些图片文字识别或者语音识别,。
(4)打码平台
这类打码平台大多数后端是使用廉价的人工资源在打,国内比较有名的有打码兔、Q赚等等。
经过上面的分析,我们大致可以知道怎样设计一个强壮的验证码,主要有以下几点:
➢最重要的是,要设置验证码错误次数,比如一个验证码只能错误一次,这就避免了暴力破解的问题。
➢不把验证码放到HTML页面或者Cookie中。
➢验证码要设置只能请求一次,请求一次后不管错误与否都在后端程序强制刷新。
➢短信或者邮件验证码必须要6位以上字母和数字混合,图片或者语音验证码需要加强混淆干扰,比如图片文字变形,增加干扰斑点等。语音验证码增加背景噪声。
➢验证码要动态生成,不能统一生成多次调用。
10.1.2 验证码资源滥用
除了验证码识别外,验证码还存在一个大问题就是资源滥用。相信大家应该对短信轰炸或者邮箱轰炸比较了解,被轰炸的手机号会在短时间内收到大量短信,从而造成受害者手机一直响,也无法愉快地看短信,工具如图10.4所示。
图10.4 短信轰炸机截图
我们来看看短信轰炸的效果,如图10.5所示。
图10.5 轰炸效果截图
从这些短信内容里面可以看到,这类工具是利用了大量网站的短信验证码接口,而这些接口没有限制获取验证码次数和时间间隔,导致了可以不断被调用,防护起来比较简单,只要注意限制单个手机号在一个时间段内请求接收短信的次数,另外就是限制某个IP在一个时间段内请求接收短信的次数,这是为了防止提交大量手机号,消耗短信资源。
注意:以上内容为教学所需的演示内容,国家目前在严厉打击这种非法的短信轰炸行为,各位同学了解就行了,以上演示软件现已下架。
10.2 用户登录
用户登录是最常见的一个功能,登录就意味着权限授予,如果攻击者能任意登录管理员的账号,也就拥有了管理员的权限,更多的访问权限就能带来更多的安全问题,所以登录的安全性尤为重要。通常登录功能有以下几个需要关注的点。
10.2.1 撞库漏洞
撞库漏洞是指登录口没有做登录次数限制,导致可以使用不同的用户及密码进行不断的登录尝试,以遍历用户密码,也可以理解为登录爆破,如图10.6所示。
图10.6 登录爆破
撞库漏洞有以下几种情况:
(1)用户名和密码错误次数都无限制。这种情况是早期比较常见的,可以载入用户名和密码字典对登录口不断进行请求尝试。
(2)单时间段内用户的密码错误次数限制。之前有个“锁QQ”的茬儿,说的是QQ登录密码连续错误次数30次,就会被锁定QQ,就有人利用这个问题不断地去锁定别人的QQ。这种方式是基于账号可信认证,密码错误次数存在限制,认证的是账号。所以这种情况也是可以撞库的,只要我们有一个用户名列表,爆破完一个密码还不能登录就换一个用户,或者干脆基于社工库的密码来撞。
(3)单时间段内IP登录错误次数限制。比较典型的是discuz,就是基于IP来限制登录,当一个IP登录5次后还没有成功登录,则会被禁止该IP登录,不过discuz获取的Client-IP存在绕过的问题。这种防御撞库的手段存在一个误杀的问题,如果出口IP里面还有一个大内网,比如企业网、学校网,这时候就会误杀其他用户。
针对撞库漏洞比较好的解决方案是使用登录验证码和多因素认证,登录验证码有很多种,选择安全的验证方式也很关键,因为目前网络上还有专门提供人工打码的服务平台。
10.2.2 API登录
2014年淘宝被曝光一个影响非常大的逻辑登录漏洞,漏洞发现者在乌云报告该漏洞后获得阿里5万元现金的奖励,随后阿里宣布拿出500万人民币建立漏洞悬赏计划。这个漏洞跟很多客户端API登录的形式差不多,相信大家都有在QQ客户端点击邮箱或者QQ空间的图标就直接免登录进入的经历,其实在后端也有一个验证登录过程。来看看淘宝当时的漏洞URL:
验证登录成功后会跳转到这个链接,这个链接里面有一个user_num_iduser_ num_id参数,代表当前登录的用户ID,请求这个链接后服务器端会返回这个用户登录成功后的Cookie信息,这里的问题就在于将用户ID交给这个程序逻辑的时候,并没有带上唯一的一个Token,这就导致只要修改user_num_iduser_num_id这个参数即可登录任意用户。同样,QQ客户端点击图标进入QQ空间的时候我们可以看到这样一个链接:
其中clientuin参数为QQ号码,clientkey参数为当前用户登录的key,只要拿到这个clientkey则可以登录当前QQ号,对于这样的登录方式需要注意以下几个安全点:
(1)登录密钥(clientkey)需要不可预测并且不固定,生成key的算法中加入随机字符。
(2)API接口禁止搜索引擎收录。
(3)登录密钥当次绑定当前主机,换机器不可用,防止QQ木马和嗅探key。
10.3 用户注册
淘宝有专门的风控团队,垃圾注册一直是比较头疼的问题,目前像贴吧、论坛、微博以及大部分的娱乐应用都有一些评论和投票功能,通过这些功能可以传播广告或者刷排名,于是就出现了商业机会,一些人开始写自动化注册机去发广告,导致社区质量下降,大部分的网站都是需要登录才能使用这些功能的,而登录的前提是有账号,所以注册账号这块拦截掉注册机是最好的防御点。
机器注册已经被拦截得差不多,现在恶意注册的诈骗团伙已经以低价向学生提供兼职注册服务,由学生人工注册账号,填写验证码。对于这样的注册方式,就只有用大数据来分析注册账号的电脑、IP以及注册人行为去防控。在注册这方面,淘宝已经加入了滑动人机识别,并且效果非常不错,如图10.7所示。
图10.7 用户注册
对于用户注册,需要有以下几个安全设计思路:
(1)设计验证码。
(2)采集用户机器唯一识别码,拦截短时间内多次注册。
(3)根据账号格式自学识别垃圾账号。
(4)防止SQL注入漏洞与XSS漏洞(常见)。
10.4 密码找回
密码找回是出现逻辑问题最多的一个功能,因为它的交互流程最多,目前找回密码的方式比较常见的有邮箱验证码、手机验证码以及密保问题,这个流程通常如图10.8所示。
图10.8 找回密码业务逻辑
这个三个大流程中都经常有一些逻辑问题,下面我们来详细看看。
1.输入用户名/邮箱/手机阶段
这里有一个交互过程,即需要输入要重置的账号信息,单击确定的时候,目前大部分的应用会直接从数据库中读取用户邮箱和手机信息,并且发送验证码,还有一部分程序在输入用户名后,会提示使用手机还是邮箱找回密码,并且邮箱和手机号中的一部分会显示在页面上,比如网易账号,如图10.9所示。
图10.9 获取验证码
提交的时候可以直接抓包修改手机或者邮箱参数,这时候如果后端没有做验证,原本发送给账号A的验证码会发送到被我们篡改的手机或者邮箱上,利用接收到的验证码即可重置密码。
2.填写验证码和新密码阶段
填写验证码和新密码就意味着我们已经拿到了验证码或者重置密码的URL,这里存在的问题主要有:
(1)验证凭证较简单,可以被暴力破解。目前大多数手机短信重置密码的验证码都是4位或者6位数字,如果提交验证码的地方没有对这个验证码进行错误次数限制,则会存在可以爆破的问题,这是目前最常见的一种找回密码漏洞利用方式。
(2)验证凭证算法简单,凭证可预测。部分网站找回密码的Token是根据当前的“用户名+邮箱”或者时间戳进行一次MD5后生成,这就存在一定的预测性,利用自己写的算法去碰撞即可拿到重置密码凭证。
(3)验证凭证直接保存在源码里。这种目前比较少,不过也存在一定比例,一种是在点击发送验证码的时候就可以直接在源码里看到给当前手机或者邮箱发送过去的验证码,还有一种是在输入验证码的时候,源码里面就直接保存了正确的验证码。
3.发送新密码阶段
凭证未绑定用户:我们在找回密码的时候,发送到邮箱的链接通常是如下这个样子。
当请求这个链接的时候,后端程序根据uid和key对应上了从而判断这个找回密码的链接有效,但是在将新密码提交到服务器的时候,服务器端并没有判断当前这个key是否跟uid或者email匹配,而是直接修改掉了uid或者email指定的用户密码,这样我们只要拦截修改密码的请求包,将里面的用户参数修改成我们要篡改密码的用户账号即可。
基于以上对密码找回的利用方法分析,应该注意的安全风险点有:
➢接收验证码的邮箱和手机号不可由用户控制,应该直接从数据库中读取出来。
➢加强验证凭证复杂度,防止被暴力破解。
➢限制验证凭证错误次数,单个用户在半个小时内验证码错误三次,半小时内禁止找回密码。
➢验证凭证设置失效时间。
➢验证凭证不要保存在页面。
➢输入用户邮箱或ID、手机号取验证凭证的地方需要设置验证码防止短信炸弹和批量找回等。
➢验证凭证跟用户名、用户ID、用户邮箱绑定,找回密码时验证当前凭证是否是当前用户的。
10.5 远程地址访问
Wordpress、phpcmsd等众多应用都有访问远程地址获取资源的功能,这个功能产生的漏洞叫作SSRF(Server-Side Request Forgery),我们在QQ消息中发送网页链接的时候,会显示出网页的标题和部分内容,这就说明腾讯的服务器有去访问我们发送的这个链接,那如果腾讯没有做地址限制,我们在聊天框里面发送一个腾讯内网的一个地址,那它再去访问的时候我们就能知道这是一个内网的什么系统,造成信息泄露,甚至利用内网漏洞,我们来看一个乌云网的例子。
缺陷编号:WooYun-2015-118052
漏洞标题:美丽说某处ssrf探测内网存活主机
相关厂商:美丽说
漏洞作者:玉林嘎
提交时间:2015-06-04 09:37
美丽说开发平台有一个填写回调地址的地方,当填写的时候服务器会去访问这个地址是否有效,如图10.10所示。
图10.10 填写回调地址
如果有人恶意填个内网呢,先看看当填写一个不存在的地址时,页面会返回“回调地址检测失败”,如图10.11所示。
图10.11 检测失败
当地址存在时,则会返回“回调地址检测成功”,如图10.12所示,那我们就可以利用这个返回结果的差异来对比,批量扫描内网。
图10.12 存在的地址会检测成功
案例里面是HTTP协议的探测,实际上这个跟协议没有关系,之前也有厂商出现过连接远程MySQL服务同样的SSRF漏洞。
这类漏洞防御看起来好像没有什么难度,只要限制填写就可以,但是大部分厂商修复的时候应该不会考虑到短地址的问题,所以在修复之后仍然可以通过生成短链接来利用,建议修复的时候注意这点。
10.6 命令/代码执行
命令执行和代码执行功能通常都在系统后台,相比来说,命令执行的功能使用得更多一点,代码执行功能在特殊应用上面才会存在,而命令执行在类似Zabbix、WDCP等大量运维系统上都存在,如图10.13所示。
图10.13 命令执行
该功能可以直接在服务器上执行系统命令,危害性自然不言而喻,命令执行和代码执行功能再加上前面提及的文件管理和数据库管理功能,目前的webshell功能也不过如此了。
一旦这个功能被拿下,基本上服务器就沦陷了,所以在设计这类功能时应该注意以下几点:
➢严格控制该功能访问权限,建议高权限才能访问。
➢在满足业务需求的情况下,可以设置命令白名单,可使用escapeshellcmd()以及escapeshellarg()函数进行过滤,命令直接写死在代码中更好。
➢给命令及代码执行功能设置独立密码。
➢代码执行功能限制脚本可访问的路径。
➢在满足需求的情况下限制当前执行命令的系统用户权限。
总结
本章主要讲解了常见的验证码、登录注册等功能的安全隐患,也提供了解决方案。希望大家在今后的项目开发中注意本章讲解的内容,同时也要自己去发掘其他的业务功能安全设计。
作业
了解本章讲解内容之外的其他常用的功能的安全设计。