阅读 2570

你的Web系统真的安全吗?

Github blog: 你的Web系统真的安全吗?

千里之堤,溃于蚁穴。

在Web系统中,一个小小的漏洞,往往能引发极其严重的后果。因此,Web安全是每个系统在设计、开发、运维时必须要重点考虑的问题。

现如今很多Web系统所采取的防御措施是偏向于基础和简单的,往往只针对常见的安全漏洞做了防御,比如:

  • Csrf
  • XSS
  • Sql注入

等等。这些基础的防御措施是必须要做的,且实施的成本不高,但它们只是系统安全防御中的基础部分。很多开发人员在意识中认为做好这些就足够应付大部分情况了,这种想法是非常危险的。实际上,除了这些基础且标准化的漏洞,每个业务系统本身的业务逻辑也很有可能成为黑客攻击的目标,一旦被抓到并攻破,那后果将是非常严重的。下面将列举一些常见的业务逻辑漏洞,这些漏洞也是之前开发系统时踩过的坑,希望能对大家有所启发。

会话凭证管理混乱

我们都知道HTTP本身是无状态的,为了能让浏览器和服务器互相知道身份并信任对方,大部分web系统都是利用“token”这种约定的凭证来实现的,token会在用户登录之后产生,并在用户主动退出或者超过一段时间后失效。也就是说,请求带上了相应的token,那么服务端就能拿到token做相应的校验,校验通过则信任该请求并执行相关业务逻辑,如果没带、带一个非法的或者过期的则认为不合法。这看上去并没有什么问,但实际的实现上可能暗藏漏洞。

来看两个例子:

1.前端开发人员小明在写用户点击退出按钮的逻辑时,只是单纯的清空了cookie或者localstorage中的token值(token一般存这两个地方),并没有向后台发起请求让token在业务中过期失效。那这个token的有效性本质上违背了用户的意图,此时就存在非常大的风险。当用户自发退出后,token仍然有效,假如该token被他人通过某种方式获取并记录下来,那他可以完美的回放用户执行过的操作,比如更改用户信息,下单等。

2.在上面的例子中,我们有提到token是要设置过期的,合理的过期时间能有效降低风险。但后台开发小哥也许在设置token过期的配置中,眼花加手抖,多打一位数,或者把单位理解错,在S级单位上用了MS级的数值,那过期时间就会被设定的很长。对于登录之后就不喜欢主动退出或者长期挂着页面的用户就非常的危险。token在用户长期不使用的情况下依然有效,如果被他人拿到token,也能干很多的坏事。

校验失效

文件上传应该是Web应用上比较常用的功能,比如上传头像,上传文件到网盘等等。恶意用户可能会在上传的时候,上传木马、病毒、恶意脚本等文件,这类文件在服务器上被执行会带来比较严重的后果。这种攻击方式成本较低,比较容易被攻击者利用。允许上传的文件类型越多,受攻击的可能性就越大。当恶意程序被成功上传后,可能被用户下载,在用户电脑上执行后使之中毒。也可能在服务器上就执行恶意程序,造成服务器被控制,进而服务器瘫痪,数据丢失。

正常情况下,程序都会对文件类型进行判断,只允许我们认为合法的文件上传到服务器。但是,这个判断在一些web程序中,只在前端做了,在后端没做。这就给攻击者带来了机会,攻击者可以轻松的串改请求,从而实现非法文件的上传。

正确的做法应该是后端进行文件扩展名判断、MIME检测以及限制上传文件大小等限制来防御。另外,可以将文件保存在一个与业务隔离的服务器来防止恶意文件攻击业务服务器导致服务不可用。

数据枚举

在登录系统,大部分系统会在用户登录的时候判断用户是否存在,然后给出提示“该手机号未注册”。如果这个逻辑是用一个单独的接口做的,那么就会存在被暴力枚举的风险。攻击者可以通过该接口利用手机号码库进行请求枚举,识别出哪些手机号是在系统中注册过的,给下一步暴力破解密码带来机会。

对于这个问题,建议是将该判断放到登录验证的接口中,并不返回明确的提示。你会看到做的好的网站上,一般会提示“该手机号未注册或密码错误”。虽然这在用户体验上打了折扣,但也更加的安全。

数据写入重放

以一个论坛的发帖举例,利用抓包工具抓取论坛发帖的请求过程,并通过该工具重放过程,会发现帖子列表出现了两条一样的帖子,这就是被重放攻击了。如果加快重放频率,不仅会在系统中产生很多的垃圾数据,还会因为频繁写入给业务数据库带来巨大压力。

对于此类有重放风险的请求,建议加上请求频率限制。比如,可以判断两个请求的时间戳,设定大于某个时间值才有效。

权限漏洞

权限校验是Web系统的基本功能,比如一个公司组织架构管理系统,里面提供了修改部门名称、部门经理的功能。加上权限校验能很好地避免任意用户能通过这些功能修改他本无权限的信息。此类系统中一定会实现权限校验,但实际上真的实现对了吗?

假设我们规定,系统中某用户需要同时满足具有超管权限且属于A部门两个条件,才能修改部门名称。往往在实际的代码实现中,开发人员只是去判断该用户是否为超管,而没有判断该用户是否属于该部门。在这种情况下,我们可以用B部门的超管账号,去修改A部门的名称,相当于越权修改了,这显然不是我们期望的结果。即使B部门的超管用户在界面上无法找到修改A部门部门名称的入口,也可以通过抓取请求修改参数来实现。

除了越权修改,当然还能越权查看。我们肯定也不期望A部门的超管能看到B部门的部门信息,是不是?

建议大家的系统要对用户访问角色的权限进行严格的检查及限制。

安全无小事,正如开头所讲,任何一个漏洞都有可能带来毁灭性的打击,希望大家能重视。不仅在业务设计上要重视,同时也要在代码审查上要重视,以避免因实现而带来的低级漏洞问题。

以上只是举了众多安全漏洞中的一小部分,更多严重的Web应用程序安全风险可以查阅 OWASP Top 10 2017 发布的Top10安全问题。http://www.owasp.org.cn/owasp-project/OWASPTop102017v1.3.pdf