查看原文
其他

网络安全开发之业务功能安全设计

计算机与网络安全 计算机与网络安全 2022-06-01

一次性进群,长期免费索取教程,没有付费教程。

教程列表见微信公众号底部菜单

进微信群回复公众号:微信群;QQ群:16004488



微信公众号:计算机与网络安全

ID:Computer-network

要打造安全的应用程序,要从业务功能的设计开始,只有功能设计得足够安全,编写代码的时候才会少出现一些漏洞,特别是逻辑漏洞。所以设计一个安全功能尤为重要。下面我们将对功能安全的痛点进行分析,这些功能包括验证码、用户登录、用户注册、密码找回、资料操作、投票、积分、抽奖、充值支付、私信反馈、文件管理、数据库管理以及命令执行等,对经常出现的漏洞以及利用方式进行详细的分析,再给出详细的安全设计应该注意的地方。


一、验证码


验证码可以解决很多业务安全问题,比如撞库、垃圾注册,等等,可谓防御业务风险必备神器。验证码有图片验证码、滑动验证码、短信/邮箱/电话、二维码等分类,而据保守估计起码有80%以上的验证码是存在可以爆破和简单识别的问题,设计一个有效的验证码尤为重要。


(一)验证码绕过


图片验证码是目前见得比较多的,各种各样的图片验证码形式也比较多和奇葩,有中文、英文、字母数字和看图识物,等等,简单列举一下,如图1、图2、图3所示。


图1

图2

图3

不得不吐槽一下,一些验证码为了避免机器识别,已经被逼得设计成人类都认不出来了,业务和体验设计与安全是有一点矛与盾的,所以从业务角度考虑,我们还是能找到很多绕过这些验证码的方法,我们来一起看看。


1、不刷新直接绕过


Web页面登录等操作的验证码能够多次使用的原因是后端程序在接收一次请求后,并没有主动刷新验证码,部分比较大的业务使用了负载均衡,验证码跟Session绑定在一起,为了能够保证验证码能够正常使用,所以会把验证码明文或者加密后放在Cookie或者POST数据包里面,所以每次只要同一个数据包里面的两个验证码对上了即可绕过。

2、暴力破解


注册或者找回密码等敏感操作时的手机或者邮箱验证码能够爆破,主要是因为程序没有设置验证码错误次数和超时,导致能够不断进行尝试。


3、机器识别


机器识别验证码对于不同的验证码类型有不同的手段,最常见的是图片验证码的机器识别,这类识别有两种情况:一种是针对不是实时生成的验证码,已经生成了部分的验证码在服务器端保存,前端直接加载验证。这类是最好绕过的,只要把全部的验证码文件保存回来,做一个图片MD5库,然后利用的时候直接匹配服务器端返回的图片MD5即可识别。另外一种是动态生成的验证码,这类需要做一些图片文字识别或者语音识别,当初有一个笑话讲的是Google出的语音识别系统干掉了自家的语言验证码。国内也有专门提供这种服务的公司,比如云速,如图4所示。


图4

4、打码平台


这类打码平台大多数后端是使用廉价的人工资源在打,比如学生什么的,国内比较有名的像打码兔(damatu1.com)、Q赚(qqearn.com),等等,让我们来看一个任务佣金表就知道成本有多低,如图5所示。


图5

经过上面的分析,我们大致可以知道怎样设计一个强壮的验证码,主要有以下几点:


1)最重要的是,要设置验证码错误次数,比如一个验证码只能错误一次,这就避免了暴力破解的问题。

2)不把验证码放到HTML页面或者Cookie中。

3)验证码要设置只能请求一次,请求一次后不管错误与否都在后端程序强制刷新。

4)短信或者邮件验证码必须要6位以上字母和数字混合,图片或者语音验证码需要加强混淆干扰,比如图片文字变形,增加干扰斑点等。语音验证码增加背景噪声。

5)验证码要动态生成,不能统一生成多次调用。


(二)验证码资源滥用


除了验证码识别外,验证码还存在一个大问题就是资源滥用。相信大家应该对短信轰炸或者邮箱轰炸比较了解,被轰炸的手机号会在短时间内收到大量短信,从而造成受害者手机一直响,也无法愉快地看短信,工具如图6所示。


图6

我们来看看短信轰炸的效果,如图7所示。


