开发人员安全须知

前言

本文来自 https://github.com/FallibleInc/security-guide-for-developers ,这是一篇web开发人员的安全须知(指南),是由 FallibleInc 公司提炼出来的,发布在github上面,我自己把的相关文档翻译成简体中文,他们也对我比较信任,给我开了这个repo的写权限,如果你发现有翻译得不正确的地方,欢迎提交PR, 我这边有权限可以合并。

目标读者

安全问题主要由以下两类原因导致:

  1. 那些刚入门的无法区分MD5和bcrypt作用的开发者
  2. 那些知道这件事但忘记/忽略了的开发者

我们的详细说明应该可以帮到第1类开发者,而我们希望的我们的checklist可以帮到第2类的开发者构建更多安全的系统。这绝不是一个综合性的指南,仅仅是覆盖了大多数我们过去发现的比较常见的问题。

目录

  1. 安全Checklist
  2. 什么东西会出问题?
  3. 安全地传输数据: HTTPS 详解
  4. 权限验证: 我是谁?
    4.1 基于表单的权限验证
    4.2 基础鉴权
    4.3 一次是不够的、二次、三次(验证)….
    4.4 为什么使用不安全的文本消息? HOTP & TOTP 介绍
    4.5 处理密码重置
  5. 权限验证: 我能做什么?
    5.1 基于Token的权限验证
    5.2 OAuth 和 OAuth2
    5.3 JWT(JSON Web Token)
  6. 数据校验和过滤: 绝不信任用户输入
    6.1 校验和过滤用户输入
    6.2 过滤输出
    6.3 跨站脚本攻击(XSS)
    6.4 注入攻击
    6.5 用户上传
    6.6 用户篡改输入
  7. 纯文本 != 编码 != 加密 != 哈希
    7.1 通用编码模式
    7.2 加密
    7.3 哈希和单向函数(功能)
    7.4 哈希速度对照表
  8. 密码: dadada、123456、cute@123
    8.1 密码策略
    8.2 密码存储
    8.3 没有密码的生活
  9. 公钥加密
  10. 会话: 请记住我
    10.1 哪里存储状态?
    10.2 使会话失效
    10.3 Cookie怪物和你
  11. 加固安全, 一次只有一个头信息
    11.1 安全的web header
    11.2 第三方代码的数据集成检测
    11.3 证书绑定
  12. 配置错误
    12.1 云上准备: 端口、Shodan、AWS
    12.2 亲,你开了debug模式
    12.3 日志(或者没有日志)
    12.4 监控
    12.5 最低优先级原理
    12.6 (请求)频率限制 和 Captchas
    12.7 把项目的密钥和密码保存在文件上
    12.8 DNS: 关于子域名和被遗忘的宠物计划
    12.9 打补丁和更新
  13. 攻击: 当坏人来临
    13.1 点击劫持
    13.2 跨站请求伪造
    13.3 拒绝服务
    13.4 服务端请求伪造
  14. 互联网公司漏洞统计
  15. 重造轮子,但做出来是方的
    15.1 Python的安全库和包
    15.2 NodeJS的安全库和包
    15.3 学习资料
  16. 掌握良好的安全习惯
  17. 安全性 vs 可用性
  18. 回到第1条: 安全Checklist解释

我们是谁?

我们是全栈开发工程师,讨厌看到那些所谓为了做某件事情而hack,但写了一堆不安全的代码的开发者。在过去六个月,我们保护了超过1500w信用卡信息以及超过4500w用户的个人信息以及被盗,以及防止了大量的公司倒闭。最近,我们发现一个安全问题就能使一家比特币交易公司数据泄露从而倒闭。我们以及帮助了若干创业公司让他们的系统更安全,大多数是免费的,有时候甚至连『谢谢』都没收到:)

如果你不同意我们的观点或者找到bug,请开启一个issue或者提交一个PR给我们。另外,你也可以通过 hello@fallible.co 与我们交流。  

 

安全checklist

