有没有办法利用此代码并以某个特定用户名(如Sam)登录? mysqli_real_escape_string()函数转义所有NUL(ASCII 0),\ n,\ r,\,',"和Control-Z字符。
我尝试使用username = "Sam"
和domain = "' union (SELECT 1, 123456) # a"
,但它不起作用..
$user = $_POST['user'];
$domain = $_POST['domain'];
$pwd = $_POST['pwd'];
function login($username, $domain, $password) {
global $vuln_db;
$starttime = microtime(true);
$username = mysqli_real_escape_string($vuln_db, trim($username));
$domain = mysqli_real_escape_string($vuln_db, trim($domain));
$password = trim($password);
if (empty($password) || empty($username) || empty($domain)) {
return FALSE;
}
// We store the password in plaintext to keep the homework's code short.
// For anything even remotely real, use a proper password storage scheme.
$query = "SELECT user_id, password FROM users WHERE username = '$username' AND domain LIKE '$domain'";
$result = mysqli_query($vuln_db, $query) or die(mysqli_error($vuln_db));
if($result) {
$row = mysqli_fetch_row($result);
if($row) {
$the_password = trim($row[1]);
for($i = 0; $i < strlen($the_password); $i++) {
/* Bruteforce is not the way! */
usleep(100000);
if($password[$i] != $the_password[$i]) {
$endtime = microtime(true);
return FALSE;
}
}
return TRUE;
} else {
return FALSE;
}
}
}
我可以通过SQL注入或其他技术从这个函数中获得真的吗?
答案 0 :(得分:1)
您展示的具体案例是mysqli_real_escape_string()
安全的。除非您的字符集是 gbk 或 sjis ,否则我无法分辨,因为我不知道您是如何连接到数据库的。
转义有许多边缘情况,它不起作用,如SQL injection that gets around mysql_real_escape_string()的答案中所述。需要仔细考虑和测试,以确保您没有实现在这些边缘情况之一中易受攻击的代码。这种思考和测试使得编写代码需要更长的时间。
这就是为什么目前的最佳做法是使用查询参数而不是转义字符串。
$query = "SELECT user_id, password FROM users WHERE username = ? AND domain LIKE ?";
$stmt = mysqli_prepare($vuln_db, $query) or die(mysqli_error($vuln_db));
$stmt->bind_param('ss', $username, $domain);
$stmt->execute() or die(mysqli_error($vuln_db));
$result = $stmt->get_result() or die(mysqli_error($vuln_db));
P.S。:这与您关于转义的问题无关,但您还应学会使用password_hash()和password_verify(),而不是以纯文本格式存储密码。