Answers:
问题是,剧本是不是正在运行,但解释(bash
,perl
,python
等)。并且解释器需要阅读脚本。这与“常规”程序(如)不同ls
,因为该程序像解释程序那样直接加载到内核中。由于内核本身正在读取程序文件,因此无需担心读取访问。解释器需要读取脚本文件,因为需要读取普通文件。
这仅适用于二进制文件。
$ chown foo:foo bar
$ chmod 701 bar
作为非特权用户:
$ ls -lha bar
-rwx-----x 1 foo foo 7.0K 2012-03-15 03:06 bar
$ cat bar
cat: bar: Permission denied
$ ./bar
baz
现在,这里是踢腿者。尽管通过常规方式无法读取文件,但实际上无法阻止读取文件。这实际上是http://smashthestack.org/(第13级)上的一个挑战。有一个众所周知的实用程序hktrace
,允许您使用读取文件ptrace
。
我认为,您可以使用进行此操作setuid
。
除非您不能,因为大多数发行版(显然)已setuid
禁用,因为那是一个巨大的安全漏洞。该功能已在我的功能上禁用,因此我实际上并不知道此答案是否有效,无论如何我都会发布它,因为我认为它应该如此。
无论如何,如果我想做您想做的事-并且我有一个setuid
启用了脚本的发行版-我会做类似的事情:
$ chmod 700 myscript
$ cat > myscript-nonroot
#!/bin/sh
bash myscript
^D
$ sudo chown root:root myscript-nonroot
$ sudo chmod 4755 myscript-nonroot # make SURE this isn't world-writable!
也就是说,我将编写另一个脚本,其唯一目的是调用root-read-only脚本,将其更改为root拥有,并为其授予setuid权限。(伴随着其他所有人的不可写状态。)
由于myscript-nonroot函数是每个人都可以读取和执行的函数,因此当您实际执行脚本的行(bash myscript
)取两行时,它将以root身份运行(或者您想要的其他人,确切的用户)没关系,只要包装文件由同一用户拥有。)
755
一点。
chmod 755
与0775八进制相同。周围有很多混乱。.(manpagez.com/man/1/chmod)此页面有一个我无法理解的可怕而无限制的水平滚动……
正如@eradman 的评论中已经提到的,这在OpenBSD上是可能的。
作为根:
hzy# cat <<'EOT' >/tmp/foo; chmod 001 /tmp/foo
#! /bin/sh
: this is secret
echo done
EOT
作为普通用户:
hzy$ cat /tmp/foo
cat: /tmp/foo: Permission denied
hzy$ /tmp/foo
done
通过将/dev/fd/3
(或脚本的任何打开fd)传递给解释器,该方法起作用。这招会不会在Linux上,在那里工作,/dev/fd/N
不是特殊字符设备,其返回dup(2)
打开时的FD的,但“神奇”的符号链接到原始文件/目录项,其中从头打开文件[1]。它可以在Free / NetBSD或Solaris中实现。
基本上,授予x
(执行)许可意味着r
对具有shebang [2]的任何文件也给予(读取)许可:
hzy$ cat /tmp/foo
cat: /tmp/foo: Permission denied
hzy$ ktrace -ti /tmp/foo
done
hzy$ kdump | tail -n8
70154 sh GIO fd 10 read 38 bytes
"#! /bin/sh
: this is secret
echo done
"
70154 sh GIO fd 1 wrote 5 bytes
"done
ktrace
不是唯一的方法;如果解释器是动态链接的可执行文件(例如perl
或)python
,LD_PRELOAD
则read(2)
可以使用覆盖该功能的ed hack 。
而且,将其设置为setuid不会阻止普通用户看到其内容。她可以简单地在下运行它ptrace(2)
,这将导致setuid位被忽略:
作为根:
hzyS# cat <<'EOT' >/tmp/bar; chmod 4001 /tmp/bar
#! /bin/sh
: this is secret
id
EOT
作为普通用户:
hzyS$ ktrace -ti /tmp/bar
uid=1001(duns) euid=0(root) gid=1001(duns) groups=1001(duns)
hzyS$ kdump
... nothing, the kernel disabled the ktrace ...
hzyS$ cc -Wall -xc - -o pt <<'EOT'
#include <unistd.h>
#include <sys/types.h>
#include <sys/ptrace.h>
#include <sys/wait.h>
#include <signal.h>
int main(int ac, char **av){
int s; pid_t pid;
if((pid = fork()) == 0){
ptrace(PT_TRACE_ME, 0, 0, 0);
execvp(av[1], av + 1);
}
while(wait(&s) > 0 && WIFSTOPPED(s)){
s = WSTOPSIG(s);
ptrace(PT_CONTINUE, pid, (caddr_t)1, s == SIGTRAP ? 0 : s);
}
}
EOT
hzyS$ ./pt ktrace -ti /tmp/bar
uid=1001(duns) gid=1001(duns) groups=1001(duns)
hzyS$ kdump | tail -5
29543 sh GIO fd 10 read 31 bytes
"#! /bin/sh
: this is secret
id
"
(很抱歉,如果这不是最直接的展示方式)
[1]这可以在Linux上使用来模拟binfmt_misc
,但是必须修改解释器,或者必须使用包装器;请参阅此答案的最后一部分,以了解一个故意制造的可笑的不安全示例。
[2]或一般而言,不会导致execve()
返回的任何文件ENOEXEC
。
为了使脚本不可读但可执行,您可以使用3个主要选项:
第一选择
使用openssl命令手动对其进行加密。将来,当您要运行脚本时,您将不得不再次手动运行openssl,并提供解密密码。
用openssl加密:
猫yourscript.sh | openssl aes-128-cbc -a -salt -k yourpassword> yourscript.enc
用openssl解密:
猫yourscript.enc | openssl aes-128-cbc -a -d -salt -k yourpassword> yourscript.dec
yourscript.dec将与原始脚本yourscript.sh相同
第二种选择
使用类似www.Enscryption.com的网站来自动加密脚本,并使脚本的加密版本可执行。该站点同时使用openssl的加密功能和其他一些混淆方法,使入侵者很难撬入您的脚本或揭露要隐藏的秘密。在此站点上,您可以加密Shell脚本和命令行perl,python,ruby脚本。我也认为PHP。
第三选择
使用诸如shc之类的工具。看起来自2012年以来就没有更新过。但是我过去曾使用过它。如果操作系统与您用来编译脚本的操作系统不同,则必须为要在其上使用脚本的每个操作系统编译脚本。
摘要:
如果隐藏代码对您来说非常重要,那么仅依靠权限和所有权就可以为您提供帮助,因为拥有root的任何人都可以使用它。那只是事实。如果您确实想防止任何人未经授权查看您的代码,您可以做的就是围绕openssl命令编写脚本。做到这一点,以便在脚本运行之前,它会提示您输入密码,并且在给出密码之后,它将在不将其写入临时文件的情况下运行该脚本。如果听起来工作量太大,那么选项2和3应该足以满足您的目的。