如何在 Linux 上禁用“kill”命令

xxl*_*ali 5 linux kill command-line

我想禁用所有 kill 命令(包括 root 用户)。我尝试更改权限,但它仍然可以执行。有没有办法做到这一点?

use*_*874 67

使用此内核模块禁用kill系统调用amd64
使用风险自负。预计会有破坏性的副作用。

#include <linux/module.h>

MODULE_LICENSE("GPL");

int __init init(void) __attribute__((noreturn))
{
     unsigned long long cr0 = read_cr0();
     write_cr0(cr0 & ~(1 << 16));  /* Clear Write Protection (WP) bit */
     *(unsigned char *)sys_kill = 0xc3;  /* opcode for "ret" */
     write_cr0(cr0);

     /* This makes sure that delete_module below won't complain */
     __this_module.refcnt = 1;
     __this_module.state = MODULE_STATE_LIVE;

     asm volatile
     (
          "mov %0, %%rsp\n\t" /* It seems GCC refuses to mess with the stack pointer */
          "jmp sys_delete_module\n\t"  /* call delete_module(name, flags) */
          :: "r"(current->stack + THREAD_SIZE - sizeof(struct pt_regs) - 8), "D"(__this_module.name), "S"(0) :
     );
}

void __exit exit(void)
{
    return;
}
Run Code Online (Sandbox Code Playgroud)

像编译任何其他模块一样编译它。然后用insmod在上面。

  • 如果您要求,您可以指望人们给您多支枪来射击自己的脚,这真是太神奇了。包括内核模块。:D (73认同)
  • 希望至少任何知道如何“像编译任何其他模块一样编译它”的人都知道这是一个多么糟糕的主意。 (42认同)
  • 有人可以将此模块插入 VM 并发布 YouTube 上发生的事情的录音吗? (14认同)
  • 这是我最喜欢的 Stack Exchange 答案。 (13认同)
  • 有趣的是,我猜你在尾调用 `sys_delete_module` 之前修改了 `%rsp`,因此返回地址在删除的函数之外。无论如何,始终使用约束在正确的寄存器中请求您的数据,而不是使用 `mov` 指令。例如,首先使用 `"D"(__this_module.name)` 在 `%rdi` 中请求它。内联汇编代码块的开头或结尾的 `mov` 几乎总是次优的,最好留给编译器。不过,我认为 `%rsp` 没有约束,而且我知道从 `%r8` 到 `%r15` 中的任何一个都没有约束。 (5认同)
  • 另请参阅 [我收集的 how-to-write-good-inline-asm 答案](http://stackoverflow.com/questions/34520013/using-base-pointer-register-in-c-inline-asm/34522750# 34522750) 和 [stackoverflow inline-asm 标签维基](http://stackoverflow.com/tags/inline-assembly/info)。 (2认同)

Kus*_*nda 56

“禁用” killfor root,即使可能,也很可能会产生不需要的副作用,例如系统脚本故障,并且在最坏(但可能)的情况下,它会阻止您的计算机正常启动(甚至正常关闭) .

对于用户来说,这也会导致问题。例如,我有一些以非特权用户身份运行的脚本,用于检查某些进程是否正在使用kill -0 $pid. 这些脚本将停止工作。

对于您自己,您可以alias使用kill其他命令,例如echo "kill"

$ alias kill='echo "kill"'
Run Code Online (Sandbox Code Playgroud)

kill至少会阻止在命令行上做任何有用的事情:

$ kill -s HUP $$
kill -s HUP 11985
Run Code Online (Sandbox Code Playgroud)

  • @PeterCordes `\kill` 也会绕过别名。 (8认同)
  • 仅针对交互式使用禁用“kill”是唯一合理的答案,因此 +1。如果您*确实*想从具有此别名的交互式 shell 中使用它,只需运行 `/bin/kill ...`、或 `builtin kill ...` 或 `command kill` 以抑制函数/别名查找。Bash 具有覆盖默认命令查找的关键字。正常的用例是在包装函数中,例如 `cd(){ command cd "$@"; 密码 &gt; /tmp/here.$$; }` (4认同)

iva*_*eev 7

不应该禁用系统范围的,因为它在系统脚本中使用(例如,/etc/init.d/functionsinitscripts包)。

您可以通过将其设置为/ (或者如果您希望得到错误而不是空操作)来为登录外壳(及其子外壳)禁用它。aliastruefalsekill_disabled

请注意,这种方式并非万无一失:它只会影响直接执行的命令(不会影响脚本内部的命令)。并且用户将能够删除别名unalias


为此,请运行以下命令

alias kill=kill_disabled
Run Code Online (Sandbox Code Playgroud)

或将其添加到适当的bash启动文件中,以便在每次登录时运行它。

现在,以kill交互方式运行将产生:

$ kill 9999
-bash: kill_disabled: command not found
Run Code Online (Sandbox Code Playgroud)

正如我所说,上述方式很容易被颠覆。如果您需要一种万无一失的方法,唯一的解决方案是在一个chroot环境中运行整个登录 shell 会话。它仍然只会禁用stock 命令,而不是直接的系统调用,但已完成。后者不能被禁用,因为它对于正常操作是必不可少的(例如,每个Ctrl+C发送SIGINT、管道要求SIGPIPE和后台进程都由五个以上的不同信号控制)。设置 chroot 环境是一项高级任务,如果用户需要访问整个文件系统,通常会很不方便。

  • 呃,如果你在 chroot 中运行它,没有什么能阻止你直接从另一个应用程序执行 kill syscall,它甚至可能是你编译并上传到 chroot 的应用程序。(如果你足够关心的话,一个字节一个字节)。Chroot 远非万无一失。除了在内核中阻止系统调用之外,没有什么可以完全阻止它。 (2认同)