3

如何避免意外在我的 WiX / MSI 中分发敏感信息?

  • 我不小心将密码、机器名称或登录凭据与我的 MSI 文件一起分发。我如何最好地处理这个问题?
  • 部署后,我的应用程序错误地连接到我的 QA / UAT 系统而不是我的生产系统 - 因为我的设置的自定义操作代码中的调试构造错误。如何检测和避免这种情况?
  • 我一般如何避免分发此类信息?

这是一个问答式问题,采用最简单的方法来避免意外通过您的 MSI 传播敏感信息

4

1 回答 1

3

Super Condensed:安装 Orca,让其他人参与帮助并按顺序浏览原始表,然后是任何自定义操作代码。


所有这一切都是显而易见的——如果这发生在你身上并且你在野外有敏感信息:你所能做的就是撤回 MSI(希望从下载中——在光学媒体时代更糟),更改任何密码或者其他任何被揭露的东西——然后确保你不会再经历它。现在对于重要的部分,未来如何避免它。

除了以下有关敏感信息的信息外,还请记住,您要包含在设置中的某些文件可能无法合法再分发。典型示例是来自 Microsoft 的调试工具或来自第三方 SDK 工具包的调试工具。请仔细阅读文档并避免在您的自定义操作中使用此类“hacky 工具”。


简洁版本

更新:让我记下,在我忘记之前,您应该从所有设置文件中删除“下载文件阻止标志”(通常也是只读标志)。

下面建议的所有内容基本上是 1)使用 Orca 扫描您的最终 MSI,2)查看已安装的设置文件以及随您的 MSI 提供的任何模板安装脚本。此外,3)很好地审查您编译的自定义操作源#ifdef _DEBUG,并可能改进发布构建配置实践(例如,见下文)。4)通过检查您的 MSI 中的实际内容(提取它们)来查看您的脚本自定义操作。至关重要的是:5)从其他人那里获得一些帮助以进行所有手动测试 - 获得一些同谋:-)。严重地:设置与应用程序一样重要——要使您的解决方案成功,您有责任让 QA 人员和其他参与测试的人员参与测试——并告诉他们测试什么以及如何测试。

我会避免自己尝试自动进行此类检查。没有什么可以替代对数据的真实关注。也许社区解决方案将有助于长期。它可以成为验证套件的一部分吗?半自动的帮助可能会起作用,但全自动的魔法:算了吧。有太多的方法可以使用你必须使用的所有绳索来击中自己的脚。

敏感数据可能是错误的术语,也许“无效内容”更合适。问题可能是由于您的应用程序在启动时指向您的测试服务器而不是生产服务器。自定义操作可能会弹出意外的消息框(有时会显示敏感数据),并且除了暴露纯敏感数据之外,还会出现类似的发布错误。


QA - 错误任务

检查意外包含的敏感数据显然与您的包的一般 QA 相关。它应该与一般测试同时进行。QA 人员忙于应用程序测试,您真的必须推动这个部署测试,并制定测试计划。没什么花哨的,但是请测试所有安装模式(install, reinstall, repair, self-repair, upgrade, patching, uninstall, administrative install, resume / suspended install(设置重新启动问题),您还应该这样做- 如果您有设备和网络来测试它)并测试所有自定义操作功能(彻底publishingadvertisement. 实际上,您必须测试安装、重新安装、卸载和升级,但请测试所有模式。

如果您正在本地化,请在所有版本的所有核心区域进行测试。还在德国地区运行英语,反之亦然,仅用于烟雾测试。事实上,在所有地区测试英语 - 我猜很明显。自定义操作很容易在由该机器上的随机状态触发的本地化机器上失败(例如,CA 试图访问硬编码的英文路径和异常结果),或者在异常处理程序代码或类似代码中显示一些被遗忘的英文消息框从未在英文盒子上触发。不好,哦,是的,而且我经常看到它应该被记录为一个问题。

而且我想应该提到一位经验丰富的开发人员的话:“ ......在发现的每个错误都是真正的惊喜之前,不要对太多人进行测试”。而且 - 他的更有趣的建议 - 预发布会留下几个已知的错误,并告诉 QA 人员有这样那样数量的错误要找到 - 只是为了一些集中注意力的动力:-)。PS:我喜欢称这位经验丰富的开发者为“老蚱蜢”,或者更常见的是他的“素食男孩”。孔子说:“永远不要相信可以用(有机)胡萝卜收买的人!

