首页 > 数据库 >web渗透测试(8):SQL注入

web渗透测试(8):SQL注入

时间:2023-08-01 16:35:09浏览次数:34  
标签:web name 渗透 使用 echo SQL id row

SQL注入是最常见的(web)漏洞之一。所有SQL注入练习,在这里找到,使用MySQL作为后端。当SQL查询中包含SQL注入时,缺少用户控制输入的编码/转义。

 

根据信息在查询中的添加方式,您需要不同的东西来破坏语法。

有三种不同的方法可以在SQL语句中回显信息:

  1. 使用引号:单引号或双引号。
  2. 使用反引号。
  3. 直接注入:将数据直接从数据库服务器发送到攻击者控制的计算机。

 

例如,如果你想使用信息作为一个字符串,你可以这样做:

SELECT * FROM user WHERE name="root";

或者

SELECT * FROM user WHERE name='root';

如果你想使用整数信息,你可以这样做:

SELECT * FROM user WHERE id=1;

 

最后,如果你想使用信息作为列名,你需要这样做:

SELECT * FROM user ORDER BY name;

或者

SELECT * FROM user ORDER BY `name`;

 

也可以使用整数作为字符串,但会更慢:

SELECT * FROM user WHERE id ='1';
 

 

回显信息的方式,甚至使用什么分隔符,将决定使用的检测技术。但是,您没有此信息,您需要尝试猜测它。您需要制定假设并尝试验证它们。这就是为什么花时间浏览liveCD上的例子非常重要的原因。

db.php文件代码:

<?php 
  $lnk = mysql_connect("localhost", "pentesterlab", "pentesterlab");
  $db = mysql_select_db('exercises', $lnk);
?>

Example 1

<?php

  require_once('../header.php');
  require_once('db.php');
    $sql = "SELECT * FROM users where name='";
    $sql .= $_GET["name"]."'";    
    $result = mysql_query($sql);
    if ($result) {
        ?>
        <table class='table table-striped'>
      <tr><th>id</th><th>name</th><th>age</th></tr>
        <?php
        while ($row = mysql_fetch_assoc($result)) {
            echo "<tr>";
                echo "<td>".$row['id']."</td>";
                echo "<td>".$row['name']."</td>";
                echo "<td>".$row['age']."</td>";
            echo "</tr>";
        }    
        echo "</table>";
    }
  require_once '../footer.php';
?>

 

在第一个例子中,我们可以看到参数是一个字符串,我们可以在表中看到一行。要理解服务器端代码,我们需要开始探索:

 

如果我们添加额外的字符,如“1234”,使用?name=root1234,表中不会显示任何记录。从这里,我们可以猜测请求在某种匹配中使用我们的值。

 

 

如果我们在请求中注入空格,则使用?name=root+++(编码后),显示记录。MySQL(默认情况下)在执行比较时将忽略字符串中的尾随空格。

 

如果我们使用双引号,?name=root"则表中不会显示任何记录。

 

如果我们使用注入单引号,?name=root'表格就会消失。我们可能打破了一些......

 

从第一部分开始,我们可以推断出整个必须如下:

SELECT * FROM users WHERE name='[INPUT]';

 

现在,让我们验证这个假设。

 

如果我们是对的,以下注入应该给出相同的结果。

  • ?name=root' and '1'='1:初始查询中的引用将在注入结束时关闭。
  • ?name=root' and '1'='1' #(不要忘记编码#):初始查询中的引用将被注释掉。
  • ?name=root' and 1=1 #(别忘了编码#):在初始查询引用将被注释掉我们不需要'1'='1'。
  • ?name=root' #(不要忘记编码#):初始查询中的引用将被注释掉,我们不需要1=1。

 

