Ubuntu26rootshutdown时被拒

admin 2026-08-09 05:02:30 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: 本文分析了Ubuntu26中root执行shutdown被拒的问题,根本原因是systemd的InhibitorLocks机制。普通进程如X终端下的python3会通过D-Bus向systemd-logind注册关机锁导致关机被阻止。文章提供了使用systemd-inhibit和gdbus命令查看及忽略锁的方法。此外作者深入探讨了D-Bus的攻击面,演示了通过gdbus远程调用LockSessions实现锁屏及UnlockSessions免密解锁的过程,揭示了D-Bus接口在系统控制中的潜在安全风险与利用价值。 综合评分: 90 文章分类: 实战经验,漏洞分析,终端安全


cover_image

Ubuntu 26 root shutdown时被拒

原创

沈沉舟 沈沉舟

青衣十三楼飞花堂

2026年7月28日 00:00 北京

在小说阅读器读本章

去阅读

创建: 2026-07-24 16:35
链接: https://scz.617.cn/unix/202607241635.txt

Q:

Ubuntu 26,以root身份shutdown时,提示被拒

# shutdown -P now

Operation inhibited by “scz” (PID 3423 “gnome-session-s”, user scz), reason is “user session inhibited”. User scz is logged in on tty2. Please retry operation after closing inhibitors and logging out other users. ‘systemd-inhibit’ can be used to list active inhibitors. Alternatively, ignore inhibitors and users with ‘systemctl poweroff -i’.

这是什么情况?

A:

精确复现方案,在X用scz登录,开Terminal,执行

python3

此时root已无法shutdown,出现前述提示。一定在X的Terminal中执行python3进行测试,在SSH Shell中执行python3,无此效果。

Ubuntu 26中init是到systemd的符号链接,shutdown是到systemctl的符号链接。

$ readlink -f $(which init)
/usr/lib/systemd/systemd

$ readlink -f $(which shutdown)
/usr/bin/systemctl

这种系统”init 0″不对应关机。”shutdown -P”实际执行”systemctl poweroff”。systemctl通过systemd、systemd-logind完成关机、重启等操作,这套机制遵循一种名为”Inhibitor Locks”的东西,参看:

https://systemd.io/INHIBITOR_LOCKS

普通进程可通过D-Bus向systemd-logind注册指定类型的inhibitor,比如说,我正在升级,请勿关机。之后的”systemctl poweroff”会通过systemd询问systemd-logind,发现有个shutdown inhibitor,systemd将拒绝关机。

可用如下命令查看当前注册生效中的inhibitor

systemd-inhibit --list
systemd-inhibit --no-pager --no-legend --list

或者更底层、更直接的命令

gdbus call \
--system \
--dest org.freedesktop.login1 \
--object-path /org/freedesktop/login1 \
--method org.freedesktop.login1.Manager.ListInhibitors

可用systemd-inhibit注册shutdown inhibitor,同时执行一个长期驻留的子进程,在子进程存活期间,inhibitor对应的fd(文件句柄)不会自动关闭,inhibitor不会自动注销。比如

systemd-inhibit \
--what=shutdown \
--who="any" \
--why="some" \
--mode=block \
bash

bash可换成”pauseme sleep 0″之类的,只要子进程能长期驻留即可。上述操作对系统有潜在影响,普通用户执行时要求输入root密码。

如果遭遇root shutdown被拒,提示信息中已给出解决方案之一

systemctl poweroff -i

“-i”是忽略inhibitor的意思。但这样过于简单粗暴,更好的解决之道是,找出那个注册了shutdown inhibitor的进程,正常结束它,再关机。

D:

D-Bus是个较大的攻击面,但我从未研究过,这次稍微多做点实验。

gdbus introspect \
--system \
--dest org.freedesktop.login1 \
--object-path /org/freedesktop/login1

上述命令向systemd-logind查询「你这个D-Bus服务提供哪些接口」,部分输出如下

  interface org.freedesktop.login1.Manager {
    methods:
...
      ListSessions(out a(susso) sessions);
      ListSessionsEx(out a(sussussbto) sessions);
      ListUsers(out a(uso) users);
...
      ListInhibitors(out a(ssssuu) inhibitors);
...
      LockSessions();
      UnlockSessions();
...
      PowerOff(in  b interactive);
...
      Reboot(in  b interactive);

gdbus可直接调用这些API。

gdbus call \
--system \
--dest org.freedesktop.login1 \
--object-path /org/freedesktop/login1 \
--method org.freedesktop.login1.Manager.LockSessions

在SSH Shell中以root身份执行LockSessions,将在主控台产生锁屏的效果,简单类比成Windows cmd中执行:

rundll32.exe user32.dll,LockWorkStation

针对LockSessions,可用gdbus取消锁屏:

gdbus call \
--system \
--dest org.freedesktop.login1 \
--object-path /org/freedesktop/login1 \
--method org.freedesktop.login1.Manager.UnlockSessions

若在主控台交互式取消锁屏,需输入密码,gdbus取消锁屏则不需要,有趣。不过,若主控台处于登录界面,UnlockSessions无法取消录登界面。

gdbus call \
--system \
--dest org.freedesktop.login1 \
--object-path /org/freedesktop/login1 \
--method org.freedesktop.login1.Manager.ListSessions

可通过D-Bus关机,以root身份执行:

gdbus call \
--system \
--dest org.freedesktop.login1 \
--object-path /org/freedesktop/login1 \
--method org.freedesktop.login1.Manager.PowerOff \
true

对于root,无论PowerOff的参数是false还是true,均不会交互式授权,因为已经是root。对于普通用户,上述命令过于底层,无法进入交互式授权环节,因为这是由其他组件配合提供的,gdbus无此能力,只会报错:

Error: GDBus.Error:org.freedesktop.DBus.Error.InteractiveAuthorizationRequired: Access denied as the requested operation requires interactive authentication. However, interactive authentication has not been enabled by the calling program.

可监控D-Bus消息,比如

dbus-monitor --system --monitor \
type=method_call,interface=org.freedesktop.login1.Manager,member=Inhibit

在X Terminal中执行python3,在dbus-monitor中将看到

method call ... path=/org/freedesktop/login1; interface=org.freedesktop.login1.Manager; member=Inhibit
   string "shutdown"
   string "scz"
   string "user session inhibited"
   string "block"

在root shell中执行

gdbus call \
--system \
--dest org.freedesktop.login1 \
--object-path /org/freedesktop/login1 \
--method org.freedesktop.login1.Manager.Inhibit \
shutdown \
any \
some \
block

在dbus-monitor中将看到

method call ...
   string "shutdown"
   string "any"
   string "some"
   string "block"

免责声明:

本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。

任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。

本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我

本文转载自:青衣十三楼飞花堂 沈沉舟 沈沉舟《Ubuntu 26 root shutdown时被拒》

评论:0   参与:  0