MIT 6.858 计算机系统安全讲义 2014 秋季(二)(3)https://developer.aliyun.com/article/1484152
回顾一下"TCP/IP 协议套件中的安全问题"
- 易受攻击:触发某些实现中的错误。
- 作者对这类问题不太感兴趣。
- 相反,希望看看**“协议级问题”**。
- 什么是协议级问题?
- 设计固有的问题。
- 正确的实现会有这个问题。
- 为什么这么重要?
- 可以修复实现中的错误。
- 要修复协议级错误,可能需要更改协议!
- 可能与现有系统不兼容。
- (正如我们将看到的,有时可能提出兼容的修复方法。)
TCP 序列号攻击
- 标准握手(第 2 页右侧的图):
C: 源=C, 目的=S, SYN(SNc)
S: 源=S, 目的=C, SYN(SNs), ACK(SNc)
C: 源=C, 目的=S, ACK(SNs)
C: 源=C, 目的=S, 数据(SNc), ACK(SNs)
- 对手如何知道数据来自客户端?
- 只有客户端应该能够接收第二条消息。
- 因此,只有客户端应该知道序列号。
- 第三条消息将被拒绝,除非具有正确的 SNs 值。
- 假设对手 A 想要模拟从 C 到 S 的连接。(假设 A 知道 C 的 IP 地址–在实践中通常不是大问题。)
A: 源=C, 目的=S, SYN(SNc)
S: 源=S, 目的=C, SYN(SNs), ACK(SNc)
– 但这将发送到 C,而不是 AA: 源=C, 目的=S, ACK(SNs)
– 但如何猜测 SNs?A: 源=C, 目的=S, 数据(SNc)
- 对手从哪里获取 SNs?
- TCP 规范建议了一种选择它们的特定方式。
- 特别是,以大约恒定的速率增加:每秒约 250,000 个。
- 为什么这么具体?
- 与重用连接(源/目的端口号)的微妙交互。
- 希望避免旧数据包(来自过去的连接)干扰新连接。
- 参考:RFC 1185 附录
- 如果对手知道最近的序列号,就可以猜测下一个序列号。
- 实现实际上会每秒增加 ISN,使其易于猜测。
- S 发送给 C 的真实数据包发生了什么(第二个数据包)?
- C 会假设数据包来自旧连接,发送
RST
作为响应。 - 即使发送了
RST
,对手也可以在RST
到达之前尝试竞争。 - 幸运的是,还有另一个奇怪的错误;稍后会讨论。
- 但是为什么序列号攻击会变成安全问题?
1. 伪造依赖 IP 地址的应用程序的连接
- 例如,伯克利远程访问工具:rlogin、rsh、rcp。
- 如果连接来自“受信任”系统,则允许无密码登录。
- 要求连接来自受信任的源端口(512-1023)。
- 为什么有这个要求?
- 受信任的 rlogin/rsh/rcp 程序发送客户端的用户名。
- 如果用户名与服务器上的帐户相同,则无需密码。
- 例如:“rsh athena.dialup.mit.edu ls”。
- 对 TCP 层提供的内容做出了错误的假设。
- 假设来自 IP 地址的 TCP 连接意味着它确实来自该主机。
- 如果对手可以猜测 SN,则可以模拟来自受信任主机的连接。
- 使用 rsh 发出任何命令。
- 可以更改用户的.rhosts 文件以允许从攻击者主机登录。
- 然后直接连接,而无需模拟连接。
- 基于主机的身份验证似乎是一个糟糕的计划。
- 特别是依赖于主机上的“受信任”与“不受信任”端口。
- 今天仍在使用:例如,用于传出邮件的 SMTP。
- 实际上,rlogin 身份验证甚至更糟:他们通过主机名进行身份验证。
- 主机名从哪里来?反向 DNS 查找。
- 例如,18.26.4.9:查找 9.4.26.18.in-addr.arpa 的 PTR 记录。
- 该域的所有者可以将 PTR 记录设置为任何主机名!
- (可以稍微改进:检查主机是否解析为相同的地址。)
- 类似的问题出现在日志文件中:记录解析(不受信任)主机名。
2. 拒绝服务攻击:连接重置
- 一旦我们知道 SNc,就可以发送一个 RST 数据包。
- 更糟糕的是:服务器将接受任何在窗口内的 SNc 值的 RST 数据包。
- 具有大窗口(~32K=2¹⁵)时,只需要 2³²/2¹⁵ = 2¹⁷ 次猜测。
连接重置有多糟糕?
- 此类攻击的一个目标是 BGP 路由器之间的 TCP 连接。
- 导致路由器假定链路故障,可能会影响几分钟的流量。
- 解决方案:
- TTL 黑客(255):通过在 TCP 数据包中设置
TTL = 1
,确保 BGP 节点只与直接邻居通信 - MD5 头部身份验证(非常专门用于路由器之间的链接)。
3. 劫持现有连接
- 类似地,还可以向现有连接中注入数据。
- 对手只需要知道当前的 SNc。
如何缓解这个问题?
- 基线:不要依赖 IP 地址进行身份验证。
- 在更高级别使用加密/身份验证。
- 下一讲:Kerberos。
- 但是,我们仍然希望为 TCP 解决当前的情况。
- ISP 可以过滤其客户发送的数据包。
- 今天经常为小客户执行,但不一致。
- 对于具有复杂网络、多重主机等的客户来说并不直接。
如何修补 TCP?
- 不能以完全随机的方式选择 ISN,而不违反 TCP 规范。
- 可能会破坏连接(端口)重用的保证。
- ISN 是 32 位,意味着在约 2¹⁶ = 65,000 个连接后,您可能会发生冲突并重用与旧连接匹配的 ISN。
- 旧连接的数据包可能被解释为新连接的一部分
- 因此,最好 ISNs 递增 以环绕方式递增,以使碰撞变得不太可能。
- 随机增量?
- 应保留增量速率(~250k/秒)。
- 没有大量的随机性(比如,每次增加低 8 位)。
- 旁注:必须小心我们如何生成随机数!
- 常见 PRNG:线性同余生成器:
R_k = A*R_{k-1}+B mod N
。 - 不安全:给定一个伪随机值,可以猜测下一个!
- 有许多更好的密码学安全 PRNG 可用。
- 理想情况下,使用内核内置的 PRNG(/dev/random,/dev/urandom)
- 参考:http://en.wikipedia.org/wiki/Fortuna_(PRNG),或任何流密码,如 http://en.wikipedia.org/wiki/RC4
- 然而,不同的源/目的地对的 SN 值永远不会相互作用!
- 因此,可以为每个源/目的地对选择使用随机偏移量来选择 ISN。
- 不错的技巧:
ISN = ISN_oldstyle + F(srcip, srcport, dstip, dstport, secret)
F
是某个伪随机函数;大致上,可以认为是 SHA1。- 不需要额外的状态来跟踪每个连接的 ISNs。
序列号攻击仍然相关吗?
- 大多数操作系统实现了上述每个连接 ISN 的解决方法。
- 参考:Linux
secure_tcp_sequence_number
innet/core/secure_seq.c
- 但其他协议遭受几乎相同的问题–例如,DNS。
- DNS 在 UDP 上运行,没有序列号,只有端口,目的端口固定(53)。
- 如果对手知道客户端正在进行查询,可以伪造响应。
- 只需要猜测 src 端口,通常是可预测的。
- 问题在 2008 年变得流行,尽管在此之前 djb 已经很好地理解了。
- 解决方案:仔细利用所有可能的随机性!
- DNS 查询包含 16 位查询 ID,并且可以随机化约 16 位 src 端口。
- 解决方案:部署 DNSSEC(签名的 DNS 记录,包括缺失记录)。
- 一个问题:密钥分发(谁被允许为每个域签名?)
- 另一个问题:名称枚举(以签署“没有这样的名称”响应)。
- 部分通过 NSEC3 缓解:http://tools.ietf.org/html/rfc5155
- 采用缓慢,没有太多升级的动力,非微不足道的成本。
- 成本包括性能和管理(密钥/证书管理)。
SYN 洪水攻击
- 请注意,服务器在接收到 SYN 数据包时必须存储一些状态。
- 它需要存储发送给该客户端的
SN_s
序列号 - 被称为半开放连接:回复了 SYN-ACK,等待 ACK。
- 如果它从许多来源接收到 SYN 消息会怎样?
- 许多实现尝试为所有半开放连接保留状态。
- 但最终会耗尽内存,必须拒绝连接!
- 恼人的问题:我们甚至不知道我们为谁保留状态!
- 对手可能有一个单一主机,并从许多 src IP 生成 SYN。
- 拒绝服务攻击:客户端+服务器资源之间存在巨大的不对称性。
- 客户端伪造一个单个数据包(少于 1 毫秒)。
- 服务器会浪费内存直到连接超时(几分钟)。
防御 SYN 洪水攻击:SYN cookies。
- 思路: 使服务器无状态,直到收到第三个数据包(ACK)。
- 这为什么很棘手?
- 需要确保对手无法从任何源地址捏造一个连接。
- 以前,这是通过存储 ISNs 并期望在 ACK 中收到来实现的。
- 使用一点密码学来实现类似的目标。
- 将服务器端状态编码到序列号中。
- ISNs =
MAC_k(源/目的地址+端口,时间戳)|| 时间戳
- 时间戳是粗粒度的(例如,分钟)。
- 服务器存储秘钥
k
,不与其他人共享。
- 当发送 SYN-ACK 响应时,服务器计算如上述的序列号。
- 服务器可以通过验证 ACK 的序列上的哈希(MAC)来验证状态是否完整。
- 不太理想:需要考虑时间戳内的重放攻击。
- 另一个问题:如果第三个数据包丢失,没有人会重传。
- 只有在服务器先发言的协议中才会有问题。
- 因为服务器不再保留连接状态,所以它不知道有一个悬挂连接,所以在等待客户端的 ACK 太久后,它永远不会重新传输其 SYN 消息给客户端。
- 同样,客户端不会知道其 ACK 数据包丢失了(它从未被 ACK 回来,而且由于客户端正在等待服务器发送第一个消息(假设),客户端也不会发送任何其他数据)。
- 在 DoS 攻击的情况下可能不是一个大问题。
另一个 DoS 攻击向量:带宽放大。
- 向网络的广播地址发送 ICMP 回显请求(ping)数据包。
- 例如,18.26.7.255。
- 以前,你会从网络上的所有机器收到 ICMP 回显回复。
- 如果你伪造一个来自受害者地址的数据包怎么办?受害者会收到所有回复。
- 在一个快速网络上找到一个有 100 台机器的子网:100 倍放大!
- 我们能修复这个问题吗?
- 路由器现在阻止“定向广播”(发送到广播地址的数据包)。
- 现代变种:DNS 放大。
- DNS 也是一个请求-响应服务。
- 服务器可能会用一个小查询发送回一个大响应。
- 使用 DNSSEC,响应包含大量签名,所以它们甚至更大!
- 由于 DNS 运行在 UDP 上,源地址完全未经验证。
- 我们能修复 DNS 攻击吗?
- 实际上相当困难!根域名服务器必须回答任何人的查询。
- 如果我们有机会从头开始重新设计 DNS 会怎样?
- 一个可能的计划:查询必须和响应一样大(需要填充)。
- 一般技术:迫使客户端至少花费同样多的工作。
TCP 拥塞控制。
- 接收方可以通过 ACK 未接收的段来促使发送方加速。
- 或者发送更多的 ACK(例如,每个字节发送一个 ACK 而不是每个数据包)。
路由协议:对参与者过于信任。
- ARP:在单个以太网网络内。
- 要发送 IP 数据包,需要路由器/下一跳的以太网 MAC 地址。
- 地址解析协议(ARP):广播一个请求目标 MAC 地址的请求。
- 任何人都可以监听广播,发送回复;没有认证。
- 对手可以冒充路由器,拦截数据包,甚至在交换网络上。
- 潜在解决方案:让交换机负责 ARP。
- 没有广泛部署:需要仔细管理 MAC/IP 地址。
- DHCP:同样,在一个以太网网络中。
- 客户端通过发送广播请求来请求 IP 地址。
- 服务器响应,没有认证(一些规范存在但并不广泛使用)。
- 如果你刚刚插入一个网络,可能不知道会发生什么。
- 很多字段:IP 地址,路由器地址,DNS 服务器,DNS 域列表,…
- 对手可以冒充网络上的新客户端的 DHCP 服务器。
- 可以选择他们的 DNS 服务器,DNS 域,路由器等。
- 同样,对服务器的 DoS 攻击:请求大量租约,来自许多 MAC 地址。
- 解决方案:让交换机负责 DHCP(将请求转发给真实服务器)。
- 没有广泛部署:需要仔细的交换机配置。
- 在无线网络上更加复杂。
- BGP:全球范围内(类似于论文中描述的 RIP 攻击)。
- 任何 BGP 参与者路由器都可以宣布到一个前缀的路由。
- 如果对手有一个路由器怎么办?可以宣布任何前缀或路由。
- 这个问题还有意义吗?
- 垃圾邮件发送者经常利用这一点:宣布一个未使用的地址,并发送垃圾邮件。
- 绕过 IP 级别的垃圾邮件发送者黑名单:选择几乎任何 IP!
- 如何解决?
- SBGP:对路由公告进行加密签名。
- 必须知道谁被允许宣布每个特定的 IP 前缀。
- 需要有人为每个 IP 前缀分发密钥/证书。
- 引导问题很棘手;也会有一些性能开销。
- 有些进展,但仍未广泛部署。
还有许多其他问题。
- 像重定向这样的 ICMP 消息:没有认证,基本上现在不再使用。
- 暴露太多信息(netstat,SNMP,finger):大部分已修复。identd(“认证服务”):设计不佳,没有真正的认证。
- 电子邮件:真正的问题,但目前没有实际解决方案。
- 认证与授权。
- 例如,PGP 无法解决垃圾邮件问题。
- 协议中的密码:仅支持密码并不是很好。
- 我们将在几周后讨论替代方案。
- FTP 数据传输协议。
- 服务器连接回客户端以向客户端发送文件。
- 客户端告诉服务器要使用的 IP 地址和端口号。
- 可以用来从服务器的 IP 进行端口扫描。
- 可以用来从服务器的 IP 发送任何流量(嵌入文件中)。
- 例如,回到 IP 认证问题:rlogin,垃圾邮件等。
对手如何知道你正在运行什么软件/协议?
- 探测:
- 检查系统是否在一个众所周知的端口上监听。
- 协议/系统通常会发送初始的横幅消息。
- nmap 可以通过测量各种实现特定的细节来猜测操作系统。
- 使用 DNS 查找 IP 地址的主机名;可能会给出一些提示。
- 猜测:假设系统存在漏洞,尝试利用漏洞。
对手如何知道要攻击的系统的 IP 地址?
- 使用 traceroute 查找沿途的路由器,用于 BGP 攻击。
- 也可以扫描整个互联网:只有 2³² 个地址。
- 1 Gbps(100 MB/s)的网络链路,64 字节最小数据包。
- 每秒约 1.5 百万个数据包。
2³² = 40 亿
个数据包在约 2500 秒内,或 45 分钟内。- zmap:这个的实现
为什么 TCP/IP 层的安全性如此不足?
- 从历史上看,设计者并没有太担心安全性。
- 即使 Bellovin 也说:“1989 年的互联网是一个更友好的地方”。
- 最初的互联网有一小部分相对可信赖的用户。
- 设计要求随时间改变。
- 端到端论点在实践中发挥作用。
- 无论如何必须在应用层提供安全性。
- 在传输层上的事情足够“好”,可以让应用程序正常工作。
- 一些修复确实被添加,但仅针对最严重的问题/更容易的解决方案。
如何提高安全性?
- 对 TCP 实现的协议兼容修复。
- 防火墙。
- 部分修复,但被广泛使用。
- 问题:对手可能在防火墙网络内。
- 问题:很难确定数据包是否“恶意”。
- 问题:即使对于存在的字段(源/目的地),也很难进行身份验证。
- TCP/IP 的设计与防火墙过滤技术不太匹配。
- 例如,IP 数据包分段:TCP 端口在一个数据包中,有效载荷在另一个数据包中。
- 在 TCP/IP 之上实现安全性:SSL/TLS,Kerberos,SSH 等。
- 注意:这篇论文在加密与认证方面并不清晰。
- 下一讲将更详细地讨论 Kerberos。
- 使用密码学(加密、签名、MAC 等)。
- 这是一个相当困难的问题:协议设计,密钥分发,信任等。
- 有些安全性很难在顶层提供:DoS 抵抗,路由。
- 部署替代协议:SBGP,DNSSEC。
Kerberos
**注意:**这些讲座笔记略有修改自 2014 年 6.858 课程网站上发布的笔记。
Kerberos 设置
- 分布式架构,从单一的分时系统演变而来。
- 许多提供服务的服务器:远程登录、邮件、打印、文件服务器。
- 许多工作站,一些是公共的,一些是私有的。
- 每个用户登录到自己的工作站,拥有根访问权限。
- 对手可能也有自己的工作站。
- 当时的替代方案:rlogin、rsh。
- 目标:允许用户通过向服务器进行身份验证来访问服务。
- 其他用户信息通过 Hesiod、LDAP 或其他目录分发。
- 广泛使用:Microsoft Active Directory 使用 Kerberos(v5)协议。
信任模型是什么?
- 所有用户、客户端、服务器都信任 Kerberos 服务器。
- 其他机器之间没有先验信任。
- 网络是不受信任的。
- 用户信任本地机器。
Kerberos 架构
- 中央 Kerberos 服务器,被所有各方信任(或至少在 MIT 被所有方信任)。
- 用户、服务器之间有一个他们与 Kerberos 共享的私钥。
- Kerberos 服务器跟踪每个人的私钥。
- Kerberos 使用密钥实现客户端、服务器之间的相互身份验证。
- 术语:用户、客户端、服务器。
- 客户端和服务器知道彼此的名称。
- 客户端确信自己正在与服务器通信,反之亦然。
- Kerberos 不提供授权(用户能否访问某些资源)。
- 应用程序需要决定这一点。
为什么我们需要这个可信的 Kerberos 服务器?
- 用户不需要在每台服务器上设置帐户、密码等。
总体架构图
+-----------------------+ c, tgs | | [ User: Kc ] <--------> [ Kerberos ] | ^ \ | Database: | | \ | c: Kc | V \ s | s: Ks | [ Server: Ks ] \--------> [ TGS ] | | KDC | +-----------------------+
Kerberos 构造
从论文中得到的基本 Kerberos 构造:
- 票证,
T_{c,s} = { s, c, addr, timestamp, life, K_{c,s} }
- 通常使用
K_s
加密
- 验证器,
A_c = { c, addr, timestamp }
- 通常使用
K_{c,s}
加密
Kerberos 协议机制:
- 对 Kerberos 数据库有两个接口:“Kerberos”和“TGS”协议。
- 相当相似;少许差异:
- 在 Kerberos 协议中,可以指定任何
c
、s
;客户端必须知道K_c
。 - 在 TGS 协议中,客户端的名称是隐式的(来自票证)。
- 客户端只需知道
K_{c,tgs}
来解密响应(而不是K_c
)。
- 客户端机器最初从哪里获取
K_c
?
- 对于用户,使用密码派生,实际上是使用哈希函数。
- 为什么我们需要这两个协议?为什么不只使用“Kerberos”协议?
- 客户端机器在获得 TGS 票证后可以忘记用户密码。
- 我们可以只存储
K_c
并忘记用户密码吗?等效于密码。
命名
- Kerberos 的关键之处:密钥与主体名称之间的映射。
- 每个主体名称由
(名称、实例、领域)
组成
- 通常写作
名称.实例@领域
- 哪些实体有主体?
- 用户:名称是用户名,实例用于特殊权限(按照惯例)。
- 服务器:名称是服务名称,实例是服务器的主机名。
- TGS:名称是’krbtgt’,实例是领域名称。
- 这些名称在哪里使用/名称在哪里重要?
- 用户记住他们的用户名。
- 服务器根据主体名称执行访问控制。
- 客户端选择他们期望与之交流的主体。
- 类似于浏览器期望 HTTPS 的特定证书名称
- 何时可以重复使用名称?
- 对于用户名:确保没有 ACL 包含该名称,很困难。
- 对于服务器(假设不在任何 ACL 上):确保用户忘记服务器名称。
- 必须更改密钥,以确保旧票据对新服务器无效。
获取初始票据:“Kerberos” 协议
- 客户端发送一对主体名称
(c, s)
,其中s
通常是tgs
。 - 服务器回复
{ K_{c,s}, { T_{c,s} }_{K_s} }_{K_c}
- Kerberos 服务器如何验证客户端?
- 不需要 – 愿意回应任何请求。
- 客户端如何验证 Kerberos 服务器?
- 解密响应并检查票据是否有效。
- 只有 Kerberos 服务器会知道
K_c
。
- 这种方式与将密码发送到服务器相比有何优劣之处?
- 密码不会通过网络发送,但更容易被暴力破解。
- 为什么从 Kerberos/TGS 服务器的响应中两次包含密钥?
- 响应中的
K_{c,s}
给予客户端访问这个共享密钥的权限。 - 票据中的
K_{c,s}
应该让服务器确信密钥是合法的。
一般弱点: Kerberos 4 假设加密提供消息完整性。
- 有一些攻击可以让对手篡改密文。
- 没有明确的 MAC 意味着没有明确定义的方法来检测篡改。
- 一次性解决方案:kprop 协议包括校验和,难以匹配。
- 弱点使得对手相对容易“伪造”票据。
一般弱点: 对手可以发动离线猜测密码攻击。
- 典型密码的熵不高。
- 任何人都可以向 KDC 请求使用用户密码加密的票据。
- 然后尝试离线暴力破解用户密码:易于并行化。
- 更好的设计:要求客户端与服务器互动以进行每次登录尝试。
一般弱点: DES 硬编码到设计中,数据包格式。
- 当 DES 变得太弱时,难以切换到另一个加密系统。
- DES 密钥空间太小:密钥仅为 56 位,2⁵⁶ 并不算大。
- 现在破解 DES 很便宜(20–20–200 通过 https://www.cloudcracker.com/)。
- 对手如何利用这个弱点破解 Kerberos?
向服务器进行身份验证:“TGS” 协议
- 客户端发送
( s, {T_{c,tgs}}_{K_tgs}, {A_c}_{K_{c,tgs}} )
- 服务器回复
{ K_{c,s}, { T_{c,s} }_{K_s} }_{K_{c,tgs}}
- 服务器如何根据票据对客户端进行身份验证?
- 使用服务器的密钥解密票据。
- 使用
K_{c,s}
解密验证器。 - 只有 Kerberos 服务器可以生成票据(知道
K_s
)。 - 只有客户端可以生成验证器(知道
K_{c,s}
)。
- 为什么票据中包含
c
?s
?addr
?life
?
- 服务器可以从票据中提取客户端的主体名称。
- Addr 试图防止被盗票据在另一台机器上被使用。
- 生命周期同样试图限制被盗票据的损害。
- 网络协议如何使用 Kerberos?
- 使用
K_{c,s}
加密/认证所有消息。 - 邮件服务器命令、发送到打印机的文档、shell I/O 等。
- 例如,在邮件服务器协议中的“DELETE 5”。
- 谁生成认证器?
- 对于每个新连接,客户端。
- 为什么客户端需要发送认证器,除了票据之外?
- 向服务器证明对手没有重放旧消息。
- 服务器必须在内存中保留最近的几个认证器,以检测重放。
- Kerberos 如何使用时间?如果时钟错误会发生什么?
- 防止被盗票据永久使用。
- 限制重放缓存的大小。
- 如果时钟错误,对手可以使用旧票据或重放消息。
- 客户端如何认证服务器?为什么这很重要?
- 连接到文件服务器:想知道您获取的是合法文件。
- 解决方案:服务器在接收到客户端的票据和认证器后可以发送
{ timestamp + 1 }_{K_{c,s}}
。
**一般弱点:**相同的密钥K_{c,s}
用于许多事情
- 对手可以用
K_{c,s}
替换任何消息为其他消息。 - 例如:跨多个会话的消息。
- 认证器不证明
K_{c,s}
是新鲜的! - 对手可以将新的认证器与旧消息拼接在一起。
- Kerberos v5 每次都使用新的会话密钥,在认证器中发送。
- 例如:不同方向的消息
- Kerberos v4 在数据包中包含了一个方向标志
(c->s 或 s->c)
- Kerberos v5 使用单独的密钥:
K_{c->s}, K_{s->c}
如果用户连接到错误的服务器(MITM /网络钓鱼攻击的类比)会发生什么?
- 如果服务器拦截数据包,了解用户连接到哪个服务。
- 如果用户意外输入 ssh malicious.server 会发生什么?
- 服务器了解用户的主体名称。
- 服务器没有获取用户的 TGS 票据或
K_c
。 - 无法冒充用户给其他人。
如果 KDC 宕机会发生什么?
- 无法登录。
- 无法获取新票据。
- 可以继续使用现有的票据。
认证到 Unix 系统。
- 访问本地文件、进程时不涉及 Kerberos 协议。
- 如果使用 Kerberos 登录,用户必须呈现合法的票据。
- 如果用户使用用户名/密码(本地或通过 SSH 使用密码)登录会发生什么?
- 用户知道自己提供的密码是否合法。
- 服务器毫无所知。
- 服务器可能受到攻击:
- 用户通过 SSH 连接,输入用户名和密码。
- 创建看起来合法的 Kerberos 响应,使用密码加密。
- 服务器无法判断此响应是否真正合法。
- 解决方案(如果服务器保持状态):服务器需要自己的主体、密钥。
- 首先获取用户的 TGS,使用用户的用户名和密码。
- 然后使用 TGS 获取服务器主体的票据。
- 如果用户伪造了 Kerberos 服务器,第二个票据将不匹配。
在应用程序中使用 Kerberos。
- 论文建议使用特殊函数封装消息,有 3 个安全级别。
- 对应用程序需要适度更改。
- 对于灵活性、性能很好。
- 不利于采用。
- 开发人员很难理解微妙的安全保证。
- 或许更好的抽象:安全通道(SSL/TLS)。
更改密码服务(管理界面)
- Kerberos 协议如何确保客户端知道密码?为什么?
- 票证中的特殊标志指示使用哪个接口获取它。
- 更改密码服务仅接受使用
K_c
获得的票证。 - 确保客户端知道旧密码,不仅仅是拥有票证。
- 客户端如何更改用户的密码?
- 连接到更改密码服务,将新密码发送到服务器。
复制
- 一个主服务器(支持密码更改),零个或多个从服务器。
- 所有服务器都可以发出票证,只有主服务器可以更改密钥。
- 为什么要这样分割?
- 只有一个主服务器确保一致性:不能有冲突的更改。
- 主服务器定期更新从服务器(在撰写本文时,大约每小时一次)。
- 更近期的实现具有增量传播:较低的延迟(但不是 0)。
- 这个有多可扩展?
- 对称加密(DES,AES)很快–在当前硬件上为 O(100MB / sec)。
- 票证很小,O(100 字节),因此可以支持每秒 1M 张票证。
- 通过添加从服务器轻松扩展。
- 潜在问题:密码更改需要一段时间才能传播。
- 对手在用户更改密码后仍然可以一段时间使用窃取的密码。
- 要了解如何正确进行复制,请参加 6.824。
Kerberos 数据库的安全性
- 主服务器和从服务器在这种设计中非常敏感。
- 受损的主/从服务器意味着所有密码/密钥都必须更改。
- 必须物理安全,Kerberos 服务器软件中没有错误,在服务器机器上的任何其他网络服务中也没有错误等。
- 我们能做得更好吗?SSL CA 基础设施略好一些,但并不多。
- 当我们谈论浏览器安全/HTTPS 时,将更详细地研究它。
- 大多数集中式身份验证系统都遭受这些问题。…并且全球唯一的自由形式名称需要一些受信任的映射机构。
为什么 Kerberos 没有使用公钥加密?
- 当时太慢了:VAX 系统,10MHz 时钟。
- 政府出口限制。
- 专利。
网络攻击。
- Kerberos 服务器上的离线密码猜测攻击。
- Kerberos v5 防止客户端请求任何主体的票证。
- 必须在请求中包含
{ timestamp }_{K_c},证明知道 K_c。
- 当时仍然容易受到网络嗅探器的密码猜测攻击。
- 有更好的替代方案:SRP,PAKE。
- 对手可以使用窃取的票证做什么?
- 对手可以使用窃取的
K_c
做什么? - 对手可以使用窃取的
K_s
做什么?
- 记住:在 Kerberos 中,两方共享每个密钥(并依赖于它)!
- 如果
K_c
被泄露后密码更改后会发生什么?
- 可以解密所有后续交换,从初始票证开始
- 甚至可以解密密码更改请求,获取新密码!
- 如果对手稍后弄清您的旧密码怎么办?
- 如果对手保存了旧数据包,可以解密所有内容。
- 可以类似地获取当前密码。
前向保密(避免密码更改问题)。
- 抽象问题:在两方之间建立共享秘密。
- Kerberos 方法:某人选择秘密,加密并发送。
- 弱点:如果加密密钥被窃取,可以稍后获取秘密。
- Diffie-Hellman 密钥交换协议:
- 两方选择自己的秘密部分。
- 互发消息。
- 消息不必保密,只需经过身份验证(无篡改)。
- 两方使用彼此的消息重建共享密钥。
- 对手无法通过观察网络消息重建密钥。
- Diffie-Hellman 的细节:
- 素数 p,生成器 g mod p。
- Alice 和 Bob 各自选择一个随机的、秘密的指数(a 和 b)。
- Alice 和 Bob 向彼此发送(g^a mod p)和(g^b mod p)。
- 每个参与方计算(g^(ab) mod p)=(gab mod p)=(gba mod p)。
- 使用(g^(ab) mod p)作为秘密密钥。
- 假设离散对数(从(g^a mod p)中恢复 a)很困难。
Kerberos 中的跨域。
- 领域之间共享密钥。
- Kerberos v4 仅支持成对的跨域(无过境)。
Kerberos 不能解决什么问题?
- 客户端、服务器或 KDC 机器可能会受到威胁。
- 访问控制或组(由服务实现)。
- 微软“扩展”了 Kerberos 以支持组。
- 实际上用户的组列表包含在票据中。
- 代理问题:Kerberos 中仍然没有很好的解决方案,但 ssh-agent 很好。
- 工作站安全性(可以木马登录,并且实际上确实发生过)。
- 基于智能卡的方法并没有起飞。
- 谷歌身份验证器使用的两步验证(基于时间的 OTP)。
- 共享桌面系统并不那么普遍:每个人都有自己的手机、笔记本电脑,…
后续步骤。
- Kerberos v5 修复了 v4 中的许多问题(一些被提及),被广泛使用(MS AD)。
- OpenID 是一个类似的协议,用于 Web 应用程序的身份验证。
- 通过 HTTP 请求传递类似的消息。