现在这些请求可能不会返回相同的内容:

  • ?name=root' and '1'='0:初始查询中的引用将在注入结束时关闭。页面不应返回任何结果(空表),因为选择标准始终返回false。
  • ?name=root' and '1'='1 #(不要忘记编码#):初始查询中的引用将被注释掉。我们应该与上面的查询具有相同的结果。
  • ?name=root' or '1'='1:初始查询中的引用将在注入结束时关闭。or将选择所有结果,第二部分始终为真。它可能会给出相同的结果,但不太可能,因为该值用作此示例的过滤器(而不是一次只显示一个结果的页面)。
  • ?name=root' or '1'='1' #(不要忘记编码#):初始查询中的引用将被注释掉。我们应该与上面的查询具有相同的结果。

 

通过所有这些测试,我们可以确保我们有一个SQL注入。此培训仅侧重于检测。您可以查看其他PentesterLab高级课程,并了解如何利用此类问题。PentesterLab高级课程后面会讲到的。PentesterLab高级课程也是指web渗透测试平台:Web Pentester II。

 

Example 2

 

<?php
  require_once('../header.php');
  require_once('db.php');

    if (preg_match('/ /', $_GET["name"])) {
        die("ERROR NO SPACE");    
    }
    $sql = "SELECT * FROM users where name='";
    $sql .= $_GET["name"]."'";

    $result = mysql_query($sql);
    if ($result) {
        ?>
        <table class='table table-striped'>
      <tr><th>id</th><th>name</th><th>age</th></tr>
        <?php
        while ($row = mysql_fetch_assoc($result)) {
            echo "<tr>";
                echo "<td>".$row['id']."</td>";
                echo "<td>".$row['name']."</td>";
                echo "<td>".$row['age']."</td>";
            echo "</tr>";
        }    
        echo "</table>";
    }
  require '../footer.php';
?>

 

在此示例中,错误消息提供了开发人员创建的保护:ERROR NO SPACE。只要在请求中注入空格,就会显示此错误消息。它阻止我们使用该' and '1'='1方法或任何使用空格字符的指纹识别。但是,使用制表符(HT或\t)可轻松绕过此过滤。您将需要使用编码,以在HTTP请求中使用它。使用此简单绕过,您应该能够看到如何检测此漏洞。

Example 3

<?php
    require_once('../header.php');
  require_once('db.php');
    if (preg_match('/\s+/', $_GET["name"])) {
        die("ERROR NO SPACE");    
    }
    $sql = "SELECT * FROM users where name='";
    $sql .= $_GET["name"]."'";

    $result = mysql_query($sql);
    if ($result) {
        ?>
        <table class='table table-striped'>
      <tr><th>id</th><th>name</th><th>age</th></tr>
        <?php
        while ($row = mysql_fetch_assoc($result)) {
            echo "<tr>";
                echo "<td>".$row['id']."</td>";
                echo "<td>".$row['name']."</td>";
                echo "<td>".$row['age']."</td>";
            echo "</tr>";
        }    
        echo "</table>";
    }
    require '../footer.php';
?>

 

在此示例中,开发人员阻止空格和制表符。有一种方法可以绕过这个过滤器。您可以在关键字之间使用注释来构建有效请求,而无需任何空格或制表。可以使用以下SQL注释:/**/。通过使用此注释替换前面示例中的所有空格/列表,您应该能够测试此漏洞。

 

Example 4

<?php
  require_once('../header.php');
  require_once('db.php');
  $sql="SELECT * FROM users where id=";
    $sql.=mysql_real_escape_string($_GET["id"])." ";
    $result = mysql_query($sql);
    

    if ($result) {
        ?>
        <table class='table table-striped'>
      <tr><th>id</th><th>name</th><th>age</th></tr>

        <?php
        while ($row = mysql_fetch_assoc($result)) {
            echo "<tr>";
                echo "<td>".$row['id']."</td>";
                echo "<td>".$row['name']."</td>";
                echo "<td>".$row['age']."</td>";
            echo "</tr>";
        }    
        echo "</table>";
    }
    require '../footer.php';
?>

 

此示例表示对如何防止SQL注入的典型误解。在前面的3个示例中,使用该功能mysql_real_escape_string可以防止漏洞。在此示例中,开发人员使用相同的逻辑。但是,使用的值是整数,并且不会在单引号之间回显。由于该值直接放在查询中,因此使用mysql_real_escape_string不会阻止任何操作。在这里,您只需要能够添加空格和SQL关键字来打破语法。检测方法与用于基于字符串的SQL注入的方法非常类似。您只需在有效负载的开头不需要引号。例如:?id=2 or 1=1。

