TL;DR
Yes, an SQL injection attack can still happen even if you only allow hexadecimal characters as input. While it makes things harder, clever attackers can encode malicious payloads in hex that your database might interpret as valid SQL commands.
How It Works
The assumption is that limiting input to hexadecimal (0-9 and A-F) prevents injection because standard SQL syntax uses characters outside of this range. However, databases often have functions to convert between different data types, including hex strings to their binary representation. Attackers exploit these conversion functions.
Step-by-step Guide
- Understand Hexadecimal Representation: Hexadecimal is a base-16 numbering system. Each byte can be represented by two hexadecimal characters. For example, the character ‘A’ has an ASCII value of 65 (decimal), which is 41 in hex.
- Identify Database Conversion Functions: Most databases have functions to convert hex strings into other data types. Common examples include:
- MySQL:
HEX(),UNHEX(),CONVERT(column_name, 16) - PostgreSQL:
decode(hex_string, 'hex') - SQL Server:
CONVERT(VARCHAR(MAX), hex_value, 2) - Oracle:
UTL_RAW.CAST_TO_VARCHAR2(UTL_RAW.HEXDECODE(hex_string))
- MySQL:
- Craft the Malicious Payload in Hex: The attacker needs to encode their SQL injection payload into a hexadecimal string that, when converted by the database, results in valid SQL syntax.
For example, let’s say you have a vulnerable query like this (in MySQL):
SELECT * FROM users WHERE username = '$username';An attacker might try to inject
' OR '1'='1. They would convert this string into its hexadecimal representation. - Convert the Payload: Convert the malicious SQL fragment (e.g., `’ OR ‘1’=’1`) into its hex equivalent. You can use online tools or programming languages for this:
# Python example hex_payload = ''.join([hex(ord(c))[2:] for c in "' OR '1'='1"]) print(hex_payload) # Output: 27204f52202731273d273127 - Inject the Hex Payload: Submit the hex-encoded payload as input. The application might accept it because it only allows hexadecimal characters.
The database then converts this hex string back into its original form, potentially executing the malicious SQL code.
- Example Attack (MySQL): If the application uses
UNHEX()to process the input:SELECT * FROM users WHERE username = UNHEX('$hex_payload');If ‘$hex_payload’ contains the hex representation of `’ OR ‘1’=’1’`, the query effectively becomes:
SELECT * FROM users WHERE username = ' OR '1'='1';
Mitigation Strategies
- Parameterized Queries (Prepared Statements): This is the most effective defense. Parameterized queries treat user input as data, not as part of the SQL command itself. The database handles escaping and prevents injection.
# Example using Python's sqlite3 library c = conn.cursor() c.execute("SELECT * FROM users WHERE username = ?", (username,)) - Input Validation: While allowing only hexadecimal characters seems secure, it’s not enough. Validate the length and format of the input even if it’s hex.
- Output Encoding: Encode output to prevent cross-site scripting (XSS) vulnerabilities that can be chained with SQL injection.
- Least Privilege Principle: Grant database users only the minimum necessary permissions. This limits the damage an attacker can do if they succeed in injecting code.
- Web Application Firewall (WAF): A WAF can detect and block common SQL injection patterns, including those using hex encoding.
Conclusion
Don’t rely solely on input character restrictions like hexadecimal. Always use parameterized queries as your primary defense against SQL injection attacks in cyber security.

