SQL Injection day 1

maymay
4 min read

信息收集

  • database() / schema(): 获取当前数据库名

      mysql> select database();
      +------------+
      | database() |
      +------------+
      | security   |
      +------------+
      1 row in set (0.04 sec)
    
      mysql> select schema();
      +----------+
      | schema() |
      +----------+
      | security |
      +----------+
      1 row in set (0.00 sec)
    
  • user() / current_user(): 获取当前执行查询的用户名

      mysql> select user();
      +----------------+
      | user()         |
      +----------------+
      | root@localhost |
      +----------------+
      1 row in set (0.01 sec)
    
      mysql> select current_user();
      +----------------+
      | current_user() |
      +----------------+
      | root@localhost |
      +----------------+
      1 row in set (0.00 sec)
    
  • version() / @@version: 获取SQL服务版本

      mysql> select version();
      +-------------------------+
      | version()               |
      +-------------------------+
      | 5.5.44-0ubuntu0.14.04.1 |
      +-------------------------+
      1 row in set (0.00 sec)
    
      mysql> select @@version;
      +-------------------------+
      | @@version               |
      +-------------------------+
      | 5.5.44-0ubuntu0.14.04.1 |
      +-------------------------+
      1 row in set (0.00 sec)
    
  • @@basedir / @@datadir: 获取MySQL安装目录 / 获取MySQL数据目录

      mysql> select @@basedir;
      +-----------+
      | @@basedir |
      +-----------+
      | /usr      |
      +-----------+
      1 row in set (0.00 sec)
    
      mysql> select @@datadir;
      +-----------------+
      | @@datadir       |
      +-----------------+
      | /var/lib/mysql/ |
      +-----------------+
      1 row in set (0.00 sec)
    

@@ 用于读取或设置MySQL服务器自身的配置和状态。

这些变量控制着数据库的行为,例如版本信息、文件路径、缓存大小等等。

系统变量分为GLOBAL(全局级别)和SESSION(会话级别)。

@variable 用于定义和访问用户自定义的变量,可以使用SETSELECT进行设置。

mysql> SET @my_name = 'may';
Query OK, 0 rows affected (0.01 sec)
mysql> select @my_name;
+----------+
| @my_name |
+----------+
| may      |
+----------+
1 row in set (0.00 sec)

mysql> select @my := (select 'may');
+-----------------------+
| @my := (select 'may') |
+-----------------------+
| may                   |
+-----------------------+
1 row in set (0.00 sec)
mysql> select @my;
+------+
| @my  |
+------+
| may  |
+------+
1 row in set (0.00 sec)

核心利用函数

