自动更新:这安全吗?

14

Dot Net自动更新

我觉得.NET缺乏一个简单安全的自动更新库,所以我实现了一些东西并放在这里。在任何人考虑使用该库之前,我都很希望更新过程能够获得同行的审查。

以下是步骤:

  • 客户端软件填充公钥和轮询的URI。
  • 客户端轮询URI以获取清单文件。
  • 下载清单并使用(单独的".signature")签名来检查清单是否有效。
  • 从清单中解析出待处理的更新列表(以显示给用户)。
  • 下载安装程序文件并再次使用相应的".signature"文件进行验证。(下载的文件将受到ACLs的保护)
  • 运行安装程序。

减轻的威胁:

  • 清单签名应防止任何恶意下载(“地毯式轰炸”)
  • 安装程序签名应防止任何中间人攻击发送恶意安装程序
  • 使用ACL保护下载的安装程序应防止任何本地提权攻击。

未减轻的威胁:

  • 攻击者始终报告“没有可用更新”的MITM攻击。(可能使客户端保持在易受攻击的版本)

参考文献:


我错过了什么?



有兴趣问一下,对于这种情况,ClickOnce 有什么问题吗? - Robert MacLean
@Robert ClickOnce只能以有限的系统访问权限进行安装。例如,无法访问系统的扫描仪。我可能错了,但我认为ClickOnce应用程序始终需要在启动之前检查更新。 - Luke Quinane
@Luke:你可以通过ClickOnce选择所需的行为(例如,有一个“应用程序可离线使用”复选框可以勾选)。 - Brann
@Robert:ClickOnce不支持所有代理方案,有时会出现不稳定的“损坏存储”消息,同时也不支持加密等功能...这只是其中一些ClickOnce的缺点。 - Brann
1
仅使用SSL怎么样?它可以解决整个问题,而且没有任何复杂性。现在它的成本大约是50美元。 - dr. evil
7个回答

8
丹·坎明斯基(Dan Kaminsky)提出了一套良好的更新程序指南:
要成功,您的更新包必须是:
- 签名的。 - 由您签名。 - 使用正确的 EKU(扩展密钥用途)由您签名。 - 来自未吊销的签名。 - 是相同的产品。 - 是一个新版本。
从您在这个问题中的描述来看,似乎您已经满足了前三个条件。

我在想,第5点和第6点应该由库的用户来执行。你对此有什么想法吗? - Luke Quinane
库的用户应该能够传递应用程序的名称和当前版本,库可以从安装程序中读取元数据以检查最后两个点。 - Jesse Weigert

4
在企业环境中构建自己的部署工具时,以下是我需要解决的一些用例:
  • 数字签名支持

  • 所有代理的支持。某些大公司有复杂的代理配置(例如通过代理配置脚本)。您应该支持所有这些。

  • 加密支持。您的客户可能希望在Web服务器上提供已部署的二进制文件,并且他们不想管理某种身份验证或访问控制;但他们也不希望未经授权的用户下载二进制文件。一个简单的解决方案是加密二进制文件并让您的工具进行部署。

  • 可插拔附加步骤的支持。企业客户通常不太喜欢使用自动部署工具。他们将希望更多的控制权。通常,允许他们运行可定制的步骤(如反病毒检查等)会有所帮助。

  • 根据消费者标识支持不同版本的软件。这在企业环境中经常需要,当您希望非常快速地更新特定消费者的副本(以修复错误或添加额外功能)而不运行所有Q&A过程时(在这种情况下,您希望将更新限制为该特定消费者)

  • 支持有限权限的情况。除了您的用户可能缺乏对其计算机的管理员访问权限外,大公司通常使用特定工具来限制您可以执行的操作。准备在用户拥有的文件夹(甚至是临时文件夹)中部署,而不是经典的“程序文件”。

  • 您的工具应由强认证机构签名。

关于您提到的MITM攻击,通过使用公共加密技术(如未知人士所述),很容易解决。


1
我是一个坐在这些复杂代理后面的人,它可能会造成严重破坏。+1 代理。 - Robert MacLean
代理支持是一个有用的功能,但它并不是更新过程中真正的安全问题。 - Luke Quinane
@Luke:这取决于你的立场。我可以向你保证,出于安全原因,许多安全部门将拒绝与互联网直接连接。 - Brann

3

你可以尝试通过在“无版本更新”响应中包含时间戳(并签名)来防止中间人攻击。然后,如果一个月过去了(或任何你的策略),没有版本更改和时间戳更新,那么你会拒绝运行软件或弹出警告对话框,通知用户可能存在中间人攻击。

这并不能解决如果服务器崩溃时该怎么办的问题 - 大概您会将其视为没有时间戳更改的情况。


+1,好主意。另外,你应该注册账户,这样就不会失去你的声望了。 - John Gietzen
我没有注册吗?除了用我的 OpenID 登录外,还需要做其他事情吗? - Vitali

1

不是要在这里充当骗子,但你正在尝试解决一个已经解决的问题。使用SSL会是一个更好的选择。这将解决您问题中列出的所有问题。

我知道这个系统对于不能负担SSL证书的人可能很有用,但任何能够获得证书的人都应该获得一个来解决这个问题。

别忘了,“复杂性是安全的敌人”。


0

这篇文章中有一些非常好的评论和解决方案。但我非常同意恶棍博士的观点。您应该使用SSL连接来进行更新,并且证书必须保存(建立在)客户端中。这样,您可以确保客户端不会接受伪造的证书。我认为这将有效地使客户端免受中间人攻击。

注意:如果客户端可以接受未经授权的证书,那么中间人攻击可能会成功,因此不要向客户端提供此选项。

编辑:我认为在这种情况下SSL证书可以自签名。


我想知道在这种情况下是否可能发生MiTM攻击。据我所知,不可能。 - Sadi

0

另外,还要在下载的文件中添加MD5校验和,否则看起来很好 :) - 下面是公正的评论。

补充:

我唯一能看到的额外事情就是深入研究诸如混淆代码、归档安装文件并锁定存档,然后一旦下载,解锁它。不过我认为你目前所做的应该已经足够了。

只有当应用程序非常安全复杂时才需要更多。现在,您可以防止DLL篡改和源头证明,这对于自动更新程序来说应该已经足够了。


代码使用RSA/SHA1计算文件签名,所以我认为这方面已经覆盖了。 - Luke Quinane
2
SHA1已经过时,请勿使用。请使用SHA256。 - Noon Silk
谢谢@silky,我会将它切换到SHA256。 - Luke Quinane

0

所以我不太清楚一个问题;下载器通过签名验证清单是否符合预期,那么它对安装的实际补丁是否也进行同样的验证呢?


是的,它也会在下载后验证安装文件。 - Luke Quinane
好的。好的,那么有没有可能以某种方式更新它验证的公钥?(和URL)? - Noon Silk
这取决于应用程序。我计划使用的方式是仅通过安装新版本(即在应用程序中硬编码)来更新密钥/URL。但是,您可以使用加密API存储密钥以便进行更改。 - Luke Quinane
我想我在建议的是,你可能需要一个安全更新的设施,以防万一,无论出于什么原因,你决定更改你的私钥,或者你预见到一个域名将要关闭/更改。 - Noon Silk

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接