第25届数证杯决赛 - 团体服务器取证 完整解题报告
比赛时间: 2026年5月
检材数量: 2 台服务器镜像
题目范围: Q36-Q52(共 17 题)
最终得分: 全部解答完毕 ✅
目录
- 环境信息
- 解题过程详解
- 关键中间过程
- 数据库表结构参考
- 常用命令模板
- 经验总结
一、环境信息
| 项目 |
检材一 (GitLab) |
检材二 (OIM后端) |
| IP 地址 |
192.168.100.234 |
192.168.100.233 |
| 主机名 |
localhost.localdomain |
iZj6chw5inj1ussq3xplaoZ |
| 操作系统 |
CentOS 7 |
CentOS 7 |
| 内核版本 |
3.10.0-1160.119.1.el7.x86_64 |
3.10.0-1127.19.1.el7.x86_64 |
| SSH 端口 |
22 |
22 |
| 初始账号 |
root / 123456 |
root / 123456 |
| 主要服务 |
GitLab (端口 9999) |
OIM 后台管理 (Spring Boot) |
| Docker 容器 |
- |
redis, mysql_master, nginx-web, elasticsearch |
SSH 连接方式:
ssh -i ~/.ssh/id_ed25519 root@192.168.100.234 # 检材一 (GitLab)
ssh -i ~/.ssh/id_ed25519 root@192.168.100.233 # 检材二 (OIM后端)
二、解题过程详解
Q36 - systemd 开机自启服务数量
题目: 通过对服务器中的检材一镜像进行分析,该服务器上systemd管理的开机自启的服务数量是多少?(答案格式:仅数字)
答案:34
解题思路
- 连接检材一服务器
- 使用
systemctl list-unit-files 命令列出所有已启用(enabled)的服务
- 统计输出结果中的服务数量
关键命令
# 列出所有已启用的 systemd 服务
systemctl list-unit-files --type=service --state=enabled
# 输出末尾显示:
# "34 unit files listed."
知识点
--type=service:只列出服务类型(排除 target、mount 等)
--state=enabled:只列出开机自启的服务
- 输出最后一行会显示总数
Q37 - 系统内核编译时间(中国时区)
题目: 通过对服务器中的检材一镜像进行分析,该服务器当前运行的系统内核的编译时间是多少?(答案格式:2024-12-24 15:29:38)
答案:2024-06-04 22:43:51
解题思路
- 使用
uname -v 查看内核编译时间戳
- 原始输出为 UTC 时间,需转换为 中国时区(UTC+8)
关键命令
# 查看内核版本和编译时间
uname -v
# 输出:#1 SMP Tue Jun 4 14:43:51 UTC 2024
# 查看完整内核信息
uname -a
时间转换计算
- 原始时间:
Tue Jun 4 14:43:51 UTC 2024
- 中国时区:UTC + 8h =
22:43:51
- 最终答案:
2024-06-04 22:43:51
知识点
uname -v 显示内核版本号和编译时间(UTC)
- CTF 中涉及时间的题目通常需要时区转换
- UTC + 8h = 北京时间(中国标准时间)
Q38 - GitLab 服务端口
题目: 通过对服务器中的检材一镜像进行分析,该服务器上GitLab服务的端口是多少?(答案格式:仅数字)
答案:9999
解题思路
- GitLab Omnibus 配置文件位于
/etc/gitlab/gitlab.rb
- Nginx 监听端口在配置文件中定义为
nginx['listen_port']
关键命令
# 查看 GitLab 配置文件中关于端口的设置
cat /etc/gitlab/gitlab.rb | grep listen_port
# 输出:nginx['listen_port'] = 9999
# 或使用 grep 精确查找
grep "listen_port" /etc/gitlab/gitlab.rb
知识点
- GitLab Omnibus 使用 Ruby DSL 配置文件
- Nginx 端口配置键为
nginx['listen_port']
- 默认端口为 80,此处被修改为 9999
Q39 - GitLab 登录失败次数
题目: 通过对服务器中的检材一镜像进行分析,该服务器上GitLab服务被登录失败的次数是多少?(答案格式:仅数字)
答案:6
解题思路
- GitLab Rails 应用日志位于
/var/log/gitlab/gitlab-rails/
- 登录操作对应
SessionsController#create
- 登录失败的状态码为
status=0(在 GitLab JSON 日志中表示失败)
- 筛选所有符合条件的日志条目并计数
关键命令
# 方法1:使用 Python 解析 JSON 日志
zcat /var/log/gitlab/gitlab-rails/production_json.log* | python3 -c "
import sys, json
count = 0
for line in sys.stdin:
obj = json.loads(line.strip())
if 'SessionsController' in obj.get('controller', '') and obj.get('status') == 0:
count += 1
print(f\"{obj.get('time')} - {obj.get('controller')}#{obj.get('action')} status={obj.get('status')}\")
print(f'Total: {count}')
"
# 方法2:使用 grep 快速筛选(粗略统计)
zcat /var/log/gitlab/gitlab-rails/production_json.log* | grep -c 'SessionsController.*status.*0'
6次失败时间线(UTC)
| 序号 |
时间 (UTC) |
说明 |
| 1 |
2025-11-06T02:51:38Z |
首次登录尝试 |
| 2 |
2025-11-06T02:52:10Z |
第二次尝试 |
| 3 |
2025-11-06T02:52:26Z |
第三次尝试 |
| 4 |
2025-11-06T02:52:43Z |
第四次尝试 |
| 5 |
2025-11-06T02:52:48Z |
第五次尝试 |
| 6 |
2025-11-06T05:08:40Z |
第六次尝试(root 尝试以 Mia 登录) |
知识点
- GitLab Rails 日志为 JSON 格式(production_json.log)
SessionsController#create = 用户登录动作
status=0 = 登录失败(密码错误或账号不存在)
status=302 = 登录成功(重定向到首页)
- 日志可能已被 gzip 压缩,需用
zcat 读取
Q40 - GitLab root 用户密码哈希与明文
题目: 通过对服务器中的检材一镜像进行分析,该服务器上GitLab服务的root用户的密码是多少?
答案:abc123654
哈希值: $2a$10$joK1mu.0whkjO8IvGSG/X.wVlUofNpX6hplpT85SQjdp.Dg0l7AKO
解题思路
- GitLab 使用 PostgreSQL 作为数据库,但需要以系统用户
git 身份通过 peer 认证连接
- 从
users 表中查询 root 用户的 encrypted_password 字段(bcrypt 哈希)
- 使用 hashcat 进行掩码攻击破解
关键命令
# 1. 以 git 用户身份连接 PostgreSQL(peer 认证)
su git -s /bin/bash -c "/opt/gitlab/embedded/bin/psql -h /var/opt/gitlab/postgresql -U gitlab -d gitlabhq_production"
# 2. 查询 root 用户的密码哈希
su git -s /bin/bash -c "/opt/gitlab/embedded/bin/psql -h /var/opt/gitlab/postgresql -U gitlab -d gitlabhq_production -t -A -c \"SELECT encrypted_password FROM users WHERE username='root';\""
# 3. 将哈希保存到文件
echo '$2a$10$joK1mu.0whkjO8IvGSG/X.wVlUofNpX6hplpT85SQjdp.Dg0l7AKO' > hash.txt
# 4. hashcat 掩码攻击破解(-m 3200 = bcrypt)
hashcat -m 3200 -a 3 hash.txt 'abc?d?d?d?d?d?d'
# -m 3200: bcrypt 哈希模式
# -a 3: mask attack(掩码攻击)
# abc?d?d?d?d?d?d: 以 abc 开头 + 7位数字
# 5. 验证结果
echo 'abc123654' | openssl passwd -1 -salt $(echo '$2a$10$joK1mu.0whkjO8IvGSG/X.wVlUofNpX6hplpT85SQjdp.Dg0l7AKO' | cut -c5-25)
破解过程详解
- 哈希类型: bcrypt($2a$ 标识)
- hashcat 模式: 3200(bcrypt)
- 掩码规则:
abc?d?d?d?d?d?d = abc + 7位数字
- 破解结果:
abc123654
知识点
- GitLab 使用 PostgreSQL peer 认证,必须以系统用户
git 身份连接
- GitLab 内置的 PostgreSQL 在
/var/opt/gitlab/postgresql/ 目录
- bcrypt 哈希格式:
$2a$<cost>$<salt><hash>
- hashcat 掩码字符:
?d = 数字 0-9, ?l = 小写字母, ?u = 大写字母, ?s = 特殊字符
Q41 - 仓库第一次提交时间(中国时区)
题目: 通过对服务器中的检材一镜像进行分析,该服务器上GitLab服务的仓库中第一次提交的时间是多少?(答案格式:2024-12-24 15:29:38)
答案:2025-11-06 11:07:02
解题思路
- GitLab 仓库可能存储在自定义路径(非默认 /var/opt/gitlab)
- 通过
git_data_dirs 配置找到实际仓库路径
- 使用
git log 查看最早的 commit 时间
- 转换为 中国时区
关键命令
# 1. 查找 GitLab 自定义仓库路径
cat /etc/gitlab/gitlab.rb | grep git_data_dirs
# 输出显示仓库在 /opt/gitlab-ce/git-data/
# 2. 找到具体仓库
find /opt/gitlab-ce/git-data/repositories -name '*.git' -type d
# 输出:/opt/gitlab-ce/git-data/repositories/@hashed/4e/07/4e07408562bedb8b60ce05c1decfe3ad16b72230967de01f640b7e4729b49fce.git
# 3. 查看最早的 commit
cd /opt/gitlab-ce/git-data/repositories/@hashed/4e/07/4e07408562bedb8b60ce05c1decfe3ad16b72230967de01f640b7e4729b49fce.git
git log --reverse --format="%ai %s" | head -1
# 4. 查看完整 commit 信息
git log --reverse -1 --pretty=fuller
知识点
- GitLab Omnibus 可通过
git_data_dirs 配置自定义仓库路径
- 默认路径为
/var/opt/gitlab/git-data/repositories/
git log --reverse 按时间正序排列(最早的在前)
%ai 显示作者日期(ISO 8601 格式,本地时区)
Q42 - root 用户电子邮件
题目: 通过对服务器中的检材一镜像进行分析,该服务器上GitLab服务的root用户的电子邮件是什么?(答案格式:a@b.com)
答案:wangdefa888@gmail.com
解题思路
- 以 git 用户身份连接 PostgreSQL
- 从 users 表查询 root 用户的 email 字段
关键命令
# 查询 root 用户邮箱
su git -s /bin/bash -c "/opt/gitlab/embedded/bin/psql -h /var/opt/gitlab/postgresql -U gitlab -d gitlabhq_production -t -A -c \"SELECT email FROM users WHERE username='root';\""
# 输出:wangdefa888@gmail.com
# 查看所有用户信息(用于其他题目分析)
su git -s /bin/bash -c "/opt/gitlab/embedded/bin/psql -h /var/opt/gitlab/postgresql -U gitlab -d gitlabhq_production -c \"SELECT id, username, name, email, last_sign_in_at FROM users ORDER BY id;\""
知识点
-t 参数:只显示数据(无表头)
-A 参数:非对齐输出(纯文本格式)
- GitLab users 表包含完整的用户信息
Q43 - Git仓库被谁下载传播(用户名)
题目: 通过对服务器中的检材一镜像进行分析,该服务器上GitLab服务的仓库是被哪个用户下载传播的?(答案格式:用户名)
答案:Mia
解题思路
这是一个典型的日志关联分析题,需要通过多条线索还原完整的事件时间线:
-
第一步:查看所有用户最后登录时间
- 发现 Mia 是唯一一个在 2025-11-06 新登录的非管理员用户
- 其他普通用户最后登录时间都是 2025-10-06
-
第二步:分析 GitLab Rails 日志
- 搜索
Projects::RepositoriesController#archive(下载 ZIP 操作)
- 找到 05:09:47 UTC 的下载记录
-
**第三步:还