在云端开发安全又健壮的 Web 应用非常难。如果你认为这很容易,那你技术水平要么已经很牛叉,要么还没有踩过坑。
如果你盲目接受最简可行产品(Minimum Viable Product,简称 MVP),并且认为你能在一个月之内创建一个既有价值又安全的产品,那么在你推出你的“产品原型”前,你还需要多想想。在你查看了下面的清单之后,确认你不会犯这些严重的安全问题。 至少,你要对你的潜在用户坦诚,让他们知道你还没有一个完整的产品,并且只提供一个没有全面安全的原型。
这个清单很简单,并且也不是那种大而全的。我已经开发安全的 Web 应用有 14 年多了。这个清单包含了一些相对重要的问题。这些问题都是我在这段时间学到的,而这个过程也是痛苦的。当你在创建 Web 应用时,我希望你能够认真地对待这些问题。
如果在这个清单中,你有我没有提到的项目,请留言补充。
可以识别用户的数据和敏感数据(如访问令牌、电子邮件地址或账单信息)需要加密。
如果你的数据库在休息状态时支持低成本加密(如AWS Aurora),那么启动该功能来保护硬盘上的数据。同时也要确保所有备份都是被加密存储的。 给用户最低访问权限的账户。不要使用数据库的 root 账户。
刻意设计一个密钥库,用它存储和分发机密内容。不要硬编码到你的应用中。
通过只使用 SQL 预处理语句(prepared statements)的方法来完全防止 SQL 注入。比如:如果要使用 NPM,不要使用 npm-mysql,而是使用 npm-mysql2,因为它支持预处理语句。
对于每个发布的版本,确保软件的所有组件都通过了漏洞扫描。组件指的是操作系统、库和包。这应该自动地进入持续集成/持续交付流程。
保证开发系统的安全。同样的,对于你使用的产品系统,也需要保持相同的警惕。在安全、隔离的开发系统中开发软件。
确保所有密码都经过合适的加密方法(如 bcrypt )的散列处理。永远不要自己实现加密方法,并且用好的随机数据来正确地初始化加密方法。
在实现登录、忘记密码、密码重置等功能时,用经过验证过的最佳实现或组件。不要重复造轮子,因为你很难保证其在所有场景中都不会出现问题。
遵循简单且合适的密码规则,鼓励用户使用较长的随机密码。
你们提供的所有服务,用多重认证来验证登录。
确保网站不会因 API 遭拒绝服务攻击(DOS)而瘫痪。至少,在相对较慢的 API 路径上(像登录和 Token 生成程序)设置频率限制器。
对用户所提交的数据和请求,在大小以及结构这两点上执行合理的限制。
通过使用全局缓存代理服务(类似 CloudFlare )来规避分布式拒绝服务(DDOS)。如果网站遭到 DDOS 攻击,你就能打开这个服务和其他类似的,以作 DNS 查询。
整个网站都使用 TLS,不仅仅是登录表单和响应。 永远不要只在登录表单中使用 TLS。
Cookie 必须设置 httpOnly、安全、被路径和域限定。
使用内容策略安全(CSP),并且不允许 unsafe-(是通配符)后门。虽然配置时很痛苦,但这是值得做的。
在客户端的响应头中使用 X-Frame-Option、X-XSS-Protection。
使用 HSTS 响应强制仅限 TLS 访问。在服务器上重定向所有 HTTP 请求到 HTTPS,作为替代方案。
在所有的表单中使用 CSRF 令牌(Token)。使用新的 SameSite Cookie 响应头,这彻底解决了所有较新浏览器上的 CSRF 问题。
确保公开 API 中没有可枚举的资源。
确保用户经过全面的认证,并且拥有适当权限的用户才能访问 API。
在 API 中使用随机检查,以检测潜在攻击的非法或异常请求。
为了给用户快速的反馈,可以在客户端做输入合法性验证,但是永远不要相信用户的输入数据。
在服务器端使用白名单,来验证所有用户的输入。永远不要直接将用户的内容添加到响应中。永远不要在 SQL 语句中使用用户输入的内容。
确保所有的服务打开尽可能少的端口。当隐晦式安全(security through obscurity)没有保护的效果时, 将默认的端口替换成非标准的端口,这样可以让攻击者更难攻破。
将后端数据库和服务托管到私有 VPC 上 (虚拟私有云),而 VPC 不能被任何公共网络访问。当你在配置 AWS 安全组和对等 VPC 时,你需要非常仔细,因为这可能导致服务无意中对外部开放。
在隔离 VPC 和对等 VPC 里隔离逻辑服务,以便支持跨服通信。
确保所有服务接收的数据,来自于一个尽可能小范围内的 IP 地址。
限制出站 IP 和端口流量,最大限度地减少 APT 攻击带来的损失和“通讯”。
始终使用 AWS 访问管理(IAM)这个身份,而不是 root 凭据。
授予所有操作和开发人员最小的访问权限。
根据时间表定期地更换密码和访问密钥。
确保你能在不停机的情况下升级。确保你能通过完全自动的方式快速升级。
使用像 Terraform 这样的工具创建所有的基础架构,而不是通过云端控制台。基础架构应该被定义为“代码”,并且能够按下按钮来重建。对于任何在云端手动创建的资源采取零容忍态度,之后 Terraform 就能审计你的配置了。
所有服务都使用集中式日志架构。你永远都不应该需要 SSH 来访问或者检索日志。
除了一次性诊断,不要通过 SSH 连接到你的服务。通常使用 SSH 意味着你没有自动执行重要任务。
永远不要在任何 AWS 服务组上保持 22 号端口为打开的状态。
创建不变的主机,而不是不断地给你长寿的服务器打补丁和升级。(参见Immutable Infrastructure Can Be More Secure).
使用入侵检测系统来最大化减少 APT 攻击带来的影响。
关闭未使用的服务和服务器。断电的服务器是最安全的。
审计你的设计和实施。
做渗透测试。除了你之外,还可以叫其他人进行渗透测试。
就关于社会工程领域中的潜在威胁和相关防护技术,要对员工(特别是高级员工)进行培训。 最后,制定一个计划
做一个威胁模型,描述你正在防御对象。按主次列出可能的威胁和参与者。
制定一份可实操的安全事故计划。总有一天你会需要的。