跳转至

Solar 应急响应赛 10 月 Writeup

工厂应急

这个流量包混杂了无用流量与其他地方的数据,因此需要先简单分析各个 IP 可能对应设备的用途:

  • 10.0.0.2 DNS 服务器
  • 10.0.0.5 某个工程机,可以外连网络
  • 10.0.0.8 工程站,接受大量请求流量
  • 10.0.0.9 网页服务器?
  • 192.168.10.21 一个终端,向 40 发送 ModBUS 请求指令
  • 192.168.10.40 可能是控制中心

工控流量分析

题目要求找出关泵相关信息(从稍后放出的描述更新中得知 flag{0xtransaction_id_0xfunction_code_0xcoil_address}),具有明显的 Modbus 特征,因此过滤出这类协议的流量。过滤后的结果中多为读取操作,只有一条写操作出现:

写操作流量

考虑其执行了关泵操作,故提取信息:

  • Transaction ID 为 6699 -> 0x1a2b
  • Function Code(两位)为 5 -> 0x05
  • Coil Address 通常位于 Function Code 后,为 0x000d

经过多次尝试,得出 Q1 Flag 为 flag{0x1a2b_0x05_0x000d}

对于 Q2,先尝试在字节流中搜索 NodeId,得到大量的 ReadRequest TCP 记录;考虑到寻找写入 NodeId 的流量,转而搜索 WriteRequest,得到唯一一条符合要求的记录:

WriteRequest 记录

NodeId 是一个字段,Q2 的 Flag 为 flag{ns=2;s=Pump/SpeedSetpoint;}

对于 Q3,搜索域名 engws.plant.local 的 DNS 流量。最终解析到的应是一个局域网地址,与其他工控设备在同一网段(即 10.0.0.x);结合对 DNS 记录 IP 的搜索,确定其解析结果为 flag{10.0.0.8}

最终的 DNS 记录

攻击分析

Q4 要确定 HMI 到工程站上首个成功发起的时间点,于是根据条件进行过滤(最初使用的是 ((ip.src == 10.0.0.5) || (ip.src == 10.0.0.8)) && ((ip.dst == 10.0.0.5) || (ip.dst == 10.0.0.8)),实际分析后可进一步缩减)。

前面的都是 Echo 与损坏的 NBNS 流量,不算是连接发起成功;首次发起成功应在 3852~3859 号记录处,双方成功进行了 TCP 握手。

首次成功握手

按提交格式,得出 Flag 为 flag{2025-03-12T14:22:09Z}

Q5 需要提交 HMI 向工程站发送 HTTP 请求的 Host 与 URI,在上述过滤的结果中进一步筛出 HTTP 协议,发现一条带 JSON 的 POST 请求:

可疑的 JSON 流量条目

POST /rpc HTTP/1.1

Host: engws.plant.local
User-Agent: Mozilla/5.0
Content-Type: application/json
Content-Length: 15
Connection: close

{"op":"invoke"}

传递的 op 参数很有问题,疑似用于攻击,故 Flag 为 flag{engws.plant.local_/rpc}

ruoyi

ruoyi API 遭到劫持,在一定条件下会触发跳转到外部链接。可能的原因:

  • 配置文件的配置有问题
  • 依赖投毒,依赖包经过了改写
  • ruoyi 中可扩展的部分被利用

从附件给出的两个 YAML 配置文件来看没有明显问题,因此需要反编译 JAR 包,分析疑似劫持的方法。经过一段时间的寻找,外部依赖并未被篡改,而是添加了一个拦截器,其在 ResourcesConfig 类中被添加:

ResourcesConfig 中的拦截器

继续分析,拦截器类的具体位置在 com.ruoyi.framework.interceptor.impl

RepeatSubmitInterceptor 构成

preRedirect 方法定义了重定向需满足的条件,即对 User Agent 与所处分钟数进行了限制,是异常劫持的来源。

要求提交异常劫持的方法名,Flag 为 flag{preRedirect}

评论