public function fetchUserData( $username, $noUpdate = false ) {
if ( DEBUG ) echo "DBInterface::fetchUserData( '$username' )\n";
$query = "SELECT * FROM logins WHERE username = '$username'";
$result = mysql_db_query( $this->database, $query, $this->dbc );
if ( $result && !$noUpdate ) {
mysql_db_query( $this->database, "UPDATE logins SET last_accessed = CURRENT_TIMESTAMP WHERE username = '$username' ", $this->dbc );
}
return $this->userData = mysql_fetch_assoc( $result );
}
public function verifyLogin( $username = null, $password = null ) {
if ( DEBUG ) echo "DBInterface::verifyLogin( '$username', '$password' )\n";
$success = ( $username && $password
&& $this->fetchUserData( $username )
&& $this->userData['password'] == $this->md5_base64( $password )
&& $this->setLoggedIn()
);
return $success;
}
显然,没有转义函数,因此可以插入' or '1'='1
以使WHERE子句为true,fetchUserData
将返回表中的所有行。但verfiyLogin
检查用户输入密码与数据库中的查询结果可能不相同,因此身份验证将失败。攻击者也无法修改表,因为mysql_db_query
只执行单个sql语句。我对吗?有什么想法吗?
答案 0 :(得分:3)
是的,使用根据用户输入构建的任何SQL查询都可以进行SQL注入。
您应该使用转义函数或优先准备的语句来保护自己免受SQL注入。但是,如果您使用的是过时且已弃用的mysql_ *函数,则无法使用预准备语句。你需要切换到mysqli或PDO。
PDO示例:
$myPDO = new PDO ('Connection options go here');
$stmt = $myPDO -> prepare ("SELECT * FROM table WHERE rowID = :rowID");
if ($stmt -> execute (array ('rowID' = $inputFromUntrustedSource))) {
while ($row = $stmt -> fetch ()) {
// do stuff with $row here
}
}
答案 1 :(得分:2)
您可以使用UNION
operation将自己的数据注入结果集。因此,攻击者可以提供自己的$this->userData['password']
值,该值等于$this->md5_base64($password)
值,例如:
' UNION SELECT 'admin', 'X03MO1qnZdYdgyfeuILPmQ==
答案 2 :(得分:0)
数据验证经常与SQL格式混淆。你正在谈论的这个“逃避”(无论你在这个模糊的术语下是什么意思)都属于“注入”,而不仅仅是格式化。你需要转义字符串不是因为注入而是因为字符串分隔符和其他一些原因。
数据验证规则可能会发生变化。 SQL格式规则是不变的。您必须格式化SQL字符串中的任何数据。无论您在构建查询之前对此数据做了什么 - 都无关紧要。