SQL injection bypassing mysql_real_escape_string(): vulnerability analysis

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

"Help! My mysql_real_escape_string() isn't working!"



If you've ever Googled "SQL injection that gets around mysql_real_escape_string()", you're not alone. This question on Stack Overflow has gathered tens of thousands of views and become a classic in web security. It would seem you just use mysql_real_escape_string() and you're protected. But no. Hackers find loopholes, and developers find gray hairs.



In this article, we'll break down exactly how SQL injections can bypass mysql_real_escape_string() escaping in PHP. You'll see real code examples, understand why the "good old" approach no longer works, and learn how to truly protect yourself. Let's go!



Why mysql_real_escape_string() is not a panacea?



First, a bit of history. The mysql_real_escape_string() function appeared in the era of PHP 4 and 5, when everyone was using the mysql_* extension. It escapes special characters like quotes, backslashes, and control characters. But the problem is that it only works within the context of a single encoding.



If the client and server encodings don't match, chaos ensues. And if you're using multi-byte encodings (e.g., GBK or SJIS), the function can become your worst enemy.



Classic example: multi-byte attack



Imagine your site uses the GBK encoding (Chinese), and you pass the string:



$_POST['name'] = "0xbf27"; // Escaped ' or just '?


In GBK, the character 0xbf27 is a valid Chinese character. But if mysql_real_escape_string() "sees" 0x27 (apostrophe), it escapes it with a backslash: 0xbf5c27. The problem is that 0xbf5c is also a valid character in GBK! As a result, the apostrophe 0x27 remains unescaped, and the hacker can inject their SQL code.



// Vulnerable code$name = mysql_real_escape_string($_POST['name']);$query = "SELECT * FROM users WHERE name = '$name'";

// If you input: 0xbf27// The function returns: 0xbf5c27// In GBK this is: Chinese character + apostrophe// The query becomes: SELECT * FROM users WHERE name = 'chinese_char' OR 1=1 -- '


Voila! Injection successful. And this isn't just theory — such vulnerabilities have been found in real projects.



Typical vulnerabilities when using mysql_real_escape_string()



Let's list the most common mistakes that allow bypassing escaping:



  • Incorrect encoding — as in the example above. If the server thinks the data is in UTF-8, but the client sends GBK, the escaping breaks.
  • Using numeric fields without quotes — if you insert a number directly, escaping won't work. For example: SELECT * FROM users WHERE id = $id — and the hacker writes 1 OR 1=1.
  • LIKE queries — escaping does not handle % and _ characters. Blind SQL injection can be performed through patterns.
  • Double escaping — if you call the function twice, the backslash is doubled, and protection is lost.


Example: attack on a numeric field



// Vulnerable code$id = mysql_real_escape_string($_GET['id']);$query = "SELECT * FROM products WHERE id = $id"; // Quotes are not needed!

// Hacker inputs: 1 UNION SELECT username, password FROM users// The query becomes: SELECT * FROM products WHERE id = 1 UNION SELECT username, password FROM users


Escaping is useless here — there are no quotes to escape. The hacker simply inserts their SQL directly.



Modern protection methods (that work)



Enough horror stories — let's get to solutions. If you're writing PHP and want to forget about SQL injections, here's your checklist:



1. Use PDO or MySQLi with prepared statements



This is

Blogs

Book Recommendations