2026.8.7(1)【日志取证】2025铸剑杯-CDF

📌 题目信息

项目内容
题目名称2025铸剑杯-CDF
题目来源玄机靶场
题目类型日志取证 / Forensics
子分类Web 日志分析
考点Content-Length 突变定位、IP 溯源、Webshell 时序分析
难度⭐⭐
最终 Flagflag{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 —— 这是关键的异常突变值

  • 为什么不是其他的?其他数字(163683273640920491048184),仔细观察会发现它们都是 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
  • IP183.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:20table.jsp
21:02:32en.jsp
21:04:392.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 文件名之间用 - 分隔。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值