美好的一天
背景:
我正在为Linux系统创建一个OpenVPN包装器应用程序,该应用程序即将完成.我遇到了一些障碍.
OpenVPN需要root访问权来修改路由表(添加和删除路由).这是事情变得模糊和混乱的地方.
希望通过扩展this question,可以共享一些行业标准答案和解决方案.
文档:
因此,经过几个小时的搜索,我编制了一个获取root访问权限的可能方法列表,但是似乎没有一个是官方的,也没有任何真正可靠的指导来获得这个SU特权.
让我们考虑以下方法.
1.使用pkexec& polkits
有关最佳做法的一些信息,请查找官方freedesktop polkit documentation here和here
使用pkexec和polkits在线发现了一些教程
– here,这帮我创建了我的polkit文件.
– SO Thread
– 用于Qt应用程序的lovely small tutorial
关于pkexec和polkits的简要解释(我的理解):
> polkits:
polkits由行动和规则组成(参见深入阅读和解释的文件).它定义了应用程序的操作以及与之关联的规则.规则可以定义为属于特定组的用户,其中操作查询规则,成功传递规则,用户自动进行身份验证(没有弹出密码提示),否则他们需要输入管理员密码
> pkexec:
用于与polkit操作进行交互并对应用程序进行身份验证以获取root访问权限的应用程序.
这些需要在/usr/share / polkit-1 / actions /和/usr/share/polkit-1/rules.d/中添加操作(在其他目录中,请参阅所有位置的文档)
这种方法似乎很好用(但需要更多的解释才能轻松理解,imo)
注意:有qt-polkit库可供使用,请参阅他们的github repository
对于简单的TL; DR版本,请参阅this
我创建的polkit文件(注意这可能不正确,但它对我有用):
可以找到/添加的位置(还有其他位置)
/usr/share/polkit-1/actions
Policy Kit文件名:
com.myappname.something.policy //需要.policy
注意:
com.myappname.something
被称为政策的命名空间(阅读文档,这将不清楚)
政策套件内容
关于我的政策文件的注释(重要的位)
>这只是一个示例,请参阅官方示例和说明的文档:
>< vendor>我的应用名称< / vendor>是应用程序名称,它可以有空格
>< action id =“com.myappname.something.myaction-name”>这里有任何动作名称.
>注意!
文件名 – > com.myappname.something.policy和,
动作ID – > com.myappname.something.myaction-name应该具有相同的命名空间
>图标名称应与最新的freedesktop图标规格here一致
TL; DR(或不想):
图标位置是:
1. /home/yourusername/.icons (sometimes not there)
2. /home/yourusername/.local/share/icons
2. /usr/share/icons
只要它们符合大小并且是.png,您只能传递文件名(省略格式)
>非常重要:
当调用pkexec< myappname>,并且没有这些行时(老实说,我不太确定它们的用途),会遇到类似这样的错误:
2017-12-19 12::58:24 Fatal: QXcbConnection: Could not connect to display ((null):0,(null))
Aborted (core dumped)
注意:保持密钥相同,但是您可以并且可能应该将exec.path密钥更改为您的应用程序位置.
政策工具包如何运作?
简而言之,如果你回顾前面提到的可爱的example(并跳过所有非常相似的文件名),它就变得清晰了.
当一个人跑:
pkexec
这会调用本地身份验证代理以root身份运行应用程序(在我们的示例中).
这由动作(上面提到的策略工具包)处理.此外,规则利用动作id来执行附加查询等,这些可以在上面提供的示例中查看.
输入管理员密码后,根据输入默认值的“设置”(参见here),我们有:
auth_admin_keep
Like auth_admin but the authorization is kept for a brief period (e.g. five minutes).
因此,用户可以(在我的OpenVPN应用程序中)在接下来的5分钟内连接到OpenVPN连接,直到再次请求密码.
2. Sudo(/ etc / sudoers):
例如通过使用参数调用singleShot QProcess,在运行主应用程序之前检查root访问权限:
/bin/sh -c sudo -v
将导致各种Linux发行版中的退出代码为1(从而导致我搜索备选方案)
3. setuid():
一个非常好的example可以在这里找到,不幸的是它似乎不适用于现代Linux发行版,因为它是一个很容易被利用的安全漏洞.
简而言之,该过程需要一个:
chmod +x
并使用getuid()检查是否在应用程序中设置了s位以获取用户ID,并使用getgid()获取用户的组ID.
但是,这似乎不适用于现代Linux系统.以下是执行s位设置的root拥有的应用程序的输出,作为普通(非特权)用户运行:
2017-12-19 12::21:08 Fatal: FATAL: The application binary appears to be running setuid,this is a security hole. ((null):0,(null))
Aborted (core dumped)
告别,setuid()
4.其他方法:
> PAM
进一步阅读,见
> man page
> tutorial/explanation
>关于跨平台PAM整合的QT Forum问题
> QT用户模式
Qt提供了small implementation for acquiring root access,但它仅适用于使用yum包管理器的Linux发行版.
关于此问题的后续问题,见this QT Forum question
问题:
上面可能只包括一小部分可用的方法来获取root访问权限,但考虑到某些应用程序是全局使用的,它们经常被攻击或撬开甚至受到攻击.
在做了这项研究之后,它扩大了我的知识,但没有给我一个推荐的确定方法,但只提示.
题:
上面哪种方法在工业上是首选的,即何时我应该使用另一种方法(PAM vs polkits vs simple sudo),如果有其他方法可用,这些是首选吗?
However,this does not seem to work with modern day Linux systems.
Here is the output of executing a root owned application with the s
bit set,run as a normal (unprivileged) user:
2017-12-19 12::21:08 Fatal: FATAL: The application binary appears to be running setuid,(null))
上述错误与现代Linux系统无关.它是对使用setuid而不理解它的愚蠢开发人员的Qt保护.
只需致电
QCoreApplication::setSetuidAllowed(true)
当你的应用程序启动时,你可以做setuid()就好了.您甚至可以在下载到“普通”用户之前运行特权命令.
摘要:
您的Qt应用程序必须具有root所有者,并且setuid位设置.示例debmaker是我想要执行特权操作的Qt应用程序.所以在我建立debmaker之后,我做了:
sudo chown root:root debmaker
sudo chmod 4755 debmaker
(后者设置setuid位)
现在运行Qt应用程序
./debmaker
应用程序做的第一件事是检查geteuid()== 0和getuid()== 1000(1000是我的用户ID,0是根)
然后它启动一个新进程(在Qt中使用QProcess).这将以特权模式运行. (示例我的子进程称为chroot)
现在通过调用将主应用程序(我的debmaker)放到正常的用户级别
setuid(getuid());
chroot(子进程)将继续以root用户身份运行.
主应用程序现在不再以提升模式运行,但可以将请求发送到仍在提升模式下运行的子进程.
QProcess *chroot = new QProcess;
blah blah setup the chroot and start it
chroot->write("chown root:root /home/oosman/foo");
最后一行将向子进程发送消息.您在子进程中读取stdin,解析命令,检查它以确保它不是恶意的(或恶意取决于您的意图!)并执行命令.