I know there have been a lot of questions asked already about this topic. And I also know that the way to go are prepared statements. However I have still not completely understood if or how the following could become a security problem:
$mysqli = new mysqli("localhost", "root", "", "myDatabase");
$mysqli->set_charset("utf8");
$pw = mysqli_real_escape_string($mysqli,$_POST['pw']);
$username = mysqli_real_escape_string($mysqli,$_POST['username']);
$str = "SELECT * FROM users WHERE id='".$id."' AND username='".$username."'";
$result = $this -> mysqli -> query($qstr);
if($result->num_rows > 0){
//user logged in
}
I tried many different inputs from a injection cheat sheet but could not find anything that passed the query. E.g. if I entered anything with an ";" then $result became false because one query cannot contain two separate statements as far as I know. Any input having an ' or " was sanitized by mysqli_real_escape_string.
Could you please explain to me, how the code above could be exploited? If you have a link, which explains it I am more than happy to read it, too!
Cheers
EDIT: This was answered already in this answer:
SQL injection that gets around mysql_real_escape_string()
This question however was about the older version of mysql but not mysqli. Secondly the answer with the most up votes statet the following example that could get around it:
mysql_query('SET NAMES gbk');
$var = mysql_real_escape_string("\xbf\x27 OR 1=1 /*");
mysql_query("SELECT * FROM test WHERE name = '$var' LIMIT 1");
However I do not fully understand this. The first line
mysql_query('SET NAMES gbk');
can not be set from the outside, correct? This is just an example if someone set 'gbk' in his program. So if I used
$mysqli->set_charset("utf8");
and also used
id='".$id."' (single quotes around $id)
then I would be 100% safe, correct?