type
Post
status
Published
date
slug
summary
tags
CTF
推荐
category
CTF-Knowledge
category (1)
icon
password
comment

前言

最近好多比赛都考rce,而且都防得很死,没办法,只能自己总结一下了。

环境准备

这里使用preg*replace替换匹配到的字符为空,、数字和下划线,等价于 [^A-Za-z0-9*],然后(?R)?这个意思为递归整个匹配模式。所以正则的含义就是匹配无参数的函数,内部可以无限嵌套相同的模式(无参数函数),将匹配的替换为空,判断剩下的是否只有;以上正则表达式只匹配a(b(c()))或a()这种格式,不匹配a(“123”),也就是说我们传入的值函数不能带有参数,所以我们要使用无参数的函数进行文件读取或者命令执行。 本文涉及的相关函数

关键函数

getenv()

getenv() :获取环境变量的值(在PHP7.1之后可以不给予参数) 适用于:php7以上的版本

getallheaders()

getallheaders():获取所有 HTTP 请求标头,是apache_request_headers()的别名函数,但是该函数只能在Apache环境下使用 传入?code=print_r(getallheaders());,数组返回 HTTP 请求头

Payload1

使用end指向最后一个请求头,用其值进行rce
● end():将数组的内部指针指向最后一个单元

Payload2

此payload适用于php7以上版本

get_defined_vars()

Payload1

利用全局变量进RCE get_defined_vars():返回由所有已定义变量所组成的数组,会返回GET,_POST,COOKIE,_FILES全局变量的值,返回数组顺序为get->post->cookie->files current():返回数组中的当前单元,初始指向插入到数组中的第一个单元,也就是会返回$_GET变量的数组值

Payload2

?flag=phpinfo();&code=print_r(get_defined_vars()); 该函数会返回全局变量的值,如get、post、cookie、file数据,
image-20231015161148700
image-20231015161148700
flag=>phpinfo();在_GET数组中,所以需要使用两次取数组值:
pos第一次取值
image-20231015161223237
image-20231015161223237
pos第二次取值
image-20231015161253711
image-20231015161253711
执行phpinfo()
image-20231015161326282
image-20231015161326282
任意命令执行
image-20231015161348734
image-20231015161348734

Payload3

而如果网站对GET,_POST,COOKIE都做的过滤那我们只能从_FILES入手了,file数组在最后一个,需要end定位,然后pos两次定位获得文件名

session_start()

适用于:php7以下的版本 ● session_start():启动新会话或者重用现有会话,成功开始会话返回 TRUE ,反之返回 FALSE,返回参数给session_id() ● session_id():获取/设置当前会话 ID,返回当前会话ID。 如果当前没有会话,则返回空字符串(””)。

文件读取

● show_source(session_id(session_start())); ● var_dump(file_get_contents(session_id(session_start()))) ● highlight_file(session_id(session_start())); ● readfile(session_id(session_start())); 抓包传入Cookie: PHPSESSID=(想读的文件)即可
读取成功:
image-20231015162215457
image-20231015162215457

命令执行

hex2bin()函数可以将十六进制转换为ASCII 字符,所以我们传入十六进制并使用hex2bin()即可
先传入eval(hex2bin(session_id(session_start())));,然后抓包传入Cookie: PHPSESSID=(“system(‘命令’)”的十六进制)即可
回显成功
image-20231015162240068
image-20231015162240068

scandir()

文件读取

查看当前目录文件名

读取当前目录文件

getcwd() 是一个PHP内置函数,用于获取当前工作目录(当前的工作路径)的绝对路径
array_flip() 是一个PHP内置函数,用于交换关联数组(associative array)中的键和值。它会创建一个新的数组,其中原数组的键变成了新数组的值,原数组的值变成了新数组的键。

查看上一级目录文件名

读取上级目录文件

payload解释: ● array_flip():交换数组中的键和值,成功时返回交换后的数组,如果失败返回 NULL。 ● array_rand():从数组中随机取出一个或多个单元,如果只取出一个(默认为1),array_rand() 返回随机单元的键名。 否则就返回包含随机键名的数组。 完成后,就可以根据随机的键获取数组的随机值。 ● array_flip()和array_rand()配合使用可随机返回当前目录下的文件名 ● dirname(chdir(dirname()))配合切换文件路径

查看和读取根目录文件

所获得的字符串第一位有几率是/,需要多试几次
参考:https://xz.aliyun.com/t/10780
2025浙江省CTF决赛腾龙杯2024
Loading...