大型互联网架构安全性设计
无论是互联网系统还是企业内网系统,无论是B/S架构还是C/S架构的系统,都会面临各种安全性问题。
总体而言,暴露在互联网上的系统面临更多的安全威胁,因此衍生出了各种安全产品网络防火墙、高防IP、网盾等。除采购各种硬件和服务外,重点是要在自己的系统设计上加大安全控制的投入。
安全控制要具有整体性,客户端、网络传输、服务端、数据库各个环节都要进行相应的安全性设计。这涉及代码混淆、App加固、加密签名、认证授权、加密存储、验证码等众多技术细节。本节将对安全性的设计原则和技巧进行整体介绍,后续章节还会继续深入这一问题。
2.4.1 安全控制的整体性
系统安全是一个庞大的领域,如图2-104所示,现在系统的架构形式非常多,可以是浏览器、App、微信、小程序、电视、冰箱等,它们都属于用户网络区,通过家中的路由或运营商基站接入互联网,经过一系列的网络设备转发,经由互联网,最终到达服务端所在的系统网络区(机房/数据中心),又要经过各种网络设备、负载设备,最终到达后端服务,而后端服务又需要与外联系统、数据库、中间件等进行交互,整个交互链条非常复杂。
图2-104 互联网系统拓扑
每个节点、每个链路(两个实体之间的连接线)都要进行安全控制。每个终端设备、每个网络设备、每个服务器都要解决自身的安全性问题,同时也要解决与其他设备交互的安全性问题。
硬件的安全性、网络设备的安全性、应用系统的安全性缺一不可。在进行安全性设计时,必须从整体考虑,某个单点系统再安全、再健壮也是没用的。就好比一个银行的App,后端服务十分健壮安全,然而它忘记了做登录校验功能,谁都可以随意使用。
2.4.2 应用系统安全性设计
由于系统开发人员对硬件设备、网络设备等安全不太关注,因此应该由更加专业的网络工程师、硬件工程师负责。开发人员应该重点关注应用系统的安全性设计。
无论是在C/S还是B/S模式下,每个节点都需要进行安全控制,如图2-105所示。
图2-105 安全设计的整体性
1. Web端安全控制点
(1) 代码安全:可以进行代码混淆、代码压缩,以降低代码可读性。
(2) Cookie存储:尽量不存储敏感信息,如果存储,则需要进行加密,必须设置有效期,并设置清空机制。
(3) Local Storage和Session Storage存储:尽量不存储敏感信息,如果存储,则需要进行加密,并设置清空机制。
(4) 防止SQL注入,防止XSS攻击:严格地进行客户端录入校验,对于有注入风险的内容予以阻止或转义,服务端需要同样的预防措施,一般可以在AOP或过滤器中做统一处理。
(5) 跨域限制:默认不允许跨域,如果需要跨域,则需要严格限定请求来源。
(6) 环境限制:如果页面只允许在微信中调用,则应该做相应控制;如果页面只允许在App中调用,则应该要做相应控制。
2. Andr oid端安全控制点(1)代码安全:可以进行代码混淆、代码压缩,以降低代码可读性。
(2) APK包:需要安全加固,使用第三方付费功能,防止反编译破解,市场上的一些免费加固的实际效果并不理想。
(3) 本地文件、SD卡文件存储:尽量不存储敏感信息,如果涉及敏感信息,则可以对文件进行加密,或者对内容进行二次加密。
(4) 本地数据库:安卓系统自带密钥安全控制,无须额外处理。
3. iOS端安全控制点
(1) 代码安全:可以进行代码混淆、代码压缩,以降低代码可读性。
(2) 安装包:苹果应用商店自动加固,企业版没有加固(可以反编译,市场上还没有加固工具)。
(3) 本地文件存储(包含数据库):尽量不存储敏感信息,如果涉及敏感信息,则可以对文件进行加密,或者对内容进行二次加密。
(4) 本地数据库:iOS系统自带加密和密钥安全控制,无须额外处理。
4.传输安全
在客户端与服务端交互的过程中,要注意传输过程的安全控制,防止传输内容被窃取或篡改。根据控制的等级不同,可分为低安全级别、中安全级别和高安全级别。
(1)低安全级别:使用HTTP,明文传输,使用明文与服务端交互,性能好但安全性较差。(2)中安全级别:使用HTTPS,加密传输,使用明文与服务端交互,性能中等但安全性较高,可以防止网络嗅探(网络嗅探就是网络抓包,可以看到所有在网络上传输的内容)。
(3)高安全级别:使用HTTPS,加密传输,与服务端的交互数据进行加密和签名,可以防止网络嗅探、数据泄露和篡改。
明文交互是指双方交互的报文内容是非加密状态,如图2-106所示,在Chrome浏览器中按“F12”键进入开发者模式,就可以看到今日头条某个页面的接口调用情况,可以很直观地看到接口请求和应答的信息。如果需要避免这种情况,则需要使用高安全级别设计。
图2-106 交互报文抓取
加密和签名交互流程如图2-107所示,分为以下4个步骤。
(1)客户端将请求报文进行加密,然后进行签名,以密文的形式请求服务端。(2)服务端接收到加密的报文后,先进行验证签名,然后进行解密。如果验证签名不通过,则说明内容可能被非法篡改;如果无法解密,则说明对方使用了错误的密钥。
(3) 服务端将应答信息同样进行先加密后签名的处理,以密文的形式应答给客户端。
(4) 客户端收到服务端应答之后,同样进行验证签名和解密处理。
图2-107 加密和签名交互流程
2.4.3 数据安全性设计
数据安全性设计需要遵循3个原则:数据脱敏原则、数据加密原则和数据隔离原则。
1.数据脱敏原则敏感数据一定要进行脱敏展示。脱敏是指用掩码、截取等方式避免展示全部数据内容。例如,用户的身份证号、银行卡号、手机号
等,展示为“152***********1233”“身份证号尾号为1233”“银行卡尾号
9899”“手机尾号9527”的方式。
数据脱敏必须从后端服务脱敏,而不能采用前端JavaScript脱敏
(假脱敏),因为通过查看页面源码和交互信息很容易获取到用户敏感数据。
对于内部管理系统,有关用户信息的报表能不展示用户敏感信息的就不展示,如果必须展示,则尽量脱敏;如果必须原文展示,则需要记录详尽的访问日志,哪个用户查询过此报表,谁导出过数据,以便日后追查。
2.数据加密原则
对于安全等级较高的数据,可以采用加密存储和分片存储的方式。
如账户的密码需要加密存储,可采用哈希算法加密存储(其他密码安全措施可参见5.3节)。
如用户的图片、视频、机密文件等重要数据,可以拆分为多份,存储在不同服务器的不同位置,在使用时才合并在一起。
如用户的聊天记录等私密信息也要先加密,再分散存储。
3.数据隔离原则
用户之间的私有数据一定要相互隔离,自己只能访问自己的数据,防止数据越权访问。如图2-108所示,这是一张简化的订单表,字段分别为用户订单
ID、用户ID、订单时间、订单金额。要求用户A、B只能访问自己的订单数据。
图2-108 用户数据访问
典型错误设计:提供RESTful接口http://xxx:xx/orderList/A,最后一项A为用户ID参数,服务端根据用户ID去查询数据库表,返回订单数据。数据库语句通常为“select * from t_order where user_id='A'”。
这看起来一切正常,但是却有极大的隐患。如果某用户的账号是 A,当其登录成功后,更改一下请求地址,如http://xxx:xx/orderList/B
,就可以查询到用户B的全部订单数据,造成数据泄露。
查询操作只会引起数据泄露,而如果是订单删除等更新类操作,则会引起更严重的问题,可以用以下两种安全设计方案来规避这种风险。
(1) 安全设计方案1: 对比当前登录用户与要操作的数据范围是否相同,实现流程如图2-109所示。① 依然使用RESTful 接口
http://xxx:xx/orderList/A;② 服务端接收到请求后,先根据用户的
Session或Token,获取到当前登录用户的ID;③ 对比此用户ID是否等于A;④ 如果相同,则允许查询;如果不同,则提示“没有数据查询权限”。
图2-109 数据访问权限校验
(2) 安全设计方案2: 使用登录用户的会话信息作为查询条件,实现流程如图2-110所示。① 提供RESTful接口http://xxx:xx/orderList,注意此接口并没有任何参数;② 服务端接收到请求后,先根据用户的
Session或Token,获取到当前登录用户的ID;③ 到数据库中查询,从而确保了登录用户只能查询自己的订单数据。
图2-110 数据访问隔离