| 1 | + | #!/bin/bash |
| 2 | + | |
| 3 | + | ###################################80 Columns################################### |
| 4 | + | # Linux Privilege Escalation Check Script |
| 5 | + | # |
| 6 | + | # [Details:] |
| 7 | + | ## Originally forked from the linuxprivchecker.py (Mike Czumak), this script |
| 8 | + | ## is intended to be executed locally on a Linux box to enumerate basic system |
| 9 | + | ## info and search for common privilege escalation vectors such as word |
| 10 | + | ## writable files, misconfigurations, clear-text password and applicable |
| 11 | + | ## exploits. |
| 12 | + | # |
| 13 | + | # [Original Author]: Mike Czumak (T_v3rn1x) -- @SecuritySift |
| 14 | + | # [Contributors]: |
| 15 | + | ## Mike Merrill (linted) -- https://github.com/linted |
| 16 | + | ## James Hogan (5aru) -- https://github.com/5aru |
| 17 | + | # |
| 18 | + | # [Modification, Distribution, and Attribution]: |
| 19 | + | ## Permission is herby granted, free of charge, to any person obtaining a copy |
| 20 | + | ## of this software and the associated documentation files (the "Software"), |
| 21 | + | ## to use, copy, modify, merge, publish, distribute, and/or sublicense copies |
| 22 | + | ## of the Software, and to permit persons to whom the Software is furnished to |
| 23 | + | ## do so, subject to the following conditions: |
| 24 | + | ## |
| 25 | + | ## The software must maintain original author attribution and may not be sold |
| 26 | + | ## or incorporated into any commercial offering. |
| 27 | + | ## |
| 28 | + | ## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| 29 | + | ## IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| 30 | + | ## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
| 31 | + | ## AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER |
| 32 | + | ## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
| 33 | + | ## FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
| 34 | + | ## DEALINGS IN THE SOFTWARE. |
| 35 | + | ##################################80 Columns#################################### |
| 36 | + | |
| 37 | + | ### Useful functions |
| 38 | + | |
| 39 | + | PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/games:/usr/games" |
| 40 | + | |
| 41 | + | TITLE_LINE=$(printf "%*s\n" "80" | tr ' ' "=") |
| 42 | + | SECTION_LINE=$(printf "%*s\n" "80" | tr ' ' "-") |
| 43 | + | |
| 44 | + | function formatCommand(){ |
| 45 | + | eval $1 | sed 's|^| |' |
| 46 | + | } |
| 47 | + | |
| 48 | + | echo ${TITLE_LINE} |
| 49 | + | echo "LINUX_PRIVILEGE ESCALATION CHECKER" |
| 50 | + | echo ${TITLE_LINE} |
| 51 | + | |
| 52 | + | echo -e "\n[*] GETTING BASIC SYSTEM INFO...\n" |
| 53 | + | |
| 54 | + | echo "[+] Operating System" |
| 55 | + | formatCommand "cat /etc/issue" |
| 56 | + | |
| 57 | + | echo -e "\n[+] Kernel" |
| 58 | + | formatCommand "cat /proc/version" |
| 59 | + | |
| 60 | + | echo -e "\n[+] Hostname/FQDN" |
| 61 | + | formatCommand "hostname -f" |
| 62 | + | |
| 63 | + | echo -ne "\n${SECTION_LINE}\n" |
| 64 | + | echo -e "[*] GETTING NETWORKING INFO...\n" |
| 65 | + | |
| 66 | + | echo "[+] Route" |
| 67 | + | |
| 68 | + | if [ -x "$(command -v route)" ]; then |
| 69 | + | formatCommand "route -n" |
| 70 | + | else |
| 71 | + | formatCommand "ip route" |
| 72 | + | fi |
| 73 | + | |
| 74 | + | echo -e "\n[+] Interfaces" |
| 75 | + | |
| 76 | + | if [ -x "$(command -v ifconfig)" ]; then |
| 77 | + | formatCommand "ifconfig -a" |
| 78 | + | else |
| 79 | + | formatCommand "ip addr show" |
| 80 | + | fi |
| 81 | + | |
| 82 | + | echo -e "\n[+] Network Connections" |
| 83 | + | |
| 84 | + | if [ -x "$(command -v netstat)" ]; then |
| 85 | + | formatCommand "netstat -tupan | grep -v TIME_WAIT" |
| 86 | + | else |
| 87 | + | formatCommand "ss -tupan | grep -v CLOSE_WAIT" |
| 88 | + | fi |
| 89 | + | |
| 90 | + | echo -ne "\n${SECTION_LINE}\n" |
| 91 | + | echo -e "[*] GETTING FILESYSTEM INFO...\n" |
| 92 | + | |
| 93 | + | echo -e "\n[+] Mount Results" |
| 94 | + | formatCommand "mount" |
| 95 | + | |
| 96 | + | echo -e "\n[+] fstab Entries" |
| 97 | + | formatCommand "cat /etc/fstab 2>/dev/null" |
| 98 | + | |
| 99 | + | echo -e "\n[+] Scheduled cron jobs" |
| 100 | + | formatCommand "ls -al /etc/cron* 2>/dev/null" |
| 101 | + | |
| 102 | + | echo -e "\n[+] Writable cron directories" |
| 103 | + | formatCommand "ls -aRl /etc/cron* 2>/dev/null | awk '$1 ~ /w.$' 2>/dev/null" |
| 104 | + | |
| 105 | + | echo -ne "\n${SECTION_LINE}\n" |
| 106 | + | echo -e "[*] ENUMERATING USER AND ENVIRONMENTAL INFO...\n" |
| 107 | + | echo -e "\n[+] Current User" |
| 108 | + | formatCommand "whoami" |
| 109 | + | |
| 110 | + | echo -e "\n[+] Current User ID" |
| 111 | + | formatCommand "id" |
| 112 | + | |
| 113 | + | echo -e "\n[+] All users" |
| 114 | + | formatCommand "cat /etc/passwd" |
| 115 | + | |
| 116 | + | echo -e "\n[+] Super Users Found" |
| 117 | + | formatCommand "grep -v -E '^#' /etc/passwd | awk -F: '\$3 == 0{print \$1}'" |
| 118 | + | |
| 119 | + | echo -e "\n[+] Root and current user history (depends on privs)" |
| 120 | + | formatCommand "ls -al ~/.*_history; ls -la /root/.*_history 2>/dev/null" |
| 121 | + | |
| 122 | + | echo -e "\n[+] Environment Variables" |
| 123 | + | formatCommand "env 2>/dev/null | grep -v 'LS_COLORS'" |
| 124 | + | |
| 125 | + | echo -e "\n[+] Sudoers (Privileged) [/etc/sudoers]" |
| 126 | + | formatCommand "cat /etc/sudoers 2>/dev/null | grep -v '#' 2>/dev/null" |
| 127 | + | |
| 128 | + | echo -e "\n[+] Sudoers Files (Privileged) [/etc/sudoers.d/*]" |
| 129 | + | formatCommand "cat /etc/sudoers.d/* 2>/dev/null | grep -v '#' 2>/dev/null" |
| 130 | + | |
| 131 | + | echo -e "\n[+] Logged in User Activity" |
| 132 | + | formatCommand "w 2>/dev/null" |
| 133 | + | |
| 134 | + | echo -ne "\n${SECTION_LINE}\n" |
| 135 | + | echo -e "[*] ENUMERATING FILE AND DIRECTORY PERMISSIONS/CONTENTS...\n" |
| 136 | + | |
| 137 | + | echo -e "\n[+] World Writable Directories for User/Group 'root'" |
| 138 | + | formatCommand "find / \( -wholename '/home/homedir*' -prune \) -o \( -type d -perm -0002 \) -exec ls -ld '{}' ';' 2>/dev/null | grep root" |
| 139 | + | |
| 140 | + | echo -e "\n[+] World Writable Directories for User other than 'root'" |
| 141 | + | formatCommand "find / \( -wholename '/home/homedir*' -prune \) -o \( -type d -perm -0002 \) -exec ls -ld '{}' ';' 2>/dev/null" |
| 142 | + | |
| 143 | + | echo -e "\n[+] World Writable Files" |
| 144 | + | formatCommand "find / \( -wholename '/home/homedir/*' -prune -o -wholename '/proc/*' -prune \) -o \( -type f -perm -0 002 \) -exec ls -l '{}' ';' 2>/dev/null" |
| 145 | + | |
| 146 | + | echo -e "\n[+] SUID/GUID Files and Directories" |
| 147 | + | formatCommand "find / \( -perm -2000 -o -perm -4000 \) -exec ls -ld {} \; 2>/dev/null" |
| 148 | + | |
| 149 | + | echo -e "\n[+] Checking if root's home folder is accessible" |
| 150 | + | formatCommand "ls -ahlR /root 2>/dev/null" |
| 151 | + | |
| 152 | + | echo -e "\n[+] Logs containing keyword 'password'" |
| 153 | + | formatCommand "find /var/log -name '*.log' 2>/dev/null | xargs -l10 egrep 'pwd|password' 2>/dev/null" |
| 154 | + | |
| 155 | + | echo -e "\n[+] Config files containing keyword 'password'" |
| 156 | + | formatCommand "find /etc -name '*.c*' 2>/dev/null | xargs -l10 egrep 'pwd|password' 2>/dev/null" |
| 157 | + | |
| 158 | + | echo -e "\n[+] Shadow Files (Privileged)" |
| 159 | + | formatCommand "cat /etc/shadow 2>/dev/null" |
| 160 | + | |
| 161 | + | echo -ne "\n${SECTION_LINE}\n" |
| 162 | + | echo -e "[*] ENUMERATING PROCESSES AND APPLICATIONS...\n" |
| 163 | + | |
| 164 | + | echo -e "[+] Installed Packages" |
| 165 | + | if [ -x "$(command -v dpkg)" ]; then |
| 166 | + | PKGMNGR=1 |
| 167 | + | formatCommand "dpkg -l | awk '{\$1=\$4=\"\"; print \$0}'" |
| 168 | + | elif [ -x "$(command -v dnf)" ]; then |
| 169 | + | PKGMNGR=2 |
| 170 | + | formatCommand "dnf -qa | sort -u" |
| 171 | + | elif [ -x "$(command -v rpm)" ]; then |
| 172 | + | PKGMNGR=3 |
| 173 | + | formatCommand "rpm -qa | sort -u" |
| 174 | + | fi |
| 175 | + | |
| 176 | + | echo -e "\n[+] Current Processes" |
| 177 | + | formatCommand "ps aux | awk '{print \$1,\$2,\$9,\$10,\$11}'" |
| 178 | + | |
| 179 | + | echo -e "\n[+] Sudo Version" |
| 180 | + | formatCommand "sudo -V | grep version 2>/dev/null" |
| 181 | + | |
| 182 | + | echo -e "\n[+] Apache Version and Modules" |
| 183 | + | formatCommand "apache2 -v 2>/dev/null; apache2ctl -M 2>/dev/null; httpd -v 2>/dev/null; apachectl -l 2>/dev/null" |
| 184 | + | |
| 185 | + | echo -e "\n[+] Apache Config File" |
| 186 | + | formatCommand "cat /etc/apache2/apache2.conf 2>/dev/null" |
| 187 | + | |
| 188 | + | echo -ne "\n${SECTION_LINE}\n" |
| 189 | + | echo -e "[*] IDENTIFYING PROCESSES AND PACKAGES RUNNING AS ROOT OR OTHER SUPERUSER...\n" |
| 190 | + | |
| 191 | + | EXTDGREP="($(ps -u 0 | tail -n+2 | rev | cut -d " " -f 1 | rev | cut -d "/" -f1 | sort | uniq | xargs | tr " " "|"))" |
| 192 | + | |
| 193 | + | if [ $PKGMNGR -eq 1 ]; then |
| 194 | + | formatCommand "dpkg -l | grep -iE '${EXTDGREP}'" |
| 195 | + | elif [ $PKGMNGR -eq 2 ]; then |
| 196 | + | formatCommand "dnf -qa | grep -iE '${EXTDGREP}'" |
| 197 | + | elif [ $PKGMNGR -eq 3 ]; then |
| 198 | + | formatCommand "rpm -qa | grep -iE '${EXTDGREP}'" |
| 199 | + | fi |
| 200 | + | |
| 201 | + | echo -ne "\n${SECTION_LINE}\n" |
| 202 | + | echo -e "[*] ENUMERATING INSTALLED LANGUAGES/TOOLS FOR SPLOIT BUILDING..." |
| 203 | + | |
| 204 | + | echo -e "\n[+] Installed Tools" |
| 205 | + | formatCommand "which awk perl python ruby gcc cc vi vim nmap find netcat nc wget tftp ftp 2>/dev/null" |
| 206 | + | |
| 207 | + | echo -e "\n[+] Related Shell Escape Sequences" |
| 208 | + | if [ -x "$(command -v vi)" ]; then |
| 209 | + | formatCommand "echo -ne \"vi-->\t:!bash\n\"" |
| 210 | + | formatCommand "echo -ne \"vi-->\t:set shell=/bin/bash:shell\n\"" |
| 211 | + | fi |
| 212 | + | |
| 213 | + | if [ -x "$(command -v vim)" ]; then |
| 214 | + | echo -ne "vim-->\t:!bash\n" | sed 's|^| |' |
| 215 | + | echo -ne "vim-->\t:set shell=/bin/bash:shell\n" | sed 's|^| |' |
| 216 | + | fi |
| 217 | + | |
| 218 | + | if [ -x "$(command -v awk)" ]; then |
| 219 | + | echo -ne "awk-->\tawk 'BEGIN {system(\"/bin/bash\")}'\n" | sed 's|^| |' |
| 220 | + | fi |
| 221 | + | |
| 222 | + | if [ -x "$(command -v perl)" ]; then |
| 223 | + | echo -ne "perl-->\tperl -e 'exec \"/bin/bash\";'\n" | sed 's|^| |' |
| 224 | + | fi |
| 225 | + | |
| 226 | + | if [ -x "$(command -v python)" ]; then |
| 227 | + | echo -ne "python-->\tpython -c '__import__(\"os\").system(\"/bin/bash\")'\n" | sed 's|^| |' |
| 228 | + | fi |
| 229 | + | |
| 230 | + | if [ -x "$(command -v find)" ]; then |
| 231 | + | echo -ne "find->\tfind / -exec /usr/bin/awk 'BEGIN {system(\"/bin/bash\")}' \\;\n" | sed 's|^| |' |
| 232 | + | fi |
| 233 | + | |
| 234 | + | if [ -x "$(command -v nmap)" ]; then |
| 235 | + | echo -ne "nmap-->\t--interactive\n" | sed 's|^| |' |
| 236 | + | fi |
| 237 | + | |
| 238 | + | echo -ne "\n${SECTION_LINE}\n" |
| 239 | + | echo -e "[*] FINDING RELEVANT PRIVILEGE ESCALATION EXPLOITS..." |
| 240 | + | |
| 241 | + | # We're gonna do this section a little different |
| 242 | + | echo -ne "\n\n\n" |
| 243 | + | printf "%*s\n" "80" | tr " " "*" |
| 244 | + | echo -ne "This project is still under development.\nToo get involved or check for updates please check \nhttps://github.com/linted/linuxprivchecker\n" |
| 245 | + | printf "%*s\n" "80" | tr " " "*" |
| 246 | + | |
| 247 | + | echo -ne "\n\n${TITLE_LINE}" |
| 248 | + | echo -ne "\nFINISHED" |
| 249 | + | echo -ne "\n${TITLE_LINE}\n" |
| 250 | + | |