使用pkexec 和其策略文件安全提权执行外部程序

news2025/4/20 15:10:58

一、pkexec 基本机制

pkexec 是 Linux 桌面环境下基于 ‌PolicyKit‌ 的安全提权工具,可通过交互式图形界面获取用户授权后,以 root 权限执行指定程序。其核心特点包括:

  1. 图形化密码输入‌:调用时自动弹出系统认证对话框,用户无需在终端输入密码‌。
  2. 最小权限原则‌:仅授权特定操作,而非全局 root 权限‌。
  3. 安全性‌:密码通过安全通道传输,避免明文存储或传输风险‌。

二、实现交互式提权启动程序的步骤

1. 基础调用方式

在 C/C++ 中通过 fork + execvp 调用 pkexec,示例代码如下:

#include <unistd.h>
#include <sys/wait.h>

int main() {
    pid_t pid = fork();
    if (pid == 0) {  // 子进程
        char* args[] = {"pkexec", "/usr/bin/your-program", nullptr};
        execvp("pkexec", args);
        _exit(1);  // execvp 失败时退出
    } else if (pid > 0) {  // 父进程
        int status;
        waitpid(pid, &status, 0);
        if (WIFEXITED(status) && WEXITSTATUS(status) == 127) {
            // 认证失败处理(如显示错误提示)‌:ml-citation{ref="8" data="citationList"}
        }
    }
    return 0;
}

关键说明‌:

  • pkexec 必须指定完整路径(如 /usr/bin/your-program)‌。
  • 返回值 127 表示用户取消授权或认证失败‌。
2. 结合 Qt 框架的示例

在 Qt 中可通过 QProcess 调用 pkexec,并实时捕获输出(参考 ‌1 的实现逻辑):

#include <QProcess>
#include <QDebug>

void startWithRoot() {
    QProcess process;
    process.setProgram("pkexec");
    process.setArguments({"/usr/bin/filezilla"});  // 示例:启动 FileZilla

    QObject::connect(&process, &QProcess::readyReadStandardOutput, ‌[&] {
        qDebug() << "Output:" << process.readAllStandardOutput();
    });

    process.start();
    if (!process.waitForStarted()) {
        qDebug() << "启动失败";
    }
}
3. 自定义策略文件(增强安全性)

通过定义 .policy 文件限制可执行操作,避免滥用 root 权限:

  1. 创建策略文件‌(如 /usr/share/polkit-1/actions/custom.policy):
<policyconfig>
  <action id="org.example.custom-action">
    <description>Run custom program</description>
    <defaults>
      <allow_any>auth_admin</allow_any>
      <allow_active>auth_admin</allow_active>
    </defaults>
    <annotate key="org.freedesktop.policykit.exec.path">/usr/bin/your-program</annotate>
  </action>
</policyconfig>

‌        2. 调用时指定 Action ID‌:

pkexec --disable-internal-agent \  // 禁用默认策略
       --action-id org.example.custom-action \
       /usr/bin/your-program

作用‌:限制仅允许执行 /usr/bin/your-program,且需管理员授权‌。


三、安全注意事项

  1. 避免硬编码敏感路径‌:动态生成或从配置文件中读取路径,防止路径劫持‌。
  2. 清理环境变量‌:调用前使用 env -i 重置环境变量,避免注入攻击‌。
  3. 错误处理‌:检查返回值 127 并提示用户重新授权‌。

四、与其他方法的对比

方法交互方式密码存储风险适用场景
pkexec图形化弹窗桌面应用程序‌
sudo -S终端输入需处理明文脚本/后台任务‌
suid无需交互高风险极端场景(不推荐)‌

通过 pkexec 实现交互式提权,既能保障安全性,又符合桌面应用的交互习惯。开发者应优先结合 PolicyKit 策略文件,遵循最小权限原则‌。

五、自定义 pkexec 策略文件的步骤

1. 创建策略文件

