php - mysqli_real_escape_string 是否可以进行 SQL 注入?
问题描述
有没有办法利用此代码并以某个特定的用户名(如 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 注入或其他类型的技术从这个函数中得到真实的结果吗?
解决方案
您展示的特定案例是安全的mysqli_real_escape_string()
。除非您的字符集是gbk或sjis,否则我无法分辨,因为我不知道您是如何连接到数据库的。
转义有许多不起作用的边缘情况,如解决 mysql_real_escape_string() 的 SQL 注入的答案中所述。需要仔细考虑和测试,以确保您没有实现在这些边缘情况之一中易受攻击的代码。这种思考和测试使得编写代码需要更长的时间。
这就是为什么当前的最佳实践是使用查询参数而不是转义字符串。
$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));
- 查询参数使代码更容易编写,代码更容易阅读
- 查询参数没有字符串转义的漏洞边缘情况
PS:这与您关于转义的问题无关,但您还应该学习使用password_hash()和password_verify(),而不是以纯文本形式存储密码。
推荐阅读
- javascript - Javascript从多个数组中查找所有重复项
- javascript - 阻止代码从 JS 中的检查元素运行?
- ffmpeg - 使用 ffmpeg 调整高清视频大小并将其裁剪为方形视频
- javascript - guild.channels.cache.array() 返回一个空数组。与 client.channels.cache.array() 相同
- prometheus - 如何使用普罗米修斯中的标签从同一个计数器中获取百分比?
- flutter - Flutter Dart 从对象列表中获取字符串列表
- python - 如何在Python中索引每行超过一个单词的输入单词
- tensorflow - 在本地 pc 上从源代码构建 tensorflow 并在远程 pc 上部署
- gmail - 如何以编程方式刷新 gmail api 的令牌?
- python - Python/Selenium 中的 is_enable 函数