跳转至

安全系统

前言

最近一位朋友让帮忙审计一套管理系统,说是从客户那接的项目,刚开始心里还是比较忐忑的,已经多年没有做代码审计工作了...,但抓了一下包,发现个未授权+读取任意账号和明文密码,"原来如此简单"... 程序直接使用http header传递要查询的数据库表和where条件,并且接口没有进行任何权限校验。
还是比较感慨,安全这几年感觉发展的很快,各种新概念层出不穷,几天不刷朋友圈,就不认识最新的名词,最传统、最基础的安全仿佛是那么的落伍,那么的过时,但从另一方面,很多研发同学,测试同学,对于最基本的安全知识是存在缺失的,很多安全知识可能听过,真正明白的很少,真正用到自身项目中的更是寥寥无几,自然很难构建出安全的系统

不禁想起 怎样才能建个安全系统?

怎样建个安全系统

看似很简单的问题,但越想越复杂,现在的系统已经非常庞大,涉及到的技术栈也是层出不穷,php,java,python,go,js等,大数据,ai等,让人眼花缭乱,哪个点做的不到位,都可能成为系统中最薄弱的环节,进而导致整个系统沦陷。
系统广义上讲是对外提供服务的,所以不仅仅包括研发编写的代码,还包括用到的所有第三方代码、运维等,安全系统将会是一个非常大的话题:安全设计、安全开发、安全运维、第三方组件安全等

本板块将从针对构建系统所涉及到的相关角色进行解析,希望参与方(产品设计、研发、测试、运维)都能关注安全,共同努力构建安全系统。

研发和测试同学

安全设计

威胁建模

从设计的角度对系统进行评估,试图确认潜在的安全问题,在软件开发生命周期早期发现安全风险,及时修复,节约成本

主要包括4步:

  • 系统边界
    一个新系统的边界是在哪里,这个为入口管控做铺垫

  • 入口管控
    权限管理/访问控制,有权限的发起方才能使用对应的功能,是一种白名单机制

  • 内部实现
    有权限的发起方只能做系统允许他们做的事情,如系统设计只允许查询表A,则保证没有SQL注入,让其查询到表B

  • 安全审计
    当出现安全问题,进行溯源,或者发现问题的根本原因

具体解释

客户端->服务器: HTTPS 
服务器-->数据库: 访问控制/数据加密
服务器->客户端: 屏蔽错误信息

客户端到服务器

  • 是否允许访问,在网络上进行限制(VPN限制,IP限制,web服务401限制)

  • 网络通信HTTPS

服务器接收到客户端请求

  • 应用层访问控制,是否允许访问(是否注册、登录、acl是否允许),会话保存到服务端session

  • 对客户端输入进行白名单校验或黑名单校验

  • 数据库参数化查询,敏感数据加密存储,展示掩码,数据及时远程备份,分权管理

  • 文件操作,禁止控制文件路径(..),文件上传后缀

  • 捕获服务异常,记录日志远程存储,日志不能包括敏感信息明文

服务器系统

  • 主机系统,第三方组件最新版本及时更新补丁

  • 服务最小化部署,删除/修改默认账号,低权限运行服务

  • 禁止上线测试代码,备份代码

服务器返回数据

  • 输出body编码,返回header设置正确如:application/json

  • 禁止返回错误信息或调试信息到客户端,禁止返回多余信息

  • 敏感数据只用于展示时,需要掩码显示

注:每个点都有无尽的需要进行补充和完善的,但基本上算是一个简易安全框架,方便记忆和扩展

权限设计

访问控制(权限设计)是一个系统安全的灵魂,如果没有访问控制,很难做一个安全的系统。

大部分系统采用基于角色的访问控制:先确定系统有哪几种角色(管理员、普通用户、审计员)等,每种角色应该有哪些功能即对应的页面/URL地址

常见的问题

无统一配置访问控制的限制

导致很多页面在开发时,由研发自己添加,最终的问题就是研发忘记了添加权限限制,就出现一个未授权访问漏洞,只要不是统一配置访问控制的系统,将会有一个99%的概率出现未授权访问漏洞。

关键字段(如userid)未随机化/加密展示

一般的系统都会有个用户id(如userid),一般是个int型,从1开始递增,如果系统出现一个遍历userid的查询他人系统的水平越权漏洞,则很容易被攻击者利用。同时根据userid值,也可以知道系统的用户数量。

从安全的角度,建议将类似userid这样的值变成随机字符串,如无法预测的uuid(补充知识:安全漏洞的生命周期:产生->发现->利用->修复,虽然编写了水平越权漏洞,使得产生了一个漏洞,经过足够长的时间,一定会被人发现,但漏洞产生危害需要进行利用(遍历这个userid),userid随机化后,将导致漏洞终止在发现环节,无法进行利用,严格意义上来讲不算一个漏洞)

有时面临的问题,userid已经创建好了,现在将其随机化,成本会是非常、非常的高,这时可以考虑,在将userid返回到前端前,做个对称加密,当前端传递过来userid后,在进行解密,保证对称加密密钥不泄露,相当于将userid进行了随机化。

这两种对userid的处理,基本上可以杜绝通过userid的权限问题,也是实现免密登录的一种解决方案。

其他建议

前后台拆分

如果您的系统非常庞大,可以将一种角色拆分成一个子系统,分开部署,如普通用户为系统A,放到外网,管理后台为系统B,仅允许内网访问。两个系统通过数据库进行交互,可以拒绝垂直越权(普通用户获得管理员权限)

有关用户身份的信息统一保存到服务器

web系统中的http协议是无状态的,为了维持一个用户的登录状态,必须将登录信息保存起来,常见的两种方案:完全保存到客户端和保存服务端。 完全保存到客户端如cookie,每次请求都会带上cookie,但由于服务端没有保存,导致无法验证,只能信任客户端传递过来的值。可能产生欺骗,因此使用这种方案时,需要在下发cookie前进行加密,保证cookie在客户端是密文,无法被篡改

保存服务端如session,这种方案借助特殊cookie与服务器存在信息的映射实现类似信息完全保存在服务端,记住这种方案,保存的信息客户端无法进行修改,比较安全。

Back to top