策略文件需放置在 /usr/share/polkit-1/actions/ 目录下,文件名格式为 <action-id>.policy(如 org.example.custom.policy)。文件内容需遵循 XML 格式,包含以下核心元素‌:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE policyconfig PUBLIC "-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN" "http://www.freedesktop.org/standards/PolicyKit/1.0/policyconfig.dtd">
<policyconfig>
  <action id="org.example.custom-action">  <!-- 唯一动作标识符 -->
    <description>Run Custom Program</description>
    <message>需要管理员权限执行此操作</message>
    <defaults>
      <allow_any>auth_admin</allow_any>    <!-- 任何用户需管理员认证 -->
      <allow_inactive>auth_admin</allow_inactive>
      <allow_active>auth_admin</allow_active>
    </defaults>
    <annotate key="org.freedesktop.policykit.exec.path">/usr/bin/your-program</annotate>  <!-- 绑定可执行路径 -->
  </action>
</policyconfig>
2. 关键配置说明
  • <action id>‌:唯一标识符,建议使用反向域名格式(如 org.example.*)‌。
  • <defaults>‌:定义授权规则,auth_admin 表示需输入管理员密码,yes 表示无需认证,no 表示禁止‌。
    • <allow_any>‌:任何用户(包括未登录用户)的默认授权行为‌
    • <allow_inactive>‌:远程会话或非活动本地用户的授权行为‌
    • <allow_active>‌:当前活动用户的授权行为‌
    • 可选值‌:
      • yes:无需认证直接授权(完全免密提权)
      • no:禁止操作
      • auth_admin:需输入管理员密码
      • auth_admin_keep:授权后一段时间内免密‌
  • <annotate>‌:通过 exec.path 绑定可执行程序路径,防止路径劫持‌。
  • <message>‌:用户授权时弹出的提示信息(支持本地化)‌
  • <description>‌:策略的简要描述(后台显示)‌

3. 调用自定义策略

在代码或终端中通过 pkexec 指定动作 ID 和程序路径:

pkexec --action-id org.example.custom-action /usr/bin/your-program
4. 增强安全性设置
  • 限制用户范围‌:通过 <annotate key="org.freedesktop.policykit.exec.user"> 指定允许的用户或组‌。
  • 环境变量过滤‌:添加 <annotate key="org.freedesktop.policykit.exec.allow_gui">true</annotate> 控制是否允许 GUI 程序‌。
5. 验证策略生效
  • 执行命令后,系统会弹出图形化密码输入框(若配置为 auth_admin)。
  • 若授权失败,pkexec 返回状态码 127‌。

示例场景

假设需授权 /usr/bin/backup-tool 仅允许用户 backup-admin 执行:

<policyconfig>
  <action id="org.example.backup-action">
    <defaults>
      <allow_active>auth_admin</allow_active>
    </defaults>
    <annotate key="org.freedesktop.policykit.exec.path">/usr/bin/backup-tool</annotate>
    <annotate key="org.freedesktop.policykit.exec.user">backup-admin</annotate>
  </action>
</policyconfig>

调用方式:

