Skip to content

Instantly share code, notes, and snippets.

@eriknl
Last active November 12, 2023 12:21
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save eriknl/2c4e6280792cd1177a61c16b7b54a27b to your computer and use it in GitHub Desktop.
Save eriknl/2c4e6280792cd1177a61c16b7b54a27b to your computer and use it in GitHub Desktop.
Reverse engineered partial Aruba PAPI implementation
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