图7

从这些短信内容里面可以看到,这类工具是利用了大量网站的短信验证码接口,而这些接口没有限制获取验证码次数和时间间隔,导致了可以不断被调用,防护起来比较简单,只要注意限制单个手机号在一个时间段内请求接收短信的次数,另外就是限制某个IP在一个时间段内请求接收短信的次数,这是为了防止提交大量手机号,消耗短信资源。


二、用户登录


用户登录是最常见的一个功能,登录就意味着权限授予,如果攻击者能任意登录管理员的账号,也就拥有了管理员的权限,更多的访问权限就能带来更多的安全问题,所以在登录的安全尤为重要。通常登录功能有以下几个需要关注的点。


(一)撞库漏洞


撞库漏洞是指登录口没有做登录次数限制,导致可以使用不同的用户及密码进行不断的登录尝试,以遍历用户密码,也可以理解为登录爆破,如图8所示。


图8

撞库漏洞有以下几种情况:


1)用户名和密码错误次数都无限制。这种情况是早期比较常见的,可以载入用户名和密码字典对登录口不断进行请求尝试。


2)单时间段内用户的密码错误次数限制。之前有个“锁QQ”的茬儿,说的是QQ登录密码连续错误次数30次,就会被锁定QQ,就有人利用这个问题不断地去锁定别人的QQ。这种方式是基于账号可信认证,密码错误次数存在限制,认证的是账号。所以这种情况也是可以撞库的,只要我们有一个用户名列表,爆破完一个密码还不能登录就换一个用户,或者干脆基于社工库的密码来撞。


3)单时间段内IP登录错误次数限制。比较典型的是discuz,就是基于IP来限制登录,当一个IP登录5次后还没有成功登录,则会被禁止该IP登录,不过discuz获取的是Client-IP存在绕过的问题。这种防御撞库的手段存在一个误杀的问题,如果出口IP里面还有一个大内网,比如企业网、学校网,这时候就会误杀其他用户。


针对撞库漏洞比较好的解决方案是使用登录验证码和多因素认证,登录验证码有很多种,选择安全的验证方式也很关键,因为目前网络上还有专门提供人工打码的服务平台。


(二)API登录


之前淘宝被曝光一个影响非常大的逻辑登录漏洞,漏洞发现者在报告该漏洞后获得阿里5万元现金的奖励,随后阿里宣布拿出500万人民币建立漏洞悬赏计划。这个漏洞跟很多客户端API登录的形式差不多,相信大家都有在QQ客户端点击邮箱或者QQ空间的图标就直接免登录进入的经历,其实在后端也有一个验证登录过程。来看看淘宝当时的漏洞URL:


https://login.taobao.com/member/login_by_safe.htm?sub=&guf=&c_is_scure=&from=tbTop&type=1&style=default&minipara=&css_style=&tpl_redirect_url=&popid=&callback=jsonp81&is_ignore=&trust_alipay=&full_redirect=&user_num_id=123456789&need_sign=&from_encoding=%810%851_duplite_str=&sign=&ll=&ei=QaIBU-XLLYze0wHy-YGoCw&usg=AFQjCNGXm310YgBJj5KDzLkZzaOAUl2UnQ&bvm=bv.61535280,d.cWc&cad=rjt


已经验证登录成功后会跳转到这个链接,这个链接里面有一个user_num_iduser_num_id参数,代表当前登录的用户ID,请求这个链接后服务器端会返回这个用户登录成功后的Cookie信息,这里的问题就在于将用户ID交给这个程序逻辑的时候,并没有带上唯一的一个Token,这就导致只要修改user_num_iduser_num_id这个参数即可登录任意用户。同样,QQ客户端点击图标进入QQ空间的时候我们可以看到这样一个链接:


http://ptlogin2.qq.com/igame?clientuin=123456&clientkey=DC81BF8E5DC1DA7918DCA17A78FDF236DD6E41C09432B1DF5694F66B04C18DF54


其中clientuin参数为QQ号码,clientkey参数为当前用户登录的key,只要拿到这个clientkey则可以登录当前QQ号,对于这样的登录方式需要注意以下几个安全点:


1)登录密钥(clientkey)需要不可预测并且不固定,生成key的算法中加入随机字符。

2)API接口禁止搜索引擎收录。