另一种检测方法是使用整数。最初的要求是?id=2。通过使用值2,我们可以检测到SQL注入:

  • ?id=2 #(#需要编码)应该返回相同的东西。
  • ?id=3-1应该返回相同的东西。数据库将自动执行减法,您将得到相同的结果。
  • ?id=2-0 应该返回相同的东西。
  • ?id=1+1(+需要编码)应该返回相同的东西。数据库将自动执行添加,您将获得相同的结果。
  • ?id=2.0 应该返回相同的东西。

 

并且以下内容不应返回相同的结果:

  • ?id=2+1。
  • ?id=3-0。

Example 5

<?php

  require_once('../header.php');
  require_once('db.php');
    if (!preg_match('/^[0-9]+/', $_GET["id"])) {
        die("ERROR INTEGER REQUIRED");    
    }
    $sql = "SELECT * FROM users where id=";
    $sql .= $_GET["id"] ;
    
    $result = mysql_query($sql);

    if ($result) {
        ?>
        <table class='table table-striped'>
      <tr><th>id</th><th>name</th><th>age</th></tr>
        <?php
        while ($row = mysql_fetch_assoc($result)) {
            echo "<tr>";
                echo "<td>".$row['id']."</td>";
                echo "<td>".$row['name']."</td>";
                echo "<td>".$row['age']."</td>";
            echo "</tr>";
        }    
        echo "</table>";
    }
    require '../footer.php';
?>

 

这个例子与以前的检测方式非常相似。如果查看代码,您将看到开发人员试图通过使用正则表达式来阻止SQL注入:

if (!preg_match('/^[0-9]+/', $_GET["id"])) {
    die("ERROR INTEGER REQUIRED");  
}
 

但是,使用的正则表达式是不正确的; 它只是确保参数id 开始以数字。先前使用的检测方法可用于检测此漏洞。例如:?id=2 or 1=1。

 

Example 6

<?php

   require_once('../header.php');
  require_once('db.php');
    if (!preg_match('/[0-9]+$/', $_GET["id"])) {
        die("ERROR INTEGER REQUIRED");    
    }
    $sql = "SELECT * FROM users where id=";
    $sql .= $_GET["id"] ;

    
    $result = mysql_query($sql);


if ($result) {
        ?>
        <table class='table table-striped'>
      <tr><th>id</th><th>name</th><th>age</th></tr>
        <?php
        while ($row = mysql_fetch_assoc($result)) {
            echo "<tr>";
                echo "<td>".$row['id']."</td>";
                echo "<td>".$row['name']."</td>";
                echo "<td>".$row['age']."</td>";
            echo "</tr>";
        }    
        echo "</table>";
    }
    require '../footer.php';
?>

 

这个例子是另一种方式。开发人员再次在正则表达式中犯了一个错误:

if (!preg_match('/[0-9]+$/', $_GET["id"])) {
    die("ERROR INTEGER REQUIRED");  
}

此正则表达式仅确保参数以数字id 结尾(由于$符号)。它不能确保参数的开头有效(缺失^)。您可以使用之前学到的方法。

 

您只需要在有效负载的末尾添加一个整数。这个数字可以是有效载荷的一部分,也可以放在SQL注释之后:?id=1 or 1=1 # 123。(#需要编码)!

 

Example 7

<?php

  require_once('../header.php');
  require_once('db.php');
    if (!preg_match('/^-?[0-9]+$/m', $_GET["id"])) {
        die("ERROR INTEGER REQUIRED");    
    }
    $sql = "SELECT * FROM users where id=";
    $sql .= $_GET["id"];
    
    $result = mysql_query($sql);

    if ($result) {
        ?>
        <table class='table table-striped'>
      <tr><th>id</th><th>name</th><th>age</th></tr>
        <?php
        while ($row = mysql_fetch_assoc($result)) {
            echo "<tr>";
                echo "<td>".$row['id']."</td>";
                echo "<td>".$row['name']."</td>";
                echo "<td>".$row['age']."</td>";
            echo "</tr>";
        }    
        echo "</table>";
    }
    require '../footer.php';