权限系统 (注册/注册/二次验证/密码重置)
  • 任何地方都使用HTTPS.
  • 使用Bcrypt存储密码哈希 (没有使用盐的必要 – Bcrypt 干的就是加密这个事情).
  • 登出之后销毁会话ID .
  • 密码重置后销毁所有活跃的会话.
  • OAuth2 验证必须包含 state 参数.
  • 登陆成功之后不能直接重定向到开放的路径(需要校验,否则容易存在钓鱼攻击).
  • 当解析用户注册/登陆的输入时,过滤 javascript://、 data:// 以及其他 CRLF 字符.
  • 使用 secure/httpOnly cookies.
  • 移动端使用OTP验证时,当调用generate OTP 或者 Resend OTP API时不能吧OTP(One Time Password)直接返回。(一般是通过发送手机验证短信,邮箱随机code等方式,而不是直接response)
  • 限制单个用户LoginVerify OTPResend OTPgenerate OTP等API的调用次数,使用Captcha等手段防止暴力破解.
  • 检查邮件或短信里的重置密码的token,确保随机性(无法猜测)
  • 给重置密码的token设置过期时间.
  • 重置密码成功后,将重置使用的token失效.
用户数据和权限校验
  • 诸如我的购物车我的浏览历史之类的资源访问,必须检查当前登录的用户是否有这些资源的访问权限。
  • 避免资源ID被连续遍历访问,使用/me/orders 代替 /user/37153/orders 以防你忘了检查权限,导致数据泄露。
  • 修改邮箱/手机号码功能必须首先确认用户已经验证过邮箱/手机是他自己的。
  • 任何上传功能应该过滤用户上传的文件名,另外,为了普适性的原因(而不是安全问题),上传的东西应该存放到例如S3之类的云存储上面,而不是存储在这几的服务器,防止代码执行。
  • 个人头像上传 功能应该过滤所有的 EXIF 标签,即便没有这个需求.
  • 用户ID或者其他的ID,应该使用 RFC compliant UUID 而不是整数. 你可以从github找到你所用的语言的实现.
  • JWT(JSON Web Token)很棒.当你需要做一个单页应用/API的使用使用.
安卓和iOS APP
  • 支付网关的 盐(salt) 不应该硬编码
  • 来自第三方的 secretauth token 不应该硬编码
  • 在服务器之间调用的API不应该在app里面调用
  • 在安卓系统下,要小心评估所有申请的 权限
  • 在iOS系统下,使用系统的钥匙串来存储敏感信息(权限token,api key等等)。 不要 把这类信息存储在用户配置里面
  • 强烈推荐证书绑定(Certificate pinning)
安全头信息和配置
  • 添加 CSP 头信息,减缓 XSS 和数据注入攻击. 这很重要.
  • 添加 CSRF 头信息防止跨站请求调用(CSRF)攻击.同时添加 SameSite 属性到cookie里面.
  • 添加 HSTS 头信息防止SSL stripping攻击.
  • 添加 你的域名到 HSTS 预加载列表
  • 添加 X-Frame-Options 防止点击劫持.
  • 添加 X-XSS-Protection 缓解XSS攻击.
  • 更新DNS记录,增加 SPF 记录防止垃圾邮件和钓鱼攻击.
  • 如果你的Javascript 库存放在第三方的CDN上面,需要添加 内部资源集成检查 。为了更加安全,添加require-sri-forCSP-directive 就不会加载到没有SRI的资源。
  • 使用随机的CSRF token,业务逻辑API可以暴露为POST请求。不要把CSRF token通过http接口暴露出来比如第一次请求更新的时候。
  • 在get请求参数里面,不要使用临界数据和token。 暴露服务器日志的同时也会暴露用户数据。
过滤输入
  • 所有暴露给用户的参数输入都应该 过滤 防止 XSS 攻击.
  • 使用参数化的查询防止 SQL 注入.
  • 过滤所有具有功能性的用户输入,比如CSV导入
  • 过滤一些特殊的用户输入,例如将robots.txt作为用户名,而你刚好提供了 coolcorp.io/username 之类的url来提供用户信息访问页面。(此时变成 coolcorp.io/robots.txt,可能无法正常工作)
  • 不要自己手动拼装JSON字符串,不管这个字符串有多么小。请使用你所用的语言相应的库或者框架来编写。
  • 过滤 那些有点像URL的输入,防止 SSRF 攻击
  • 输出显示给用户之前需要过滤,防止XSS攻击.