3)登录密钥当次绑定当前主机,换机器不可用,防止QQ木马和嗅探key。


三、用户注册


淘宝有专门的风控团队,垃圾注册一直是比较头疼的问题,目前像贴吧、论坛、微博以及大部分的娱乐应用都有一些评论和投票功能,通过这些功能可以传播广告或者刷排名,于是就出现了商业机会,一些人开始写自动化注册机去发广告,导致社区质量下降,大部分的网站都是需要登录才能使用这些功能的,而登录的前提是有账号,所以注册账号这块拦截掉注册机是最好的防御点。


机器注册已经被拦截得差不多,现在恶意注册的诈骗团伙已经以低价向学生提供兼职注册服务,由学生人工注册账号,填写验证码。对于这样的注册方式,就只有用大数据来分析注册账号的电脑、IP以及注册人行为去防控。在注册这方面,淘宝已经加入了滑动人机识别,并且效果非常不错,如图9所示。


图9

对于用户注册,需要有以下几个安全设计思路:


1)设计验证码。

2)采集用户机器唯一识别码,拦截短时间内多次注册。

3)根据账号格式自学习识别垃圾账号。

4)防止SQL注入漏洞与XSS漏洞(常见)。


四、密码找回


密码找回是出现逻辑问题最多的一个功能,因为它的交互流程最多,目前找回密码的方式比较常见的有邮箱验证码、手机验证码以及密保问题,这个流程通常如图10所示。


图10

这个三个大流程中都经常有一些逻辑问题,下面我们来详细看看。


1、输入用户名/邮箱/手机阶段


这里有一个交互过程,即需要输入要重置的账号信息,单击确定的时候,目前大部分的应用会直接从数据库中读取用户邮箱和手机信息,并且发送验证码,还有一部分程序在输入用户名后,会提示使用手机还是邮箱找回密码,并且邮箱和手机号中的一部分会显示在页面上,比如网易账号,如图11所示。


图11

提交的时候可以直接抓包修改手机或者邮箱参数,这时候如果后端没有做验证,原本发送给账号A的验证码会发送到被我们篡改的手机或者邮箱上,利用接收到的验证码即可重置密码。


2、填写验证码和新密码阶段


填写验证码和新密码就意味着我们已经拿到了验证码或者重置密码的URL,这里存在的问题主要有:


1)验证凭证较简单,可以被暴力破解。目前大多数手机短信重置密码的验证码都是4位或者6位数字,如果提交验证码的地方没有对这个验证码进行错误次数限制,则会存在可以爆破的问题,这是目前最常见的一种找回密码漏洞利用方式。


2)验证凭证算法简单,凭证可预测。部分网站找回密码的Token是根据当前的“用户名+邮箱”或者时间戳进行一次MD5后生成,这就存在一定的预测性,利用自己写的算法去碰撞即可拿到争取到的重置密码凭证。


3)验证凭证直接保存在源码里。这种目前比较少,不过也存在一定比例,一种是在点击发送验证码的时候就可以直接在源码里看到给当前手机或者邮箱发送过去的验证码,还有一种是在输入验证码的时候,源码里面就直接保存了正确的验证码。


3、发送新密码阶段


凭证未绑定用户:我们在找回密码的时候,发送到邮箱的链接通常是如下这个样子:


http://www.xxx.com/user.php?m=repwd&uid=用户ID&key=凭证密钥&email=邮箱


当请求这个链接的时候,后端程序根据uid和key对应上了从而判断这个找回密码的链接有效,但是在将新密码提交到服务器的时候,服务器端并没有判断当前这个key是否跟uid或者email匹配,而是直接修改掉了uid或者email指定的用户密码,这样我们只要拦截修改密码的请求包,将里面的用户参数修改成我们要篡改密码的用户账号即可。


基于以上对密码找回的利用方法分析,可以想到的安全风险点应该注意的有:

1)接收验证码的邮箱和手机号不可由用户控制,应该直接从数据库中读取出来。

2)加强验证凭证复杂度,防止被暴力破解。

3)限制验证凭证错误次数,单个用户在半个小时内验证码错误三次,半小时内禁止找回密码。

4)验证凭证设置失效时间。

5)验证凭证不要保存在页面。

