linux suid提权
做了nebula
的练习之后,发现其基本都是利用suid
程序漏洞进行提权,这里特此做个总结
linux特殊权限
在linux权限当中,除了rwx
三种基本权限之外,还有三种特殊权限,SUID
、SGID
、SBIT
三种,例如以下:
|
|
SUID
即SET UID
权限,其只出现于二进制文件拥有者执行权限x上,标注为s,其作用是如果执行者有其对应执行权限x,那么在程序运行过程中,程序将获得程序拥有者的权限
举个例子:
|
|
注意的是,s权限只有二进制程序有效,shell脚本或目录是无效的,因为这个权限的存在,如果程序有漏洞可以被利用,我们就可以通过此方式获取更高的权限,例如如果owner 为root的二进制程序有set uid权限,且存在任意命令执行,那么我们就可以通过这个程序进行root提权,具体的在后面讨论
SGID & SBIT
# SGID
同SUID
,是在owner的x权限上有s标志,那么如果在群组x权限上的s标志,即为SET GID
权限,即SGID
,可以合理推测,是二进制程序在执行期间获取群组的权限支持。
|
|
例如,上面的例子,locate
程序具有SGID
权限,其他用户(nyrae)有执行权限,当执行时,可以去读取mlocate.db的内容
当SGID
用在目录上时,也是一种常见的操作,如果使用者对于此目录有进入权限(r、x),使用者在此目录下的有效群组将变为目录的群组,即,若此用户可以在此目录下创建文件,则所创建的文件群组为目录群组用户。
# SBIT
Sticky Bit
只针对目录有效,其作用是在其目录中,使用者只能对自己创建的文件或目录进行删除/更名/移动等动作,而无法删除他人的文件,最为常见的就是tmp
目录
|
|
很容易理解,在/tmp
中,每个用户只能操作自身创建的文件或目录
利用SUID提权
因为SUID
的独特性,我们之前也说了,如果SUID
的程序owner为root且程序存在漏洞,我们就可以通过这个方式进行提权利用。
首先,查找可以owner为root且suid的二进制文件。
|
|
这是在我的阿里云主机上得到的结果,一些其他的系统或版本提供的suid程序不尽相同,可能要具体去看,对于网上的一些可用来提权的linux可执行文件,除了和版本有关,其主要依赖于管理员配置错误,将一些常见的程序加上了suid权限:
|
|
同时利用一些其他的suid程序,通过分析其漏洞,利用提权。具体的利用,根据环境不同而异。
渗透测试练习 —— nebula
官方地址 在这里,也可以使用ichunqiu的靶机 总共分了20关,以levelXX
的形式进行。
注: ichunqiu 上的问题描述有些问题 可以去官网看
这里所有的程序,基本都是利用suid程序漏洞进行提权,也算是作为linux suid提权的一个练习。
level00
寻找将以
flag00
运行的suid程序
推测为find
查找特权文件:
|
|
所以我们可以通过:
|
|
或
|
|
得到/bin/.../flag00
文件,运行,然后提示运行getflag
程序,运行之后,提示已经在target 账户已生成flag,在~
里面找了好久没找到,最后才发现~
的绝对路径是/home/level0
level01
以level01登录账户,在/home/flag01里面找
在相应路径中发现一个二进制文件,我们使用ll /bin/getflag
发现,使用权限必须是root,而flag01
的权限时suid
,即执行时可获得其程序拥有者的权限,其中flag01
源码如下:
|
|
我们发现其使用了/usr/bin/env
使用env
来运行好处的原因是它会根据你的环境寻找并运行默认的版本,提供灵活性,所以这里的思路是,想办法去修改$PATH
使用找到的echo
是我们的getflag
文件,这样在运行时,其有root权限,则可以getflag成功。于是,我们首先创建一个echo链接到getflag:
|
|
然后去修改$PATH
内容:
|
|
于是我们修改path内容export PATH=/tmp:$PATH
然后运行./flag01
发现生成了flag
内容,发现其权限为:
|
|
只有flag01
用户才可以读取,所以我们利用之前的思路,在tmp下生成一个test.c,然后运行gcc -o echo test.c
,内容为下:
|
|
其返回一个shell
,使用whoami
可以看到当前用户为flag01
,则可以查看flag内容。
level02
同样,以下代码存在任意代码执行,找到并获取flag
|
|
直接运行看下程序逻辑:
|
|
可以看到其根据$USER内容进行输出,然后将/bin/echo $USER is cool
内容执行,很容易想到使用;
进行截断,然后执行任意代码,即修改$USER
内容为export USER=;getflag
同level01,依旧无法读flag内容,根据同样的思路,尝试你返回shell。
|
|
于是得到flag内容
level03
flag03中有定时任务 在/home/flag03中
题目说有个定时任务,crontab -l
没有发现,难道是其他用户执行的?去看一下所有的crontab任务,uname -a
可以看到是ubuntu
,所以用户定时任务应该在/var/spool/cron/crontabs
中,发现没权限,切换至root
(官网在介绍时说可以使用nebula-nebula切换到root)。。ichunqiu这个靶机切不成,思路终结,我们来看下脚本内容。
可以看到有个writable.sh
文件内容如下:
|
|
按题目说的,推测应该是定时几分钟,然后执行这个脚本,脚本内容依次执行writable.d
文件夹里的内容,限制时间5s,执行完后删除,而writable.d
中的内容是可以被任何人写入的,所以我们的思路应该是构造sh脚本,然后将flag内容输出到/tmp
这样都能读到。
|
|
过一阵,即可查看/tmp/flag03
中flag内容
level04
需要bypass 读到token
|
|
很明显,需要绕过的点是strstr
里面,一开始思考以为是像0字节截断之类的,但好像不行,最后想到链接,由于后面是直接将argv[1]
作为文件名打开的,所以可以使用链接
|
|
即可读到token,然后使用token作为flag04
的密码登陆,拿到flag
level05
寻找脆弱的目录权限
文件下有两个目录.ssh
与.backup
, 推测这道题应该是拿到私钥登陆,而.ssh
文件没有权限进入,转而查看备份文件,解压文件,发现当前路径下没有写权限,于是写到/tmp
目录下。
|
|
然后我们使用私钥登陆,即可查看flag内容
|
|
level06
flag06的凭证来自传统的unix系统
看题目描述,猜测可能凭证可猜解或可破解。/home/flag06
没有东西,于是查看/etc/passwd
,按理说,由于/etc/passwd
可以被所有人看到,不应该在其中有口令信息,而使用x
来占位表示在/etc/shadow
当中存储真正口令(shadow只有root才能看到),但由于来源于古老的unix系统,flag06
的口令存在于/etc/passwd
中
|
|
使用john进行破解,得到密码hello
level07
允许ping任意host
|
|
看了代码很容易想到传入的host
可以造成任意命令执行。最主要对perl
不是很熟,在thttpd.conf
文件中可以看到端口为7007
所以访问的方式为http://172.16.12.2:7007/index.cgi?Host=xxx
尝试访问http://172.16.12.2:7007/index.cgi?Host=127.0.0.1
可以看到反悔了结果,于是尝试构造:
|
|
注意这里要使用+
来代替空格,得到flag值
level08
同样读文件的限制,想办法绕过
查看/home/flag08
路径,发现有两个可能存在问题的内容,.cache/
和capture.pcap
,.cache
文件无法访问,但看到了pcap
包,猜测是分析数据包流量得到密钥。
可以根据hex内容推测得出密码:backd00Rmate
从而登陆flag08
得到flag值
level09
php代码存在漏洞
|
|
分析一下代码,其匹配[email [email protected]]
转变为cc AT xx DOT com
,其中使用了/e
模式,此模式会将替换串作为代码执行,那么很明显这里存在任意代码执行。
其漏洞是:
|
|
level10
任意文件上传代码,其中满足acess系统调用
这道题程序大致意思是,首先判断传入的文件是否有读权限,如果有将其内容发送到host的18211端口,这里使用access
来判断是否有读权限。其中这个access在手册中有这么一段话:
Warning: Using access() to check if a user is authorized to, for example, open a file before actually doing so using open(2) creates a security hole, because the user might exploit the short time interval between checking and opening the file to manipulate it. For this reason, the use of this system call should be avoided.
即不推荐使用access
判断权限再使用open
打开,由于时间差从而容易被攻击,所以思路就是在第一次文件权限判断的时候,指向一个/tmp/token
文件,这是我们level10
创建的且具有读权限的文件,然后再open
的时候,将它指向我们的/home/flag10/token
文件,由于二进制程序有s
标志,从而可以读取内容,发送给我们监听的18211端口,得到token值。
由于我们没有办法做到手动在程序执行期间更改其指向,所以我们用while循环来让其不停的变化,直到得到结果。
所以我们首先在本地监听18211端口,并将内容持续输出到文件中。(这里我们从官网下了虚拟机本地运行的,ichunqiu哪个没法监听)
|
|
之后我们
|
|
之后运行
|
|
最后查out即可得到615a2ce1-b2b5-4c76-8eed-8aa5c4015c27
之后即可登录查看
再补充一点,access
是使用进程运行的用户的权限去判断的,而open
运行时,使用的是s
之后的权限去运行的。
level11
同样任意命令执行
找到system
函数,发现其执行了buffer
中的内容,推测构造buffer
数据进行绕过,且buff内容对在执行前做过了处理,所以推测方法为倒序执行解密即可。
level12
存在一个50001端口的后门
我们看下程序,发现其判断password的hash值的1-40为是不是和给定的相同,可以通过构造hash值,不过会死人。我们看到其执行命令时,拼接了passwd
,则很明显存在任意命令执行漏洞。
|
|
level13
其会检查运行程序时的uid是否为1000
这道题考察反汇编知识,即在运行时我去们修改$eax
寄存器中的值,这个值即为1014
即level13的uid值,我们通过修改其值为1000
进行绕过,流程如下:
首先是反编译flag13文件
|
|
之后反编译main函数
|
|
看到:
|
|
应该是判断$eax
寄存器中的内容和0x3e8
是否相等,即是否为1000,我们在这里设置断点:
|
|
之后我们运行run
程序,会发现其停到断点处,修改之后在continue
:
|
|
可以看到得到了token值
level14
破解加密程序
随便输入:
|
|
推测为char(i)+index(i)的值,写个程序解密token即可
level15
动态链接库劫持,不太明白,之后在深入研究
level16
perl 1616端口 web认证
代码如下:
|
|
我们可以看到,整个流程大概是首先去获取username
和password
的值,然后对username进行大写之后在去除空格之后的所有内容,之后调用调用系统调用去处理,可以看到,很明显是一个任意代码执行的漏洞,不过要绕过username的处理。
egrep
用于在文件内进行内容查找,而由于username中会被变成大写,于是需要利用一个技巧,shell中转为小写:
|
|
使用${x,,}
的方式可以使命令转为小写。
于是我们构造username
为:
|
|
其中"
用于闭合,#
用于注释后面的语句,其中我们需要新建一个/tmp/level16
文件,内容如下,且设置为可执行:
|
|
之后访问提交即可
level17
攻击python脚本
看到pickle
,很明显,应该是反序列化问题,与传统的对象反序列化不同,python反序列化可能执行shellcode
,除了可以序列化对象,也可以通过操作码,反序列化出代码:
想要使用模块,则用操作码c,比如这关要使用到os模块,则:cos;如果要使用python内置函数,则是:cbuiltin。 想要使用一个字符串,则S’字符串’ 想要把参数带入“栈”中调用函数,则(S’参数’,官方叫它MARK对象 t操作码则是从栈顶开始弹出所有值,包括MARK对象。 R则pop栈顶两项内容最后,”.”代表pickle结束标志。
所以可以新建一个/tmp/sc
,内容如下:
|
|
然后传入nc连接即可