Last active
October 4, 2024 08:57
-
-
Save eriknl/2c4e6280792cd1177a61c16b7b54a27b to your computer and use it in GitHub Desktop.
Reverse engineered partial Aruba PAPI implementation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import hashlib | |
from struct import * | |
""" | |
This implementation was reverse engineered using Wireshark (and source code), strace and two excellent articles: | |
- https://x-c3ll.github.io/posts/CVE-2018-7081-RCE-ArubaOS/ | |
- https://packetstormsecurity.com/files/136997/Aruba-Authentication-Bypass-Insecure-Transport-Tons-Of-Issues.html | |
""" | |
def papi_encrypt(data): | |
decrypted = '' | |
for c in data: | |
decrypted += chr(c ^ 0x93) | |
return bytes(decrypted, 'latin-1') | |
def papi_header(dst_host, src_host, dst_port, src_port, sequence_number, message_code, body, calculate_checksum, natport=0): | |
# Description Offset | |
header = b'\x49\x72' # Magic Header for PAPI message 0x00 | |
header += b'\x00\x03' # Protocol Version ??? I have observed values 1 and 3 0x02 | |
header += bytes(map(int, dst_host.split('.'))) # Destination host 0x04 | |
header += bytes(map(int, src_host.split('.'))) # Source host 0x08 | |
header += pack('>H', natport) # NAT Port number 0x0C | |
header += b'\x00\x00' # "garbage" 0x0E | |
header += pack('>H', dst_port) # Destination port 0x10 | |
header += pack('>H', src_port) # Source port 0x12 | |
header += b'\x20\x04' # Packet type ??? 0x14 | |
header += b'\x00\x00' # Packet size ??? Seems unused in version 3 0x16 | |
header += pack('>H', sequence_number) # sequence_number 0x18 | |
header += pack('>H', message_code) # PAPI message code - application specific 0x1A | |
checksum = b'\x00'*16 # Empty checksum | |
padding = b'\x00'*32 | |
if calculate_checksum: | |
m = hashlib.md5() | |
m.update(header + checksum + padding + body) | |
key = b'asdf;lkj763' | |
key = b'eG3eAUwZ5UEen1xu' # 'enhanced security' | |
m.update(key) | |
checksum = m.digest() # Calculated checksum | |
header += checksum # Checksum 0x1C | |
header += padding # Header padding 0x2C | |
# End 0x4C | |
return header | |
def sxdr_write_ip(str_ip): | |
msg = b'\x05' | |
msg += bytes(map(int, str_ip.split('.')))[::-1] #??? | |
return msg | |
def sxdr_write_u8(value): | |
msg = b'\x02' | |
msg += pack('B', value) | |
return msg | |
def sxdr_write_u16(value): | |
msg = b'\x03' | |
msg += pack('>H', value) | |
return msg | |
def sxdr_write_u32(value): | |
msg = b'\x04' | |
msg += pack('>I', value) | |
return msg | |
def sxdr_write_s32(value, sign): | |
msg = b'\x06' | |
msg += sxdr_write_bool(sign) | |
msg += sxdr_write_u32(value) | |
return msg | |
def sxdr_write_bool(value): | |
msg = b'\x07' | |
if value: | |
msg += sxdr_write_u8(1) | |
else: | |
msg += sxdr_write_u8(0) | |
return msg | |
def sxdr_write_str(value): | |
msg = b'\x00' | |
msg += pack('>H', len(value)) | |
msg += bytes(value, 'latin-1') | |
return msg | |
def sxdr_write_mac(value): | |
msg = b'\x01' | |
msg += bytes.fromhex(value.replace(':', '')) | |
return msg | |
def sxdr_write_ipv6(str_ip6): | |
msg = b'\x0A' | |
msg += b'\x00'*16 | |
return msg | |
def sxdr_write_ip_af(str_ip): | |
msg = b'\x0B' | |
msg += b'\x00'*20 | |
return msg | |
def sxdr_write_hex(value): | |
msg = b'\x08' | |
msg += pack('>H', len(value)) | |
msg += bytes(value, 'latin-1') | |
return msg |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment