侧边栏壁纸
  • 累计撰写 47 篇文章
  • 累计创建 22 个标签
  • 累计收到 27 条评论

目 录CONTENT

文章目录

网络安全 05-SQL注入

vchopin
2022-04-28 / 0 评论 / 0 点赞 / 177 阅读 / 12,119 字

SQL注入

task 1 熟悉SQL语句

我们这里使用docker搭建的www和mysql,docker-compose文件提供在附件。首先解压文件进入到Labsetup文件夹,然后按照以下步骤搭建环境:

  1. 通过docker-compose build开始构建多个docker,如下:

image-1651133818715

  1. 通过docker-compose up启动docker-compose

image-1651133986787

  1. 新建一个terminal通过docker ps查看mysql数据库镜像id

image-1651134121198

  1. 发现mysql的序列号是c4e441c69754,输入docker exec -it c4e /bin/bash进入mysql镜像,并输入mysql -u root -p dees进入mysql数据库

image-1651134244649

  1. 查看相关数据库

image-1651134305011

task 2 通过SELECT语句注入

  1. 首先进入我们上述使用docker搭建的www网页页面,地址是10.9.0.5,可以在 /etc/hosts配置域名映射

image-1651134591201

  1. 为了更好的理解该方法,我们首先查看该网站的服务器页面的思路。查看位于/var/www/SQL_Injectionunsafe home.php文件,该文件就是用来验证登录的文件
    文件内容如下:
<!DOCTYPE html>
<html lang="en">
<head>
  <!-- Required meta tags -->
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

  <!-- Bootstrap CSS -->
  <link rel="stylesheet" href="css/bootstrap.min.css">
  <link href="css/style_home.css" type="text/css" rel="stylesheet">

  <!-- Browser Tab title -->
  <title>SQLi Lab</title>
