Sarix Encoding Cracked
_____ . .___ _ _ _ .____ __ _ ___ ___ .___ _ __ _ ___ ___ .___ . ___ . .____ .___
( /| / \ | `. / / |\ | .' \ .' `. / ` | |\ | .' \ .' \ / \ /| .' \ / / / / `
`--. / \ |__-' | \,' |__. | \ | | | | | | | | \ | | | |__-' / \ | |_-' |__. | |
| /---'\ | \ | ,'\ | | \ | | | | | | | | \ | | _ | | \ /---'\ | | \ | | |
\___.,' \ / \ / / \ /----/ | \| `.__, `.__.' /---/ / | \| `.___| `.__, / ,' \ `.__, / \ /----/ /---/
Reverse Engineering Sarix Camera Password Encoding: A Journey Through "Security by Obscurity"
Sometimes, corporate policy demands password changes every 3, 6, or 12 months. While this isn't fun for regular accounts, it becomes a real headache when you're required to change passwords for a bunch of IoT devices—including cameras, SSH access, and web portal credentials. Therefore, I created a solution and documented my journey below.
Initial Discovery
First of all, huge props to Pelco and Motorola for allowing SSH access into Sarix cameras and running arbitrary code on them. Through trial and error, I discovered something peculiar: shadow files are rewritten every time the system boots, which is quite strange behavior.
But wait! There's a NAND directory containing a SQLite database where the real password data lives:
SELECT * FROM CONFIG WHERE NAME="account.admin.password";
-- Returns something like: "YWRtXwejM="
Base64! Obviously! Except... no. Decoding it gave me complete gibberish.
The Sarix Encoding "Mystery"
After some digital archaeology and debugging using CyberChef with chosen plaintext attacks, I discovered that Sarix uses what I can only describe as "ASCII + ROT39 to Base64." Here's how it works:
- Take your password
- Convert each character to its ASCII value
- Subtract 39 from each value (because... reasons?)
- Encode the result with Base64
The Solution
I've created the following methods to encode and decode Sarix passwords:
@staticmethod
def encode(ascii_string: str, step: int = DEFAULT_STEP) -> str:
"""Encode a password using Sarix's custom encoding scheme."""
try:
hex_values = [
format((ord(char) - step) % 256, "02x") for char in ascii_string
]
decoded_bytes = bytes(int(hex_val, 16) for hex_val in hex_values)
base64_string = base64.b64encode(decoded_bytes).decode("utf-8")
return base64_string
except Exception as e:
raise ValueError(f"Failed to encode string: {e}")
@staticmethod
def decode(base64_string: str, step: int = DEFAULT_STEP) -> str:
"""Decode a Sarix-encoded password back to plaintext."""
try:
decoded_bytes = base64.b64decode(base64_string)
hex_values = [
format((byte + step) % 256, "02x") for byte in decoded_bytes
]
ascii_chars = "".join(
chr(int(hex_val, 16)) for hex_val in hex_values
)
return ascii_chars
except Exception as e:
raise ValueError(f"Failed to decode Sarix string: {e}")
Why Sarix Encoding Isn't Real Security
Let's break down what this "encoding" really accomplishes:
Security through obscurity – The only requirement to reverse it is knowing the magic number 39. That's the entire "protection" mechanism.
Easily reversible – Once you know the step value, you can undo it completely. There's no salting, hashing, or real encryption involved.
Misleading appearance – It may look like secure Base64-encoded text, but it's essentially a basic Caesar cipher with extra steps.
A stronger approach would use proven methods like bcrypt, scrypt, or at minimum a salted SHA-256 hash.
Other Sarix Quirks
Sarix makes a lot of strange and bizarre design choices. For example:
- Client-side password hashing: When logging in, passwords are hashed on the client side and MD5 hashes are passed to the server
- Cleartext password exposure: When logged in as a user and changing passwords through the user tab, passwords are sent in cleartext, making them visible during the change process
- SSH password parsing issues: Including
$
as part of your SSH password will break SSH password authentication due to poor parsing - Inconsistent bruteforecing timeouts: There's a clear timeout for SSH sessions, but not for the web interface
I could continue, but I'll spare you the details.
Conclusion
This was a simple exploration into reverse engineering a custom encoding scheme. While Sarix cameras have their place in the security ecosystem, their password handling demonstrates why relying on obscurity rather than proven cryptographic methods is problematic.
Understanding these implementation details helps when managing large deployments of IoT devices and reinforces the importance of using established security practices in our own projects.
Thanks for reading!