6)输入用户邮箱或ID、手机号取验证凭证的地方需要设置验证码防止短信炸弹和批量找回等。

7)验证凭证跟用户名、用户ID、用户邮箱绑定,找回密码时验证当前凭证是否是当前用户的。


五、资料查看与修改


用户的资料操作涉及权限问题,其实这里主要介绍的是越权漏洞的利用场景,为了保护用户的隐私,大多数网站提供了用户权限控制的功能,用户可以自己设置个人资料是否允许别人查看,在权限控制方面,主要有以下几种利用场景:


1)未验证用户权限。这里说的未验证用户权限是指直接修改当前资源ID即可浏览该资源,没有验证当前这个资源是否属于当前用户,比如用户A的订单ID是111,用户B的订单ID为222,用户A登录后查看自己订单详情的时候,将URL中的订单ID参数改为222即可看到用户B的订单,之前阿里巴巴国际贸易站因为这个漏洞被炒作受了很大的舆论影响。


2)未验证当前登录用户。上一种情况是没有验证当前这个资源是否属于当前用户,而这种情况是虽然程序绑定了用户ID和资源ID,但是这个用户ID是在访问资源时直接从cookie或者post、get参数里面获取的,所以我们只要在cookie里面把用户ID修改成另外一个用户的ID,就可以利用他的权限操作他的东西,这是目前见得比较多的一种情况。


上面介绍的两种情况,虽然只是列举用户资料查看,但是更多的出现是在用户资料修改,比如个人资料、订单、密码,等等。


对于用户注册功能我们需要用到的防御思路有:


  • 用户资源ID(订单ID、地址ID类似,等等)绑定到用户,只允许有权限的用户查看。

  • 当前用户信息存储到session,不放到request中,避免攻击者修改当前用户ID。


六、投票/积分/抽奖


投票和抽奖以及积分在很多促销活动或者推广手段上都经常用到,背后的奖品成本可能上数十万,如果这些奖品被恶意用户(黄牛)刷走了,不仅推广的效果没有,而且浪费了成本投入,如图12所示。

图12

通常抽奖和投票有如下几种利用方法:


1)cookie或POST请求正文绕过。有的应用将验证是否抽奖或者领取积分的判断值放置在cookie或者POST的请求正文里,服务器端获取到这个结果后判断是否还有机会抽奖,而这个数据我们是可以直接在数据包中修改的,所以就会产生绕过,比如cookie中isok=1代表已经抽奖,isok=0代表还没有抽奖,而我们只要再点击抽奖,然后把isok的值改为0即可一直抽奖。


2)基于IP验证。做得比较弱的统计是直接基于IP验证,像访问量、推广获取积分等,这类要看程序获取IP的方式,如果是client-ip或者x_forword_for获取IP,则可以直接伪造IP绕过。


3)基于用户认证。也有一部分应用需要登录以后才能抽奖或者投票,这类可以结合看看能不能批量注册,如果可以,则可以用程序实现批量登录刷票,或者投票的时候POST包或者cookie里面的当前uid、用户名等是否可以随意修改绕过用户单次限制。


从上面利用手段可以看到主要的三个点是IP、登录用户cookie,分析出可用性较高的防御手段如下:

  • 机器识别码验证,每台机器都可以根据硬件信息生成唯一的识别码。

  • 操作需要登录,当前用户信息从session中读取。

七、充值支付


关于支付漏洞已经在《漏洞挖掘与防范(三)》详细介绍过,主要有四种,分别是客户端可修改单价、总价和购买数量以及利用时间差多次购买,这里不再反复介绍,针对这四种情况的主要应对手法是:


1)保证数据可信,商品单价及总价不可从客户端获取。

2)购买数量不能小于等于0。

3)账户支付锁定机制,当一个支付操作开始就应该立马锁定当前账户,不能同时两个后端请求对余额进行操作。


八、私信及反馈


私信和反馈功能在大多数网站中都能见到,特别是社交应用,私信是必不可少的功能。这个功能是两个用户之间互动使用,两端都是人,除了特殊情况下可以滤去的SQL注入或者命令执行等少见漏洞外,最常见的就是XSS漏洞以及越权漏洞。


私信和反馈功能在大多数网站中都能见到,特别是社交应用,私信是必不可少的功能。这个功能是两个用户之间互动使用,两端都是人,除了特殊情况下可以滤去的SQL注入或者命令执行等少见漏洞外,最常见的就是XSS漏洞以及越权漏洞。