</head>
<body>
  <nav class="navbar fixed-top navbar-expand-lg navbar-light" style="background-color: #3EA055;">
    <div class="collapse navbar-collapse" id="navbarTogglerDemo01">
      <a class="navbar-brand" href="unsafe_home.php" ><img src="seed_logo.png" style="height: 40px; width: 200px;" alt="SEEDLabs"></a>

      <?php
      session_start();
      // if the session is new extract the username password from the GET request
      $input_uname = $_GET['username'];
      $input_pwd = $_GET['Password'];
      $hashed_pwd = sha1($input_pwd);

      // check if it has exist login session
      if($input_uname=="" and $hashed_pwd==sha1("") and $_SESSION['name']!="" and $_SESSION['pwd']!=""){
        $input_uname = $_SESSION['name'];
        $hashed_pwd = $_SESSION['pwd'];
      }

      // Function to create a sql connection.
      function getDB() {
        $dbhost="10.9.0.6";
        $dbuser="seed";
        $dbpass="dees";
        $dbname="sqllab_users";
        // Create a DB connection
        $conn = new mysqli($dbhost, $dbuser, $dbpass, $dbname);
        if ($conn->connect_error) {
          echo "</div>";
          echo "</nav>";
          echo "<div class='container text-center'>";
          die("Connection failed: " . $conn->connect_error . "\n");
          echo "</div>";
        }
        return $conn;
      }

      // create a connection
      $conn = getDB();
      // Sql query to authenticate the user
      $sql = "SELECT id, name, eid, salary, birth, ssn, phoneNumber, address, email,nickname,Password
      FROM credential
      WHERE name= '$input_uname' and Password='$hashed_pwd'";
      if (!$result = $conn->query($sql)) {
        echo "</div>";
        echo "</nav>";
        echo "<div class='container text-center'>";
        die('There was an error running the query [' . $conn->error . ']\n');
        echo "</div>";
      }
      /* convert the select return result into array type */
      $return_arr = array();
      while($row = $result->fetch_assoc()){
        array_push($return_arr,$row);
      }

      /* convert the array type to json format and read out*/
      $json_str = json_encode($return_arr);
      $json_a = json_decode($json_str,true);
      $id = $json_a[0]['id'];
      $name = $json_a[0]['name'];
      $eid = $json_a[0]['eid'];
      $salary = $json_a[0]['salary'];
      $birth = $json_a[0]['birth'];
      $ssn = $json_a[0]['ssn'];
      $phoneNumber = $json_a[0]['phoneNumber'];
      $address = $json_a[0]['address'];
      $email = $json_a[0]['email'];
      $pwd = $json_a[0]['Password'];
      $nickname = $json_a[0]['nickname'];
      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;
      }
      // close the sql connection
      $conn->close();

      function drawLayout($id,$name,$eid,$salary,$birth,$ssn,$pwd,$nickname,$email,$address,$phoneNumber){
        if($id!=""){
          session_start();
          $_SESSION['id'] = $id;
          $_SESSION['eid'] = $eid;
          $_SESSION['name'] = $name;
          $_SESSION['pwd'] = $pwd;
        }else{
          echo "can not assign session";
        }
        if ($name !="Admin") {
          // If the user is a normal user.
          echo "<ul class='navbar-nav mr-auto mt-2 mt-lg-0' style='padding-left: 30px;'>";
          echo "<li class='nav-item active'>";
          echo "<a class='nav-link' href='unsafe_home.php'>Home <span class='sr-only'>(current)</span></a>";
          echo "</li>";
          echo "<li class='nav-item'>";
          echo "<a class='nav-link' href='unsafe_edit_frontend.php'>Edit Profile</a>";
          echo "</li>";
          echo "</ul>";
          echo "<button onclick='logout()' type='button' id='logoffBtn' class='nav-link my-2 my-lg-0'>Logout</button>";
          echo "</div>";
          echo "</nav>";
          echo "<div class='container col-lg-4 col-lg-offset-4 text-center'>";
          echo "<br><h1><b> $name Profile </b></h1>";
          echo "<hr><br>";
          echo "<table class='table table-striped table-bordered'>";
          echo "<thead class='thead-dark'>";
          echo "<tr>";
          echo "<th scope='col'>Key</th>";
          echo "<th scope='col'>Value</th>";
          echo "</tr>";
          echo "</thead>";
          echo "<tr>";
          echo "<th scope='row'>Employee ID</th>";
          echo "<td>$eid</td>";
          echo "</tr>";
          echo "<tr>";
          echo "<th scope='row'>Salary</th>";
          echo "<td>$salary</td>";
          echo "</tr>";
          echo "<tr>";
          echo "<th scope='row'>Birth</th>";
          echo "<td>$birth</td>";
          echo "</tr>";
          echo "<tr>";
          echo "<th scope='row'>SSN</th>";
          echo "<td>$ssn</td>";
          echo "</tr>";
          echo "<tr>";
          echo "<th scope='row'>NickName</th>";
          echo "<td>$nickname</td>";
          echo "</tr>";
          echo "<tr>";
          echo "<th scope='row'>Email</th>";
          echo "<td>$email</td>";
          echo "</tr>";
          echo "<tr>";
          echo "<th scope='row'>Address</th>";
          echo "<td>$address</td>";
          echo "</tr>";
          echo "<tr>";
          echo "<th scope='row'>Phone Number</th>";
          echo "<td>$phoneNumber</td>";
          echo "</tr>";
          echo "</table>";
        }
        else {
          // if user is admin.
          $conn = getDB();
          $sql = "SELECT id, name, eid, salary, birth, ssn, password, nickname, email, address, phoneNumber
          FROM credential";
          if (!$result = $conn->query($sql)) {
            die('There was an error running the query [' . $conn->error . ']\n');
          }
          $return_arr = array();
          while($row = $result->fetch_assoc()){
            array_push($return_arr,$row);
          }
          $json_str = json_encode($return_arr);
          $json_aa = json_decode($json_str,true);
          $conn->close();
          $max = sizeof($json_aa);
          echo "<ul class='navbar-nav mr-auto mt-2 mt-lg-0' style='padding-left: 30px;'>";
          echo "<li class='nav-item active'>";
          echo "<a class='nav-link' href='unsafe_home.php'>Home <span class='sr-only'>(current)</span></a>";
          echo "</li>";
          echo "<li class='nav-item'>";
          echo "<a class='nav-link' href='unsafe_edit_frontend.php'>Edit Profile</a>";
          echo "</li>";
          echo "</ul>";
          echo "<button onclick='logout()' type='button' id='logoffBtn' class='nav-link my-2 my-lg-0'>Logout</button>";
          echo "</div>";
          echo "</nav>";
          echo "<div class='container'>";
          echo "<br><h1 class='text-center'><b> User Details </b></h1>";
          echo "<hr><br>";
          echo "<table class='table table-striped table-bordered'>";
          echo "<thead class='thead-dark'>";
          echo "<tr>";
          echo "<th scope='col'>Username</th>";
          echo "<th scope='col'>EId</th>";
          echo "<th scope='col'>Salary</th>";
          echo "<th scope='col'>Birthday</th>";
          echo "<th scope='col'>SSN</th>";
          echo "<th scope='col'>Nickname</th>";
          echo "<th scope='col'>Email</th>";
          echo "<th scope='col'>Address</th>";
          echo "<th scope='col'>Ph. Number</th>";
          echo "</tr>";
          echo "</thead>";
          echo "<tbody>";
          for($i=0; $i< $max;$i++){
            //TODO: printout all the data for that users.
            $i_id = $json_aa[$i]['id'];
            $i_name= $json_aa[$i]['name'];
            $i_eid= $json_aa[$i]['eid'];
            $i_salary= $json_aa[$i]['salary'];
            $i_birth= $json_aa[$i]['birth'];
            $i_ssn= $json_aa[$i]['ssn'];
            $i_pwd = $json_aa[$i]['Password'];
            $i_nickname= $json_aa[$i]['nickname'];
            $i_email= $json_aa[$i]['email'];
            $i_address= $json_aa[$i]['address'];
            $i_phoneNumber= $json_aa[$i]['phoneNumber'];
            echo "<tr>";
            echo "<th scope='row'> $i_name</th>";
            echo "<td>$i_eid</td>";
            echo "<td>$i_salary</td>";
            echo "<td>$i_birth</td>";
            echo "<td>$i_ssn</td>";
            echo "<td>$i_nickname</td>";
            echo "<td>$i_email</td>";
            echo "<td>$i_address</td>";
            echo "<td>$i_phoneNumber</td>";
            echo "</tr>";
          }
          echo "</tbody>";
          echo "</table>";
        }
      }
      ?>
      <br><br>
      <div class="text-center">
        <p>
          Copyright &copy; SEED LABs
        </p>
      </div>
    </div>
    <script type="text/javascript">
    function logout(){
      location.href = "logoff.php";
    }
    </script>
  </body>
  </html>