一个大题外话,回到真正的话题:错误包含敏感数据。


检查 MSI 文件

在检查我的 MSI 文件中是否有敏感信息时,我会保持简单。

  1. 首先快速浏览一下硬编码的 dev-box sins的源文件(WiX、Installshield、Advanced Installer 或您使用的任何工具)。
  2. 然后非常注意检查完成的候选版本 MSI 文件本身。真正的麦考伊。所有表格,以及一些嵌入内容的提取以进行验证(脚本、自定义操作 dll 等)。
  3. 所有安装模式下的实际安装,如上所述。敏感内容可能会被泄露,但许多其他问题也可能会被泄露——例如弹出的意外消息框——有时带有敏感的调试信息(自定义操作测试焦点)。

如何检查?一些脚本检查可能很有用,但从经验来看,我并不喜欢它。如果我是诚实的,我更喜欢第二双眼睛而不是花哨的脚本检查。只是我从真正的发布工作中获得的两分钱。

  1. 安装逆戟鲸
    • Orca 与 MSI 一样精益求精——其他工具通常会显示虚假的专有表格。Orca 是文件内容的直接视图。
    • 如果您安装了 Visual Studio,请在此处搜索“Orca”以快速找到安装程序 - 或者告诉安装了 Visual Studio 的人向您发送安装程序 MSI。
    • 你也可以试试“超级逆戟鲸”——但推荐使用逆戟鲸。
  2. 现在只需使用 Orca 打开您的发布候选 MSI,然后浏览表格
    • 只是说显而易见的:
      • 在真实源中强制执行任何更改,不要修复已完成的 MSI。
      • 如果你问我,根本没有原位修补程序 - 在我看来,你需要在源头进行修复并重建完整的 MSI 文件。然后你给你的源代码贴上标签(如果你有适当的、老式的源代码控制,带有美味的修订和标签)。
    • 大多数易受攻击的表可能是:Registry, Property, IniFile- 但在其他几个位置可能存在某些问题。
    • 如果您实际使用 MSI GUI:tables relating to GUI也容易受到攻击。
      • 许多人只是使用标准的 GUI 而不进行修改。这应该可以消除大部分风险。
      • 如果您有自定义 GUI,那么MSI GUI 声明中涉及很多表。我会盯着他们所有人看。
      • 也许特别关注:ListBox, ComboBox, UIText,Dialog
      • 显然,要特别关注您自己的自定义对话框——如果有的话。
    • 第三方工具为诸如 XML 文件更新之类的事情提供易受攻击的自定义表。眼球这些也是。
      • 任何看起来像 XMLFile、SQLUpdates 等的东西......
      • 来自不同供应商的此类自定义表格越来越多。它们现在涉及到各种各样的东西,而不仅仅是配置文件(防火墙规则、SQL 脚本等......)
    • 检查任何包含的脚本。
      • 签入源代码控制,但也...
      • CustomAction表或Binary表 - 后者要求您流式传输任何脚本 - 或在其源位置检查它们)。
  3. 检查应用程序安装的任何设置文件(通过 MSI 的文件表)。
    • 具有硬编码设置的 INI 文件可以通过 File 表安装,因此它们的值在 Orca 中不可见(与 INIFile 表相反,INIFile 表显示要写入的 INI 的所有字段)。
      • 这里的区别本质上是文件是作为文件处理还是作为一组组值对处理以写入 INI。后一种方法是“正确”的方法。
      • 请注意,如果某些 INI 文件具有非标准格式(与正常的键值对格式相反的额外字段和各种奇怪),或者更常见:INI 文件可能有大量的注释部分,则可能需要将其安装为文件您想要保留的信息(通常用于开发人员工具) - 您不能通过 INI 文件表。然后选择将其安装为文件。
    • 其他设置文件(例如 XML 文件)可以以相同的方式安装。事实上很多时候。
      • 如上所述,第三方工具通常支持从 Orca 中可查看的自定义表写入更新。
      • 可以有许多这样不同的表(加密字段?里面有什么?)
    • 像这样包含的文件通常由开发人员维护,但检查仍然是发布责任。对您的 MSI进行管理安装(链接答案中的进一步链接)并检查创建的网络映像中提取的设置文件。msiexec.exe /a "Your.msi", 或setup.exe /a(Installshield), 或setup.exe /extract(高级安装程序)。一些 setup.exe 信息
  4. 检查支持的批量安装脚本Powershell 脚本或随您的设置提供的其他形式的脚本- 以进行软件的实际安装。
    • 有时您会看到带有一些设置以帮助自动化部署的现成脚本,通常某种形式的硬编码信息会潜入此处(UNC 路径,甚至 IP 地址或其他类型的测试数据)。
    • 这些脚本,有时作为单独的下载交付,可能是事后的想法,根据我的经验,最终被 QA 忽略了。
    • 如果可用,在 QA 和测试期间积极使用这些脚本,或者更好:在单页 PDF 中记录大规模部署(更通用且不易出错)。
  5. 警告:即使在 Orca 中看不到任何内容,编译的自定义操作仍可能包含敏感内容 - 显然。有时一时冲动很容易忘记。这是非常重要的(新宠词)——回到源代码。
    • 编译后的自定义操作不能直接“查看”,因此任何硬编码的敏感内容“暴露较少”。
    • 但是,错误的硬编码 IP 地址可能会导致您的所有用户尝试连接到您的测试服务器或您自己想要的任何其他服务器......我怀疑这不会在设置期间发生,而是在首次应用程序启动期间发生。
    • 再次:获得帮助 - 第二双眼睛会为您省去麻烦,但这次也让他们阅读实际的源代码。告诉他们专注于意想不到的、硬编码的值和奇怪的定义——任何看起来“实验性”的东西。
      • 这样的“白盒”或“透明”质量保证在这里可能很好。招募其他开发人员?我将专注于只关注“奇怪的东西”的代码,而不是测试实际功能(即用于黑盒测试)。
      • 显然,该代码仅适用于用户输入或在命令行设置的值的 MSI PUBLIC PROPERTIES。任何硬编码的东西都不应该真的存在。然而,在现实世界中,大多数开发人员最终会在调试版本中设置硬编码。
      • 应该告诉QA 专业人员如何测试相同的自定义操作“黑匣子” - 以及第一个应用程序启动以测试正确的值是否写入到任何地方。
      • 您能否为他们知道存在并且知道如何使用的 QA 人员提供一些方便的应用程序级别日志记录(并且他们应该检查它?)。然后你应该在他们发现你的发布应用程序访问你的内部测试服务器而不是你的生产服务器之前几分钟。
    • 对于已编译的 C++ 自定义操作,如果您坚持使用硬编码,我建议您使用良好的挑剔调试实践。用于#ifdef _DEBUG包装debugging message boxes和任何hard coded test variables. 请参阅下面的 C++ 片段。这意味着发布版本中根本没有实验值(预处理器将删除所有调试结构)。
    • 也许也可以添加NOMB到您的发布版本中?请参阅下面的示例 - 应该防止杂散发布构建消息框 - 定义基本上“禁止”它们(其他可能的定义:如何驯服 Windows 标头(有用的定义)?)。
      • 我只是简单地测试了这个。不过,我在发布版本中弹出了相当多的被遗忘的 C++ 消息框——我不得不承认——幸运的是没有灾难(敲木头等等等等)。
      • 请记住,这样的消息框可能会在没有任何警告或明确原因(通常没有日志消息)的情况下神秘地停止以静默模式远程运行的安装程序。
      • 此类消息通常可能由大多数安装通常不会触发的某种错误条件或异常触发 - 所以它突然出现在某些 PC 上。远程部署时无法恢复。设置没有正确回滚,它只是卡住了。如果没有用户在本地登录,则也无法在机器上将其关闭。不是完全关于敏感信息,而是相关的(究竟是什么显示在盒子上?),以及在测试自定义操作时要查看的内容。
      • 一个自然的问题是,是否有办法让消息框自动超时我简要地对这个建议的MessageBoxTimeout方法(来自)进行了烟雾测试user32.dll,它似乎甚至支持上述NOMB功能以及超时。换句话说,您可以将消息框设置为在发布版本中禁止和在调试版本中超时。没有彻底测试。
    • C++ 不是我的事,请使用贵公司定义的发布版本的最佳实践。也许寻找定义和字符串变量。或者所有设置都可能位于仅包含在调试版本中的设置文件中(但奇怪的东西往往会到处蔓延)。
    • 对于托管代码,我问自己的问题是:这个托管二进制文件的反编译能力如何?我在这里的经验很少。我从来没有花时间反编译托管二进制文件。
      • 无论如何,代码中不应该有任何敏感内容——除非你有一个隐藏的私钥、许可证密钥或类似的奇怪的东西——我绝对不会这样做,让应用程序去做。
      • 对于为您的应用程序设置试用期等功能,我想您可能希望更好地“隐藏实现”。某种混淆可能很常见,我没有跟上速度。也许这是 .NET 世界中更大的问题之一?相关专家:请多多指教
      • 我将关注与上述相同的问题:调试错误地包含在发布模式二进制文件中的构造以及设置为测试服务器和测试资源的错误链接和路径。
  6. 意外在您的正式版本中包含调试构建二进制文件
    • 在某些情况下很容易发生的另一个问题:您在 MSI 中包含自定义操作 DLL 的调试版本
    • 这显然会发生在您设置中的任何文件上,不仅仅是您的自定义操作 DLL,而且自定义操作 DLL 在构建后特别“隐藏”在您的包中(嵌入在 MSI 的二进制表中 - 验证它)。
    • 也许确保d为您编译的自定义操作 dll 或任何其他文件添加一个文件名?即使它会给你带来一些额外的工作?
    • 我不确定调试 dll 到底有多“敏感”(一个合适的 C++ 专家必须详细说明)——但我肯定不想无意中在我的设置中分发这些文件。我有时(很少)为 QA 团队制作调试构建 MSI 文件,仅包含用于测试目的的调试二进制文件和符号,在我看来,这些设置应该在一两个月后过期,并且永远不容易安装并且永远不会在您的 QA 团队之外使用. 可以添加要安装的密码,但 MSI 是一种开放格式,仍然可以提取。没有戏剧性,我猜只是要记住和管理的东西。
  7. 现在这有点推动“敏感数据”的话题,但是对您打算以数字方式签署并公开发布的任何内容进行彻底的恶意软件扫描怎么样?签名的恶意软件不是您想要体验的东西。
    • 验证发布文件(如果有)上的数字签名。使用 UAC 等进行测试...
    • 也许使用Virustotal.com或等效的恶意软件扫描服务/解决方案来扫描您的最终 MSI 文件中的恶意软件(或误报)。
    • 测试安装后使用procexp64.exe(Sysinternals Process Explorer 直接下载)扫描所有正在运行的进程。在此处查看该工具的一些建议使用步骤
    • 使用这些工具也可以帮助您消除解决方案的误报。随着安全软件加强安全性和恶意软件变得更加普遍,一个可怕的问题似乎变得越来越严重。
      • 误报可能会导致您部署的程序包无休止的自我修复(请参阅该链接中的问题 7),因为文件被反复隔离,然后由 Windows 安装程序通过自我修复放回。
      • 误报讽刺对于真正的恶意软件,您告诉用户重建他们的计算机。对于误报,您面临与安全软件供应商解决问题的压力。现在如何为数十种安全工具和套件做到这一点?

