调用操作符(&)是否比Invoke-Expression更不易遭代码注入攻击?
PowerShell中Invoke-Expression与&操作符的代码注入风险差异分析
核心执行机制差异
- Invoke-Expression(iex):本质是将传入的字符串当作完整的PowerShell脚本代码解析执行。它会扫描字符串中的所有PowerShell语法元素(比如分号
;、管道|、调用操作符&等),并按脚本逻辑执行,相当于动态编译运行一段代码。 - &调用操作符:专门用于执行外部可执行文件、脚本或函数的原生调用工具。它的第一个参数仅被视为目标程序的路径,后续的参数(或通过
@展开的参数数组)会被直接作为原生命令行参数传递给目标程序,不会经过PowerShell的代码解析环节。
代码注入风险的本质区别
用Invoke-Expression拼接字符串的风险
假设你的原代码是类似这样的拼接方式:
$command = "$reportGeneratorPath $argumentString" Invoke-Expression $command
如果$reportGeneratorPath或$argumentString中包含PowerShell特殊语法(比如; Remove-Item C:\CriticalData.txt),iex会将其解析为两段独立的PowerShell命令:先运行目标exe,再执行删除文件的恶意命令,这就是典型的代码注入攻击。
用&+参数数组的安全逻辑
改用以下写法后:
& $reportGeneratorPath @argumentArray
$reportGeneratorPath仅被当作路径字符串处理,哪怕路径里包含特殊字符,也只会被当作路径的一部分传递给系统,不会触发PowerShell代码解析。@argumentArray展开的每个参数元素,都会原封不动作为目标exe的命令行参数传递,哪怕参数里包含;、&这类字符,也只会被目标exe当作普通参数内容处理,不会被PowerShell解析为额外命令,完全不存在代码注入风险。
关于“改完仍觉得有风险”的澄清
你可能混淆了“运行时未知路径”和“代码注入风险”的概念:
- NuGet包的exe路径只是设计时无法确定,但只要你是通过可靠渠道获取路径(比如从NuGet包的安装目录读取,而非直接使用未过滤的用户输入),路径本身是可信的。
- 参数数组如果是你主动构造的(而非拼接用户输入的字符串),每个参数都是独立的元素,不会被解析为PowerShell代码,不存在注入隐患。
内容的提问来源于stack exchange,提问作者sbridewell
相关产品推荐
相关产品推荐

