第五篇 SQL注入基础知识
1 什么是SQL注入
一种将SQL语句插入到用户输入的参数中,进行攻击,这些会通过后端服务器传入到SQL服务器,执行对应的SQL语句,比如可以获取数据库信息、用户信息、管理员权限等
2 常见的SQL注入技巧
2.1 识别数据库类型
常见的数据库类型有:Oracle、MySQL、SQL Server、Access、Postgresql等
- 首先根据web前端的技术栈,如:
asp和.net 通常使用sqlserver,asp有的时候也适用access
php通常使用mysql,postgresql
java通常使用oracle,mysql
-
其次根据使用的操作系统进行判断,比如windows,使用的数据库很有可能就是sqlserver,linux一般都是mysql,postgresql
-
再次,基于查询、报错信息进行识别
1. 基于version:
sqlserver :
1)select @@version, 返回结果示例:
Microsoft SQL Server 2019 (RTM-CU14) (KB5007182) - 15.0.4188.2 (X64)
mysql:
1)select @@version,返回结果示例:
+-----------+
| @@version |
+-----------+
| 8.0.26 |
+-----------+
2) select version(),返回结果示例:
+-----------+
| version() |
+-----------+
| 8.0.26 |
+-----------+
postgresql:
1)select version(),返回结果示例:
PostgreSQL 14.1 (Debian 14.1-1.pgdg110+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 10.2.1-6) 10.2.1 20210110, 64-bit
oracle:
1) select banner from v$version,返回结果示例:
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production
PL/SQL Release 11.2.0.1.0 - Production
CORE 11.2.0.1.0 Production
TNS for Linux: Version 11.2.0.1.0 - Production
NLSRTL Version 11.2.0.1.0 - Production
2. 基于字符串的拼接方式:somestring
sqlserver: select 'some'+'string';
mysql:select 'some' 'string'
postgresql:select 'some' || 'string'
oracle:select 'some' || 'string' from dual
3. 使用数字参数
sqlserver:
1) @@pack_reveived:返回数据包信息,示例:
1> select @@pack_received
2> go
-----------
132
2) @@rowcount:返回上一句影响的行数,示例:
1> select @@rowcount
2> go
-----------
1
mysql:
1)connection_id():返回连接的id,示例:
mysql> select connection_id();
+-----------------+
| connection_id() |
+-----------------+
| 12 |
+-----------------+
1 row in set (0.00 sec)
2)last_insert_id():获取最近插入主键的id,示例:
mysql> select last_insert_id();
+------------------+
| last_insert_id() |
+------------------+
| 0 |
+------------------+
3)row_count():获取上次受影响的行数,示例:
mysql> select row_count();
+-------------+
| row_count() |
+-------------+
| -1 |
+-------------+
oracle:
1)bitand:返回按位进行运算的结果,示例:
SQL> select bitand(1,1) from dual;
BITAND(1,1)
-----------
1
postgresql:
1)extract():提取时间或者日期信息,示例:
postgres=# select extract(dow from now());
extract
---------
4
(1 row)
4. 注释
mysql:#,--,/* */
oracle和sqlserver:--,/* */,oracle不支持;符号
2.2 常用注入语句
2.2.1 UNION语句
用来合并两条或多条SELECT语句的查询结果
SELECT col1,col2 ... coln FROM table1
UNION
SELECT col1,col2 ... coln FROM table2
默认情况下,结果中只包含不同的值,如果需要包含所有的值,就需要改为:UNION ALL,如果应用程序返回第一个表查询所得的数据,那么就可以利用UNION来查询任何一张表,但是也需要满足一定的条件
1)两个查询返回的列数必须相同。想要获取准确的列数,有两种方法:
a)通过对第二个语句进行注入多次,每次逐渐增大列数,直到查询正确执行,为了避免数据类型不一致导致错误,可以使用null来代替
b)使用ORDER BY子句,可以增大列的数字来判断列数,示例:ORDER BY 1(2,3,等),如果ORDER BY 3报错,证明是2列,该方法比较推荐,主要原因是可以使用二分查找的方式,速度更快,同时留下的痕迹更少
2)两个SELECT语句对应列所返回的数据类型必须相同(或至少是兼容的)。在获取列数之后,想要判断数据类型,就可以通过null的方式来进行替换,比如:UNION SELECT 'test', NULL,NULL ...
2.2.2 条件语句
有的情况,查询结果只有两种答案:是或否,这个时候就可以通过使用条件语句,格式示例:
IF 条件 THEN 执行 ELSE 执行其他
2.2.2.1 基于时间
比如想知道执行查询的语句是不是系统管理员账号
常用的有:
-
获取数据库信息,比如:数据库名(substr(),left()),数据库长度(length()),示例猜测数据库长度
-
获取数据表信息,示例猜测表名长度
-
获取列信息,示例猜测列名长度
2.2.2.2 基于错误
基于时间不适用于提取多位信息,比如出现1和0的概率都是一样的,主要方法有利用回显的报错注入和利用报错信息的报错注入