Может ли скрипт быть исполняемым, но не читаемым?

65

Можно ли выполнить скрипт, если нет разрешения на его чтение? В режиме root я создал скрипт и хочу, чтобы другой пользователь выполнил этот скрипт, но не прочитал его. Я сделал, chmodчтобы запретить чтение и запись, но разрешить выполнение, однако в пользовательском режиме я увидел сообщение, которое говорит: разрешение отказано.

как он
источник

Ответы:

68

Вопрос заключается в том , что сценарий не то , что работает, но переводчик ( bash, perl, pythonи т.д.). И переводчик должен прочитать сценарий. Это отличается от «обычной» программы, например ls, в том, что программа загружается непосредственно в ядро, как это делает интерпретатор. Поскольку само ядро ​​читает программный файл, ему не нужно беспокоиться о доступе для чтения. Интерпретатор должен прочитать файл сценария, так как обычный файл должен быть прочитан.

Arcege
источник
2
Да, но в его случае есть решение?
Оливье Понс,
13
Одной из возможностей будет иметь простую C-программу, которая встраивает скрипт и явно вызывает интерпретатор. Программа AC не должна иметь разрешения на чтение для выполнения.
Arcege
1
Строго говоря, ядро не различает в этом случае , и это будет на самом деле запустить оболочку (так же, как если исполняемый файл был бинарным). Однако сама оболочка сразу же аварийно завершает работу, поскольку не может прочитать входной файл (содержимое файла сценария).
Юзеф
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.

kwarrick
источник
Очень интересно (hktrace).
fthinker
1
Можно ли конвертировать сценарий оболочки в двоичный формат?
Ашим
4
На самом деле, вы можете предотвратить это, я думаю. Текущие версии ядра Linux устанавливают процесс как не подлежащий дампированию, что означает, что ни один нормальный пользователь не сможет больше его отслеживать, если пользователю не разрешено читать двоичный файл.
thejh
6

Это невозможно, по крайней мере, в Linux (другие Unices могут разрешить это); Подумайте об этом, когда вы запускаете скрипт, оболочка должна прочитать его, чтобы знать, что делать.

Ренан
источник
3
Это конечно возможно; OpenBSD позволяет выполнять любой скрипт без разрешения на чтение. Под капотом это делается путем создания дубликата файлового дескриптора для использования интерпретатором.
Эрадман
@eradman Я поместил это (вместе с примером, объяснением и некоторыми моими замечаниями) в ответ .
Мосви
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, изменить его на принадлежащий root и дать ему разрешение setuid. (Наряду с сопутствующим незаписываемым статусом всех остальных.)

Поскольку функция myscript-nonroot доступна для чтения всем, ее можно прочитать и выполнить, и к тому времени, когда вы получите две строки, где вы фактически выполняете свой скрипт ( bash myscript), она запускается от имени пользователя root (или того, кого вы хотите, точного пользователя). не имеет значения, если файл-оболочка принадлежит одному и тому же пользователю.)

quodlibetor
источник
Что значит 4755? Я новичок в этом, поэтому я хотел бы знать, что это значит. Я понимаю 755 часть. Спасибо
Kevdog777
2
то 4устанавливает УИП бит. См. Раздел «Режимы» на странице руководства chmod на manpagez .
quodlibetor
Хорошо, я все еще не совсем понимаю, но мне потребовалось некоторое время, чтобы понять 755немного.
Kevdog777
да, на самом деле chmod 755это то же самое, что 0775 восьмеричный. вокруг этого много путаницы .. На этой странице ( manpagez.com/man/1/chmod ) есть ужасная и ненужная горизонтальная прокрутка, которую я не могу понять ...
erm3nda
2

В этой ситуации я использовал sudo с параметром NOPASSWD, чтобы пользователи могли запускать скрипт, не имея возможности его прочитать.

user33577
источник
2

В предыдущих заявлениях есть половина правды. Вы можете настроить скрипт так, чтобы он не читался пользователем, но оставался исполняемым. Процесс немного затягивается, но его можно выполнить, сделав исключение в / etc / sudoer, чтобы пользователь мог временно запускать скрипт от своего имени без запроса пароля. Этот метод: - обходит патч setuid для других дистрибутивов. - позволяет временно предоставлять повышенные разрешения для конкретного сценария, не предоставляя пользователю права sudo на все.

Следуйте инструкциям на этот пост: разрешение на выполнение файла

Сантана
источник
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(или чего бы то ни было открытого сценария для скрипта) интерпретатору. Этот трюк не сработает в Linux, где /dev/fd/Nиспользуются не специальные символьные устройства, которые возвращают dup(2)fd при открытии, а «магические» символические ссылки на оригинальный файл / dentry, которые открывают файл с нуля [1]. Это может быть реализовано в Free / NetBSD или Solaris ...

Но дело не в том, что

По сути, предоставление xразрешения (execute) означает также предоставление разрешения r(read) для любого файла, который имеет 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хак ed, который переопределяет read(2)функцию.

И нет, установка 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.

mosvy
источник
-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 ваш пароль> yourscript.enc

Расшифровка с помощью openssl:

кошка yourscript.enc | openssl aes-128-cbc -a -d -salt -k ваш пароль> yourscript.dec

yourscript.dec будет таким же, как ваш оригинальный скрипт yourscript.sh

Второй вариант

Используйте сайт, такой как www.Enscryption.com, чтобы автоматически зашифровать ваш скрипт и сделать зашифрованную версию скрипта исполняемой. Этот сайт использует как возможности шифрования openssl, так и некоторые другие методы обфускации, чтобы злоумышленникам было довольно трудно заглянуть в ваш сценарий или раскрыть секреты, которые вы хотите скрыть. С помощью этого сайта вы можете зашифровать сценарии оболочки и сценарии командной строки perl, python, ruby. Я думаю, что php также.

Третий вариант

Используйте такой инструмент, как shc . Похоже, он не обновлялся с 2012 года, но я использовал его в прошлом. Вы должны скомпилировать свой скрипт для каждой ОС, в которой вы хотите его использовать, если ОС отличается от той, которую вы использовали для его компиляции.

Резюме:

Если для вас очень важно скрыть свой код, то вам могут помочь только полномочия и права собственности, поскольку любой, кто имеет права root, сможет получить к нему доступ. Это просто факт. Если вы действительно хотите предотвратить несанкционированный просмотр вашего кода кем-либо, вы можете написать скрипт вокруг команды openssl. Сделайте так, чтобы перед запуском скрипта он запрашивал пароль И после того, как пароль задан, он запускает скрипт, не записывая его во временный файл. Если это звучит как слишком много работы, то вариантов 2 и 3 должно быть достаточно для ваших целей.

AncientMinds
источник
Ссылка "shc" также указывает на предыдущую страницу. Вы случайно не связаны с этой страницей / услугой?
phk
3
Если вы зашифруете свой скрипт, он не сможет работать без ключа. Если вы отправили ключ пользователю для его запуска, сможете увидеть его содержимое. Это так глупо ...
erm3nda