├── CONTRIBUTORS.md ├── CHANGELOG.md ├── README.md └── LinEnum.sh /CONTRIBUTORS.md: -------------------------------------------------------------------------------- 1 | Following People have contributed to various features (list in no particular order): 2 | 3 | * @roo7break (http://roo7break.co.uk/) : added reporting functionality [added to version 3 (support discontinued in later versions).] 4 | * @Reboare : added lxc container checks 5 | * @phackt : added various checks (adm group, SELinux Presence, fstab) 6 | * @anantshri (http://anantshri.info) : code optimization, loaded kernel modules listing -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | Note: Export functionality is currently in the experimental stage. 4 | 5 | ## V0.7 (work in progress) 6 | Additions 7 | * LX Container checks 8 | * Loaded Kernel Modules list 9 | * adm group listing 10 | * SELinux Presence 11 | 12 | Modifications 13 | * Code optimization: everything is in functions, cat grep awk pair optimized. 14 | 15 | ## V0.6 (release 12-05-2017) 16 | Additions 17 | * ARP information added 18 | * Shows users currently logged onto the host 19 | * Added checks to show env information 20 | * Displays enabled Apache modules 21 | * Checks to see if we're in a Docker container 22 | * Checks to see if we're hosting Docker services 23 | 24 | Modifications 25 | * Tweaked the SSH search as we were getting false negatives 26 | * Tweaked the searches used for SUID, GUID binaries 27 | * Fixed issues with some commands not, or incorrectly, redirecting to error 28 | 29 | ## V0.5 (release 27-01-2014) 30 | Additions 31 | * Interface tweaks including the following additional switches: 32 | ** -e :export functionality 33 | ** -r :generate report output 34 | ** -t :perform thorough tests 35 | * Thorough tests include lengthy checks, if the -t switch is absent, a default 'quick' scan is performed 36 | * Export functionality copies 'interesting' files to a specified location for offline analysis 37 | * Checks added for inetd.conf binary ownership 38 | * Extracts password policy and hashing information from /etc/login.defs 39 | * Checks umask value 40 | 41 | Modifications 42 | * Reporting functionality now has a dependency on 'tee' 43 | * Fixed/modified user/group scan 44 | * Tidied sudoer file extraction command 45 | 46 | ## V0.4 (release 05-08-2013) 47 | Additions 48 | * Added basic usage details to display on start-up 49 | * Added cron.deny/cron.allow checks 50 | 51 | Modifications 52 | * Fixed printing of scan start date when output is saved to file 53 | * Tidied up output when output is saved to a file 54 | 55 | ## V0.3 (release 30-08-2013) 56 | Edited by Nikhil Sreekumar (@roo7break) 57 | Enhancements 58 | * Support for multiple keywords for searching added (space separated) 59 | * Search for keywords optimised 60 | * Store output to file and pass seach keywords from command line (e.g. ./LinEnum.sh output.txt "password credential username" 61 | 62 | ## V0.2 (release 30-08-2013) 63 | Additions 64 | * Date/time is displayed when the scan is started 65 | * Checks for word-readable files in /home and displays positive matches 66 | * Apache user config (user/group) details displayed (if applicable) 67 | * Details all members of our users' current groups 68 | * Lists available shells 69 | * Performs basics SSH checks (i.e. what can be read/where is it stored and associated permissions) 70 | * Locates and lists password hashes that may be found in /etc/passwd on old setups (big thanks to www.pentestmonkey.net) 71 | * Locates credentials file and username/passwords in /etc/fstab 72 | 73 | Modifications: 74 | * ifconfig command simplified so 'br' & 'em' interfaces details are also shown 75 | * Keyword search also includes *.ini files 76 | 77 | ## V0.1 (release 19-08-2013) 78 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # LinEnum 2 | For more information visit www.rebootuser.com 3 | 4 | Note: Export functionality is currently in the experimental stage. 5 | 6 | General usage: 7 | 8 | version 0.7 (work in progress) 9 | 10 | * Example: ./LinEnum.sh -k keyword -r report -e /tmp/ -t 11 | 12 | OPTIONS: 13 | * -k Enter keyword 14 | * -e Enter export location 15 | * -t Include thorough (lengthy) tests 16 | * -r Enter report name 17 | * -h Displays this help text 18 | 19 | 20 | Running with no options = limited scans/no output file 21 | 22 | * -e Requires the user enters an output location i.e. /tmp/export. If this location does not exist, it will be created. 23 | * -r Requires the user to enter a report name. The report (.txt file) will be saved to the current working directory. 24 | * -t Performs thorough (slow) tests. Without this switch default 'quick' scans are performed. 25 | * -k An optional switch for which the user can search for a single keyword within many files (documented below). 26 | 27 | See CHANGELOG.md for further details 28 | 29 | High-level summary of the checks/tasks performed by LinEnum: 30 | 31 | * Kernel and distribution release details 32 | * System Information: 33 | * Hostname 34 | * Networking details: 35 | * Current IP 36 | * Default route details 37 | * DNS server information 38 | * User Information: 39 | * Current user details 40 | * Last logged on users 41 | * Shows users logged onto the host 42 | * List all users including uid/gid information 43 | * List root accounts 44 | * Extracts password policies and hash storage method information 45 | * Checks umask value 46 | * Checks if password hashes are stored in /etc/passwd 47 | * Extract full details for ‘default’ uid’s such as 0, 1000, 1001 etc 48 | * Attempt to read restricted files i.e. /etc/shadow 49 | * List current users history files (i.e .bash_history, .nano_history etc.) 50 | * Basic SSH checks 51 | * Privileged access: 52 | * Determine if /etc/sudoers is accessible 53 | * Determine if the current user has Sudo access without a password 54 | * Are known ‘good’ breakout binaries available via Sudo (i.e. nmap, vim etc.) 55 | * Is root’s home directory accessible 56 | * List permissions for /home/ 57 | * Environmental: 58 | * Display current $PATH 59 | * Displays env information 60 | * Jobs/Tasks: 61 | * List all cron jobs 62 | * Locate all world-writable cron jobs 63 | * Locate cron jobs owned by other users of the system 64 | * Services: 65 | * List network connections (TCP & UDP) 66 | * List running processes 67 | * Lookup and list process binaries and associated permissions 68 | * List inetd.conf/xined.conf contents and associated binary file permissions 69 | * List init.d binary permissions 70 | * Version Information (of the following): 71 | * Sudo 72 | * MYSQL 73 | * Postgres 74 | * Apache 75 | * Checks user config 76 | * Shows enabled modules 77 | * Default/Weak Credentials: 78 | * Checks for default/weak Postgres accounts 79 | * Checks for default/weak MYSQL accounts 80 | * Searches: 81 | * Locate all SUID/GUID files 82 | * Locate all world-writable SUID/GUID files 83 | * Locate all SUID/GUID files owned by root 84 | * Locate ‘interesting’ SUID/GUID files (i.e. nmap, vim etc) 85 | * List all world-writable files 86 | * Find/list all accessible *.plan files and display contents 87 | * Find/list all accessible *.rhosts files and display contents 88 | * Show NFS server details 89 | * Locate *.conf and *.log files containing keyword supplied at script runtime 90 | * List all *.conf files located in /etc 91 | * Locate mail 92 | * Platform/software specific tests: 93 | * Checks to determine if we're in a Docker container 94 | * Checks to see if the host has Docker installed 95 | -------------------------------------------------------------------------------- /LinEnum.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | #A script to enumerate local information from a Linux host 3 | v="version 0.7" 4 | #@rebootuser 5 | 6 | #help function 7 | usage () 8 | { 9 | echo -e "\n\e[00;31m#########################################################\e[00m" 10 | echo -e "\e[00;31m#\e[00m" "\e[00;33mLocal Linux Enumeration & Privilege Escalation Script\e[00m" "\e[00;31m#\e[00m" 11 | echo -e "\e[00;31m#########################################################\e[00m" 12 | echo -e "\e[00;33m# www.rebootuser.com | @rebootuser \e[00m" 13 | echo -e "\e[00;33m# $v\e[00m\n" 14 | echo -e "\e[00;33m# Example: ./LinEnum.sh -k keyword -r report -e /tmp/ -t \e[00m\n" 15 | 16 | echo "OPTIONS:" 17 | echo "-k Enter keyword" 18 | echo "-e Enter export location" 19 | echo "-t Include thorough (lengthy) tests" 20 | echo "-r Enter report name" 21 | echo "-h Displays this help text" 22 | echo -e "\n" 23 | echo "Running with no options = limited scans/no output file" 24 | 25 | echo -e "\e[00;31m#########################################################\e[00m" 26 | } 27 | header() 28 | { 29 | echo -e "\n\e[00;31m#########################################################\e[00m" 30 | echo -e "\e[00;31m#\e[00m" "\e[00;33mLocal Linux Enumeration & Privilege Escalation Script\e[00m" "\e[00;31m#\e[00m" 31 | echo -e "\e[00;31m#########################################################\e[00m" 32 | echo -e "\e[00;33m# www.rebootuser.com\e[00m" 33 | echo -e "\e[00;33m# $version\e[00m\n" 34 | 35 | } 36 | 37 | debug_info() 38 | { 39 | echo "Debug Info" 40 | 41 | if [ "$keyword" ]; then 42 | echo "keyword = $keyword" 43 | else 44 | : 45 | fi 46 | 47 | if [ "$report" ]; then 48 | echo "report name = $report" 49 | else 50 | : 51 | fi 52 | 53 | if [ "$export" ]; then 54 | echo "export location = $export" 55 | else 56 | : 57 | fi 58 | 59 | if [ "$thorough" ]; then 60 | echo "thorough tests = enabled" 61 | else 62 | echo "thorough tests = disabled" 63 | fi 64 | 65 | sleep 2 66 | 67 | if [ "$export" ]; then 68 | mkdir $export 2>/dev/null 69 | format=$export/LinEnum-export-`date +"%d-%m-%y"` 70 | mkdir $format 2>/dev/null 71 | else 72 | : 73 | fi 74 | 75 | who=`whoami` 2>/dev/null 76 | echo -e "\n" 77 | 78 | echo -e "\e[00;33mScan started at:"; date 79 | echo -e "\e[00m\n" 80 | } 81 | 82 | system_info() 83 | { 84 | echo -e "\e[00;33m### SYSTEM ##############################################\e[00m" 85 | 86 | #basic kernel info 87 | unameinfo=`uname -a 2>/dev/null` 88 | if [ "$unameinfo" ]; then 89 | echo -e "\e[00;31mKernel information:\e[00m\n$unameinfo" 90 | echo -e "\n" 91 | else 92 | : 93 | fi 94 | 95 | procver=`cat /proc/version 2>/dev/null` 96 | if [ "$procver" ]; then 97 | echo -e "\e[00;31mKernel information (continued):\e[00m\n$procver" 98 | echo -e "\n" 99 | else 100 | : 101 | fi 102 | 103 | #search all *-release files for version info 104 | release=`cat /etc/*-release 2>/dev/null` 105 | if [ "$release" ]; then 106 | echo -e "\e[00;31mSpecific release information:\e[00m\n$release" 107 | echo -e "\n" 108 | else 109 | : 110 | fi 111 | 112 | #target hostname info 113 | hostnamed=`hostname 2>/dev/null` 114 | if [ "$hostnamed" ]; then 115 | echo -e "\e[00;31mHostname:\e[00m\n$hostnamed" 116 | echo -e "\n" 117 | else 118 | : 119 | fi 120 | } 121 | 122 | user_info() 123 | { 124 | echo -e "\e[00;33m### USER/GROUP ##########################################\e[00m" 125 | 126 | #current user details 127 | currusr=`id 2>/dev/null` 128 | if [ "$currusr" ]; then 129 | echo -e "\e[00;31mCurrent user/group info:\e[00m\n$currusr" 130 | echo -e "\n" 131 | else 132 | : 133 | fi 134 | 135 | #last logged on user information 136 | lastlogedonusrs=`lastlog 2>/dev/null |grep -v "Never" 2>/dev/null` 137 | if [ "$lastlogedonusrs" ]; then 138 | echo -e "\e[00;31mUsers that have previously logged onto the system:\e[00m\n$lastlogedonusrs" 139 | echo -e "\n" 140 | else 141 | : 142 | fi 143 | 144 | 145 | #who else is logged on 146 | loggedonusrs=`w 2>/dev/null` 147 | if [ "$loggedonusrs" ]; then 148 | echo -e "\e[00;31mWho else is logged on:\e[00m\n$loggedonusrs" 149 | echo -e "\n" 150 | else 151 | : 152 | fi 153 | 154 | #lists all id's and respective group(s) 155 | grpinfo=`for i in $(cut -d":" -f1 /etc/passwd 2>/dev/null);do id $i;done 2>/dev/null` 156 | if [ "$grpinfo" ]; then 157 | echo -e "\e[00;31mGroup memberships:\e[00m\n$grpinfo" 158 | #added by phackt - look for adm group (thanks patrick) 159 | adm_users=$(echo -e "$grpinfo" | grep "(adm)") 160 | if [[ ! -z $adm_users ]]; 161 | then 162 | echo -e "\nSeems we met some admin users!!!\n" 163 | echo -e "$adm_users\n" 164 | fi 165 | echo -e "\n" 166 | else 167 | : 168 | fi 169 | 170 | #checks to see if any hashes are stored in /etc/passwd (depreciated *nix storage method) 171 | hashesinpasswd=`grep -v '^[^:]*:[x]' /etc/passwd 2>/dev/null` 172 | if [ "$hashesinpasswd" ]; then 173 | echo -e "\e[00;33mIt looks like we have password hashes in /etc/passwd!\e[00m\n$hashesinpasswd" 174 | echo -e "\n" 175 | else 176 | : 177 | fi 178 | 179 | #locate custom user accounts with some 'known default' uids 180 | readpasswd=`grep -v "^#" /etc/passwd | awk -F: '$3 == 0 || $3 == 500 || $3 == 501 || $3 == 502 || $3 == 1000 || $3 == 1001 || $3 == 1002 || $3 == 2000 || $3 == 2001 || $3 == 2002 { print }'` 181 | if [ "$readpasswd" ]; then 182 | echo -e "\e[00;31mSample entires from /etc/passwd (searching for uid values 0, 500, 501, 502, 1000, 1001, 1002, 2000, 2001, 2002):\e[00m\n$readpasswd" 183 | echo -e "\n" 184 | else 185 | : 186 | fi 187 | 188 | if [ "$export" ] && [ "$readpasswd" ]; then 189 | mkdir $format/etc-export/ 2>/dev/null 190 | cp /etc/passwd $format/etc-export/passwd 2>/dev/null 191 | else 192 | : 193 | fi 194 | 195 | #checks to see if the shadow file can be read 196 | readshadow=`cat /etc/shadow 2>/dev/null` 197 | if [ "$readshadow" ]; then 198 | echo -e "\e[00;33m***We can read the shadow file!\e[00m\n$readshadow" 199 | echo -e "\n" 200 | else 201 | : 202 | fi 203 | 204 | if [ "$export" ] && [ "$readshadow" ]; then 205 | mkdir $format/etc-export/ 2>/dev/null 206 | cp /etc/shadow $format/etc-export/shadow 2>/dev/null 207 | else 208 | : 209 | fi 210 | 211 | #checks to see if /etc/master.passwd can be read - BSD 'shadow' variant 212 | readmasterpasswd=`cat /etc/master.passwd 2>/dev/null` 213 | if [ "$readmasterpasswd" ]; then 214 | echo -e "\e[00;33m***We can read the master.passwd file!\e[00m\n$readmasterpasswd" 215 | echo -e "\n" 216 | else 217 | : 218 | fi 219 | 220 | if [ "$export" ] && [ "$readmasterpasswd" ]; then 221 | mkdir $format/etc-export/ 2>/dev/null 222 | cp /etc/master.passwd $format/etc-export/master.passwd 2>/dev/null 223 | else 224 | : 225 | fi 226 | 227 | #all root accounts (uid 0) 228 | echo -e "\e[00;31mSuper user account(s):\e[00m" | tee -a $report 2>/dev/null; grep -v -E "^#" /etc/passwd 2>/dev/null| awk -F: '$3 == 0 { print $1}' 2>/dev/null 229 | echo -e "\n" 230 | 231 | #pull out vital sudoers info 232 | sudoers=`grep -v -e '^$' /etc/sudoers 2>/dev/null |grep -v "#" 2>/dev/null` 233 | if [ "$sudoers" ]; then 234 | echo -e "\e[00;31mSudoers configuration (condensed):\e[00m$sudoers" | tee -a $report 2>/dev/null 235 | echo -e "\n" 236 | else 237 | : 238 | fi 239 | 240 | if [ "$export" ] && [ "$sudoers" ]; then 241 | mkdir $format/etc-export/ 2>/dev/null 242 | cp /etc/sudoers $format/etc-export/sudoers 2>/dev/null 243 | else 244 | : 245 | fi 246 | 247 | #can we sudo without supplying a password 248 | sudoperms=`echo '' | sudo -S -l 2>/dev/null` 249 | if [ "$sudoperms" ]; then 250 | echo -e "\e[00;33mWe can sudo without supplying a password!\e[00m\n$sudoperms" 251 | echo -e "\n" 252 | else 253 | : 254 | fi 255 | 256 | #known 'good' breakout binaries 257 | sudopwnage=`echo '' | sudo -S -l 2>/dev/null | grep -w 'nmap\|perl\|'awk'\|'find'\|'bash'\|'sh'\|'man'\|'more'\|'less'\|'vi'\|'emacs'\|'vim'\|'nc'\|'netcat'\|python\|ruby\|lua\|irb' | xargs -r ls -la 2>/dev/null` 258 | if [ "$sudopwnage" ]; then 259 | echo -e "\e[00;33m***Possible Sudo PWNAGE!\e[00m\n$sudopwnage" 260 | echo -e "\n" 261 | else 262 | : 263 | fi 264 | 265 | #checks to see if roots home directory is accessible 266 | rthmdir=`ls -ahl /root/ 2>/dev/null` 267 | if [ "$rthmdir" ]; then 268 | echo -e "\e[00;33m***We can read root's home directory!\e[00m\n$rthmdir" 269 | echo -e "\n" 270 | else 271 | : 272 | fi 273 | 274 | #displays /home directory permissions - check if any are lax 275 | homedirperms=`ls -ahl /home/ 2>/dev/null` 276 | if [ "$homedirperms" ]; then 277 | echo -e "\e[00;31mAre permissions on /home directories lax:\e[00m\n$homedirperms" 278 | echo -e "\n" 279 | else 280 | : 281 | fi 282 | 283 | #looks for files we can write to that don't belong to us 284 | if [ "$thorough" = "1" ]; then 285 | grfilesall=`find / -writable -not -user \`whoami\` -type f -not -path "/proc/*" -exec ls -al {} \; 2>/dev/null` 286 | if [ "$grfilesall" ]; then 287 | echo -e "\e[00;31mFiles not owned by user but writable by group:\e[00m\n$grfilesall" 288 | echo -e "\n" 289 | else 290 | : 291 | fi 292 | fi 293 | 294 | #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 295 | if [ "$thorough" = "1" ]; then 296 | wrfileshm=`find /home/ -perm -4 -type f -exec ls -al {} \; 2>/dev/null` 297 | if [ "$wrfileshm" ]; then 298 | echo -e "\e[00;31mWorld-readable files within /home:\e[00m\n$wrfileshm" 299 | echo -e "\n" 300 | else 301 | : 302 | fi 303 | else 304 | : 305 | fi 306 | 307 | if [ "$thorough" = "1" ]; then 308 | if [ "$export" ] && [ "$wrfileshm" ]; then 309 | mkdir $format/wr-files/ 2>/dev/null 310 | for i in $wrfileshm; do cp --parents $i $format/wr-files/ ; done 2>/dev/null 311 | else 312 | : 313 | fi 314 | else 315 | : 316 | fi 317 | 318 | #lists current user's home directory contents 319 | if [ "$thorough" = "1" ]; then 320 | homedircontents=`ls -ahl ~ 2>/dev/null` 321 | if [ "$homedircontents" ] ; then 322 | echo -e "\e[00;31mHome directory contents:\e[00m\n$homedircontents" 323 | echo -e "\n" 324 | else 325 | : 326 | fi 327 | else 328 | : 329 | fi 330 | 331 | #checks for if various ssh files are accessible - this can take some time so is only 'activated' with thorough scanning switch 332 | if [ "$thorough" = "1" ]; then 333 | 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 \;` 334 | if [ "$sshfiles" ]; then 335 | echo -e "\e[00;31mSSH keys/host information found in the following locations:\e[00m\n$sshfiles" 336 | echo -e "\n" 337 | else 338 | : 339 | fi 340 | else 341 | : 342 | fi 343 | 344 | if [ "$thorough" = "1" ]; then 345 | if [ "$export" ] && [ "$sshfiles" ]; then 346 | mkdir $format/ssh-files/ 2>/dev/null 347 | for i in $sshfiles; do cp --parents $i $format/ssh-files/; done 2>/dev/null 348 | else 349 | : 350 | fi 351 | else 352 | : 353 | fi 354 | 355 | #is root permitted to login via ssh 356 | sshrootlogin=`grep "PermitRootLogin " /etc/ssh/sshd_config 2>/dev/null | grep -v "#" | awk '{print $2}'` 357 | if [ "$sshrootlogin" = "yes" ]; then 358 | echo -e "\e[00;31mRoot is allowed to login via SSH:\e[00m" ; grep "PermitRootLogin " /etc/ssh/sshd_config 2>/dev/null | grep -v "#" 359 | echo -e "\n" 360 | else 361 | : 362 | fi 363 | } 364 | 365 | environmental_info() 366 | { 367 | echo -e "\e[00;33m### ENVIRONMENTAL #######################################\e[00m" 368 | 369 | #env information 370 | envinfo=`env 2>/dev/null | grep -v 'LS_COLORS' 2>/dev/null` 371 | if [ "$envinfo" ]; then 372 | echo -e "\e[00;31m Environment information:\e[00m\n$envinfo" 373 | echo -e "\n" 374 | else 375 | : 376 | fi 377 | 378 | #check if selinux is enabled 379 | sestatus=`sestatus 2>/dev/null` 380 | if [ "$sestatus" ]; then 381 | echo -e "\e[00;31mSELinux seems present:\e[00m\n$sestatus" 382 | echo -e "\n" 383 | fi 384 | 385 | #phackt 386 | 387 | #current path configuration 388 | pathinfo=`echo $PATH 2>/dev/null` 389 | if [ "$pathinfo" ]; then 390 | echo -e "\e[00;31mPath information:\e[00m\n$pathinfo" 391 | echo -e "\n" 392 | else 393 | : 394 | fi 395 | 396 | #lists available shells 397 | shellinfo=`cat /etc/shells 2>/dev/null` 398 | if [ "$shellinfo" ]; then 399 | echo -e "\e[00;31mAvailable shells:\e[00m\n$shellinfo" 400 | echo -e "\n" 401 | else 402 | : 403 | fi 404 | 405 | #current umask value with both octal and symbolic output 406 | umask=`umask -S 2>/dev/null & umask 2>/dev/null` 407 | if [ "$umask" ]; then 408 | echo -e "\e[00;31mCurrent umask value:\e[00m\n$umask" 409 | echo -e "\n" 410 | else 411 | : 412 | fi 413 | 414 | #umask value as in /etc/login.defs 415 | umaskdef=`grep -i "^UMASK" /etc/login.defs 2>/dev/null` 416 | if [ "$umaskdef" ]; then 417 | echo -e "\e[00;31mumask value as specified in /etc/login.defs:\e[00m\n$umaskdef" 418 | echo -e "\n" 419 | else 420 | : 421 | fi 422 | 423 | #password policy information as stored in /etc/login.defs 424 | logindefs=`grep "^PASS_MAX_DAYS\|^PASS_MIN_DAYS\|^PASS_WARN_AGE\|^ENCRYPT_METHOD" /etc/login.defs 2>/dev/null` 425 | if [ "$logindefs" ]; then 426 | echo -e "\e[00;31mPassword and storage information:\e[00m\n$logindefs" 427 | echo -e "\n" 428 | else 429 | : 430 | fi 431 | 432 | if [ "$export" ] && [ "$logindefs" ]; then 433 | mkdir $format/etc-export/ 2>/dev/null 434 | cp /etc/login.defs $format/etc-export/login.defs 2>/dev/null 435 | else 436 | : 437 | fi 438 | } 439 | 440 | job_info() 441 | { 442 | echo -e "\e[00;33m### JOBS/TASKS ##########################################\e[00m" 443 | 444 | #are there any cron jobs configured 445 | cronjobs=`ls -la /etc/cron* 2>/dev/null` 446 | if [ "$cronjobs" ]; then 447 | echo -e "\e[00;31mCron jobs:\e[00m\n$cronjobs" 448 | echo -e "\n" 449 | else 450 | : 451 | fi 452 | 453 | #can we manipulate these jobs in any way 454 | cronjobwwperms=`find /etc/cron* -perm -0002 -type f -exec ls -la {} \; -exec cat {} 2>/dev/null \;` 455 | if [ "$cronjobwwperms" ]; then 456 | echo -e "\e[00;33m***World-writable cron jobs and file contents:\e[00m\n$cronjobwwperms" 457 | echo -e "\n" 458 | else 459 | : 460 | fi 461 | 462 | #contab contents 463 | crontab=`cat /etc/crontab 2>/dev/null` 464 | if [ "$crontab" ]; then 465 | echo -e "\e[00;31mCrontab contents:\e[00m\n$crontab" 466 | echo -e "\n" 467 | else 468 | : 469 | fi 470 | 471 | crontabvar=`ls -la /var/spool/cron/crontabs 2>/dev/null` 472 | if [ "$crontabvar" ]; then 473 | echo -e "\e[00;31mAnything interesting in /var/spool/cron/crontabs:\e[00m\n$crontabvar" 474 | echo -e "\n" 475 | else 476 | : 477 | fi 478 | 479 | anacronjobs=`ls -la /etc/anacrontab 2>/dev/null; cat /etc/anacrontab 2>/dev/null` 480 | if [ "$anacronjobs" ]; then 481 | echo -e "\e[00;31mAnacron jobs and associated file permissions:\e[00m\n$anacronjobs" 482 | echo -e "\n" 483 | else 484 | : 485 | fi 486 | 487 | anacrontab=`ls -la /var/spool/anacron 2>/dev/null` 488 | if [ "$anacrontab" ]; then 489 | echo -e "\e[00;31mWhen were jobs last executed (/var/spool/anacron contents):\e[00m\n$anacrontab" 490 | echo -e "\n" 491 | else 492 | : 493 | fi 494 | 495 | #pull out account names from /etc/passwd and see if any users have associated cronjobs (priv command) 496 | cronother=`cut -d ":" -f 1 /etc/passwd | xargs -n1 crontab -l -u 2>/dev/null` 497 | if [ "$cronother" ]; then 498 | echo -e "\e[00;31mJobs held by all users:\e[00m\n$cronother" 499 | echo -e "\n" 500 | else 501 | : 502 | fi 503 | } 504 | networking_info() 505 | { 506 | echo -e "\e[00;33m### NETWORKING ##########################################\e[00m" 507 | 508 | #nic information 509 | nicinfo=`/sbin/ifconfig -a 2>/dev/null` 510 | if [ "$nicinfo" ]; then 511 | echo -e "\e[00;31mNetwork & IP info:\e[00m\n$nicinfo" 512 | echo -e "\n" 513 | else 514 | : 515 | fi 516 | 517 | arpinfo=`arp -a 2>/dev/null` 518 | if [ "$arpinfo" ]; then 519 | echo -e "\e[00;31mARP history:\e[00m\n$arpinfo" 520 | echo -e "\n" 521 | else 522 | : 523 | fi 524 | 525 | #dns settings 526 | nsinfo=`grep "nameserver" /etc/resolv.conf 2>/dev/null` 527 | if [ "$nsinfo" ]; then 528 | echo -e "\e[00;31mNameserver(s):\e[00m\n$nsinfo" 529 | echo -e "\n" 530 | else 531 | : 532 | fi 533 | 534 | #default route configuration 535 | defroute=`route 2>/dev/null | grep default` 536 | if [ "$defroute" ]; then 537 | echo -e "\e[00;31mDefault route:\e[00m\n$defroute" 538 | echo -e "\n" 539 | else 540 | : 541 | fi 542 | 543 | #listening TCP 544 | tcpservs=`netstat -antp 2>/dev/null` 545 | if [ "$tcpservs" ]; then 546 | echo -e "\e[00;31mListening TCP:\e[00m\n$tcpservs" 547 | echo -e "\n" 548 | else 549 | : 550 | fi 551 | 552 | #listening UDP 553 | udpservs=`netstat -anup 2>/dev/null` 554 | if [ "$udpservs" ]; then 555 | echo -e "\e[00;31mListening UDP:\e[00m\n$udpservs" 556 | echo -e "\n" 557 | else 558 | : 559 | fi 560 | } 561 | services_info() 562 | { 563 | echo -e "\e[00;33m### SERVICES #############################################\e[00m" 564 | 565 | #running processes 566 | psaux=`ps aux 2>/dev/null` 567 | if [ "$psaux" ]; then 568 | echo -e "\e[00;31mRunning processes:\e[00m\n$psaux" 569 | echo -e "\n" 570 | else 571 | : 572 | fi 573 | 574 | #lookup process binary path and permissisons 575 | procperm=`ps aux 2>/dev/null | awk '{print $11}'|xargs -r ls -la 2>/dev/null |awk '!x[$0]++' 2>/dev/null` 576 | if [ "$procperm" ]; then 577 | echo -e "\e[00;31mProcess binaries & associated permissions (from above list):\e[00m\n$procperm" 578 | echo -e "\n" 579 | else 580 | : 581 | fi 582 | 583 | if [ "$export" ] && [ "$procperm" ]; then 584 | procpermbase=`ps aux 2>/dev/null | awk '{print $11}' | xargs -r ls 2>/dev/null | awk '!x[$0]++' 2>/dev/null` 585 | mkdir $format/ps-export/ 2>/dev/null 586 | for i in $procpermbase; do cp --parents $i $format/ps-export/; done 2>/dev/null 587 | else 588 | : 589 | fi 590 | 591 | #anything 'useful' in inetd.conf 592 | inetdread=`cat /etc/inetd.conf 2>/dev/null` 593 | if [ "$inetdread" ]; then 594 | echo -e "\e[00;31mContents of /etc/inetd.conf:\e[00m\n$inetdread" 595 | echo -e "\n" 596 | else 597 | : 598 | fi 599 | 600 | if [ "$export" ] && [ "$inetdread" ]; then 601 | mkdir $format/etc-export/ 2>/dev/null 602 | cp /etc/inetd.conf $format/etc-export/inetd.conf 2>/dev/null 603 | else 604 | : 605 | fi 606 | 607 | #very 'rough' command to extract associated binaries from inetd.conf & show permisisons of each 608 | inetdbinperms=`awk '{print $7}' /etc/inetd.conf 2>/dev/null |xargs -r ls -la 2>/dev/null` 609 | if [ "$inetdbinperms" ]; then 610 | echo -e "\e[00;31mThe related inetd binary permissions:\e[00m\n$inetdbinperms" 611 | echo -e "\n" 612 | else 613 | : 614 | fi 615 | 616 | xinetdread=`cat /etc/xinetd.conf 2>/dev/null` 617 | if [ "$xinetdread" ]; then 618 | echo -e "\e[00;31mContents of /etc/xinetd.conf:\e[00m\n$xinetdread" 619 | echo -e "\n" 620 | else 621 | : 622 | fi 623 | 624 | if [ "$export" ] && [ "$xinetdread" ]; then 625 | mkdir $format/etc-export/ 2>/dev/null 626 | cp /etc/xinetd.conf $format/etc-export/xinetd.conf 2>/dev/null 627 | else 628 | : 629 | fi 630 | 631 | xinetdincd=`grep "/etc/xinetd.d" /etc/xinetd.conf 2>/dev/null` 632 | if [ "$xinetdincd" ]; then 633 | 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 634 | echo -e "\n" 635 | else 636 | : 637 | fi 638 | 639 | #very 'rough' command to extract associated binaries from xinetd.conf & show permisisons of each 640 | xinetdbinperms=`awk '{print $7}' /etc/xinetd.conf 2>/dev/null |xargs -r ls -la 2>/dev/null` 641 | if [ "$xinetdbinperms" ]; then 642 | echo -e "\e[00;31mThe related xinetd binary permissions:\e[00m\n$xinetdbinperms" 643 | echo -e "\n" 644 | else 645 | : 646 | fi 647 | 648 | initdread=`ls -la /etc/init.d 2>/dev/null` 649 | if [ "$initdread" ]; then 650 | echo -e "\e[00;31m/etc/init.d/ binary permissions:\e[00m\n$initdread" 651 | echo -e "\n" 652 | else 653 | : 654 | fi 655 | 656 | #init.d files NOT belonging to root! 657 | initdperms=`find /etc/init.d/ \! -uid 0 -type f 2>/dev/null |xargs -r ls -la 2>/dev/null` 658 | if [ "$initdperms" ]; then 659 | echo -e "\e[00;31m/etc/init.d/ files not belonging to root (uid 0):\e[00m\n$initdperms" 660 | echo -e "\n" 661 | else 662 | : 663 | fi 664 | 665 | rcdread=`ls -la /etc/rc.d/init.d 2>/dev/null` 666 | if [ "$rcdread" ]; then 667 | echo -e "\e[00;31m/etc/rc.d/init.d binary permissions:\e[00m\n$rcdread" 668 | echo -e "\n" 669 | else 670 | : 671 | fi 672 | 673 | #init.d files NOT belonging to root! 674 | rcdperms=`find /etc/rc.d/init.d \! -uid 0 -type f 2>/dev/null |xargs -r ls -la 2>/dev/null` 675 | if [ "$rcdperms" ]; then 676 | echo -e "\e[00;31m/etc/rc.d/init.d files not belonging to root (uid 0):\e[00m\n$rcdperms" 677 | echo -e "\n" 678 | else 679 | : 680 | fi 681 | 682 | usrrcdread=`ls -la /usr/local/etc/rc.d 2>/dev/null` 683 | if [ "$usrrcdread" ]; then 684 | echo -e "\e[00;31m/usr/local/etc/rc.d binary permissions:\e[00m\n$usrrcdread" 685 | echo -e "\n" 686 | else 687 | : 688 | fi 689 | 690 | #rc.d files NOT belonging to root! 691 | usrrcdperms=`find /usr/local/etc/rc.d \! -uid 0 -type f 2>/dev/null |xargs -r ls -la 2>/dev/null` 692 | if [ "$usrrcdperms" ]; then 693 | echo -e "\e[00;31m/usr/local/etc/rc.d files not belonging to root (uid 0):\e[00m\n$usrrcdperms" 694 | echo -e "\n" 695 | else 696 | : 697 | fi 698 | } 699 | software_configs() 700 | { 701 | echo -e "\e[00;33m### SOFTWARE #############################################\e[00m" 702 | 703 | #sudo version - check to see if there are any known vulnerabilities with this 704 | sudover=`sudo -V 2>/dev/null| grep "Sudo version" 2>/dev/null` 705 | if [ "$sudover" ]; then 706 | echo -e "\e[00;31mSudo version:\e[00m\n$sudover" 707 | echo -e "\n" 708 | else 709 | : 710 | fi 711 | 712 | #mysql details - if installed 713 | mysqlver=`mysql --version 2>/dev/null` 714 | if [ "$mysqlver" ]; then 715 | echo -e "\e[00;31mMYSQL version:\e[00m\n$mysqlver" 716 | echo -e "\n" 717 | else 718 | : 719 | fi 720 | 721 | #checks to see if root/root will get us a connection 722 | mysqlconnect=`mysqladmin -uroot -proot version 2>/dev/null` 723 | if [ "$mysqlconnect" ]; then 724 | echo -e "\e[00;33m***We can connect to the local MYSQL service with default root/root credentials!\e[00m\n$mysqlconnect" 725 | echo -e "\n" 726 | else 727 | : 728 | fi 729 | 730 | #mysql version details 731 | mysqlconnectnopass=`mysqladmin -uroot version 2>/dev/null` 732 | if [ "$mysqlconnectnopass" ]; then 733 | echo -e "\e[00;33m***We can connect to the local MYSQL service as 'root' and without a password!\e[00m\n$mysqlconnectnopass" 734 | echo -e "\n" 735 | else 736 | : 737 | fi 738 | 739 | #postgres details - if installed 740 | postgver=`psql -V 2>/dev/null` 741 | if [ "$postgver" ]; then 742 | echo -e "\e[00;31mPostgres version:\e[00m\n$postgver" 743 | echo -e "\n" 744 | else 745 | : 746 | fi 747 | 748 | #checks to see if any postgres password exists and connects to DB 'template0' - following commands are a variant on this 749 | postcon1=`psql -U postgres template0 -c 'select version()' 2>/dev/null | grep version` 750 | if [ "$postcon1" ]; then 751 | echo -e "\e[00;33m***We can connect to Postgres DB 'template0' as user 'postgres' with no password!:\e[00m\n$postcon1" 752 | echo -e "\n" 753 | else 754 | : 755 | fi 756 | 757 | postcon11=`psql -U postgres template1 -c 'select version()' 2>/dev/null | grep version` 758 | if [ "$postcon11" ]; then 759 | echo -e "\e[00;33m***We can connect to Postgres DB 'template1' as user 'postgres' with no password!:\e[00m\n$postcon11" 760 | echo -e "\n" 761 | else 762 | : 763 | fi 764 | 765 | postcon2=`psql -U pgsql template0 -c 'select version()' 2>/dev/null | grep version` 766 | if [ "$postcon2" ]; then 767 | echo -e "\e[00;33m***We can connect to Postgres DB 'template0' as user 'psql' with no password!:\e[00m\n$postcon2" 768 | echo -e "\n" 769 | else 770 | : 771 | fi 772 | 773 | postcon22=`psql -U pgsql template1 -c 'select version()' 2>/dev/null | grep version` 774 | if [ "$postcon22" ]; then 775 | echo -e "\e[00;33m***We can connect to Postgres DB 'template1' as user 'psql' with no password!:\e[00m\n$postcon22" 776 | echo -e "\n" 777 | else 778 | : 779 | fi 780 | 781 | #apache details - if installed 782 | apachever=`apache2 -v 2>/dev/null; httpd -v 2>/dev/null` 783 | if [ "$apachever" ]; then 784 | echo -e "\e[00;31mApache version:\e[00m\n$apachever" 785 | echo -e "\n" 786 | else 787 | : 788 | fi 789 | 790 | #what account is apache running under 791 | apacheusr=`grep -i 'user\|group' /etc/apache2/envvars 2>/dev/null |awk '{sub(/.*\export /,"")}1' 2>/dev/null` 792 | if [ "$apacheusr" ]; then 793 | echo -e "\e[00;31mApache user configuration:\e[00m\n$apacheusr" 794 | echo -e "\n" 795 | else 796 | : 797 | fi 798 | 799 | if [ "$export" ] && [ "$apacheusr" ]; then 800 | mkdir --parents $format/etc-export/apache2/ 2>/dev/null 801 | cp /etc/apache2/envvars $format/etc-export/apache2/envvars 2>/dev/null 802 | else 803 | : 804 | fi 805 | 806 | #installed apache modules 807 | apachemodules=`apache2ctl -M 2>/dev/null; httpd -M 2>/dev/null` 808 | if [ "$apachemodules" ]; then 809 | echo -e "\e[00;31mInstalled Apache modules:\e[00m\n$apachemodules" 810 | echo -e "\n" 811 | else 812 | : 813 | fi 814 | 815 | #anything in the default http home dirs 816 | 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` 817 | if [ "$apachehomedirs" ]; then 818 | echo -e "\e[00;31mAnything in the Apache home dirs?:\e[00m\n$apachehomedirs" 819 | echo -e "\n" 820 | else 821 | : 822 | fi 823 | } 824 | interesting_files() 825 | { 826 | echo -e "\e[00;33m### INTERESTING FILES ####################################\e[00m" 827 | 828 | #checks to see if various files are installed 829 | echo -e "\e[00;31mUseful 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 830 | echo -e "\n" 831 | 832 | #limited search for installed compilers 833 | 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` 834 | if [ "$compiler" ]; then 835 | echo -e "\e[00;31mInstalled compilers:\e[00m\n$compiler" 836 | echo -e "\n" 837 | else 838 | : 839 | fi 840 | 841 | #manual check - lists out sensitive files, can we read/modify etc. 842 | echo -e "\e[00;31mCan 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 843 | echo -e "\n" 844 | 845 | #search for suid files - this can take some time so is only 'activated' with thorough scanning switch (as are all suid scans below) 846 | if [ "$thorough" = "1" ]; then 847 | findsuid=`find / -perm -4000 -type f -exec ls -la {} 2>/dev/null \;` 848 | if [ "$findsuid" ]; then 849 | echo -e "\e[00;31mSUID files:\e[00m\n$findsuid" 850 | echo -e "\n" 851 | else 852 | : 853 | fi 854 | else 855 | : 856 | fi 857 | 858 | if [ "$thorough" = "1" ]; then 859 | if [ "$export" ] && [ "$findsuid" ]; then 860 | mkdir $format/suid-files/ 2>/dev/null 861 | for i in $findsuid; do cp $i $format/suid-files/; done 2>/dev/null 862 | else 863 | : 864 | fi 865 | else 866 | : 867 | fi 868 | 869 | #list of 'interesting' suid files - feel free to make additions 870 | if [ "$thorough" = "1" ]; then 871 | intsuid=`find / -perm -4000 -type f 2>/dev/null | grep -w 'nmap\|perl\|'awk'\|'find'\|'bash'\|'sh'\|'man'\|'more'\|'less'\|'vi'\|'vim'\|'emacs'\|'nc'\|'netcat'\|python\|ruby\|lua\|irb\|pl' | xargs -r ls -la 2>/dev/null` 872 | if [ "$intsuid" ]; then 873 | echo -e "\e[00;33m***Possibly interesting SUID files:\e[00m\n$intsuid" 874 | echo -e "\n" 875 | else 876 | : 877 | fi 878 | else 879 | : 880 | fi 881 | 882 | #lists word-writable suid files 883 | if [ "$thorough" = "1" ]; then 884 | wwsuid=`find / -perm -4007 -type f -exec ls -la {} 2>/dev/null \;` 885 | if [ "$wwsuid" ]; then 886 | echo -e "\e[00;31mWorld-writable SUID files:\e[00m\n$wwsuid" 887 | echo -e "\n" 888 | else 889 | : 890 | fi 891 | else 892 | : 893 | fi 894 | 895 | #lists world-writable suid files owned by root 896 | if [ "$thorough" = "1" ]; then 897 | wwsuidrt=`find / -uid 0 -perm -4007 -type f -exec ls -la {} 2>/dev/null \;` 898 | if [ "$wwsuidrt" ]; then 899 | echo -e "\e[00;31mWorld-writable SUID files owned by root:\e[00m\n$wwsuidrt" 900 | echo -e "\n" 901 | else 902 | : 903 | fi 904 | else 905 | : 906 | fi 907 | 908 | #search for guid files - this can take some time so is only 'activated' with thorough scanning switch (as are all guid scans below) 909 | if [ "$thorough" = "1" ]; then 910 | findguid=`find / -perm -2000 -type f -exec ls -la {} 2>/dev/null \;` 911 | if [ "$findguid" ]; then 912 | echo -e "\e[00;31mGUID files:\e[00m\n$findguid" 913 | echo -e "\n" 914 | else 915 | : 916 | fi 917 | else 918 | : 919 | fi 920 | 921 | if [ "$thorough" = "1" ]; then 922 | if [ "$export" ] && [ "$findguid" ]; then 923 | mkdir $format/guid-files/ 2>/dev/null 924 | for i in $findguid; do cp $i $format/guid-files/; done 2>/dev/null 925 | else 926 | : 927 | fi 928 | else 929 | : 930 | fi 931 | 932 | #list of 'interesting' guid files - feel free to make additions 933 | if [ "$thorough" = "1" ]; then 934 | intguid=`find / -perm -2000 -type f 2>/dev/null | grep -w 'nmap\|perl\|'awk'\|'find'\|'bash'\|'sh'\|'man'\|'more'\|'less'\|'vi'\|'emacs'\|'vim'\|'nc'\|'netcat'\|python\|ruby\|lua\|irb\|pl' | xargs -r ls -la 2>/dev/null` 935 | if [ "$intguid" ]; then 936 | echo -e "\e[00;33m***Possibly interesting GUID files:\e[00m\n$intguid" 937 | echo -e "\n" 938 | else 939 | : 940 | fi 941 | else 942 | : 943 | fi 944 | 945 | #lists world-writable guid files 946 | if [ "$thorough" = "1" ]; then 947 | wwguid=`find / -perm -2007 -type f -exec ls -la {} 2>/dev/null \;` 948 | if [ "$wwguid" ]; then 949 | echo -e "\e[00;31mWorld-writable GUID files:\e[00m\n$wwguid" 950 | echo -e "\n" 951 | else 952 | : 953 | fi 954 | else 955 | : 956 | fi 957 | 958 | #lists world-writable guid files owned by root 959 | if [ "$thorough" = "1" ]; then 960 | wwguidrt=`find / -uid 0 -perm -2007 -type f -exec ls -la {} 2>/dev/null \;` 961 | if [ "$wwguidrt" ]; then 962 | echo -e "\e[00;31mAWorld-writable GUID files owned by root:\e[00m\n$wwguidrt" 963 | echo -e "\n" 964 | else 965 | : 966 | fi 967 | else 968 | : 969 | fi 970 | 971 | #list all world-writable files excluding /proc 972 | if [ "$thorough" = "1" ]; then 973 | wwfiles=`find / ! -path "*/proc/*" -perm -2 -type f -exec ls -la {} 2>/dev/null \;` 974 | if [ "$wwfiles" ]; then 975 | echo -e "\e[00;31mWorld-writable files (excluding /proc):\e[00m\n$wwfiles" 976 | echo -e "\n" 977 | else 978 | : 979 | fi 980 | else 981 | : 982 | fi 983 | 984 | if [ "$thorough" = "1" ]; then 985 | if [ "$export" ] && [ "$wwfiles" ]; then 986 | mkdir $format/ww-files/ 2>/dev/null 987 | for i in $wwfiles; do cp --parents $i $format/ww-files/; done 2>/dev/null 988 | else 989 | : 990 | fi 991 | else 992 | : 993 | fi 994 | 995 | #are any .plan files accessible in /home (could contain useful information) 996 | usrplan=`find /home -iname *.plan -exec ls -la {} \; -exec cat {} 2>/dev/null \;` 997 | if [ "$usrplan" ]; then 998 | echo -e "\e[00;31mPlan file permissions and contents:\e[00m\n$usrplan" 999 | echo -e "\n" 1000 | else 1001 | : 1002 | fi 1003 | 1004 | if [ "$export" ] && [ "$usrplan" ]; then 1005 | mkdir $format/plan_files/ 2>/dev/null 1006 | for i in $usrplan; do cp --parents $i $format/plan_files/; done 2>/dev/null 1007 | else 1008 | : 1009 | fi 1010 | 1011 | bsdusrplan=`find /usr/home -iname *.plan -exec ls -la {} \; -exec cat {} 2>/dev/null \;` 1012 | if [ "$bsdusrplan" ]; then 1013 | echo -e "\e[00;31mPlan file permissions and contents:\e[00m\n$bsdusrplan" 1014 | echo -e "\n" 1015 | else 1016 | : 1017 | fi 1018 | 1019 | if [ "$export" ] && [ "$bsdusrplan" ]; then 1020 | mkdir $format/plan_files/ 2>/dev/null 1021 | for i in $bsdusrplan; do cp --parents $i $format/plan_files/; done 2>/dev/null 1022 | else 1023 | : 1024 | fi 1025 | 1026 | #are there any .rhosts files accessible - these may allow us to login as another user etc. 1027 | rhostsusr=`find /home -iname *.rhosts -exec ls -la {} 2>/dev/null \; -exec cat {} 2>/dev/null \;` 1028 | if [ "$rhostsusr" ]; then 1029 | echo -e "\e[00;31mrhost config file(s) and file contents:\e[00m\n$rhostsusr" 1030 | echo -e "\n" 1031 | else 1032 | : 1033 | fi 1034 | 1035 | if [ "$export" ] && [ "$rhostsusr" ]; then 1036 | mkdir $format/rhosts/ 2>/dev/null 1037 | for i in $rhostsusr; do cp --parents $i $format/rhosts/; done 2>/dev/null 1038 | else 1039 | : 1040 | fi 1041 | 1042 | bsdrhostsusr=`find /usr/home -iname *.rhosts -exec ls -la {} 2>/dev/null \; -exec cat {} 2>/dev/null \;` 1043 | if [ "$bsdrhostsusr" ]; then 1044 | echo -e "\e[00;31mrhost config file(s) and file contents:\e[00m\n$bsdrhostsusr" 1045 | echo -e "\n" 1046 | else 1047 | : 1048 | fi 1049 | 1050 | if [ "$export" ] && [ "$bsdrhostsusr" ]; then 1051 | mkdir $format/rhosts 2>/dev/null 1052 | for i in $bsdrhostsusr; do cp --parents $i $format/rhosts/; done 2>/dev/null 1053 | else 1054 | : 1055 | fi 1056 | 1057 | rhostssys=`find /etc -iname hosts.equiv -exec ls -la {} 2>/dev/null \; -exec cat {} 2>/dev/null \;` 1058 | if [ "$rhostssys" ]; then 1059 | echo -e "\e[00;31mHosts.equiv file details and file contents: \e[00m\n$rhostssys" 1060 | echo -e "\n" 1061 | else 1062 | : 1063 | fi 1064 | 1065 | if [ "$export" ] && [ "$rhostssys" ]; then 1066 | mkdir $format/rhosts/ 2>/dev/null 1067 | for i in $rhostssys; do cp --parents $i $format/rhosts/; done 2>/dev/null 1068 | else 1069 | : 1070 | fi 1071 | 1072 | #list nfs shares/permisisons etc. 1073 | nfsexports=`ls -la /etc/exports 2>/dev/null; cat /etc/exports 2>/dev/null` 1074 | if [ "$nfsexports" ]; then 1075 | echo -e "\e[00;31mNFS config details: \e[00m\n$nfsexports" 1076 | echo -e "\n" 1077 | else 1078 | : 1079 | fi 1080 | 1081 | if [ "$export" ] && [ "$nfsexports" ]; then 1082 | mkdir $format/etc-export/ 2>/dev/null 1083 | cp /etc/exports $format/etc-export/exports 2>/dev/null 1084 | else 1085 | : 1086 | fi 1087 | 1088 | if [ "$thorough" = "1" ]; then 1089 | #phackt 1090 | #displaying /etc/fstab 1091 | fstab=`cat /etc/fstab 2>/dev/null` 1092 | if [ "$fstab" ]; then 1093 | echo -e "\e[00;31mNFS displaying partitions and filesystems - you need to check if exotic filesystems\e[00m" 1094 | echo -e "$fstab" 1095 | echo -e "\n" 1096 | fi 1097 | fi 1098 | 1099 | #looking for credentials in /etc/fstab 1100 | 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` 1101 | if [ "$fstab" ]; then 1102 | echo -e "\e[00;33m***Looks like there are credentials in /etc/fstab!\e[00m\n$fstab" 1103 | echo -e "\n" 1104 | else 1105 | : 1106 | fi 1107 | 1108 | if [ "$export" ] && [ "$fstab" ]; then 1109 | mkdir $format/etc-exports/ 2>/dev/null 1110 | cp /etc/fstab $format/etc-exports/fstab done 2>/dev/null 1111 | else 1112 | : 1113 | fi 1114 | 1115 | 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` 1116 | if [ "$fstabcred" ]; then 1117 | echo -e "\e[00;33m***/etc/fstab contains a credentials file!\e[00m\n$fstabcred" 1118 | echo -e "\n" 1119 | else 1120 | : 1121 | fi 1122 | 1123 | if [ "$export" ] && [ "$fstabcred" ]; then 1124 | mkdir $format/etc-exports/ 2>/dev/null 1125 | cp /etc/fstab $format/etc-exports/fstab done 2>/dev/null 1126 | else 1127 | : 1128 | fi 1129 | 1130 | #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 1131 | if [ "$keyword" = "" ]; then 1132 | echo -e "Can't search *.conf files as no keyword was entered\n" 1133 | else 1134 | confkey=`find / -maxdepth 4 -name *.conf -type f -exec grep -Hn $keyword {} \; 2>/dev/null` 1135 | if [ "$confkey" ]; then 1136 | echo -e "\e[00;31mFind keyword ($keyword) in .conf files (recursive 4 levels - output format filepath:identified line number where keyword appears):\e[00m\n$confkey" 1137 | echo -e "\n" 1138 | else 1139 | echo -e "\e[00;31mFind keyword ($keyword) in .conf files (recursive 4 levels):\e[00m" 1140 | echo -e "'$keyword' not found in any .conf files" 1141 | echo -e "\n" 1142 | fi 1143 | fi 1144 | 1145 | if [ "$keyword" = "" ]; then 1146 | : 1147 | else 1148 | if [ "$export" ] && [ "$confkey" ]; then 1149 | confkeyfile=`find / -maxdepth 4 -name *.conf -type f -exec grep -lHn $keyword {} \; 2>/dev/null` 1150 | mkdir --parents $format/keyword_file_matches/config_files/ 2>/dev/null 1151 | for i in $confkeyfile; do cp --parents $i $format/keyword_file_matches/config_files/ ; done 2>/dev/null 1152 | else 1153 | : 1154 | fi 1155 | fi 1156 | 1157 | #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 1158 | if [ "$keyword" = "" ];then 1159 | echo -e "Can't search *.log files as no keyword was entered\n" 1160 | else 1161 | logkey=`find / -name *.log -type f -exec grep -Hn $keyword {} \; 2>/dev/null` 1162 | if [ "$logkey" ]; then 1163 | echo -e "\e[00;31mFind keyword ($keyword) in .log files (output format filepath:identified line number where keyword appears):\e[00m\n$logkey" 1164 | echo -e "\n" 1165 | else 1166 | echo -e "\e[00;31mFind keyword ($keyword) in .log files (recursive 2 levels):\e[00m" 1167 | echo -e "'$keyword' not found in any .log files" 1168 | echo -e "\n" 1169 | fi 1170 | fi 1171 | 1172 | if [ "$keyword" = "" ];then 1173 | : 1174 | else 1175 | if [ "$export" ] && [ "$logkey" ]; then 1176 | logkeyfile=`find / -name *.log -type f -exec grep -lHn $keyword {} \; 2>/dev/null` 1177 | mkdir --parents $format/keyword_file_matches/log_files/ 2>/dev/null 1178 | for i in $logkeyfile; do cp --parents $i $format/keyword_file_matches/log_files/ ; done 2>/dev/null 1179 | else 1180 | : 1181 | fi 1182 | fi 1183 | 1184 | #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 1185 | if [ "$keyword" = "" ];then 1186 | echo -e "Can't search *.ini files as no keyword was entered\n" 1187 | else 1188 | inikey=`find / -maxdepth 4 -name *.ini -type f -exec grep -Hn $keyword {} \; 2>/dev/null` 1189 | if [ "$inikey" ]; then 1190 | echo -e "\e[00;31mFind keyword ($keyword) in .ini files (recursive 4 levels - output format filepath:identified line number where keyword appears):\e[00m\n$inikey" 1191 | echo -e "\n" 1192 | else 1193 | echo -e "\e[00;31mFind keyword ($keyword) in .ini files (recursive 2 levels):\e[00m" 1194 | echo -e "'$keyword' not found in any .ini files" 1195 | echo -e "\n" 1196 | fi 1197 | fi 1198 | 1199 | if [ "$keyword" = "" ];then 1200 | : 1201 | else 1202 | if [ "$export" ] && [ "$inikey" ]; then 1203 | inikey=`find / -maxdepth 4 -name *.ini -type f -exec grep -lHn $keyword {} \; 2>/dev/null` 1204 | mkdir --parents $format/keyword_file_matches/ini_files/ 2>/dev/null 1205 | for i in $inikey; do cp --parents $i $format/keyword_file_matches/ini_files/ ; done 2>/dev/null 1206 | else 1207 | : 1208 | fi 1209 | fi 1210 | 1211 | #quick extract of .conf files from /etc - only 1 level 1212 | allconf=`find /etc/ -maxdepth 1 -name *.conf -type f -exec ls -la {} \; 2>/dev/null` 1213 | if [ "$allconf" ]; then 1214 | echo -e "\e[00;31mAll *.conf files in /etc (recursive 1 level):\e[00m\n$allconf" 1215 | echo -e "\n" 1216 | else 1217 | : 1218 | fi 1219 | 1220 | if [ "$export" ] && [ "$allconf" ]; then 1221 | mkdir $format/conf-files/ 2>/dev/null 1222 | for i in $allconf; do cp --parents $i $format/conf-files/; done 2>/dev/null 1223 | else 1224 | : 1225 | fi 1226 | 1227 | #extract any user history files that are accessible 1228 | usrhist=`ls -la ~/.*_history 2>/dev/null` 1229 | if [ "$usrhist" ]; then 1230 | echo -e "\e[00;31mCurrent user's history files:\e[00m\n$usrhist" 1231 | echo -e "\n" 1232 | else 1233 | : 1234 | fi 1235 | 1236 | if [ "$export" ] && [ "$usrhist" ]; then 1237 | mkdir $format/history_files/ 2>/dev/null 1238 | for i in $usrhist; do cp --parents $i $format/history_files/; done 2>/dev/null 1239 | else 1240 | : 1241 | fi 1242 | 1243 | #can we read roots *_history files - could be passwords stored etc. 1244 | roothist=`ls -la /root/.*_history 2>/dev/null` 1245 | if [ "$roothist" ]; then 1246 | echo -e "\e[00;33m***Root's history files are accessible!\e[00m\n$roothist" 1247 | echo -e "\n" 1248 | else 1249 | : 1250 | fi 1251 | 1252 | if [ "$export" ] && [ "$roothist" ]; then 1253 | mkdir $format/history_files/ 2>/dev/null 1254 | cp $roothist $format/history_files/ 2>/dev/null 1255 | else 1256 | : 1257 | fi 1258 | 1259 | #is there any mail accessible 1260 | readmail=`ls -la /var/mail 2>/dev/null` 1261 | if [ "$readmail" ]; then 1262 | echo -e "\e[00;31mAny interesting mail in /var/mail:\e[00m\n$readmail" 1263 | echo -e "\n" 1264 | else 1265 | : 1266 | fi 1267 | 1268 | #can we read roots mail 1269 | readmailroot=`head /var/mail/root 2>/dev/null` 1270 | if [ "$readmailroot" ]; then 1271 | echo -e "\e[00;33m***We can read /var/mail/root! (snippet below)\e[00m\n$readmailroot" 1272 | echo -e "\n" 1273 | else 1274 | : 1275 | fi 1276 | 1277 | if [ "$export" ] && [ "$readmailroot" ]; then 1278 | mkdir $format/mail-from-root/ 2>/dev/null 1279 | cp $readmailroot $format/mail-from-root/ 2>/dev/null 1280 | else 1281 | : 1282 | fi 1283 | } 1284 | docker_checks() 1285 | { 1286 | #specific checks - check to see if we're in a docker container 1287 | dockercontainer=` grep -i docker /proc/self/cgroup 2>/dev/null; find / -name "*dockerenv*" -exec ls -la {} \; 2>/dev/null` 1288 | if [ "$dockercontainer" ]; then 1289 | echo -e "\e[00;33mLooks like we're in a Docker container:\e[00m\n$dockercontainer" 1290 | echo -e "\n" 1291 | else 1292 | : 1293 | fi 1294 | 1295 | #specific checks - check to see if we're a docker host 1296 | dockerhost=`docker --version 2>/dev/null; docker ps -a 2>/dev/null` 1297 | if [ "$dockerhost" ]; then 1298 | echo -e "\e[00;33mLooks like we're hosting Docker:\e[00m\n$dockerhost" 1299 | echo -e "\n" 1300 | else 1301 | : 1302 | fi 1303 | 1304 | #specific checks - are we a member of the docker group 1305 | dockergrp=`id | grep -i docker 2>/dev/null` 1306 | if [ "$dockergrp" ]; then 1307 | echo -e "\e[00;33mWe're a member of the (docker) group - could possibly misuse these rights!:\e[00m\n$dockergrp" 1308 | echo -e "\n" 1309 | else 1310 | : 1311 | fi 1312 | 1313 | #specific checks - are there any docker files present 1314 | dockerfiles=`find / -name Dockerfile -exec ls -l {} 2>/dev/null \;` 1315 | if [ "$dockerfiles" ]; then 1316 | echo -e "\e[00;31mAnything juicy in the Dockerfile?:\e[00m\n$dockerfiles" 1317 | echo -e "\n" 1318 | else 1319 | : 1320 | fi 1321 | 1322 | #specific checks - are there any docker files present 1323 | dockeryml=`find / -name docker-compose.yml -exec ls -l {} 2>/dev/null \;` 1324 | if [ "$dockeryml" ]; then 1325 | echo -e "\e[00;31mAnything juicy in docker-compose.yml?:\e[00m\n$dockeryml" 1326 | echo -e "\n" 1327 | else 1328 | : 1329 | fi 1330 | } 1331 | 1332 | lxc_container_checks() 1333 | { 1334 | #specific checks - are we in an lxd/lxc container 1335 | lxccontainer=`grep -qa container=lxc /proc/1/environ 2>/dev/null` 1336 | if [ "$lxccontainer" ]; then 1337 | echo -e "\e[00;33mLooks like we're in an lxc container:\e[00m\n$lxccontainer" 1338 | echo -e "\n" 1339 | fi 1340 | 1341 | #specific checks - are we a member of the lxd group 1342 | lxdgroup=`id | grep -i lxd 2>/dev/null` 1343 | if [ "$lxdgroup" ]; then 1344 | echo -e "\e[00;33mWe're a member of the (lxd) group - could possibly misuse these rights!:\e[00m\n$lxdgroup" 1345 | echo -e "\n" 1346 | fi 1347 | 1348 | } 1349 | 1350 | footer() 1351 | { 1352 | echo -e "\e[00;33m### SCAN COMPLETE ####################################\e[00m" 1353 | } 1354 | 1355 | call_each() 1356 | { 1357 | header 1358 | debug_info 1359 | system_info 1360 | user_info 1361 | environmental_info 1362 | job_info 1363 | networking_info 1364 | services_info 1365 | software_configs 1366 | interesting_files 1367 | docker_checks 1368 | lxc_container_checks 1369 | footer 1370 | } 1371 | 1372 | while getopts "h:k:r:e:t" option; do 1373 | case "${option}" in 1374 | k) keyword=${OPTARG};; 1375 | r) report=${OPTARG}"-"`date +"%d-%m-%y"`;; 1376 | e) export=${OPTARG};; 1377 | t) thorough=1;; 1378 | h) usage; exit;; 1379 | *) usage; exit;; 1380 | esac 1381 | done 1382 | 1383 | 1384 | 1385 | call_each | tee -a $report 2> /dev/null 1386 | #EndOfScript 1387 | --------------------------------------------------------------------------------