如何防止 PowerShell 中的变量注入?

2023-12-02

@Ansgar Wiechers 对最近 PowerShell 问题的评论再次触发了我:DO NOT use Invoke-Expression关于一个安全问题,我已经在脑海中思考了很长时间并且需要问。

强烈的声明(参考调用表达式被认为是有害的文章)表明,调用可以覆盖变量的脚本被认为是有害的。

还有PS脚本分析器建议不要使用Invoke-Expression,参见避免使用InvokeExpression规则.

但我自己曾经使用过一种技术来更新递归脚本中的公共变量,该变量实际上可以覆盖其任何父作用域中的值,就像这样简单:

([Ref]$ParentVariable).Value = $NewValue

据我所知,潜在的恶意脚本可以使用此技术在任何情况下注入变量,无论它是如何调用的......

考虑以下“恶意”Inject.ps1 script:

([Ref]$MyValue).Value = 456
([Ref]$MyString).Value = 'Injected string'
([Ref]$MyObject).Value = [PSCustomObject]@{Name = 'Injected'; Value = 'Object'}

My Test.ps1 script:

$MyValue = 123
$MyString = "MyString"
$MyObject = [PSCustomObject]@{Name = 'My'; Value = 'Object'}
.\Inject.ps1
Write-Host $MyValue
Write-Host $MyString
Write-Host $MyObject

Result:

456
Injected string
@{Name=Injected; Value=Object}

正如您所看到的所有三个变量Test.ps1范围被覆盖Inject.ps1脚本。这也可以使用 Invoke-Command cmdlet 来完成,并且我是否将变量的范围设置为Private either:

New-Variable -Name MyValue -Value 123 -Scope Private
$MyString = "MyString"
$MyObject = [PSCustomObject]@{Name = 'My'; Value = 'Object'}
Invoke-Command {
    ([Ref]$MyValue).Value = 456
    ([Ref]$MyString).Value = 'Injected string'
    ([Ref]$MyObject).Value = [PSCustomObject]@{Name = 'Injected'; Value = 'Object'}
}
Write-Host $MyValue
Write-Host $MyString
Write-Host $MyObject

有没有办法完全隔离调用的脚本/命令以覆盖当前范围内的变量?
如果不是,这是否可以被视为以任何方式调用脚本的安全风险?


反对使用的建议Invoke-Expression使用主要是为了防止无意的执行代码(代码注入)。

如果您调用一段 PowerShell 代码 - 无论是直接调用还是通过Invoke-Expression- 它确实可以(可能是恶意的)操纵父作用域,包括全局作用域。
请注意,这种潜在的操纵并不限于变量: 例如,功能 and aliases也可以修改。

Caveat: 运行未知代码有问题在两个方面:

  • Primarily for the potential to perform unwanted / destructive actions directly.[1]
  • 其次,对于潜力恶意修改调用者的state(变量,...),即the only请注意以下解决方案以防止.

提供期望的隔离,你有两个基本选择:

  • 在a中运行代码child process:

    • 通过启动另一个 PowerShell 实例;例如(使用powershell代替pwsh在 Windows PowerShell 中):

      • pwsh -c { ./someUntrustedScript.ps1 }
    • 通过启动一个后台工作; e.g.:

      • Start-Job { ./someUntrustedScript.ps1 } | Receive-Job -Wait -AutoRemove
  • 在a中运行代码分离thread在同一过程中:

    • As a 线程作业,通过Start-ThreadJobcmdlet(随 PowerShell [Core] 6+ 一起提供;在 Windows PowerShell 中,可以安装来自 PowerShell 库与类似的东西
      Install-Module -Scope CurrentUser ThreadJob); e.g.:

      • Start-ThreadJob { ./someUntrustedScript.ps1 } | Receive-Job -Wait -AutoRemove
    • 通过创建一个新的运行空间通过 PowerShell SDK;例如。:

      • [powershell]::Create().AddScript('./someUntrustedScript.ps1').Invoke()
      • 请注意,您必须做额外的工作才能获取输出流other与成功的相比,特别是错误流的输出;还,.Dispose()命令完成后应在 PowerShell 实例上调用。