操作
  • 如果你的业务很小或者你缺乏经验,可以评估一下使用AWS或者一个PaaS平台来运行你的代码
  • 在云上使用正规的脚本创建虚拟结
  • 检查所有机器没有必要开放的端口
  • 检查数据库是否没有密码或者使用默认密码,特别是MongoDB和Redis
  • 使用SSH登录你的机器,不要使用密码,而是使用 SSH key 验证来登录
  • 及时更新系统,防止出现0day漏洞,比如Heartbleed、Shellshock等
  • 修改服务器配置,HTTPS使用TLS1.2,禁用其他的模式。(值得这么做)
  • 不要在线上开启DEBUG模式,有些框架,DEBUG模式会开启很多权限或者后门,或者暴露一些敏感数据到错误栈信息里面
  • 对坏人和DDOS攻击要有所准备,选择那些提供DDOS清洗的主机服务
  • 监控你的系统,同时写到日志里面 (例如使用 New Relic ).
  • 如果是2B的业务,坚持顺从需求。如果使用AWS S3,可以考虑使用 数据加密 功能. 如果使用AWS EC2,考虑使用磁盘加密功能(现在系统启动盘也能加密了)
关于人
  • 开一个邮件组和搜集页面,方便安全研究人员提交漏洞
  • 信任你所创造的东西,限制用户数据库的访问
  • 对报告bug、漏洞的人有礼貌
  • 将你的代码给那些有安全编码观念的同伴review (More eyes)
  • 出现被黑或者数据泄露是,检查数据访问前的日志,让相关的人改密码。你可能需要外部的机构来帮助审计
  • 使用 Netflix Scumblr 及时了解你的组织(公司)在社交网络或者搜索引擎上的一些讨论信息,比如黑客攻击、漏洞等等。

 

Hackerone 公开漏洞统计

目前为止,Hackerone平台已经发现1731个公开的漏洞,主要来自 Twitter、Uber、Dropbox、Github 等公司。其中8个已经删除,9个来自互联网或者特定的语言,剩下的1714个中,有1359个我们可以通过代码或者人工的方式进行分类。

按照错误的类型划分

类型 数量 占比
用户输入过滤 481 27.8
其他代码问题 549 31.7
配置问题 325 18.8
无法归类+信息+垃圾 376 21.7

按照发生的频率排序

其中1/3的问题与XSS、不安全的数据引用 (数据泄露) 或者忘记设置 CSRF token有关,这个 页面 列举的这些问题非常有趣,值得一读.

类型 数量 占比
XSS 375 21.87
非安全引用 + 数据泄露 104 6.06
CSRF Token 99 5.77
开放重定向 59 3.44
信息/源代码泄露 57 3.32
DNS 配置错误 + Apache/Nginx + 子域名接管 + Open AWS_S3 44 2.56
不正确的session管理/固定 39 2.27
TLS/SSL/POODLE/Heartbleed 39 2.27
HTML/JS/XXE/内容注入 37 2.15
HTTP 头信息问题 34 1.98
空指针 + 段错误 + 在free()之后使用内存 33 1.92
DMARC/DKIM/邮件SPF设置 31 1.8
SQL 注入 28 1.63
点击劫持 27 1.57
不正确的cookie使用 (secure/httpOnly/暴露) 25 1.45
路径暴露 25 1.45
开放权限 24 1.4
暴力破解 24 1.4
内容欺诈 20 1.16
缓冲区溢出 20 1.16
拒绝服务 19 1.1
服务端请求伪造 18 1.05
Adobe Flash 漏洞 18 1.05
用户/信息 枚举 17 0.99
远程代码执行 15 0.87
密码重置 token 过期/尝试/其他 13 0.75
整型溢出 11 0.64
版本泄露 11 0.64
CSV 注入 10 0.58
权限放大 9 0.52
OAuth 状态/泄露和其他问题 9 0.52
密码策略 7 0.4
CRLF 7 0.4
python语言 6 0.35
单向攻击 6 0.35
文件上传类型/大小/存储位置 过滤 6 0.35
Captcha 5 0.29
远程/本地 文件包含 4 0.23
目录列表 4 0.23
路径遍历 4 0.23
远程文件上传 4 0.23
(WEB表单)开启自动填充 4 0.23
通过引用泄露 3 0.17
Pixel Flood Attack 3 0.17
输入控制字符 2 0.11

一些唯一的漏洞类型

  1. 竞态条件漏洞
  2. Pixel Flood Attack
  3. IDN Homograph Attack
  4. 输入控制字符后输入一些有趣的东西