仔细阅读上述php代码,可以看到该方法是从credential数据库中选择id,name,salary,ssn等信息,并且没有加任何prepare_statements,只是简单的字符串拼接,因此我们可以使用input_namehashed_pwd两个参数来构造SQL注入,

  • 从web页面构造SQL注入。我们这里将input_name设置为admin'#,而hashed_pwd我们则不用填。其中#号可以将SQL语句的后续内容忽略,这样我们就可以重新进入

image-1651135719598

  • 从cmd行命令构造SQL注入。我们使用命令:curl 'www.seed-server.com/unsafe_home.php?username=admin%27%23%26Password=11测试代码

部分特殊符号对应urlencode

符号 意义 urlencode
+ URL 中+号表示空格 %2B
空格 URL中的空格可以用+号或者编码 %20
/ 分隔目录和子目录 %2F
? 分隔实际的URL和参数 %3F
% 指定特殊字符 %25
# 表示书签 %23
& URL 中指定的参数间的分隔符 %26
= URL 中指定参数的值 %3D

image-1651136127566

成功获取管理员内容

task 3 通过UPDATE执行SQL注入

  1. 还是进入www的docker,查看更新Profile操作的关键代码,如下
$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);

  1. 查看更新操作Profile页面

image-1651136530911

  1. Edit页面并没有更新salary字段的方法,我们尝试使用SQL注入更改Salary字段

  2. 编写SQL语句如下,原理:通过分号;可以继续编写多条语句。
    在NickName中输入如下:

vchopin',Salary='3000

查看修改结果,修改成功
image-1651137664999

  1. 修改别人的salary字段
Boby',Salary='1' WHERE name = 'boby'#

image-1651138032429

  1. 防止注入–预处理机制
    正常SQL语法:
$sql = "SELECT name, local, gender
FROM USER_TABLE
WHERE id = $id AND password =’$pwd’ ";
$result = $conn->query($sql)

使用Prepared Statements

$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();
0

评论区