读程序员的制胜技笔记14_安全审查(下)

1. 拒绝服务

1.1. denial of service,DoS

1.1.1. 一系列让你没法正常提供网络服务的攻击手段的通用名称

1.2. 一个较为通用的方法就是使用验证码

1.2.1. 验证码简直是万维网祸根

1.2.2. 验证码的确有它的作用,但是弊大于利,它算另一种形式的DoS

1.2.2.1. 看不出来是什么?那我拒绝为你服务

1.3. 验证码的代替品

1.3.1. 编写高性能的代码,积极进行缓存,并在必要时使用节流

1.4. 代替节流的办法

1.4.1. 工作量证明(proof of work)

1.4.1.1. 工作量证明相当消耗客户端的运算资源,对那些性能较低的设备不友好,并且它还会影响设备电池的使用寿命

1.4.1.2. 有可能会严重降低用户体验,其后果甚至比验证码的还要恶劣

2. 缓存

2.1. 字典可能是网络框架中最常用的数据结构

2.1.1. HTTP请求和响应头、cookie和缓存条目都被保存在字典当中

2.1.2. 典的运算速度快得惊人,因为它们的复杂度为O(1)

2.1.3. 查询得到结果基本是瞬时的

2.2. 字典的隐患

2.2.1. 我们可能直接启用字典当作保存某个东西的缓存

2.2.2. 在.NET中甚至有ConcurrentDictionary,它是线程安全(thread-safe)的,使得它有作为手动缓存的潜力

2.2.3. 哈希碰撞攻击(hash collision attack)

2.2.4. 字典没有默认的限制机制,它们会无限制地增长

2.3. 为面向网络的组件开发的自定义字典,如SipHash,通常使用一种不同的哈希算法,它具有更好的分布特性,因此碰撞概率更小

2.3.1. 算法的平均运算速度可能比常规哈希算法略慢,但由于它们能抵抗哈希碰撞攻击,因此在最坏的情况下表现得更好

2.4. 请考虑利用现有的缓存基础设施,最好是框架提供的缓存

3. 存储机密信息

3.1. 机密信息(密码、私钥和API令牌)是通向你“领地”的钥匙

3.2. 分区是缓解安全威胁最好的措施之一

3.3. 理想的方法是将机密信息存储在专门为该目的而设计的独立存储中

3.4. 从长远来看,所有的源代码都被托管在GitHub上

3.5. 别收集你不需要的数据

3.5.1. 如果数据一开始就不存在,那么它就不会被泄露

3.5.2. 除了你的服务必须的数据之外,绝不收集其他数据

3.5.2.1. 存储需求更少,性能更强,数据管理工作更少,用户体验更好

3.6. 正确的密码哈希算法

3.6.1. 防止密码被泄露的最常见方法是使用哈希算法

3.6.2. 你存储的不再是密码本身,而是密码的加密安全哈希值

3.6.3. 对于进行密码哈希,首选的方法是只使用一种加密算法,将这一种算法进行多次迭代,来降低执行速度

3.6.4. 永远不要使用单次迭代的哈希算法

3.6.4.1. 即使它们在密码学上是安全的,如SHA2、SHA3

3.6.5. 永远不要使用MD5或SHA1

3.6.5.1. 因为它们早已被破解

3.6.6. 密码学上的安全属性只能确保算法具有特别低的碰撞概率,并不能确保它们能抵抗暴力攻击

3.6.6.1. 所有现代的抗暴力哈希算法要么以难度系数(difficulty coefficient)为参数,要么以迭代次数(number of iteration)为参数

3.6.7. 一个常见的专门用来减缓工作速度的哈希函数为PBKDF2

3.6.7.1. “password- based key derivation function two”(基于密码的密钥导出函数二)的缩写

3.6.8. 一些较新的哈希算法,如bcrypt、scrypt和Argon2,也能抵抗基于GPU或ASIC的攻击

3.6.9. 建议对你的密码哈希难度进行基准测试

3.6.9.1. 确保它不会在以后为难你,因为一旦方案开展,再去改变哈希算法是很困难的

3.6.10. 建议优先选择你使用的框架所支持的算法

3.6.10.1. 你应该选择经过最多测试的一种

3.6.10.2. 新的算法通常不会有像老的算法那样多的测试和验证次数

3.7. 安全地比较字符串

3.7.1. 不提前返回,而是保留结果,即使比较失败也继续进行比较

3.7.2. 我们所有的比较都需要一个恒定的时间,避免泄露用户的哈希值

3.8. 不要使用固定的“盐”

3.8.1. “盐”,是引入密码哈希算法中的附加值,使得加密值产生偏离

3.8.2. 它旨在解决相同哈希值这一问题

3.8.3. 你不希望攻击者只通过猜测一个密码的哈希值就能破解所有相同的密码

3.8.3.1. 即便用户的所有密码都是hunter2,但所有密码都会有不同的哈希值,增加了攻击者的破解难度

3.8.4. 你应该始终使用随机值作为盐,但不是普通的伪随机值,而是由CSPRNG(密码学上安全的伪随机值生成器)生成的值

3.8.5. 常规随机值是用简单和可预测的算法生成的

3.8.6. 它们的目标并不是创造真正的随机值,而仅仅是模仿生成随机值,让人觉得是随机值

3.9. UUID并不是随机的

3.9.1. 通用唯一标识符(universally unique identifie,UUID)或者全局唯一标识符(globally unique identifier,GUID),在微软世界里,被称为随机数字(random-looking number)

3.9.2. 虽然被设计为唯一的,可不一定是安全的

3.9.2.1. 因为不能保证它们是用加密安全的伪随机值生成器(CSPRNG)创建的

3.9.3. 始终使用CSPRNG来生成安全敏感的令牌

3.9.4. UUID可能不是完全随机的,但它们作为标识符肯定比简单地逐一递增的整数更安全

3.9.5. 新的UUID标准,即UUID v6、UUID v7和UUID v8仍然有随机性,但它们包含时间戳,能创造更均匀的索引散布

4. 如果一条捷径阻碍了你的进步,那么它就不是真正的捷径

posted @ 2023-11-16 06:45  躺柒  阅读(69)  评论(0编辑  收藏  举报