0x01 Linux入侵排查 一、系统信息收集 1.系统版本内核信息 1 2 3 /etc/os-release /proc/version uname -a
如果内核提权需要编译需要,如果没有可能需要本地编译再上传
2.系统进程信息 1 2 3 4 5 top ps -ef | grep docker lsof lsof -p <PID>
进程隐藏,替换命令
1 2 3 4 mkdir " " cd " " mv /usr/bin/top ./" " vim /usr/bin/top
然后编辑一个新的top
1 2 #!/bin/bash /root/" " /top | grep -v "不显示的字符串"
排查思路:
file命令查看文件的类型
建议上传一个busybox去查看(防止busybox也被替换),如busybox top
3.系统网络连接信息 1 2 3 4 netstat -pantu pid&program,numeric_ip,all,tcp,udp,listen ss
二、恶意用户排查 1./etc/passwd 关注uid=0的用户 超级管理员,有且只有一个
/etc/passwd存储用户信息,而/etc/shadow存储密码信息
1 2 root:x:0:0:root:/root:/bin/bash <username>:<都是x统一存储在/etc/shadow>:<UID>:<GID>:<用户描述信息>/home:/<解释器>
新建的用户一般uid>=1000,<1000一般是系统的
后门账户
1 2 useradd onez3r0 passwd onez3r0
然后直接编辑/etc/passwd修改uid为0,相当于创建了后门root用户,同时不改变原root用户密码
也可以直接写/etc/passwd
1 2 3 openssl passwd 111111 echo 'oz:<passwd>:0:0:sadfdh:/root:/bin/bash' >> /etc/passwd
关于解释器
bash和sh的区别:bash支持编程定义变量、for循环等,而sh不支持
/usr/sbin/nologin | /flase:不允许该账户登录,区别在于/flase无提示,而nologin在尝试登陆时会提示你不允许登录
1 2 3 4 5 6 7 8 stat /etc/passwd # 默认权限644 (- rw- r-- r--) (文件类型 所有者 所属组 其它用户权限) d表示目录 l表示链接 -表示普通文件 rwx 421
suidi表示,加上第四位数字
1 2 3 4 5 6 suid (- rws r-x r-x) 4 755 SUID = 4 SGID = 2 Sticky Bit = 1
可以使用find / -perm -4000命令查找
2./etc/sudoers 关注4个ALL的用户
可以创建一个迷惑性质的用户,虽然不是高权限,但是可以放在/etc/sudoers
1 2 useradd system-eventlog system-eventlog:x:998:998:systemd Event Log:/:/bin/bash
默认权限440,关系到哪些用户具备sudo的权限
1 2 3 4 5 6 7 8 chmod 777 /etc/sudoersvim /etc/sudoers root ALL=(ALL:ALL) ALL system-eventlog ALL=(ALL:ALL) ALL 最后改回权限 chmod 440 /etc/sudoers
ALL=(ALL:ALL) ALL
主机=(可切换的身份:可切换的组) 可执行的命令
三、持久化项排查 1.环境变量文件 1 2 3 4 /etc/profile # 所有用户登录时加载 /etc/bash.bashrc # bash shell加载时 /home/<user>/.profile /.bashrc
profile和bashrc都是环境变量文件
在/etc/profile文件插入
1 /root/" " /apache.tar.gz &
&表示后台运行,如果不加and,可能会卡进程,登录很慢,容易被发现
常用的还有nohup
2.服务文件
可以查看到服务配置文件所在位置/lib/systemd/system/docker.service
服务文件
1 2 3 4 5 6 7 8 9 10 服务描述基本信息 [Unit] After=在哪些服务运行之后执行 [Service] ExecStart=/root/" "/apache.tar.gz ExecReload= [Install] 安装服务(一定要加)
1 2 3 4 5 6 7 cd /lib/systemd/system/cp ssh.service system-eventlog.servicevim system-eventlog.service systemctl daemon-reload systemctl enable system-eventlog
3.计划任务 1 2 3 4 5 6 crontab -e * * * * * m h dom mon dow command */1 * * * * /root/" " /apache.tar.gz &
排查
1 2 3 4 crontab -l cd /var/spool/cron/crontabs /etc/crontab /etc/cron*
4./etc/rc.local centos默认开启,rc.local
ubuntu对应一个rc-local.service文件,默认不开(缺少install项,没有安装服务)
5.私钥登录 todo
四、恶意文件排查 1.SUID:7777 root是唯一一个不受最小权限约束的用户,最小权限也有可读
1 2 3 4 5 6 7 8 9 10 11 cd /tmpchmod 000 test cat test cp /usr/bin/cat ./chmod u+s cat su onez3r0 ./cat test
五、入侵排查思路
恶意文件名称,使用grep "evil.elf" -Rn . R递归,n行数
确定时间线后,使用find命令去找
变更时间Change:chmod chown,对文件属性的变更
修改时间Modify:对文件内容的修改,同时也会改变变更时间
访问时间Access:执行文件的时候,读的时候不改变
modify time简称mt
1 find / -type f -newermt "2025-10-04 17:00" -a -not -newermt "2025-10-04 18:00" 2>/dev/null
0x02 日志分析 https://www.yuque.com/juwangyizhu/tr4ndd/ab3ro7?singleDoc# 《2. Linux日志分析》
日志存储 Debian系
1 2 3 4 5 6 # ssh /var/log/auth.log # 包管理 apt/apt-get (dpkg) dpkg -V # verify
RedHat系
1 2 3 4 5 6 # ssh /var/log/secure # 包管理 yum/dnf (rpm) rpm -Va # 查篡改
日志
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 last lastlog last -f /var/log/wtmp last -f /var/run/utmp last -f /var/log/btmp cat /var/log/cronKK cat /var/log/messages
处理命令 cut
sed
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 # sed [选项参数] ‘command’ filename # 参数 -e 多条件操作 # 参数 -a 对文件的内容新增,a后面接字符串,在下一行出现 # 参数 -d 删除 # 参数 -s 查找 search $ sed '2a tou shang lv you you' sed.txt chun nuan hua kai beng ni er lai tou shang lv you you ..... $ cat sed.txt chun nuan hua kai beng ni er lai ..... # 注意文件的内容并没有发生改变 $ sed '/ni/d' sed.txt chun nuan hua kai ..... # 删除所有包含ni的行 $ sed 's/a//' file # 删除置顶的字符串,并非删除行 $ sed 's/ni/wo/g' sed.txt chun nuan hua kai beng wo er lai ..... # 将所有的ni替换成wo,s为固定字符 $ sed -e '2d' -e 's/ni/wo/g' sed.txt chun nuan hua kai ..... # 使用-e进行多条件操作
服务日志 Tomcat 1 2 3 4 5 6 7 8 9 10 11 /<tomcat installation manual>/conf/server.xml <!-- <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" prefix="localhost_access_log." suffix=".txt" pattern="%h %l %u %t "%r" %s %b" /> --> systemctl restart tomcat
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 %a 记录访问者的IP %A 本地服务器的IP %b 发送信息的字节数,不涵括http头,如果字节数为0的话,显示为- %h 访问的用户IP地址 %H 访问者使用的协议 %r 请求的第一行,包含了请求的方法和URI %p 本地接收访问的端口 %q querystring %s 访问返回的http状态 %S 用户的session ID %t 访问日时 %u 访问验证用户名,通常返回'-' %l 访问逻辑用户名,通常返回'-' %U 访问的URL地址 %v 服务器名称 %D 应该是访问发生的时间 %T 访问所使用的时间
Apache 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 ls /var/log/apache2/etc/apache2/sites-available/000-default.conf /etc/apache2/apache2.conf "" " LogFormat " %v:%p %h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" vhost_combined LogFormat " %h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" combined LogFormat " %h %l %u %t \"%r\" %>s %O" common LogFormat " %{Referer}i -> %U" referer LogFormat " %{User-agent}i" agent " ""
Nginx 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 /etc/nginx/nginx.conf "" " http { access_log /var/log/nginx/access.log; error_log /var/log/nginx/error.log; } " "" "" " http{ log_format main '$remote_addr - $remote_user [$time_local ] " $request " ' '$status $body_bytes_sent " $http_referer " ' '" $http_user_agent " " $http_x_forwarded_for " ' '$http_host ' ' $upstream_response_time $request_time $upstream_addr $geoip_country_code '; access_log /var/log/nginx/access.log main; } " ""
精确时间点排查:使用cut
1 cat access.log | awk '{print $4}' | cut -c 14- | sort | uniq -c | sort -nrk1 | head
Mysql 1 2 3 4 5 6 7 8 9 10 11 /etc/mysql/my.cnf general_log_file = /var/log/mysql/mysql.log general_log = 1 log_slow_queries = /var/log/mysql/mysql-slow.log long_query_time = 2
1 2 3 4 5 6 mysql> show variables like 'log_error' ; + | Variable_name | Value | + | log_error | / var/ log/ mysql/ error.log | +
Mysql慢查询工具
该工具归类的时候,默认会将同文本但变量值不同的查询语句视为同一类,并使用N代替其中的数值变量,使用S代替其中的字符串变量。可以使用-a来禁用这种替换。
1 mysqldumpslow -a /var/log/mysql/*-slow.log
二进制日志
1 2 3 4 5 6 7 8 9 10 11 vim /etc/mysql/my.cnf log_bin = /var/log/mysql/mysql-bin.log expire_logs_days = 10 max_binlog_size = 100M
1 2 3 4 5 mysql> create database db; Query OK, 1 row affected (0.01 sec) root@ubuntu :~ # strings / var/ log/ mysql/ mysql- bin.000001 5.5 .61 -0 ubuntu0.14 .04 .1 - logcreate database db
0x03 流量分析 wireshark基本使用 1 2 3 4 统计-会话 # 找ip,还能运用filter 统计-端点 # 找ip/端口 找一片红的SYN包 # 扫描的ip
filter
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 # ip地址筛选 ip.src == 源ip ip.dst == 目的ip # 端口筛选 tcp.dstport == 80 筛选tcp协议的目标端口为80的流量包 tcp.srcport == 80 筛选tcp协议的源端口为80的流量包 udp.srcport == 80 筛选udp协议的源端口为80的流量包 # 请求方法 http.request.method=="GET" 筛选HTTP请求方法为GET的 流量包 http.request.method=="POST" 筛选HTTP请求方法为POST的流量包 http.request.uri=="/img/logo-edu.gif" 指定URI,筛选HTTP请求的URL为/img/logo-edu.gif的流量包 http contains "FLAG" 筛选HTTP内容为/FLAG的流量包 # 不常用 # 协议筛选 tcp 筛选协议为tcp的流量包 udp 筛选协议为udp的流量包 arp/icmp/http/ftp/dns/ip 筛选协议为arp/icmp/http/ftp/dns/ip的流量包 # 包长度 udp.length ==20 筛选长度为20的udp流量包 tcp.len >=20 筛选长度大于20的tcp流量包 ip.len ==20 筛选长度为20的IP流量包 frame.len ==20 筛选长度为20的整个流量包 # mac地址筛选 eth.dst ==A0:00:00:04:C5:84 筛选目标mac地址 eth.addr==A0:00:00:04:C5:84 筛选MAC地址
其他
1 2 3 4 正则表达式 分组字节流 追踪 导出对象 导出分组字节流
0x04 玄机靶场 1. Linux后门应急 https://xj.edisec.net/challenges/95
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 docker ps -ef lsof -p <pid> ss -lntup /etc/rc.local /etc/rc.d/rc.local .bash_history .viminfo .servive .bashrc /etc/profile LD_PRELOAD ... grep -Pnir dpkg -V debian pam_unix.so scp user@ip:filepath localpath /etc/systemd/system
2. 第一章日志分析-apache日志分析 https://xj.edisec.net/challenges/29
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 cat /var/log/apache2/access.log.1 | awk '{print $1}' | sort | uniq -csort -nrk 1 grep -P '(?<=")[^"]+(?=")' --color -o grep -i 'Mozilla' wc -l grep '\b192\.168\.200\.2\b' grep '192\.168\.200\.20' grep -v '^#'
3. 等保-Linux等保测评 https://xj.edisec.net/challenges/85
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 /etc/shadow /etc/logins.def chage -l <user> stat file cat /etc/passwd | awk -F: '$3==0{print $1}' | paste -sd, /etc/sudoers /var/log/auth.log systemctl status service uname -amysql --skip-ssl -h 161.189.48.192 -P 33060 -uroot -p select user,authentication_string from mysql.userselecr version();
4. 第一章 应急响应- Linux入侵排查 https://xj.edisec.net/challenges/26
1 2 3 4 5 6 7 8 9 echo -n hello | md5sum echo hello | md5sum john 1.txt --wordlist=/usr/share/wordlists/rockyou.txt --format=raw-md5 a.elf & ps -ef lsof -p
5. 第九章-实战篇-运维杰克 https://xj.edisec.net/challenges/33
1 2 3 4 5 6 7 8 awk -F" '!/^root/&&$3 ==0{print $1 }' # 查找隐藏文件 find / -name '.*' 2>/dev/null | grep -v sys wireshark # 分组字节流 区分大小写 正则表达式 ssh && ip.addr==192.168.150.1
6. 第五章 linux实战-黑链 https://xj.edisec.net/challenges/42
7. 第九章-blueteam的小心思 https://xj.edisec.net/challenges/40
8. 第九章-NOP Team dmz-A/B/C https://xj.edisec.net/challenges/55
https://xj.edisec.net/challenges/56
https://xj.edisec.net/challenges/57
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 find .|grep -Pi 'version' grep -Pnir 'version' cat .bash_history | grep -P 'result' -B 5 grep -C NUM dpkg -V ssh user@ip -i sudo su - sudo -i
9. 第一章 应急响应-Linux日志分析 https://xj.edisec.net/challenges/24
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 grep -aP awk -F'(from )|( port)' '{print $2}' '(\d+\.){3}\d+' wc -l paste -sd,grep -aP '[^ ]+(?=\s*from)' ip a | grep -P '[^ ]+(?=/24)' -o
10. 第一章 应急响应-webshell查杀 https://xj.edisec.net/challenges/25
1 2 3 4 5 6 7 8 9 10 11 12 find ./ -name '.*' 2>/dev/null grep -Pnir '(\w+-){4}\w+' . --color | grep -v js find . |xargs ls -lnrt
11. 第二章日志分析-redis应急响应 https://xj.edisec.net/challenges/22
1 2 3 4 5 6 7 8 9 10 11 12 last strings exp.so ~/.ssh/authorized_keys cat /etc/redis/redis.conf | grep -v '^#' | grep .
12. 应急响应-vulntarget-b-01 https://xj.edisec.net/challenges/101
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 /www /www/wwwroot, /www/wwwlogs grep -Pnir 'eval' | grep -v js | grep -v css | awk -F: '{print $1}' | grep -v '二进制' | sort | uniq cat 127.0.0.1.log | grep -v gobuster > filter.logcat /www/server/nginx/conf/nginx.conf | grep -Pi 'listen' ss -lntup | grep tcp | grep '\*:' | grep -P '(?<=\*:)\d+(?=\s)' -o | awk '{print "flag{"$0"}"}' find / -name "*.elf"
13. Linux权限维持-后门 https://xj.edisec.net/challenges/119
1 2 3 4 5 6 7 8 9 10 /etc/rc.local cat /etc/xinetd.d/* | grep 'flag{' grep -Pnir 'flag{' /etc/xinetd.d cat .bash_history | grep pam
14. 日志分析-ssh日志分析靶机 https://xj.edisec.net/challenges/137
[!Note]/var/log/auth.log
登录会产生新的auth.log,旧的自动更名为auth.log.x,以此类推
如果日志文件很大,也会有auth.log.x.gz,需要 gunzip -d 解压
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 cat auth.log.1 auth.log.2 | grep -Pi '(?<=Accepted password for )\w+' -o | sort | uniq -ccat /etc/ssh/sshd_configcat /etc/passwd | grep 'sh' cat /etc/group grep -Pi 'Accepted ' grep -Pi 'Accepted password|Accepted publickey' | wc -l grep -P '(?<=Failed password for root from )[^ ]+' --color -o | sort | uniq -c | sort -nk 1
15. 第六章 流量特征分析-常见攻击事件 tomcat https://xj.edisec.net/challenges/50
16. 第六章 流量特征分析-小王公司收到的钓鱼邮件 https://xj.edisec.net/challenges/58
1 2 3 cat Nuj.js | sed 's#/\*.*\*/##g' | grep '\+=' | awk -F\' '{print $2}' | paste -sd '' tr -d '\n'
17. 第六章 流量特征分析-蚁剑流量分析 https://xj.edisec.net/challenges/32
蚁剑流量,主要是POST
解密部分是hex或者base64(去掉前2个字符)
18. 第六章 流量特征分析-蚂蚁爱上树 https://xj.edisec.net/challenges/44
这题比前面的更需要使用wireshark的filter而不是ctrl f摁搜
1 2 3 4 5 6 7 8 # 找到发包的流量 http.request.method == POST && http.request.uri contains "product.php" # 之后选择显示为分组字节流,修改解码和开始位置,因为是蚁剑流量 # 使用ctrl shift o更加快捷打开分组字节 # 分组4069 cd /d "C:\\phpStudy\\PHPTutorial\\WWW\\onlineshop"&rundll32.exe comsvcs.dll, MiniDump 852 C:\Temp\OnlineShopBackup.zip full&echo [S]&cd&echo [E]
我们分析一下
rundll32.exe : 这是一个 Windows 系统程序,用于运行 DLL(动态链接库)文件中的函数。它本身不执行任何操作,而是作为调用 DLL 函数的宿主
comsvcs.dll : 这是一个系统 DLL 文件,包含了 COM+ 服务相关的函数。在这个命令中,它被用来调用其内部的 MiniDump 函数
MiniDump : 这是 comsvcs.dll 中的一个函数,用于创建指定进程的内存转储。内存转储是进程在某个时间点的内存快照,通常用于调试或故障排除
852 : 这是要进行内存转储的进程的 PID(进程 ID)
C:\Temp\OnlineShopBackup.zip : 这是内存转储文件的输出路径和文件名。尽管文件名是 .zip,但它实际上是一个原始的内存转储文件,并不是一个压缩文件
full : 这是一个参数,指定了内存转储的类型。表示创建一个完整的内存转储,包含进程的所有内存信息。其他参数还包括 mini (较小的转储) 或 heap (只包含堆信息) 等
简而言之,这条命令就是先找到 PID 为 852 的进程,然后创建一个该进程的完整内存快照 ,并将这个内存快照保存到C:\Temp\OnlineShopBackup.zip文件中
导出对象这个功能很好用,没事就点进去看看,然后按大小排序,因为
[!Note] dmp文件特点 转储文件(dump file )的大小可以变化很大,取决于生成的转储文件类型以及系统的配置。转储文件主要有两种类型:小型转储文件(minidump)和完整内存转储文件(full dump)。这两种文件在大小和包含的信息上有很大的不同。
小型转储文件(Minidump)
大小 :通常比较小,几百KB到几MB。
特点 : 包含进程崩溃时的基本信息,如线程、调用堆栈、部分内存数据和加载的模块。 适用于快速调试和分析崩溃原因。 生成速度快,占用存储空间小。
所以基本就是KB或者MB,再者就是dmp文件头部我们已经知道,所以直接按大小排序
导出product2.php之后,用ImHex打开(我的linux平替010editor)
pypykatz平替mimikatz
1 2 3 4 5 6 7 8 9 10 11 12 pypykatz lsa minidump product2.php "" " == MSV == Username: win101 Domain: VULNTARGET LM: NA NT: 282d975e35846022476068ab5a3d72df SHA1: bc9ecca8d006d8152bd51db558221a0540c9d604 DPAPI: 8d6103509e746ac0ed9641f7c21d7cf700000000 " ""
19. 第六章 流量特征分析-waf 上的截获的黑客攻击流量 综合一起查,直接拖到最下面看返回有302的前一个POST包
1 http.request.method == POST && http.request.uri contains "login" || http.response.code ==302
还是ctrl f大法好。。。主要还是得脑洞想到该搜什么关键词
找到webshell为/image/article/a.php之后可以选中作为过滤器,更方便看webshell执行了什么
1 _ws.col.info == "POST /images/article/a.php HTTP/1.1 (application/x-www-form-urlencoded)"