在 C++ 自定义操作中仅调试消息框:

我使用消息框将调试器附加到 C++ 自定义操作代码。如何避免这些小动物出现在发布版本中?这里有一个建议:

#ifdef _DEBUG //Display Debug information only for debug builds
     MessageBox(NULL, "Text", "Caption", MB_OK|MB_SYSTEMMODAL);
#endif

高级 C++ 人员会立即看到他们应该为此创建一个更好的宏 - 将所有内容都包含在内 - 我不是 C++ 专家,所以我暂时将其排除在外(SafeMessageBox?DeploymentMessageBox?)。

stdafx.h中,可能还启用NOMB(应防止MessageBox编译,除非用#ifdef _DEBUG-包装,MessageBoxes仅在调试版本中可用):

#ifndef _DEBUG // Forbid MessageBox in Release builds
    #define NOMB
#endif

公平的赌注,这可能会成为你最讨厌的定义之一 :-)。谁闻到了注释掉的部分?我不会使用#undef添加临时发布消息框 - 它会破坏整个保护功能 - 可能会导致您希望避免的事情:一个杂散的消息框。stdafx.h如果必须的话,也许只需注释掉 #define ,然后再次启用定义 - 通过构建过程自动 - 对于真正的公共发布构建,触发任何杂散消息框的编译错误)