pkexec --action-id org.example.backup-action /usr/bin/backup-tool
注意事项
  • 修改策略文件需 root 权限,保存后立即生效‌。
  • 避免使用通配符路径(如 /usr/bin/*),防止权限滥用‌。

通过自定义策略文件,可实现细粒度的权限控制,同时遵循最小权限原则提升系统安全性‌。

六、pkexec 策略文件支持的 <annotate> 标签列表

pkexec 的策略文件中,<annotate> 标签用于定义与权限执行相关的元数据配置。以下是所有支持的标签及其功能说明:


1. org.freedesktop.policykit.exec.path
  • 作用‌:‌绑定可执行文件的绝对路径‌,防止路径劫持攻击‌。
  • 格式‌:
<annotate key="org.freedesktop.policykit.exec.path">/usr/bin/your-program</annotate>
  • 强制要求‌:必须配置,否则策略文件可能失效‌。

2. org.freedesktop.policykit.exec.allow
  • 作用‌:‌显式声明保留的环境变量‌(如 GUI 程序依赖的 DISPLAY 或自定义变量)‌。
  • 格式‌:
<annotate key="org.freedesktop.policykit.exec.allow">VAR1,VAR2</annotate>
  • 默认行为‌:未配置时仅保留 DISPLAYXAUTHORITYWAYLAND_DISPLAYXDG_RUNTIME_DIR‌。

3. org.freedesktop.policykit.exec.allow_gui
  • 作用‌:‌允许图形界面(GUI)环境变量传递‌,适用于需要显示图形界面的程序‌。
  • 格式‌:
<annotate key="org.freedesktop.policykit.exec.allow_gui">true</annotate>
  • 依赖‌:需同时配置 exec.allow 保留 DISPLAY 等变量‌。

4. org.freedesktop.policykit.exec.argv
  • 作用‌:‌覆盖命令行参数‌,限制可执行程序接受的参数范围‌。
  • 格式‌:
<annotate key="org.freedesktop.policykit.exec.argv">arg1 arg2</annotate>
  • 示例‌:仅允许 pkexec /usr/bin/apt update 中的 update 参数。

5. org.freedesktop.policykit.exec.user
  • 作用‌:‌限制允许执行命令的用户或用户组‌,遵循最小权限原则‌。
  • 格式‌:
<annotate key="org.freedesktop.policykit.exec.user">username</annotate>
  • 扩展‌:支持 group:groupname 形式指定用户组‌。

完整策略文件示例
<?xml version="1.0" encoding="UTF-8"?>
<policyconfig>
  <action id="org.example.custom-action">
    <description>运行自定义程序</description>
    <defaults>
      <allow_active>auth_admin</allow_active>
    </defaults>
    <!-- 绑定程序路径 -->
    <annotate key="org.freedesktop.policykit.exec.path">/usr/bin/custom-app</annotate>
    <!-- 保留环境变量 -->
    <annotate key="org.freedesktop.policykit.exec.allow">DISPLAY,CUSTOM_VAR</annotate>
    <!-- 允许 GUI -->
    <annotate key="org.freedesktop.policykit.exec.allow_gui">true</annotate>
    <!-- 限制参数 -->
    <annotate key="org.freedesktop.policykit.exec.argv">start stop</annotate>
    <!-- 用户限制 -->
    <annotate key="org.freedesktop.policykit.exec.user">app-admin</annotate>
  </action>
</policyconfig>
注意事项
  1. 安全规范‌:
    • 避免使用通配符(如 *)或过度开放的配置‌。
    • 所有路径和参数需明确指定,防止注入攻击‌。
  2. 验证方法‌:
    • 使用 pkexec --action-id <action-id> <command> 测试策略生效性‌。
    • 检查日志文件(如 /var/log/auth.log)定位权限错误‌。

七、sudo  -S交互式提示

#include <iostream>
#include <string>
#include <cstring>
#include <unistd.h>
#include <sys/wait.h>
#include <vector>

// 安全清理密码的内存(避免被泄露)
void secure_clear_password(char* ptr, size_t len) {
    if (ptr != nullptr) {
        memset(ptr, 0, len);
    }
}

// 执行需要 root 权限的命令(传入密码和命令)
bool run_as_root(const std::string& password, const std::string& command) {
    int pipefd;
    if (pipe(pipefd) == -1) {
        perror("pipe");
        return false;
    }

    pid_t pid = fork();
    if (pid == -1) {
        perror("fork");
        close(pipefd);
        close(pipefd);
        return false;
    }

    if (pid == 0) { // 子进程
        close(pipefd); // 关闭写端

        // 将管道读端重定向到标准输入
        if (dup2(pipefd, STDIN_FILENO) == -1) {
            perror("dup2");
            _exit(EXIT_FAILURE);
        }
        close(pipefd);

        // 构造 sudo 命令参数
        std::vector<char*> args;
        args.push_back(strdup("sudo"));
        args.push_back(strdup("-S"));
        args.push_back(strdup("--"));
        args.push_back(strdup(command.c_str()));
        args.push_back(nullptr);

        execvp("sudo", args.data());
        perror("execvp");
        _exit(EXIT_FAILURE);
    } else { // 父进程
        close(pipefd); // 关闭读端

        // 写入密码(附加换行符)
        std::string input = password + "\n";
        ssize_t written = write(pipefd, input.c_str(), input.size());
        if (written == -1) {
            perror("write");
            close(pipefd);
            return false;
        }
        close(pipefd);

        // 等待子进程结束
        int status;
        waitpid(pid, &status, 0);

        // 清理敏感数据
        secure_clear_password(const_cast<char*>(input.data()), input.size());

        if (WIFEXITED(status)) {
            return (WEXITSTATUS(status) == 0);
        }
        return false;
    }
}

int main() {
    std::string password;   // 假设已通过安全方式获取密码
    std::string command = "/usr/bin/echo 'Running as root!'";

    std::cout << "请输入 root 密码: ";
    std::getline(std::cin, password);  // 仅为示例,实际应从安全输入源获取

    if (run_as_root(password, command)) {
        std::cout << "命令执行成功" << std::endl;
    } else {
        std::cerr << "命令执行失败" << std::endl;
    }

    // 清理密码内存
    secure_clear_password(const_cast<char*>(password.data()), password.size());
    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2327871.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

机器学习、深度学习和神经网络

机器学习、深度学习和神经网络 术语及相关概念 在深入了解人工智能&#xff08;AI&#xff09;的工作原理以及它的各种应用之前&#xff0c;让我们先区分一下与AI密切相关的一些术语和概念&#xff1a;人工智能、机器学习、深度学习和神经网络。这些术语有时会被交替使用&#…

数字孪生在智慧城市中的前端呈现与 UI 设计思路

一、数字孪生技术在智慧城市中的应用与前端呈现 数字孪生技术通过创建城市的虚拟副本&#xff0c;实现了对城市运行状态的实时监控、分析与预测。在智慧城市中&#xff0c;数字孪生技术的应用包括交通流量监测、环境质量分析、基础设施管理等。其前端呈现主要依赖于Web3D技术、…

Android OpenGLES 360全景图片渲染(球体内部)

概述 360度全景图是一种虚拟现实技术&#xff0c;它通过对现实场景进行多角度拍摄后&#xff0c;利用计算机软件将这些照片拼接成一个完整的全景图像。这种技术能够让观看者在虚拟环境中以交互的方式查看整个周围环境&#xff0c;就好像他们真的站在那个位置一样。在Android设备…

LETTERS(DFS)

【题目描述】 给出一个rowcolrowcol的大写字母矩阵&#xff0c;一开始的位置为左上角&#xff0c;你可以向上下左右四个方向移动&#xff0c;并且不能移向曾经经过的字母。问最多可以经过几个字母。 【输入】 第一行&#xff0c;输入字母矩阵行数RR和列数SS&#xff0c;1≤R,S≤…

NVM 多版本Node.js 管理全指南(Windows系统)

&#x1f9d1; 博主简介&#xff1a;CSDN博客专家、全栈领域优质创作者、高级开发工程师、高级信息系统项目管理师、系统架构师&#xff0c;数学与应用数学专业&#xff0c;10年以上多种混合语言开发经验&#xff0c;从事DICOM医学影像开发领域多年&#xff0c;熟悉DICOM协议及…

C,C++语言缓冲区溢出的产生和预防

缓冲区溢出的定义 缓冲区是内存中用于存储数据的一块连续区域&#xff0c;在 C 和 C 里&#xff0c;常使用数组、指针等方式来操作缓冲区。而缓冲区溢出指的是当程序向缓冲区写入的数据量超出了该缓冲区本身能够容纳的最大数据量时&#xff0c;额外的数据就会覆盖相邻的内存区…

《Linux内存管理:实验驱动的深度探索》【附录】【实验环境搭建 2】【vscode搭建调试内核环境】

1. 如何调试我们的内核 1. GDB调试 安装gdb sudo apt-get install gdb-multiarchgdb-multiarch是多架构版本&#xff0c;可以通过set architecture aarch64指定架构 QEMU参数修改添加-s -S #!/usr/bin/shqemu-7.2.0-rc1/build/aarch64-softmmu/qemu-system-aarch64 \-nogr…

Flutter项目之登录注册功能实现

目录&#xff1a; 1、页面效果2、登录两种状态界面3、中间按钮部分4、广告区域5、最新资讯6、登录注册页联调6.1、网络请求工具类6.2、注册页联调6.3、登录问题分析6.4、本地缓存6.5、共享token6.6、登录页联调6.7、退出登录 1、页面效果 import package:flutter/material.dart…

ctfshow VIP题目限免 源码泄露

根据题目提示是源代码泄露&#xff0c;右键查看页面源代码发现了 flag

移动神器RAX3000M路由器变身家庭云之七:增加打印服务,电脑手机无线打印

系列文章目录&#xff1a; 移动神器RAX3000M路由器变身家庭云之一&#xff1a;开通SSH&#xff0c;安装新软件包 移动神器RAX3000M路由器变身家庭云之二&#xff1a;安装vsftpd 移动神器RAX3000M路由器变身家庭云之三&#xff1a;外网访问家庭云 移动神器RAX3000M路由器不刷固…

《函数基础与内存机制深度剖析:从 return 语句到各类经典编程题详解》

一、问答题 &#xff08;1&#xff09;使用函数的好处是什么&#xff1f; 1.提升代码的复用性 2.提升代码的可维护性 3.增强代码的可读性 4.提高代码的灵活性 5.方便进行单元测试 &#xff08;2&#xff09;如何定义一个函数&#xff1f;如何调用一个函数&#xff1f; 在Pytho…

Python | 使用Matplotlib绘制Swarm Plot(蜂群图)

Swarm Plot&#xff08;蜂群图&#xff09;是一种数据可视化图表&#xff0c;它用于展示分类数据的分布情况。这种图表通过将数据点沿着一个或多个分类变量轻微地分散&#xff0c;以避免它们之间的重叠&#xff0c;从而更好地显示数据的分布密度和分布趋势。Swarm Plot特别适用…

新版本Xmind结合DeepSeek快速生成美丽的思维导图

前言 我的上一篇博客&#xff08;https://quickrubber.blog.csdn.net/article/details/146518898&#xff09;中讲到采用Python编程可以实现和Xmind的互动&#xff0c;并让DeepSeek来生成相应的代码从而实现对内容的任意修改。但是&#xff0c;那篇博客中提到的Xmind有版本的限…

set和map封装

目录 set和map区别 set和map的插入 set和map的实现 修改红黑树的模板参数 修改比较时使用的变量 迭代器的实现 迭代器的定义 *解引用重载 ->成员访问重载 自增重载 重载 封装迭代器 RBTree迭代器封装 封装set迭代器 对set迭代器进行修改 封装map迭代器 修改…

【Linux】Orin NX + Ubuntu22.04配置国内源

1、获取源 清华源 arm 系统的源,可以在如下地址获取到 https://mirror.tuna.tsinghua.edu.cn/help/ubuntu-ports/ 选择HTTPS,否则可能报错: 明文签署文件不可用,结果为‘NOSPLIT’(您的网络需要认证吗?)查看Orin NX系统版本 选择jammy的源 2、更新源 1)备份原配…

Open-Sora:开源AI视频生成的新星

一.引言 近年来&#xff0c;AI视频生成技术快速发展&#xff0c;从文本生成图像&#xff08;如Stable Diffusion、DALLE&#xff09;到文本生成视频&#xff08;如Runway、Pika&#xff09;&#xff0c;AI在多媒体创作领域的应用日益广泛。近期&#xff0c;Open-Sora作为一款开…

【堆】《深入剖析优先级队列(堆):数据结构与算法的高效搭档》

文章目录 前言例题一、最后一块石头的重量二、数据流中的第 K 大元素三、前K个高频单词四、数据流的中位数 结语 前言 什么是优先级队列算法呢&#xff1f;它的算法原理又该怎么解释&#xff1f; 优先级队列&#xff08;堆&#xff09;算法是一种特殊的数据结构和算法&#xf…

【CMOS输出缓冲器驱动强度】

一 、学习笔记 原始资料&#xff1a;https://www.ti.com.cn/cn/lit/an/zhcae18/zhcae18.pdf?ts1743589394832 Q1、电平转换芯片的其中一个关键指标是转换速率&#xff0c;转换速率跟什么因素有关系呢&#xff1f; 1、瞬态驱动强度 上升或下降时间用于评估瞬态驱动强度。需要…

【C++】Cplusplus进阶

模板的进阶&#xff1a; 非类型模板参数 是C模板中允许使用具体值&#xff08;而非类型&#xff09;作为模板参数的特性。它们必须是编译时常量&#xff0c;且类型仅限于整型、枚举、指针、引用。&#xff08;char也行&#xff09; STL标准库里面也使用了非类型的模板参数。 …

透明的卡组收费模式IC++

IC是信用卡处理商用来计算每笔交易相关费用的定价模型。与统一或混合定价相比&#xff0c;IC提供了额外的透明度。 作为企业主&#xff0c;了解IC定价的来龙去脉至关重要&#xff0c;以确定它是否对您的运营有意义。 什么是IC&#xff1f; IC或interchange plus是一种流行的定…