参数注入
awk
system
awk 支持 system 命令来执行命令:
$ awk 'BEGIN {system("cmdname arg1 arg2")}' /dev/null
# 执行命令与文件中的行数相同
$ awk 'system("cmdname arg1 arg2")' /path/to/file如果不能插入空格,可以使用 sprintf 来绕过:
$ awk 'BEGIN{system(sprintf("cmdname%carg1",32))}'参考:
bundler
bundler install
bundler install 在底层使用 gem,因此可以重用 gem 的功能来获利。
Gemfile
Gemfile 描述了执行相关 Ruby 代码所需的 gem 依赖项。由于它是一个 ruby 文件,您可以编写任意代码,在运行 bundle install 时执行。
当运行 bundle install 时,任意的 ruby 代码将被执行。
gem 依赖项
由于 bundler 使用 gem install 来安装 Gemfile 中指定的依赖项,您可以使用扩展来嵌入任意代码。
当运行 bundle install 时,任意的 ruby 代码将被执行。
参考:
git 依赖项
bundler 的 gem 源之一是包含 gem 源代码的 git 仓库。由于 git 仓库包含源代码,bundler 在安装前会构建它。因此,您可以编写任意代码,在运行 bundle install 时执行。
在 github.com 上创建一个包含以下 hola.gemspec 文件的仓库:
将仓库作为 git 依赖项添加到 Gemfile 中。
当运行 bundle install 时,任意的 ruby 代码将被执行。
参考:
path 依赖项
您可以指定 gem 位于文件系统上的特定位置。相对路径相对于包含 Gemfile 的目录解析。由于 git 仓库包含源代码,bundler 在安装前会构建它。因此,您可以编写任意代码,在运行 bundle install 时执行。
您可以指定 gem 位于文件系统上的特定位置。相对路径相对于包含 Gemfile 的目录解析。
与 :git 选项的语义类似,:path 选项要求相关目录包含 gem 的 .gemspec,或者您指定 bundler 应使用的显式版本。
因此,您可以使用带有任意代码的 .gemspec 文件或带有原生扩展的构建 gem来获得代码执行。
当运行 bundle install 时,任意的 ruby 代码将被执行。
参考:
curl
curl 可用于泄露本地文件或向它们写入任意内容。
此外,file: 方案可用于读取或复制本地文件:
参考:
find
exec
-exec 选项可用于执行任意命令:
参考:
execdir
-execdir 类似于 -exec,但指定的命令从包含匹配项的子目录中运行。-execdir 可用于执行任意命令:
fprintf
-fprintf 可用于写入本地文件:
参考:
gem
gem build
gemspec 文件是一个 ruby 文件,定义了 gem 中的内容、谁制作了它以及 gem 的版本。由于它是一个 ruby 文件,您可以编写任意代码,在运行 gem build 时执行。
当运行 gem build 时,任意的 ruby 代码将被执行。
参考:
gem install
扩展
gemspec 允许您定义在安装 gem 时要构建的扩展。许多 gem 使用扩展来包装用 C 编写的库与 ruby 包装器。gem 使用 extconf.rb 在安装期间构建扩展。由于它是一个 ruby 文件,您可以编写任意代码,在运行 gem install 时执行。
当运行 gem install 时,任意的 ruby 代码将被执行。
参考:
git
-c/--config-env
-c/--config-env 将配置参数传递给命令。给定的值将覆盖配置文件中的值。查看 通过 .git/config 滥用 部分以找到可滥用的参数。
滥用 git 目录
git 目录维护与 git 仓库相关的内部状态或元数据。它在用户的机器上创建,当:
用户执行
git init来初始化一个空的本地仓库用户执行
git clone <repository>从远程位置克隆现有仓库
git 目录的结构记录在 https://git-scm.com/docs/gitrepository-layout
注意,git 目录通常是但不一定是名为 .git 的目录,位于仓库的根目录。有几个变量可以重新定义路径:
GIT_COMMON_DIR 环境变量或 commondir 文件指定将从中获取非工作树文件的路径,这些文件通常在
$GIT_DIR中。
注意,裸仓库 根本没有 .git 目录。
参考:
通过 .git/config 滥用
.git/config 允许在每个仓库的基础上配置选项。许多选项允许指定将在各种情况下执行的命令,但其中一些情况仅在用户以特定方式与 git 仓库交互时出现。
至少有以下几种设置选项的方法:
在系统范围内使用 /etc/gitconfig 文件
在全局范围内使用 ~/git/config 或 ~/.gitconfig 文件
在本地每个仓库的基础上使用 .git/config 文件
在本地每个仓库的基础上使用 .git/config.worktree 文件。这是可选的,只有当
.git/config中存在extensions.worktreeConfig时才会搜索在本地每个仓库的基础上使用 git -c/--config-env 选项
在本地每个仓库的基础上使用 git-clone -c/--config 选项
core.gitProxy
core.gitProxy 给出一个在使用 git:// 协议建立与远程的连接时将执行的命令
core.fsmonitor
core.fsmonitor 选项用作命令,该命令将标识自请求的日期/时间以来可能已更改的所有文件。
换句话说,git 提供的许多操作将调用 core.fsmonitor 给出的命令,以快速将操作范围限制为已知已更改的文件,以提高性能。
至少以下 git 操作调用 core.fsmonitor 给出的命令:
git status用于显示有关工作树状态的信息,包括是否有任何文件有未提交的更改git add <pathspec>用于暂存更改以提交到仓库git rm --cached <file>用于取消暂存更改git commit用于提交暂存的更改git checkout <pathspec>用于检出文件、提交、标签、分支等
对于接受文件名的操作,即使提供的文件名不存在,core.fsmonitor 也会触发。
参考:
core.hooksPath
core.hooksPath 为钩子设置不同的路径。您可以在仓库中创建 post checkout 钩子,使用 hooksPath 设置钩子的路径,并执行任意代码。
要执行 payload,运行 git-clone:
参考:
core.pager
core.pager 指定 Git 命令使用的文本查看器(例如,less)。该值旨在由 shell 解释,可用于执行任意命令。
例如,在以下代码片段中,git-grep 具有 --open-files-in-pager 键,如果参数中未指定值,则使用 core.pager 中的默认分页器:
如果分页器值不是由用户直接设置的,则有优先级顺序:
GIT_PAGER环境变量。core.pager配置。PAGER环境变量。编译时选择的默认值(通常是
less)。
因此,以下代码片段也可用于执行命令:
core.sshCommand
core.sshCommand 给出一个在使用 SSH 协议建立与远程的连接时将执行的命令。如果设置了此变量,当它们需要连接到远程系统时,git fetch 和 git push 将使用指定的命令而不是 ssh。
diff.external
diff.external 给出一个将代替 git 内部 diff 函数使用的命令。
filter.<driver>.clean 和 filter.<driver>.smudge
filter..clean 用于在提交时将工作树文件的内容转换为 blob。
filter..smudge 用于在检出时将 blob 对象的内容转换为工作树文件。
参考:
http.proxy 和 http.<URL>.proxy
http.proxy 或 http.<URL>.proxy 覆盖 HTTP 代理。您可以使用它来获得 SSRF:
注意其他 http.* 配置和 remote.<name>.proxy,它们可以帮助增加影响。
参考:
通过 .git/hooks/ 滥用
.git/hooks/ 中的各种文件在某些 git 操作时执行。例如:
pre-commit和post-commit分别在提交操作之前和之后执行post-checkout在检出操作之后执行pre-push在推送操作之前执行
在区分可执行文件和不可执行文件的文件系统上,只有当相应的文件是可执行的时才会执行钩子。此外,钩子只在给定的用户交互时执行,例如在执行提交时。
例如,您可以使用裸仓库来传递自定义 git 钩子并执行任意代码:
如果易受攻击的代码对准备好的仓库执行以下 bash 命令,它将触发自定义钩子执行并导致任意代码被执行:
参考:
通过 .git/index 滥用
您可以使用精心制作的 .git/index 文件实现任意写入原语,查看公告。
通过 .git/HEAD 滥用
通过损坏 .git/HEAD 可以欺骗 Git 从意外位置加载配置。在这种情况下,Git 开始在当前文件夹中查找仓库,攻击者可以完全控制该文件夹,例如,如果当前文件夹是包含克隆的远程仓库所有文件的工作树。利用流程可能如下:
参考:
git-blame
--output
git-blame 具有 --output 选项,该选项在手册中没有记录,并且通常出现在其他 git 子命令中。执行 git blame --output=foo 导致有趣的行为:
虽然命令失败了,但创建了一个名为 foo 的空文件。如果同名的文件已经存在,目标文件将被截断。此选项提供任意文件截断原语。例如,攻击者可以使用它来损坏 .git 文件夹中的关键文件,如 .git/HEAD,并欺骗 Git 从意外位置加载配置,查看 通过 .git/HEAD 滥用 部分。
参考:
git-clone
-c/--config
-c/--config 在新创建的仓库中设置配置变量;这在仓库初始化后立即生效,但在获取远程历史记录或检出任何文件之前生效。查看 通过 .git/config 滥用 部分以找到可滥用的变量。
ext URL
git-clone 允许在 ext URL 中为远程仓库指定 shell 命令。例如,下一个示例将执行 whoami 命令来尝试连接到远程仓库:
参考:
<directory>
git-clone 允许指定一个新目录来克隆到。只有当目录为空时才允许克隆到现有目录中。您可以使用它来将仓库写入默认文件夹之外。
-u/--upload-pack
upload-pack 指定在通过 ssh 访问要克隆的仓库时在另一端运行的命令的非默认路径。您可以像这样执行任意代码:
参考:
git-diff
git-diff 对 /dev/null
git-diff 对 /dev/null 可用于读取文件的整个内容,即使在 git 目录之外。
参考:
--no-index
--no-index 键可用于将 git-diff 变为对 git 仓库中另一个文件的正常 diff,该文件不必被跟踪。
参考:
git-fetch
--upload-pack
--upload-pack 标志可用于执行任意命令。输出不显示,但可以使用 >&2 将输出路由到 stderr。
参考:
git-fetch-pack
--exec
与 --upload-pack 相同。查看下面的部分。
--upload-pack
--upload-pack 标志可用于执行任意命令。输出不显示,但可以使用 >&2 将输出路由到 stderr。
git-grep
--no-index
no-index 告诉 git-grep 搜索当前目录中不被 Git 管理的文件。换句话说,如果工作目录与仓库目录不同,no-index 允许您访问工作目录中的文件。
参考:
-O/--open-files-in-pager
-O/--open-files-in-pager 在 pager 中打开匹配的文件。它可以用于运行任意命令:
参考:
git-log
--output
output 定义一个特定的输出文件而不是 stdout。您可以使用它来重写任意文件。
参考:
git-ls-remote
--upload-pack
--upload-pack 标志可用于执行任意命令。输出不显示,但可以使用 >&2 将输出路由到 stderr。
参考:
git-pull
--upload-pack
--upload-pack 标志可用于执行任意命令。输出不显示,但可以使用 >&2 将输出路由到 stderr。
参考:
git-push
--receive-pack/--exec
receive-pack or exec 指定远程端 git-receive-pack 程序的路径。您可以像这样执行任意代码:
maven
在 mvn <PHASE> 执行期间执行任意命令或代码是可能的,通过使用各种插件,如 exec-maven-plugin 或 groovy-maven-plugin。为了在阶段 <PHASE> 期间使用 groovy-maven-plugin 插件执行恶意 payload,您可以使用以下配置:
例如,您可以使用以下 pom.xml 文件在 mvn initialize 或 mvn compile 期间执行插件:
参考:
npm scripts
package.json 文件的 scripts 属性支持许多内置脚本及其预设生命周期事件以及任意脚本。所有这些都可以使用 npm run-script 或简写 npm run 执行。
具有匹配名称的 pre 和 post 命令也将为这些运行(例如 premyscript、myscript、postmyscript)。要为 package.json 的 scripts 部分中定义的任何脚本创建 pre 或 post 脚本,只需创建另一个具有匹配名称的脚本并在其开头添加 pre 或 post。
在以下示例中,npm run compress 将按描述执行这些脚本。
有一些特殊的生命周期脚本只在某些情况下发生。除了 pre<event>、post<event> 和 <event> 脚本之外,这些脚本也会发生。
prepare(自 [email protected] 起)在打包之前的任何时候运行,即在
npm publish和npm pack期间在包打包之前运行
在包发布之前运行
在没有参数的本地
npm install上运行在
prepublish之后运行,但在prepublishOnly之前运行注意:如果通过 git 安装的包包含
prepare脚本,其dependencies和devDependencies将被安装,并且 prepare 脚本将在包打包和安装之前运行从
npm@7开始,这些脚本在后台运行。要查看输出,请运行:--foreground-scripts
prepublish(已弃用)在
npm publish期间不运行,但在npm ci和npm install期间运行
prepublishOnly在包准备和打包之前运行,仅在
npm publish上运行
prepack在打包 tarball 之前运行(在
npm pack、npm publish和安装 git 依赖项时)注意:
npm run pack与npm pack不同。npm run pack是任意的用户定义脚本名称,而npm pack是 CLI 定义的命令
postpack在生成 tarball 之后但在将其移动到最终目的地之前运行(如果有的话,发布不会在本地保存 tarball)
npm cache add
npm cache add 运行以下生命周期脚本:
prepare
npm ci
npm ci 运行以下生命周期脚本:
preinstallinstallpostinstallprepublishprepreparepreparepostprepare
这些都在实际将模块安装到 node_modules 之后运行,按顺序,中间没有内部操作。
npm diff
npm diff 运行以下生命周期脚本:
prepare
npm install
npm install 运行以下生命周期脚本(当您运行 npm install -g <pkg-name> 时也会运行):
preinstallinstallpostinstallprepublishprepreparepreparepostprepare
如果在包的根目录中有 binding.gyp 文件并且未定义 install 或 preinstall 脚本,npm 将默认 install 命令使用 node-gyp 通过 node-gyp rebuild 进行编译。
npm pack
npm pack 运行以下生命周期脚本:
prepackpreparepostpack
npm publish
npm publish 运行以下生命周期脚本:
prepublishOnlyprepackpreparepostpackpublishpostpublish
prepare 在 --dry-run 期间不会运行
npm rebuild
npm rebuild 运行以下生命周期脚本:
preinstallinstallpostinstallprepare
prepare 只有在当前目录是符号链接时才会运行(例如,使用链接的包)
npm restart
npm restart 运行 restart 脚本(如果已定义),否则如果存在 stop 和 start 都会运行(包括它们的 pre 和 post 迭代):
prerestartrestartpostrestart
npm start
npm start 运行以下生命周期脚本:
prestartstartpoststart
如果在包的根目录中有 server.js 文件,那么 npm 将默认 start 命令为 node server.js。在这种情况下,prestart 和 poststart 仍会运行。
npm stop
npm stop 运行以下生命周期脚本:
prestopstoppoststop
npm test
npm test 运行以下生命周期脚本:
pretesttestposttest
pip
pip install
扩展 setuptools 模块允许您挂钩几乎任何 pip 命令。例如,您可以使用 setup.py 文件中的 install 类在 pip install 运行期间执行任意代码。
当运行 pip install 时,将调用 PostInstallCommand.run 方法。
参考:
ssh
authorized_keys 和 id_*.pub
OpenSSH 支持 command 选项,该选项指定每当密钥用于身份验证时执行的命令。
参考:
ssh_config
ssh 从以下来源按以下顺序获取配置数据:
命令行
用户的配置文件
~/.ssh/config系统范围的配置文件
/etc/ssh/ssh_config
LocalCommand
LocalCommand 指定在成功连接到服务器后在本地机器上执行的命令。以下 ssh_config 可用于执行任意命令:
参考:
ssh-keygen
-D
ssh-keygen 可以使用 -D 键加载共享库,导致任意命令执行:
参考:
tar
检查点
检查点 是在将第 n 个记录写入存档(写入检查点)之前,或从存档中读取第 n 个记录之前(读取检查点)的时间点。检查点 允许定期执行任意操作。
--to-command
当使用 --to-command 键时,tar 调用命令并将文件的内容通过管道传输到其标准输出,而不是创建指定的文件。因此它可以用于执行任意命令。
参考:
-I/--use-compress-program
-I/--use-compress-program 用于指定可以滥用来执行任意命令的外部压缩程序命令:
参考:
terraform
terraform-plan
Terraform 依赖于称为"提供者"的插件来与远程系统交互。Terraform 配置必须声明它们需要哪些提供者,以便 Terraform 可以安装和使用它们。
您可以编写自定义提供者,将其发布到 Terraform Registry 并将提供者添加到 Terraform 代码中。
提供者将在 terraform init 期间被拉入,当运行 terraform plan 时,任意的 ruby 代码将被执行。
此外,Terraform 提供 external provider,它提供了在 Terraform 和外部程序之间接口的方式。因此,您可以使用 external 数据源来运行任意代码。来自文档的以下示例在 terraform plan 期间执行 python 脚本。
参考:
wget
--use-askpass
--use-askpass 指定提示用户和密码的命令。此键可用于执行任意命令,而无需任何参数和 stdout/stderr。
如果未指定命令,则使用环境变量 WGET_ASKPASS 中的命令。如果 WGET_ASKPASS 未设置,则使用环境变量 SSH_ASKPASS 中的命令。此外,可以在 .wgetrc 中设置 use-askpass 的默认命令。
参考:
--post-file
--post-file 可用于在 POST 请求中泄露文件。
参考:
-O/--output-document
-o/--output-document 可用于通过 GET 请求下载远程文件并将其保存到特定位置。
参考:
-o/--output-file
-o/--output-file 指定一个日志文件,用于记录通常报告到标准错误的所有消息。它可以用于将输出写入文件。
参考:
-i/--input-file
-i/--input-file 从本地或外部文件读取 URL。此键可用于在错误消息中暴露文件内容:
参考:
zip
-TT/--unzip-command
-TT/--unzip-command 用于指定在使用 -T 选项时测试存档的命令。
参考:
最后更新于