对于私信和反馈的XSS漏洞防御并没有什么特别的手段,跟我们之前介绍过的XSS防御方法一样,最主要的是将特殊字符进行过滤,另外是使用白名单和黑名单结合的方式。


九、远程地址访问


Wordpress、phpcmsd等众多应用都有访问远程地址获取资源的功能,这个功能产生的漏洞叫做SSRF(Server-Side Request Forgery),我们在QQ消息中发送网页链接的时候,会显示出网页的标题和部分内容,这就说明腾讯的服务器有去访问我们发送的这个链接,那如果腾讯没有做地址限制,我们在聊天框里面发送一个腾讯内网的一个地址,那它再去访问的时候我们就能知道这是一个内网的什么系统,造成信息泄露,甚至内网漏洞利用。


这类漏洞防御看起来好像没有什么难度,只要限制填写就可以,但是大部分厂商修复的时候应该不会考虑到短地址的问题,所以在修复之后仍然可以通过生成短链接来利用,建议修复的时候注意这点。


十、文件管理


文件管理功能本身就是一个高危功能,可以直接对服务器中的文件进行操作,包括上传、下载、修改、删除,如果权限管理不当,可能导致被黑客直接利用该功能写入webshell,实际上目前大多数上传webshell的方式确实是利用了文件操作功能,dedecms后台的文件管理就是非常典型的一个例子,如图13所示。


图13

一个文件管理功能为了保证安全,在满足业务需求的情况下,设计的时候应该遵循以下几个点:


1)禁止写入脚本可在服务器端执行的文件。比如服务器能解析,那么在设计文件管理这个功能的时候,就需要限制不能操作扩展名的文件和标签的代码。为什么说连代码标签也要限制?因为前端页面的都套用了HTML模板,大多是直接包含了HTML文件,如果我们直接在模板文件中插入代码,最终也能执行。


2)限制文件管理功能操作的目录。通常需要被管理的文件只有模板文件以及图片文件,所以我们可以在文件管理功能上限制只能操作这两个目录,目录不能从客户端提交,直接在代码中设置好即可,如果实在需要进行目录跳转的话,一定要禁止提交../以及\..,避免越权操作其他目录。


3)限制文件管理功能访问权限。之前我们已经说到文件管理功能本身就是一个非常敏感的功能,虽然是一个正常的功能,但是已经有一点后门的性质,所以对于这个功能的访问权限一定要进行严格的控制。


4)禁止上传特殊字符文件名的文件。大多数应用都会对上传的文件进行展示,特别是对外开发的网盘类应用,这时候就要注意对上传的文件名进行检查,禁止文件名中有尖括号、单双引号等特殊字符,避免攻击者用文件名来进行XSS攻击。


十一、数据库管理


数据库管理跟文件管理一样,也是一个高危功能,可以直接操作数据库,对数据库进行备份、执行SQL语句,等等,如果启动数据库服务的系统用户以及数据库用户的权限都够大,那么完全可以利用这个功能直接执行系统命令以及操作服务器上的文件,如图14所示。


图14

数据库管理有多个功能形式,比如discuz的数据库管理就是一个备份和优化的功能,其备份功能是可以操作所有表,另外一种是可以直接执行SQL语句进行操作。对于这两种情况下的安全设计,应该注意以下几个点:


1)限制可以操作的数据库表,如果是数据库备份可以直接在代码里面写死只能操作哪些表,如果是执行SQL语句的方式可以另建一个MySQL用户,限制可以操作的表和字段。


2)限制备份到服务器上的文件名,需要系统随机生成类似md5并且长度不能低于16位,扩展名不能自定义,这样做的目的一是防止攻击者利用该功能导出webshell,二是防止被猜解到文件名直接下载。


十二、命令/代码执行


命令执行和代码执行功能通常都在系统后台,相比来说,命令执行的功能使用的更多一点,代码执行功能在特殊应用上面才会存在,而命令执行在类似Zabbix、WDCP等大量运维系统上都存在,如图15所示。


图15

该功能可以直接在服务器上执行系统命令,危害性自然不言而喻,命令执行和代码执行功能再加上前面提及的文件管理和数据库管理功能,目前的webshell功能也不过如此了。