?>

 

另一个坏正则表达式的例子:

if (!preg_match('/^-?[0-9]+$/m', $_GET["id"])) {
  die("ERROR INTEGER REQUIRED");    
}

 

 

在这里我们可以看到字符串的开始(^)和结束($)被正确检查。但是,正则表达式包含修饰符PCRE_MULTILINE(/m)。多行修饰符仅验证其中一行仅包含整数,因此以下值有效(由于其中包含新行):

123\nPAYLOAD;

PAYLOAD\n123;

PAYLOAD\n123\nPAYLOAD。

在URL中使用时,需要对这些值进行编码,但是通过使用编码和先前看到的技术,您应该能够检测到此漏洞。例如:

http://192.168.1.11/sqli/example7.php?id=2%0A%20or%201=1

 

Example 8

<?php

  require_once('../header.php');
  require_once('db.php');
    $sql = "SELECT * FROM users ORDER BY `";
    $sql .= mysql_real_escape_string($_GET["order"])."`";
    $result = mysql_query($sql);
    
    if ($result) {
        ?>
        <table  class='table table-striped'>
        <tr>
            <th><a href="example8.php?order=id">id</th>
            <th><a href="example8.php?order=name">name</th>
            <th><a href="example8.php?order=age">age</th>
        </tr>
        <?php
        while ($row = mysql_fetch_assoc($result)) {
            echo "<tr>";
                echo "<td>".$row['id']."</td>";
                echo "<td>".$row['name']."</td>";
                echo "<td>".$row['age']."</td>";
            echo "</tr>";
        }    
        echo "</table>";
    }
    require '../footer.php';
?>

 

在此示例中,参数名称表示它将在SQL查询中回显的位置。如果查看MySQL文档,有两种方法可以在ORDER BY语句中提供值:

  • 直接:ORDER BY name;
  • 在反引号之间:ORDER BY `name`。

 

该ORDER BY声明不能与单引号或双引号内的值一起使用。如果使用它,则不会对任何内容进行排序,因为MySQL将这些视为常量。

 

要检测此类漏洞,我们可以尝试使用不同的有效负载获得相同的结果:

  • name` #(#需要编码)应该给出相同的结果。
  • name` ASC #(#需要编码)应该给出相同的结果。
  • name`, `name:初始查询中的反向标记将在注入结束时关闭。

 

以下有效负载应该给出不同的结果:

  • name` DESC #(#需要编码)。
  • name` 不应该给出任何结果,因为语法不正确。

 

Example 9

<?php
  require_once('../header.php');
  require_once('db.php');
    $sql = "SELECT * FROM users ORDER BY ";
  $sql .= mysql_real_escape_string($_GET["order"]);
    $result = mysql_query($sql);
    if ($result) {
        ?>
        <table class='table table-striped'>
        <tr>
            <th><a href="example9.php?order=id">id</th>
            <th><a href="example9.php?order=name">name</th>
            <th><a href="example9.php?order=age">age</th>
        </tr>
        <?php
        while ($row = mysql_fetch_assoc($result)) {
            echo "<tr>";
                echo "<td>".$row['id']."</td>";
                echo "<td>".$row['name']."</td>";
                echo "<td>".$row['age']."</td>";
            echo "</tr>";
        }    
        echo "</table>";
    }
  require '../footer.php';
?>

 