A 子进程基于 的解决方案将很慢并且在您可以返回的数据类型方面受到限制(由于涉及序列化/反序列化),但它提供了针对调用的代码使进程崩溃的隔离。

基于线程的作业速度要快得多,可以返回任何数据类型,但可能会使整个进程崩溃。

在所有情况下,您都必须从调用者传递被调用代码需要访问的任何值论点或者,使用后台作业和线程作业,或者通过$using:范围说明符。


js2010提到了其他不太理想的替代方案:

  • Start-Process(基于子进程,带有纯文本参数和输出)

  • PowerShell 工作流程,它们已过时(它们未移植到 PowerShellCore并且不会)。

  • Using Invoke-Command与“环回远程处理”(-ComputerName localhost) 假设也是一种选择,但这样会带来子进程和基于 HTTP 的通信的双重开销;此外,您的计算机必须设置为远程处理,并且您必须以提升权限运行(以管理员身份)。


[1] A way to mitigate the problem is to limit which commands, statements, types, ... are permitted to be called when the string is evaluated, which can be achieved via the PowerShell SDK in combination with language modesand/or by explicitly constructing an initial session state. See this answer for an example of SDK use with language modes.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何防止 PowerShell 中的变量注入? 的相关文章

随机推荐

  • 使用 Javascript forEach 和 indexOf 在 JSON 中搜索多个过滤器

    我有 JSON 格式的数据 需要在其中执行搜索 有不同的可用标签 当我单击它们时 它会在 JSON 中搜索并返回具有这些标签的项目 为此 我使用了 js 函数 它第一次工作正常 但是当我在函数中推送第二个过滤器时 它返回错误的数据 可用的过
  • RFC_READ_TABLE 传递“选项”和“字段”参数 (c#)

    需要帮助 我正在尝试使用 RFC READ TABLE 从 SAP 获取销售数据 但不知道如何将 OPTIONS 和 FIELDS 参数传递给 SAP 这是我的应用程序的示例代码 连接正常 执行后出现异常 DATA BUFFER EXCEE
  • 有没有办法防止opencv矩阵除法的舍入

    我有一个整数矩阵 我想对其进行整数除法 但opencv总是对结果进行四舍五入 我知道我可以手动划分每个元素 但我想知道是否有更好的方法 Mat c Mat
  • TCP Keepalive 是确定断开链接的唯一机制吗?

    我最近遇到了一个问题 TCP 服务器和客户端之间的中间链路出现故障 如果主服务器宕机 客户端需要连接到辅助服务器 当主服务器被关闭时 例如 通过在终端上执行 C TCP 关闭序列会通过 并且客户端成功检测到断开的链接并尝试辅助服务器 然而
  • Tomcat 7 上部署时出现 Omnifaces 异常

    我正在尝试将 Omnifaces 2 1 添加到 Web 应用程序以使用 FullAjaxExceptionHandler 以及 Omnifaces 2 1 中可能的其他功能 我已阅读并关注了 BallusC 的以下帖子 但仍然陷入困境 如
  • 格式良好的 XML?标记名称和属性名称中的 XML 引用

    我一直在尝试确认我对 XML 规范的阅读 我的解释是 标签名称和属性名称中不允许使用预定义实体和数字字符引用 例如 XML 1 0 规范不允许这样做
  • MS Edge:IntersectionObserver。对你起作用吗?

    在任何人在这里付出太多努力之前 我已经有了一个令人讨厌的解决方法 我只是想知道是否有人可以使用它 Edge 版本 15 现已发布 并支持交叉观察器 用于延迟加载 我已经实现了它 它在所有支持它的浏览器中都可以正常工作 Chrome 和 Op
  • Rails 随机记录生成器

    我问自己是否有一个gem或一种方法可以用随机数据生成大量记录 对模型有效 目标是使用数据库中的大量数据来测试我的应用程序 我在网上没有找到任何内容 但我没有使用正确的关键字 你知道类似的事情吗 您可以使用Faker宝石 并且 以下是创建 1
  • 如何将查询语句记录到Neo4j服务器,可能吗?

    我想将整个查询语句记录到 Neo4j 服务器 但是 在搜索 SO 和文档之后我没有成功 我发现这个问题 Neo4j 服务器上记录的剩余查询 但是更改这些配置设置并没有达到我所希望的效果 我在 Golang 工作并使用Go CQ库与 Neo4
  • 如何让 Twitter Bootstrap Accordion 保持一组开放?

    我正在尝试使用 Twitter 引导程序使用手风琴和折叠插件来模拟 Outlook 栏 到目前为止 我已经实现了折叠和手风琴工作 但它目前允许折叠所有部分 我想限制它 以便始终显示一个且仅一个 这是我正在研究的一个 http jsfiddl
  • 用于在 JSON 数组中查找元素的索引

    我有一个看起来像这样的表 CREATE TABLE tracks id SERIAL artists JSON INSERT INTO tracks id artists VALUES 1 name blink 182 INSERT INT
  • 我是否正确解析此 HTTP POST 请求?

    首先我要说的是 我正在使用twisted web框架 Twisted web的文件上传没有像我想要的那样工作 它只包含文件数据 而不包含任何其他信息 cgi parse multipart没有像我想要的那样工作 同样的事情 twisted
  • 如何从Android中的普通java类调用Activity类[重复]

    这个问题在这里已经有答案了 我有一个 noraml java 类 在该类的构造函数中称为 ReceivedChat java 我想调用 Android 的 Activity public class ReceivedChat String
  • Grid.MVC 与 ASP.NET MVC 5 兼容吗?

    在我开始搞乱一些不起作用的东西之前 Grid MVC 可以与 ASP NET MVC 5 一起使用吗 在 gridmvc codeplex com 上他们只写 MVC3 4 但我想知道是否有人尝试过 MVC5 你尝试过 但没有成功 试试这个
  • 有没有办法可以将 GeoFireStore 查询与普通 Firestore 查询结合起来?

    我想查询我存储在名为 Users 的集合中的用户 每个用户都有年龄和体重等字段 有没有办法可以通过距使用 GeoFire 运行搜索的用户的距离来查询用户 并将其与 FireStore 搜索查询结合起来 例如 我是一名用户 正在寻找 20 英
  • .js 文件适用于 Chrome 和 Firefox,但不适用于 IE

    当在 IE11 中测试我的网站时 它的某些部分不起作用 我相信问题出在我的 custom js 文件上 因为所有问题都链接到该 js 不过 该页面在 Chrome 和 Firefox 中运行良好 我在页面的页脚中加载名为 custom js
  • Firebase 查询是否可扩展

    在我的应用程序中 要检查注册时是否使用了电子邮件 和用户名 我使用这样的查询 let emailRef Firebase url https photocliq5622144 firebaseio com users emailRef qu
  • SwiftUI:“onDrop”覆盖层在 LazyVGrid 中不会消失?

    我正在测试 Asperi 对单元格重新排序的出色答案 SwiftUI 使用 onDrag 和 onDrop 对单个 LazyGrid 中的项目重新排序 我遇到的问题是 当我简单地进入拖动模式然后放置到位时 覆盖层不会重置 请参见单元格 3
  • 在 Django 中使用 fullCalendar

    有点像这里发布的问题的后续 Django 通过自定义模板标签使用用户输入修改数据 但自从提出这个问题以来 我决定采取不同的方法 正如你所知 我是个新手 所以请放轻松 我希望 Django 应用程序中有一个每周日历 显示数据库中的班次 以下是
  • 如何防止 PowerShell 中的变量注入?

    Ansgar Wiechers 对最近 PowerShell 问题的评论再次触发了我 DO NOT use Invoke Expression关于一个安全问题 我已经在脑海中思考了很长时间并且需要问 强烈的声明 参考调用表达式被认为是有害的