一旦这个功能被拿下,基本上服务器就沦陷了,所以在设计这类功能时应该注意以下几点:


1)严格控制该功能访问权限,建议高权限才能访问。

2)在满足业务需求的情况下,可以设置命令白名单,可使用escapeshellcmd()以及escapeshellarg()函数进行过滤,命令直接写死在代码中更好。

3)给命令及代码执行功能设置独立密码。

4)代码执行功能限制脚本可访问的路径。

5)在满足需求的情况下限制当前执行命令的系统用户权限。


十三、文件/数据库备份


网站源码备份和数据库备份是非常常见的一个功能,也是非常容易出现安全问题的一个功能,如图16所示为discuz数据库备份功能,需要配置多个选项,图中为discuz后台数据库导出功能。


图16

通常文件和数据库备份功能容易出现的问题有如下几种情况:


1)未授权访问和越权访问。未授权访问体现在这个备份功能直接在不登录或登录验证存在漏洞的情况下可以直接使用,以及存在CSRF漏洞可以直接劫持管理员账号进行备份,discuz的CSRF备份数据漏洞就是非常好的一个例子。


2)备份文件名可预测。备份文件名要么是备份的时候人工设置的,要么是自动生成的,如果是人工设置的,在使用完这个功能后可能存在忘记删除备份文件,导致恶意用户可以利用枚举的方式扫描到这个备份包。而自动生成则可能存在生成的文件名比较弱的问题,比如生成的文件名为当前日期,只要简单遍历下即可扫描到,非常不可靠。


3)生成的文件可利用Web中间件解析漏洞执行代码。渗透测试中写入webshell经常会用到Web中间件的解析漏洞,而当备份功能可以自定义文件名的时候,只要在数据库中写入代码,然后在IIS下时,利用数据库备份功能生成类似“1.asp;.jpg”文件名的文件,到Apache的下就备份成文件名为“1.***.zip”这样的文件,就可以直接执行我们在数据库中插入的代码。


针对如上的分析,我们来总结一下怎么设计备份功能:


1)进行权限控制,由于备份功能是一个非常高危敏感的功能,一定要限制高权限才能使用。


2)文件名随机生成,不可预测,可以把当前时间戳加上6位以上字母和数字随机生成的字符串进行md5来做为文件名。


十四、API


API(Application Programming Interface,应用程序编程接口)是一些预先定义好的类和函数,为其他程序提供一个简单的资源调用接口,调用API接口通常需要给它一个参数,API根据这个参数计算结果返回给调用方,返回形式有JSON、序列化、Base64编码等方式,这种API随处可见,如图17所示为新浪网的一个API接口。


图17

从图中可以看到这个接口传入了很多参数,这种接口如果是在安卓、iOS等APP中使用时,传统的漏洞扫描器很难进行高覆盖率漏洞扫描,因为爬虫无法抓取到这种API接口,所以接口的SQL注入等漏洞就相对较多。


从API漏洞可以看到目前API最多的问题是未授权访问以及数据遍历漏洞,如果一个接口随随便便就可以被调用,在业务有一定价值的情况下,相信肯定会有不少人利用这个接口进行一些不当操作,而频繁操作会给服务器造成非常大的资源消耗,因此设计一个安全的API应该从以下几点着重考虑:


1)访问权限控制。必要的情况下加入账户体系,严格控制数据调用权限,比如当前用户必须在登录情况下,接口参数中传入自己登录成功的凭证才能调用这个用户的数据。另外不需要账户体系的情况下也要注意加入不可暴力破解的访问密钥进行权限验证。


2)防止敏感信息泄露。之前对知乎的App进行了抓包分析,其中用户资料的API就存在注册邮箱信息泄露,该接口会返回当前查看的用户资料,其中包括注册邮箱,这样只要知道某个人的知乎账号即可知道他的个人邮箱,类似于这种没必要输出的信息应该要注意禁止输出。


3)SQL注入等常规漏洞。由于传统扫描器很难抓取到完整的接口和参数,当检测变得少了,漏洞自然就多了,所以我们在开发接口的时候要特别注意代码安全,注意防止SQL注入、代码执行等漏洞的产生。

微信公众号:计算机与网络安全

ID:Computer-network

【推荐书籍】

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存