sql注入入门
SQL注入入门
声明
“SQL 注入,是网络安全领域里最经典、最广为人知的漏洞之一。它的出现,曾让无数网站和数据库在一夜之间陷入危机。今天,我们将通过实际案例,了解 SQL 注入的原理、危害以及如何防御。但在此之前,务必记住:本课程仅用于学习与研究,请勿将所学用于任何非法用途。”
前置知识点
学习sql注入首先需要知道sql是什么
sql是结构化查询语言,也是一种编程语言
通过这个语言我们可以对数据库执行下面操作:
- 查询数据
- 修改数据
- 删除数据
- 添加数据
- ……
什么是数据库
可以用来高效存储大量数据,就和excel表格一样
sql例子
假如test数据库中有一个叫users的表,我们想要知道这个表里面有什么内容,则:
select * from users;
这个语句会输出users表中的所有内容

可以看到有两个字段分别是username和password
对应的有两行数据
这个时候就可以简单了解了sql的用法
需求
现在需要实现一个登录的功能,其实很简单,就是用户输入用户名和密码发送到服务器,服务器在将用户提交的内容到数据库中查询,如果查询存在这个用户且密码正确的话,就登录成功,否则登录失败
那么这个时候的sql语句就可以是:
select username,password from users where username='' and password='';
单引号的内容就是用户输入的内容,如果数据库里面存在这个用户的话就会返回用户这个数据,如果没有的话就是空的数据,例如我们的用户是chuxue:

可以看到服务器查询到了1行数据,如果用户不存在呢:

虽然写着结果1,但是是0行数据
作为开发者
现在已经了解了sql语句以及登录功能是如何实现的
需要你完成一个登录的功能,这个时候我们去动手写一个web服务
我们使用php作为后端程序:
# /var/www/html/sql.php
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>SQL注入练习</title>
<style>
.form-box{
width: fit-content;
margin: 150px auto;
background-color: #eee;
padding: 20px;
display: flex;
flex-direction: column;
gap: 10px;
font-size: 22px;
transform: scale(1.2)
}
input[type="submit"]{
padding: 5px;
font-size: 22px;
}
.success{
color:green;
font-size: 22px;
text-align :center;
}
.fail{
font-size: 22px;
text-align :center;
color: red;
}
</style>
</head>
<body>
<form method="get" action="./sql.php" class="form-box">
<label for="username">
username:
<input type="text" name="username" id="username">
</label>
<br>
<label for="password">
password:
<input type="password" name="password" id="password">
</label>
<br>
<input type="submit" value="登录">
</form>
</body>
</html>
<?php
// 成功和失败的样式
// <div class='success'>登录成功</div>
// <div class='fail'>登录失败</div>
$username = $_GET["username"];
$password = $_GET["password"];
$dbhost ='localhost';
$dbuser = 'root';
$dbpass = 'root';
$dbname = 'test';
$conn = mysqli_connect($dbhost,$dbuser,$dbpass,$dbname);
if(!$conn){
echo "<div class='fail'>连接失败</div>";
}
$sql = "select username,password from users where username='$username' and password='$password'";
$result = mysqli_query($conn, $sql);
if(mysqli_num_rows($result)>0){
echo "<div class='success'>登录成功</div>";
}else{
echo "<div class='fail'>登录失败</div>";
}
?>
上面的代码就简单实现了一个登录的功能,现在介绍一下关键的代码:
# 创建两个变量username和password,变量的值是前端通过get方式提交的数据
$username = $_GET["username"];
$password = $_GET["password"];
# 设计一个查询语句,包含用户和密码的变量
$sql = "select username,password from users where username='$username' and password='$password'";
# 执行查询,并把结果返回给$result变量
$result = mysqli_query($conn, $sql);
# 这个方法会返回查询结果有几行
mysqli_num_rows($result)
# 和前面说的一样,如果有这个用户的话上面返回的是1,如果没有的话返回的是0
本地使用phpstudy搭建了php环境:

上来就是登录失败是因为一开始没有用户数据查询,问题不大
我们尝试输入一个正确的用户看看能不能登录:

可以看到登录成功
作为攻击者
作为攻击者,我们没有账号和密码应该怎么去登录到系统中呢?
这就是我们今天要学习的sql注入了
我们先看看我们在后端的语句
$sql = "select username,password from users where username='$username' and password='$password'";
我们发现用户输入的内容直接拼接到了sql语句当中,这样带来的后果就是攻击者可以控制输入的内容来改变sql语句的结构,例如:
# 攻击者输入的是英文单引号:'
# 那么原来的sql语句就变成了:
$sql = "select username,password from users where username=''' and password='$password'";
# 那么这个sql的结构就乱了,username的内容提前闭合了,并且多了一个单引号,那么这个语句是会报错的

页面确实报错了,证明我们的确可以通过输入的内容去控制sql语句的结构,现在我们就可以通过构造语句去绕过用户密码直接登录:
payload:
' or 1=1 -- asd
解释一下上面的内容
首先使用单引号提前闭合用户名,不然我们输入的sql语句都算是用户名的内容,然后加上条件判断or,or的作用就是只要两边有一个成立那么这个查询语句就成立,所以不管用户名对不对,我们输入的1=1肯定是对的。
其次就是两个横杆“--”,这个在mysql中是注释符号,sql语句不会执行后面的内容,这两个横杆后面必须带上空格,这里输入了asd是随便输入的,为了给你们体现空格,那么之前说了一个单引号会提前闭合语句,然后导致多了一个单引号并报错,所以我们需要使用注释符号去把后面的单引号注释了。
这样一来,攻击者输入的内容到服务器执行的语句就变成了:
select username,password from users where username='' or 1=1 --
由于1=1条件成立,所以查询一定是有结果的并且是所有的结果,之前mysqli_num_rows的结果就会大于0,登录成功:

防范
预处理 操作:
$stmt = $conn->prepare("SELECT username, password FROM users WHERE username = ? AND password = ?");
$stmt->bind_param("ss", $username, $password); // s 表示字符串
$stmt->execute();
$result = $stmt->get_result();
认识sql注入
看到这里你已经初步了解到了sql注入的原理
实际上sql注入的方式有很多,不仅仅可以绕过登录,不仅仅只是这种绕过
我们如果每种情况都自己写靶机来训练的话有点费时间,所以已经有人专门搭建好一个sql注入的训练平台:sqli-labs
项目地址:sqli-labs
小结
SQL注入是一种常见且危险的网络攻击方式,它通过恶意输入改变SQL语句的结构,进而窃取或修改数据库中的敏感数据。通过本教程,你已经了解了SQL注入的基本原理及一种常见攻击方式。为了防止SQL注入攻击,我们应始终采用参数化查询、使用ORM框架、严格验证用户输入等安全措施。

浙公网安备 33010602011771号