1. 字符串操纵函数

  • LENGTH(str): 返回字符串的字节长度。

      mysql> select length(password) from users where username = 'admin';
      +------------------+
      | length(password) |
      +------------------+
      |                5 |
      +------------------+
      1 row in set (0.01 sec)
    

    从攻击者的角度来看,这是盲注的第一步:探测未知数据的长度。例如,猜测数据库名、表名或密码的长度。

  • SUBSTRING(str, start, length): 从字符串str中,在指定的start位置开始,提取length个字符。

    为了兼容性,MySQL为子字符串函数提供了两个别名:substrmid;它们本质上指向的是同一个函数。

      mysql> select SUBSTRING('admin@may.com',1,5);
      +--------------------------------+
      | SUBSTRING('admin@may.com',1,5) |
      +--------------------------------+
      | admin                          |
      +--------------------------------+
      1 row in set (0.03 sec)
    
      mysql> select SUBSTR('admin@may.com',1,5);
      +-----------------------------+
      | SUBSTR('admin@may.com',1,5) |
      +-----------------------------+
      | admin                       |
      +-----------------------------+
      1 row in set (0.00 sec)
    
      mysql> select MID('admin@may.com',1,5);
      +--------------------------+
      | MID('admin@may.com',1,5) |
      +--------------------------+
      | admin                    |
      +--------------------------+
      1 row in set (0.00 sec)
    

    从攻击者的角度来看,这是逐字符提取数据的核心武器。在确定数据长度后,你可以手动或通过脚本循环——从位置1开始,一次提取一个字符,并与你的猜测进行比较。

  • ASCII(char) / ORD(char): 返回单个字符的ASCII值。

      mysql> select ASCII('m');
      +------------+
      | ASCII('m') |
      +------------+
      |        109 |
      +------------+
      1 row in set (0.03 sec)
    
      mysql> select ORD('m');
      +----------+
      | ORD('m') |
      +----------+
      |      109 |
      +----------+
      1 row in set (0.01 sec)
    

    ASCII()ORD()并不等价,其区别主要在于对单字节和多字节字符处理时的差异:

    • 在处理单字节字符时,它俩是等价的

    • 而在处理中文、日文、emoji等多字节字符时则存在差异

  • CONCAT(str1, str2, …): 将多个字符拼接成一个字符串。

      mysql> select concat(username,password) from users;
      +---------------------------+
      | concat(username,password) |
      +---------------------------+
      | DumbDumb                  |
      | AngelinaI-kill-you        |
      | Dummyp@ssword             |
      | securecrappy              |
      | stupidstupidity           |
      | supermangenious           |
      | batmanmob!le              |
      | adminadmin                |
      | dhakkandumbo              |
      | admin4admin4              |
      +---------------------------+
      10 rows in set (0.01 sec)
    
  • GROUP_CONCAT(column): 将多行中指定列的值,连接成一个单一的字符串。

      mysql> select group_concat(username) from users;
      +---------------------------------------------------------------------------------------------+
      | group_concat(username)                                                                      |
      +---------------------------------------------------------------------------------------------+
      | Dumb,Angelina,Dummy,secure,stupid,superman,batman,admin,admin1,admin2,admin3,dhakkan,admin4 |
      +---------------------------------------------------------------------------------------------+
      1 row in set (0.03 sec)
    

2. 条件逻辑函数

  • IF(condition, value_if_true, value_if_false): 执行一个简单的“如果…那么…否则…”决策。

      mysql> select id,username,if(id > 5,'vip','regular') from users;
      +----+----------+----------------------------+
      | id | username | if(id > 5,'vip','regular') |
      +----+----------+----------------------------+
      |  1 | Dumb     | regular                    |
      |  2 | Angelina | regular                    |
      |  3 | Dummy    | regular                    |
      |  4 | secure   | regular                    |
      |  5 | stupid   | regular                    |
      |  6 | superman | vip                        |
      |  7 | batman   | vip                        |
      |  8 | admin    | vip                        |
      |  9 | admin1   | vip                        |
      | 10 | admin2   | vip                        |
      | 11 | admin3   | vip                        |
      | 12 | dhakkan  | vip                        |
      | 14 | admin4   | vip                        |
      +----+----------+----------------------------+
      13 rows in set (0.00 sec)
    
  • CASE WHEN … THEN … ELSE … END: 实现更复杂的多分支条件逻辑,类似于编程语言中的switch-caseif-elseif-else

      mysql> SELECT
          ->      id,password,
          ->      CASE
          ->      WHEN length(password) > 5 then 'strong-pwd'
          ->      WHEN length(password) < 5 then 'easy-pwd'
          ->      ELSE 'low-pwd'
          ->      END AS strong_check
          ->      FROM users;
      +----+------------+--------------+
      | id | password   | strong_check |
      +----+------------+--------------+
      |  1 | Dumb       | easy-pwd     |
      |  2 | I-kill-you | strong-pwd   |
      |  3 | p@ssword   | strong-pwd   |
      |  4 | crappy     | strong-pwd   |
      |  5 | stupidity  | strong-pwd   |
      |  6 | genious    | strong-pwd   |
      |  7 | mob!le     | strong-pwd   |
      |  8 | admin      | low-pwd      |
      |  9 | admin1     | strong-pwd   |
      | 10 | admin2     | strong-pwd   |
      | 11 | admin3     | strong-pwd   |
      | 12 | dumbo      | low-pwd      |
      | 14 | admin4     | strong-pwd   |
      +----+------------+--------------+
      13 rows in set (0.00 sec)
    

    在这个CASE语句的例子中,AS关键字为由CASE表达式计算出的结果列,分配了一个别名。

0
Subscribe to my newsletter

Read articles from may directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

may
may