这个例子类似于前一个例子,但不是反向引号```

 

在这种情况下可以使用其他方法,因为我们之前没有反向引号直接注入请求。我们可以使用MySQL IF语句生成更多有效负载:

  • IF(1, name,age) 应该给出相同的结果。
  • IF(0, name,age)应该给出不同的结果。您可以看到列按年龄排序,但sort函数将值比较为字符串,而不是整数(10小于2)。这是一个副作用IF,如果列中的一个包含字符串,则会将值排序为字符串。

标签:web,name,渗透,使用,echo,SQL,id,row
From: https://www.cnblogs.com/shanhubei/p/17596879.html

相关文章

  • PostgreSQL-PITR 增量备份与恢复
    Point-in-TimeRecovery(PITR)基于时间点的备份(恢复)。归档对于PITR(增量备份与恢复)至关重要,如果归档不一致,会产生各种各样的问题。以下的测试截图中,我将归档清零,重新生成,再做相关PITR的操作。这里是简单的操作过程,详情查看相关的官方文档说明 26.3.ContinuousArchivingandPoi......
  • mysql安装及使用语句
    http://www.mysql.com/downloads/ubuntu安装sqlite http://blog.chinaunix.net/uid-20672803-id-3049747.htmlhttp://wenku.baidu.com/link?url=dl9lRAhX82e9Lg5EnQB7l1fWtdBueLoiyKuzxPhDiOxxuxPQpORaD-_jxFajOkpQfw-BEG1VYwAZBxbAYzJK5QA_8grUtGJU41Wyo43wGzihttp://www.yiiba......
  • ubuntu安装mysql数据库
    http://www.2cto.com/database/201401/273423.htmlhttp://www.linuxidc.com/Linux/2013-01/78716.htm......
  • 《为研发同学定制的MySQL面试指南》-- 连载中
    一、给研发同学看的面试指南1、MySQL的修仙之路,图文谈谈如何学MySQL、如何进阶!2、数据库面经,常见的面试题....3、谈谈MySQL中基数是什么?4、聊聊什么是慢查?如何监控?如何排查?5、对NotNull字段插入Null值有啥现象?6、能谈谈year、date、datetime、time、timestamp的区别吗?7、你有没有......
  • MySQL的修仙者之旅,不来看看你的修为如何吗?
    目录因为我个人比较喜欢看修仙类的小说,所以本文的主体部分借用修仙者的修为等级,将学习旅程划分成:练气、筑基、结丹、元婴、化神、飞升六个段位,你可以看下你大概在哪个段位上哦!本文目录:我为什么要写这篇文章都这么卷了,是时候好好学MySQL了!勾勒脑图练气期筑基期结丹期元婴期化神期飞......
  • webpack的部分知识
    webpack真的好累啊什么是webpackwebpack是一个现代javascript应用的静态模块打包工具,其主要功能就是模块和打包这里我一直觉得和maven很像,早在之前的学习过程中,maven具体的工作是什么我一直百思不得其解,认为我们普通的java程序就能够很好的跑起来为什么还要maven呢?这里先说we......
  • PostgreSQL-由于与数据库的某些自动连接而无法删除数据库
    PostgreSQL常见问题解决1.删除databaseDROPDATABASEviid; 执行上述sql报错信息如下:ERROR:database"viid"isbeingaccessedbyotherusersDETAIL:Thereis1othersessionusingthedatabase. 原因是有其他的session正在使用该数据库 解决方法:强......
  • Unity 将UnityWebRequest改为async/await异步
    花了一点时间,对UnityWebRequest进行了简单封装,使用起来更方便一些,顺便实现了post接口轮询、重试的功能usingSystem;usingSystem.Collections;usingSystem.Collections.Generic;usingSystem.Runtime.CompilerServices;usingSystem.Text;usingSystem.Threading.Tasks;......
  • MySQL 账号密码永不过期为什么不起作用?
    背景客户反馈MySQL账号已经设置成密码永不过期了,但是在登录后总是提示报错ERROR1862(HY000):Yourpasswordhasexpired.Tologinyoumustchangeitusingaclientthatsupportsexpiredpasswords.排查方法首先检查一下MySQL服务器设置的密码过期时间,可以看到默认密......
  • sql语言主要分为哪几类?
    1、sql语言主要分为哪几类?2、sql语言的特点3、SQL是一种什么样的语言?4、sql是什么sql语言主要分为哪几类?1、SQL包含四种程序设计语言类别的语句:数据定义语言(DDL)、数据操作语言(DML)、数据控制语言(DCL)和事物控制语言(TCL)。2、SQL语言包括三种主要程序设计语言类别的语句:数......