如上所述,您可以尝试新的MessageBoxTimeout方法(从 开始user32.dll,从 XP 开始显然可用)来显示不会“卡住”但在指定秒数后超时的消息框。不用于发布,但可能对调试和 QA 有用。

一些上下文#ifdef DEBUG 与 #if DEBUG。真正了解 C++ 的人,可以根据需要随时澄清或详细说明。以上来自一个非常古老的 C++ 项目。

基本上就是这样——几乎不是火箭科学——只是“咬人的小事”。关于以下主题的一些进一步讨论,但没有替代此手动扫描恕我直言。我诚实的建议,抓住一些人(经理很好:-) - 把他们作为同谋拉进来!),为他们安装 Orca 并告诉他们单击表格并查看所有设置文件 - 并让开发人员帮助编译自定义操作代码。仅仅查看原始的 Orca 表甚至可以有效地发现其他错误或缺陷。


敏感的信息

在开发过程中,有很多机会在您的 MSI 源中意外包含敏感信息:login credentialspasswordsdatabase connection stringsuser namesshare nameIP-addressmachine names、或.ftp passwordsweb host login credentialsother sensitive data

您的 MSI 显然根本不应该包含任何此类敏感信息- 当然,除非您想指向您自己的网站,或者提供联系电子邮件电话号码。然而,其他任何事情几乎总是不受欢迎的——并且由于开发实验(通常在脚本自定义操作中——或为此编译的自定义操作——甚至更糟且无法检测到),很快就会忘记从生产 MSI 文件中删除此类硬编码信息通过上面建议的 Orca 审查方法,但用户通常无法查看,除非它通过意外消息框显示 - 或者如果 .NET 托管代码被反汇编)。

如果安装确实需要,则此类“敏感”信息应该是最终用户在安装时设置的参数(属性),可以通过设置的交互式 GUI 设置,也可以通过 PUBLIC PROPERTIES 设置,或者在安装时在命令行转换正在安装。这里有一些关于使用转换和公共属性的信息:如何更好地利用 MSI 文件进行 MSI 文件的静默企业部署(链接的答案还提供了对 MSI 问题和更一般意义上的好处的相当特别的描述)。

于 2018-01-17T22:25:50.790 回答