ctf show web入门108

这是一道非常经典的 PHP 代码审计/CTF 题目。我们需要绕过两个关键的条件判断来获取 $flag。

题目主要有两层过滤和判断:

php 复制代码
if (ereg ("^[a-zA-Z]+$", $_GET['c'])===FALSE) {
    die('error');
}

含义:使用 ereg 正则表达式匹配输入参数 c。它要求整个字符串必须完全由大小写英文字母组成([1](#1)+$)。如果不匹配(返回 FALSE),程序就会终止并输出 error

php 复制代码
//只有36d的人才能看到flag
if(intval(strrev($_GET['c']))==0x36d){
    echo  $flag;
}

strrev($_GET'c'):将参数 c 的字符串反转。

intval(...):将反转后的字符串转换为整数。

== 0x36d:判断转换后的整数是否等于十六进制的 0x36d。

计算:十六进制的 0x36d 转换为十进制是 877

逆向推导:要让 intval 的结果为 877,那么反转前的字符串开头(或者反转后的字符串)必须代表数字 877。既然 strrev('c') 要变成以 877 开头的数字,那么原本的参数 c 就必须以 778 结尾(例如 778 反转后变成 877)

条件一要求:参数 c 只能包含纯字母。

条件二要求:参数 c 必须以数字 778 结尾。

绕过第一关:ereg() 的 %00 截断漏洞

ereg() 函数存在一个著名的漏洞:字符串截断漏洞

在 ereg 处理字符串时,如果遇到了空字符 %00(即 \x00),它会认为字符串到这里就已经结束了

构造手法:如果我们让 c 的开头全是字母,紧接着一个 %00,后面再放数字

对于 ereg 来说,它只检测 %00 前面的纯字母部分,因此会成功匹配,返回 TRUE(不触发 die)。

例如输入:a%00778

满足第二关:strrev() 与 intval() 的处理

当我们传入 c = a%00778 时,看看第二关会发生什么:

strrev("a\x00778"):反转字符串,结果变成 "877\x00a"

intval("877\x00a"):PHP 的 intval() 函数在弱类型转换时,会从字符串的开头开始读取数字,直到遇到非数字字符为止。在这里,它读取到 "877",遇到 \x00 停止,因此成功转换成了十进制整数 877

弱类型比较:877 == 0x36d(即 877 == 877),条件成立

所以最终payload为:

?c=a%00778

flag为:ctfshow{33571543-8c21-4834-9080-7e870e5ed0dd}


  1. a-zA-Z ↩︎
相关推荐
L@ncor12 小时前
第五章 基于低代码平台的智能体搭建 · 学习笔记(Coze / Dify / FastGPT / n8n)
笔记·学习·低代码·agent·prompt工程
知潮网12 小时前
被嫌弃的五仁月饼,一吨千元在养猪场翻了身
笔记
2601_9606312312 小时前
中药前处理及提取的工艺环节与技术要点
笔记
2601_9653842612 小时前
口腔黏膜清洁中的几何约束与流体动力学边界层问题分析
经验分享·笔记
一米阳光866112 小时前
软考高级【信息系统项目管理师】高项重要考点(9)组织 助你顺利上岸!
笔记·职场发展·软考·高项·信息系统项目管理师·高级职称
白杨尚青13 小时前
C++入门篇(十):string(上)——认识string:构造与三大遍历(一条龙讲透operator[]、迭代器、auto、范围for)
java·开发语言·c++·笔记·stl
Chen—LSN13 小时前
C语言——⽂件操作(1)
c语言·开发语言·c++·经验分享·笔记·算法·链表
Chen—LSN14 小时前
C语言——文件操作(2)
c语言·开发语言·c++·经验分享·笔记·算法·c#
Lintongzg14 小时前
千卡训练的隐形账单:通信不是瓶颈
笔记·学习·性能优化·llm
LuminousCPP14 小时前
从零开始学 C++(三):类和对象入门|从 struct 到 class,理解封装、对象与 this 指针
c++·笔记·学习·类和对象