📌 题目信息
| 项目 | 内容 |
|---|---|
| 题目名称 | 2025铸剑杯-CDF |
| 题目来源 | 玄机靶场 |
| 题目类型 | 日志取证 / Forensics |
| 子分类 | Web 日志分析 |
| 考点 | Content-Length 突变定位、IP 溯源、Webshell 时序分析 |
| 难度 | ⭐⭐ |
| 最终 Flag | flag{2018-2-23/183.62.9.42/table.jsp-en.jsp-2.jsp} |

🛠️ 使用工具
- Linux
grep(文本检索) - Python3
📝 解题思路
一道典型的 Web 日志取证分析题,核心思路是通过对比同一文件返回字节数(Content-Length)的突变来锁定木马上传事件,再用异常 IP 反查其访问的 Webshell。
核心:不依赖复杂工具,先搜题面线索
banner_home.jpg,通过观察该文件返回字节数是否突变判断是否有木马替换;突变点的那条记录的时间和 IP 就是上传事件的关键证据;最后围绕该 IP 筛出当晚访问的可疑脚本并按时间排序。
第 1 步:搜索关键文件,找到大小突变点
拿到题目后有很多日志文件,其中access.log 是"总账本",而exYMMDD.log 是"按天切出来的分账本" —— 内容其实来源相同,只是粒度不同。
两者关系:
access.log(总)≈ ex130101.log + ex130102.log + ... + ex180223.log + ...
即:access.log 理论上就是把所有 ex*.log 按天切分前的那份原始汇总,或者反过来,ex*.log 是从 access.log 里按日期拆出来的。
根据题目提示,需要搜索banner_home.jpg的相关信息,很明显日志中有用的信息就是banner_home.jpg的大小,因此需要统计不同banner_home.jpg的大小及其出现的时间。

上面的搜索可以用python代码实现:
# -*- coding: utf-8 -*-
import re, glob, datetime
from collections import Counter
pat = re.compile(
r'^(\S+) - - \[([^\]]+)\] "([A-Z]+) ([^ "]+)[^"]*" (\d{3}) (\S+)')
size_days = Counter()
size_count = Counter()
for f in glob.glob('./logs/*.log'):
with open(f, errors='ignore') as fh:
for line in fh:
if 'banner_home' not in line:
continue
m = pat.match(line)
if not m:
continue
_, tm, _, _, status, size = m.groups()
if status != '200':
continue
day, mon, rest = tm.split('/')
yr = rest.split(':')[0]
date = f'{day}/{mon}/{yr}'
size_count[size] += 1
size_days[(size, date)] += 1
items = list(size_count.items())
if not items:
print("没有找到任何记录。")
else:
max_size_len = max(len(str(size)) for size, _ in items)
max_count_len = max(len(str(count)) for _, count in items)
header1 = "字节大小"
header2 = "出现次数"
max_size_len = max(max_size_len, len(header1))
max_count_len = max(max_count_len, len(header2))
h_line = '+' + '-' * (max_size_len + 2) + '+' + '-' * (max_count_len + 2) + '+'
print(h_line)
print(f"| {header1:^{max_size_len}} | {header2:^{max_count_len}} |")
print(h_line)
for size, count in items:
print(f"| {str(size):>{max_size_len}} | {str(count):>{max_count_len}} |")
print(h_line)

52917: 1043 ← 最初正常图片大小(老文件)
50428: 8415 ← 第二版图片大小(中期)
37756: 155 ← 异常值!只有155次,且集中在2018-02-23
其他: 16368/32736/40920/49104/8184 都是 50428 的整数倍/分数(分块传输),'-' 是 304
锁定“木马异常值37756”(突变点),解释如下:
-
'37756': 155—— 这是关键的异常突变值! -
为什么不是其他的?其他数字(
16368、32736、40920、49104、8184),仔细观察会发现它们都是 50428 的约数或倍数(比如 50428 ÷ 3 ≈ 16809,接近 16368;50428 × 0.65 ≈ 32778)。这些通常是浏览器断点续传(Range请求)、Gzip压缩或网络分片导致的大小变体,属于正常访问的“噪音”,可以直接忽略。 -
'-': 129—— 这代表Content-Length响应头缺失(可能是分块传输或连接中断),也是正常网络波动,不影响判断。 -
而
37756与 50428 没有明显的倍数/压缩关系,且出现了 155 次,说明它在某个时间段内持续稳定地返回了这个大小——这就是木马文件被上传替换后的真实大小(关键!!)。
在日志目录中搜索大小为37756的数据包第一次出现的地方,发现在 ex180223.log中(2018年2月23日)。
grep -rh "banner_home.jpg" ./ex*.log 2>/dev/null \
| grep -m1 -E '" 200 37756'

