脚本可以执行但不可读吗?


Answers:


67

问题是,剧本是不是正在运行,但解释(bashperlpython等)。并且解释器需要阅读脚本。这与“常规”程序(如)不同ls,因为该程序像解释程序那样直接加载到内核中。由于内核本身正在读取程序文件,因此无需担心读取访问。解释器需要读取脚本文件,因为需要读取普通文件。


2
是的,但是在他的情况下有解决方案吗?
奥利维尔·庞斯

13
一种可能性是拥有一个简单的C程序,该程序嵌入脚本并显式调用解释器。AC程序无需具有读取权限即可执行。
Arcege 2012年

1
严格来说,在这种情况下,内核没有区别,实际上它将运行外壳程序(就像可执行文件是二进制文件一样)。但是,shell本身将立即崩溃,因为它无法读取输入文件(脚本文件的内容)。
约瑟夫

34

这仅适用于二进制文件。

$ 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


非常有趣(hktrace)。
fthinker 2012年

1
是否可以将Shell脚本转换为二进制格式?
ashim 2012年

4
我认为,实际上,您可以阻止它。当前的Linux内核版本将进程设置为不可转储,这意味着如果不允许该用户读取二进制文件,则没有普通用户可以再跟踪它。
thejh 2014年

6

这是不可能的,至少在Linux上(其他Unices可能允许);想想看,当您运行脚本时,shell需要阅读它才能知道该怎么做。


3
当然有可能;OpenBSD允许在没有读取许可的情况下执行任何脚本。在后台,它通过创建供解释器使用的重复文件描述符来做到这一点。
eradman

@eradman我已将其(连同示例,解释和我的一些评论)放入了答案中
mosvy

3

我认为,您可以使用进行此操作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身份运行(或者您想要的其他人,确切的用户)没关系,只要包装文件由同一用户拥有。)


4755是什么意思?我是新手,所以我想知道它的意思。我了解755部分。谢谢
Kevdog777

2
4的setuid位。请参见manpagez上chmod手册页中的“模式”部分。
quodlibetor 2012年

好的,我仍然不太了解,但是花了我一段时间才了解了755一点。
Kevdog777

是的,实际上chmod 755与0775八进制相同。周围有很多混乱。.(manpagez.com/man/1/chmod)此页面有一个我无法理解的可怕而无限制的水平滚动……
erm3nda

2

前面的陈述有一半的道理。您可以设置一个脚本,使该脚本不被用户读取,但仍可执行。这个过程有些麻烦,但是可以通过在/ etc / sudoer中创建一个异常来实现,以便用户可以临时以自己的身份运行脚本,而无需提示输入密码。此方法:-避开其他发行版的setuid补丁。-允许您临时为特定脚本授予提升的权限,而无需授予用户对所有内容的sudo权限。

请遵循此信息上的说明: 仅执行文件权限


1

在这种情况下,我将sudo与NOPASSWD选项一起使用,以便用户可以运行脚本而无法读取脚本。


0

它可以在OpenBSD上运行

正如@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或)pythonLD_PRELOADread(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


-2

是的,如果您是root用户,则可以在没有读取权限的情况下执行文件

# echo "echo hello" > test
# chmod 100 test
# ll test
---x------ 1 root root 10 Nov 29 12:13 test
# ./test
hello

但是,如果您以任何其他用户身份登录,则无法执行此文件

$ ./test
-bash: ./test: Permission denied

3
这并不能真正回答问题,因为即使未经许可,root用户仍然可以读取文件。
wjandrea

-5

为了使脚本不可读但可执行,您可以使用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应该足以满足您的目的。


“ shc”链接也指向之前的一页。您是否偶然与此页面/服务相关联?
phk

3
如果您对脚本进行加密,那么如果没有密钥,它将无法运行。如果您将密钥发送给用户来运行它,将能够看到其内容。这让我们感到非常愚蠢……
erm3nda
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.