2023年第四届 “赣网杯” 网络安全大赛 gwb-web3 Write UP【PHP 临时函数名特性 + 绕过trim函数】

本文主要是介绍2023年第四届 “赣网杯” 网络安全大赛 gwb-web3 Write UP【PHP 临时函数名特性 + 绕过trim函数】,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、题目如下:

在这里插入图片描述


二、代码解读:

这段代码是一个简单的PHP脚本,它接受通过GET请求传递的两个参数:‘pass’和’func’:
$password = trim($_GET['pass'] ?? '');:从GET请求中获取名为’pass’的参数,然后使用trim函数去除首尾空格,并将结果赋给变量 $password。如果’pass’参数不存在,则使用空字符串。
$func = trim($_GET['func'] ?? 'hint');:从GET请求中获取名为’func’的参数,然后使用trim函数去除首尾空格,并将结果赋给变量$func。如果’func’参数不存在,则默认使用字符串’hint’。
function hint() {show_source(__FILE__);} :定义了一个名为hint的函数,它的作用是显示当前文件的源代码,使用了show_source函数。
if (md5(\$password)==='21c6008facc283f8839d3b9fed640c15') {:检查通过GET请求传递的’pass’参数的MD5哈希值是否等于指定的值。如果匹配,进入条件块。
function youwin() {echo file_get_contents("/flag");}:在条件成立时,定义了一个名为youwin的函数,它的作用是输出名为’/flag’的文件的内容,使用了file_get_contents函数。
$func();:调用根据’func’参数确定的函数。默认情况下,如果’func’参数不存在,将调用hint函数。


二、解题思路:

常规思路就是绕过 md5 效验。但是这里是强比较,显然无法绕过。尝试参数爆破,看有没有除pass、func 额外的请求参数, bp 跑参数字典:

在这里插入图片描述

果然发现了一个 file 请求参数,使用 readfile() 函数读取文件,尝试任意文件读取:

在这里插入图片描述尝试读取 flag, 发现存在拦截:

在这里插入图片描述

readfile() 可以直接读取 php 文件,且php代码不会被解析

读取当前文件源代码:

在这里插入图片描述尝试绕过 preg_match 正则,传递数组参数:

在这里插入图片描述成功绕过,但是 readfile() 不接受数组作为参数, 网上没找到 readfile() 相关漏洞的文献资料。故放弃…


想起上上周看到 p 牛10月份写的一篇文章,提到了 PHP 临时函数名特性 , 且给的题目案例跟这题很像。 ==> 2023年10月PHP函数小挑战

PHP在编译“函数定义”的时候,会使用 zend_compile_func_decl 函数。这个函数有个关键的参数叫 toplevel,这个参数表示当前的函数定义是否在顶层作用域。

顶层作用域: 顶层作用域通常是指在全局范围内声明的变量、函数或类,而不是在任何函数或控制结构内声明的。

<?php// 在顶层作用域定义的函数
function func1() {echo 'func1';
}if (true) {// 在if条件判断内部定义的函数,不是顶层作用域function func2() {echo 'func2';}
}

当toplevel为true的时候,就是直接将当前函数名 lcname 加入函数表;当 toplevel为false的时候,使用 zend_build_runtime_definition_key 函数生成一个 key,将 key 作为函数名加入函数表。也就是说,根据函数所在的位置的不同(是否是顶级作用域),PHP编译时生成的函数名也会不同。
在这里插入图片描述

key 是按照如下算法生成:

'\0' + name + filename + ':' + start_lineno + '$' + rtd_key_counter

除了第一个 \0 字符,后面四部分的含义如下:

  • name 函数名
  • filename PHP文件绝对路径
  • start_lineno 函数起始定义行号(以1为第一行)
  • rtd_key_counter 一个全局访问计数,每次执行会自增1,从0开始

最后保存在函数表中的函数名,就是上面这个以 \0 开头的字符串。


以上是看 p 牛的文章简要梳理一下核心知识点。但是我发现一个问题:

在这里插入图片描述图中说只要构造:'\0' + name + filename + ':' + start_lineno + '$' + rtd_key_counter 调用就可以了,但是后面图中 payload 又是:
'%00' + name + filename + ':' + start_lineno + '$' + rtd_key_counter 这种方式:

在这里插入图片描述在这里插入图片描述
为什么又变成了 %00 而不是 \0 呢?小小的探究一下:

前提:windows,php 7.4 (要限制7.4版本,稍后会说), vld.dll 内存监控插件 (要下载和php版本相对应的)

本地编写和比赛环境一样的代码,文件名为:965ee283f4c848ad99b0a7961ed89199.php,使用php7.4 配合vld插件解释运行:

 ./php -d vld.execute=0 -d vld.active=1  E:\phpstudy_pro\WWW\php-learn\965ee283f4c848ad99b0a7961ed89199.php

在这里插入图片描述在这里插入图片描述可以看到实际的临时函数名确实是以 %00 开头的。php 底层是由C语言编写的,在C语言中,\0和%00实际上有相似的作用,都表示空字符(null character)。\0是C语言中用于表示空字符的一种方式,通常用在字符串中作为字符串的结束标志。%00通常是在格式化输入输出函数中使用的格式说明符,表示空字符。 我们请求参数被php接收并解释运行,也是一个输入的过程,所以要使用 %00 为开头构建。(个人见解)


为什么要限制 php7.4 这个版本去复现呢?

我尝试使用 php7.3 版本配合vld插件去解释运行相同的代码,得到如下:

在这里插入图片描述在这里插入图片描述不同版本有差异性,7.4 版本结尾更加具有规律性,能爆破。


按照上面的思路,按照 zend_build_runtime_definition_key 的算法计算出 key 作为函数名:(rtd_key_counter 从 0 开始爆破)

%00youwin/var/www/html/965ee283f4c848ad99b0a7961ed89199.php:7$rtd_key_counter

比赛环境没了,本地搭了一个。

发现爆破不出flag:

在这里插入图片描述

trim 函数在接收参数的时候会去除掉字符串首尾的空白字符。可以加反斜杠绕过:\%00

故要改写成如下:

\%00youwin/var/www/html/965ee283f4c848ad99b0a7961ed89199.php:7$rtd_key_counter

bp 开始爆破 rtd_key_counter 得 flag:

在这里插入图片描述

这篇关于2023年第四届 “赣网杯” 网络安全大赛 gwb-web3 Write UP【PHP 临时函数名特性 + 绕过trim函数】的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/512693

相关文章

Rust中的Drop特性之解读自动化资源清理的魔法

《Rust中的Drop特性之解读自动化资源清理的魔法》Rust通过Drop特性实现了自动清理机制,确保资源在对象超出作用域时自动释放,避免了手动管理资源时可能出现的内存泄漏或双重释放问题,智能指针如B... 目录自动清理机制:Rust 的析构函数提前释放资源:std::mem::drop android的妙

Python itertools中accumulate函数用法及使用运用详细讲解

《Pythonitertools中accumulate函数用法及使用运用详细讲解》:本文主要介绍Python的itertools库中的accumulate函数,该函数可以计算累积和或通过指定函数... 目录1.1前言:1.2定义:1.3衍生用法:1.3Leetcode的实际运用:总结 1.1前言:本文将详

轻松上手MYSQL之JSON函数实现高效数据查询与操作

《轻松上手MYSQL之JSON函数实现高效数据查询与操作》:本文主要介绍轻松上手MYSQL之JSON函数实现高效数据查询与操作的相关资料,MySQL提供了多个JSON函数,用于处理和查询JSON数... 目录一、jsON_EXTRACT 提取指定数据二、JSON_UNQUOTE 取消双引号三、JSON_KE

MySQL数据库函数之JSON_EXTRACT示例代码

《MySQL数据库函数之JSON_EXTRACT示例代码》:本文主要介绍MySQL数据库函数之JSON_EXTRACT的相关资料,JSON_EXTRACT()函数用于从JSON文档中提取值,支持对... 目录前言基本语法路径表达式示例示例 1: 提取简单值示例 2: 提取嵌套值示例 3: 提取数组中的值注意

Java function函数式接口的使用方法与实例

《Javafunction函数式接口的使用方法与实例》:本文主要介绍Javafunction函数式接口的使用方法与实例,函数式接口如一支未完成的诗篇,用Lambda表达式作韵脚,将代码的机械美感... 目录引言-当代码遇见诗性一、函数式接口的生物学解构1.1 函数式接口的基因密码1.2 六大核心接口的形态学

Python脚本实现自动删除C盘临时文件夹

《Python脚本实现自动删除C盘临时文件夹》在日常使用电脑的过程中,临时文件夹往往会积累大量的无用数据,占用宝贵的磁盘空间,下面我们就来看看Python如何通过脚本实现自动删除C盘临时文件夹吧... 目录一、准备工作二、python脚本编写三、脚本解析四、运行脚本五、案例演示六、注意事项七、总结在日常使用

在MyBatis的XML映射文件中<trim>元素所有场景下的完整使用示例代码

《在MyBatis的XML映射文件中<trim>元素所有场景下的完整使用示例代码》在MyBatis的XML映射文件中,trim元素用于动态添加SQL语句的一部分,处理前缀、后缀及多余的逗号或连接符,示... 在MyBATis的XML映射文件中,<trim>元素用于动态地添加SQL语句的一部分,例如SET或W

五大特性引领创新! 深度操作系统 deepin 25 Preview预览版发布

《五大特性引领创新!深度操作系统deepin25Preview预览版发布》今日,深度操作系统正式推出deepin25Preview版本,该版本集成了五大核心特性:磐石系统、全新DDE、Tr... 深度操作系统今日发布了 deepin 25 Preview,新版本囊括五大特性:磐石系统、全新 DDE、Tree

Oracle的to_date()函数详解

《Oracle的to_date()函数详解》Oracle的to_date()函数用于日期格式转换,需要注意Oracle中不区分大小写的MM和mm格式代码,应使用mi代替分钟,此外,Oracle还支持毫... 目录oracle的to_date()函数一.在使用Oracle的to_date函数来做日期转换二.日

PHP执行php.exe -v命令报错的解决方案

《PHP执行php.exe-v命令报错的解决方案》:本文主要介绍PHP执行php.exe-v命令报错的解决方案,文中通过图文讲解的非常详细,对大家的学习或工作有一定的帮助,需要的朋友可以参考下... 目录执行phpandroid.exe -v命令报错解决方案执行php.exe -v命令报错-PHP War