查看该日志,发现 21:02 还是旧大小、21:18 已经是新大小,说明木马上传发生在 21:02~21:18 之间,上传者就是 183.62.9.42。


因此得到如下信息:
- 日期:
2018-02-23 - IP:
183.62.9.42
第 2 步:围绕异常 IP 筛出 Webshell 并按时间排序
183.62.9.42 只在 ex180223.log(当晚)出现,无跨日记录。提取它当晚访问的所有动态脚本,按首次访问时间排序:
grep "^183.62.9.42 " ex180223.log \
| grep -E '\.jsp|\.php|\.asp' \
| sed -E 's/^[^ ]+ - - \[([^]]+)\].*"([A-Z]+) ([^ ?]+).*/\1 \2 \3/' \
| sort

得到以下3个文件:
| 时间 | 文件名 |
|---|---|
| 21:02:20 | table.jsp |
| 21:02:32 | en.jsp |
| 21:04:39 | 2.jsp |
其实到这里就可以提交flag了,下面分析一下这些文件是干什么的。
先过滤出table.jsp的日志:
grep "^183.62.9.42 " ex180223.log | grep "table.jsp"

说明:
状态码是 404(Not Found,文件不存在)→ 所以"试探性访问(文件不存在)"。黑客在扫目录/猜文件名,试着访问这个 jsp,但服务器说没有这个文件。只来了这一条、且是 GET(试探),没有再往它 POST 数据,说明它没法利用,试探一下就放弃了。
然后过滤出en.jsp的日志:
先看首次访问(确认它是网站的日期控件文件):
grep "^183.62.9.42 " ex180223.log | grep -m1 "lang/en.jsp"
再看被利用的行为(发登录请求进去):
grep "^183.62.9.42 " ex180223.log | grep "lang/en.jsp?act=login"

说明:
- 路径里有
My97DatePicker/lang/→ 一看就知道是 My97 日期控件的语言包(这点靠常识:My97 是常见开源日历控件,log 里常被网站引用)。 - 黑客对这个"语言文件"发
POST+?act=login(登录动作) → 正常加载日历根本不会 POST 登录,所以判定"被当登录入口利用"。
最后过滤出2.jsp的日志:
grep "^183.62.9.42 " ex180223.log | grep "2.jsp"

说明(判断"2.jsp"是攻击者的后门):
① 全日志只有这一个 IP 碰过它(2.jsp文件)
② 请求方式异常:大量 POST,而非正常 GET
数一下输出:
- GET(读取)只有 3 次:21:04:39、21:14:28、21:20:55
- POST(写入/执行)有 22 次,密集发生在 21:16:06 ~ 21:20:35
正常浏览器访问网页只会 GET(拉取内容)。POST 是"提交命令/上传文件"用的,22 次 POST 说明攻击者一直在给这个 jsp 发指令、传数据 → 在用它执行控制。
③ 时间线:木马替换紧跟 POST 之后
关键交叉比对:2.jsp 疯狂 POST 的时段是 21:16~21:20,而 banner_home.jpg 变成木马(37756)正好在 21:18。可见木马是用 2.jsp 当上传通道塞进去的。
④ 行为特征本身就"攻击性"
- 对着一个 jsp 连续快速 POST 十几次 = 自动化攻击/批量执行命令的手工痕迹
- POST 返回体从 3~2177 字节不等 = 在测试不同命令的回显
- 整个过程集中在晚上 21:04~21:22(非正常工作时间)= 可疑时段
🏁 最终 Flag
按时间先后拼接:table.jsp-en.jsp-2.jsp
⚠️ 注意:题目只填文件名、不填路径,所以
/sxzn/js/My97DatePicker/lang/en.jsp只取en.jsp;分隔符用-,不是中文顿号。
flag{2018-2-23/183.62.9.42/table.jsp-en.jsp-2.jsp}
⚠️ 注意拼接细节:日期直接是
2018-02-23(零填充的两位月/日);IP 之间、与文件名之间都用/分隔;Webshell 文件名之间用-分隔。
【日志取证】2025铸剑杯-CDF&spm=1001.2101.3001.5002&articleId=163560644&d=1&t=3&u=4d5270b722dc4552a7a315c3740ddedd)

被折叠的 条评论
为什么被折叠?



