1. 安全配置出现失误 1.1. 攻击者已经通过使用开箱默认的admin登录名和密码,进入了不少应用程序、网络设备和数据库 1.2. 出现配置的遗漏 1.2.1. 服务器默认启用不需要的特性 1.2.1.1. 我们忘记(或不知道)禁用它们,从而开放了这些未经配置和未被监控的系统入口点 1.3. 禁止在生产服务器上使用默认密码 1.4. 服务器监听了过多的内容 1.4.1. 将内部管理流量分离到独立于公共流量的专用网卡上,从而立即提高信息安全性 1.4.2. 将内部管理接口拆分出来,就能缩小攻击面 1.5. 确保每个管理员都使用个人账户,而不是组账户 1.6. 不能将示例应用程序投入生产环境 1.6.1. 某些服务器附带的示例应用程序的安全保护意识极差,并且可能会过时 2. 敏感数据泄露 2.1. 泄露并不意味着黑客破解了你的秘密 2.2. 不要存储不需要的敏感信息 2.3. 使用HSTS机制,这比优先尝试HTTPS的做法更安全 2.3.1. 它会阻止客户端通过不安全的协议使用网络 2.4. 停止使用SHA-1,再也不要用了,这个加密方法已经不够安全了 2.5. 避免明文形式存储密码 2.6. 确保敏感数据在数据库中已被加密 2.7. 在解密数据时,先获得用户而不是服务器的授权 2.8. 不要将解密密钥随便放在攻击者可以找到的位置 2.8.1. 可以考虑使用HashiCorp公司的Vault产品,相比KMS,它能管理更多种类的“秘密” 2.9. 无论选择哪种工具,都不要浅尝辄止,要将该工具作为整体安全开发过程中的一部分充分利用 3. 防范攻击不足 3.1. 如果生产环境的服务被防火墙保护起来,那么它就应该是安全的,不会受到攻击者的侵袭 3.1.1. 必须始终假设攻击者能无限制地访问防火墙后面的其他机器,可以随心所欲地对服务器发出访问请求,比如对未授权数据的格式良好的请求,以及旨在让服务本身陷入险境的格式错误的请求 3.2. 为所有服务提供允许访问的消费者白名单不太可能实现 3.3. API网关是一道有用的防线 3.3.1. 可以通过其API密钥屏蔽调用者 3.3.2. 可以抑制调用者的请求速率 3.4. 如果服务位于能够控制的数据中心内,那么网络设备就会有所帮助 3.4.1. 应用层防火墙(也称为“第7层”防火墙)可以检测并屏蔽可疑调用,也可以根据日常熟知的攻击特征阻止探测行为 4. CSRF 4.1. cross-site request forgery 4.1.1. 伪跨站请求 4.2. CSRF攻击始于另一个站点 4.2.1. 攻击者把带有JavaScript、CSS或HTML的网页当作“陷阱”,其中包含指向目标系统的恶意链接 4.2.2. 当倒霉的用户使用浏览器通过这个陷阱页面访问目标系统时,目标系统认为这是该用户的有效请求 4.2.2.1. 这个用户就成了攻击者的傀儡 4.2.3. 用户浏览器发送的所有cookie(包括会话cookie)都是正常的 4.2.3.1. 用户仅是看似拥有登录会话,并不意味着该请求是用户真正的意图 4.3. 确保你的网站不能用来发起CSRF攻击 4.4. 确保具有副作用的请求(例如更改密码、更新邮寄地址或购买)使用反CSRF攻击的令牌 4.4.1. 大多数框架已实现了这一功能,但你可能需要在服务的配置中启用CSRF保护 4.5. 可以使用相对较新的SameSite(同站点)属性来强化cookie策略 4.5.1. 同站点cookie这一功能并不是零成本的,它可能会要求你更改会话管理方法 4.6. 建议使用一对cookie 4.6.1. 会话“读取”cookie:不要求访问必须来自同站点,允许HTTP GET请求 4.6.2. 会话“写入”cookie:严格要求访问必须来自同站点,状态改变的请求需要如此设置 5. 使用含有已知漏洞的组件 5.1. 一旦知道存在漏洞,就应该更新系统的补丁版本并重新部 5.2. 让应用程序保持最新状态,这意味着要处理依赖关系树 5.3. 许多漏洞从未发布出来 5.3.1. 有些漏洞只在项目的邮件列表中或问题跟踪器上讨论过,但没有相应的CVE,所以也应该关注这些漏洞 6. API保护不足 6.1. REST和富客户端的崛起将API提升为主要的架构关注点 6.2. API难以区分攻击者 6.2.1. API就是供程序使用的,而攻击工具也是程序,这一点让保护API变得更加困难 6.3. 关键点 6.3.1. 要做好舱壁隔离 6.3.1.1. 如果一个客户的授权证书被盗,那很糟糕 6.3.1.2. 如果攻击者可以使用这个客户的证书获取其他客户的数据,那简直是灾难 6.3.2. API必须对开放出去的链接进行授权,然后当请求返回时还要重新对该请求授权 6.3.3. API应该使用最安全的通信方式 6.3.3.1. 对于面向公众的API,这意味着要使用TLS 6.3.3.2. 一定要将其配置为拒绝协议降级 6.3.3.3. 保持根证书颁发机构文件的最新状态 6.3.3.3.1. 损害证书行为发生的频率会超出你的想象 6.3.3.4. 企业对企业的API最好使用双向证书,这样每个端点都能验证另一端的安全性 6.3.4. 无论使用哪种数据解析器(JSON、YAML、XML、Transit、EDN、Avro、Protobufs或莫尔斯码等),都要确保解析器能够抵御恶意的输入 6.3.5. 用Fuzz方法测试API尤其重要 6.3.5.1. API应该尽快响应更多的请求,这样的测试能帮助API抵御自动化破解器的攻击 7. 最小特权原则 7.1. 要求进程只具有完成其任务所需的最低特权级别 7.2. 任何应用程序服务都须如此,应该以非管理员的用户身份工作 7.3. root级别软件中的任何漏洞都会自动成为关键问题 7.3.1. 如果攻击者破解了shell来获得root权限,那么确保服务器安全的唯一方法是重新格式化硬盘并重新安装系统 7.4. 容器为系统的彼此隔离创造了很好的条件 7.4.1. 将容器镜像视为“易腐货物” 7.4.2. 务必为那些已经过了开发活跃期的应用程序配置定时构建任务 7.4.2.1. 这样做可以修补安全漏洞 8. 密码的配置 8.1. 以密码安全的绝对最低标准来看,生产数据库的密码应独立于其他任何配置文件单独保存,尤其要放在软件安装目录之外 8.2. 包含密码的文件应仅对密码所有者可读,这个密码所有者应该是应用程序用户 8.3. 密码保管库将密码保存在加密文件中,这将安全问题降低到了保护单个加密密钥,而不是保护多个文本文件 8.4. 在任何情况下,尽快删除内存中的密钥都非常重要 9. 安全即持续的过程 9.1. 保证安全是一项持续的活动,必须是系统架构的一部分,关于加密通信、静态数据加密、身份验证和鉴权的关键决策 9.2. 用新API的新技术将会存在漏洞,但这并不意味着应该放弃其提供的优势 9.3. 意味着你需要及时给它打补丁,确保可以立即重新部署服务器 9.4. 既要考虑组件级行为,也要考虑整个系统的行为 9.5. 两个安全的组件混合在一起,不一定能构成一个安全的系统 9.6. 攻击者眼中最常见的价值目标是用户数据,特别是信用卡信息 9.7. 工业间谍活动真实存在,这些活动有时看起来毫无杀伤力