Un script peut-il être exécutable mais non lisible?

65

Est-il possible d'exécuter un script s'il n'y a pas d'autorisation de le lire? En mode racine, j'ai créé un script et je veux que l'autre utilisateur exécute ce script mais ne le lise pas. J'ai fait chmodinterdire la lecture et l'écriture, mais autoriser l'exécution, mais en mode utilisateur, j'ai vu le message qui dit: permission refusée.

comme lui
la source

Réponses:

68

Le problème est que le script n'est pas ce qui est en cours d' exécution, mais l'interprète ( bash, perl, python, etc.). Et l'interprète doit lire le script. C'est différent d'un programme "normal", comme lsdans le sens où le programme est chargé directement dans le noyau, comme le ferait l'interpréteur. Puisque le noyau lui-même lit un fichier programme, il n’a pas à se préoccuper de l’accès en lecture. L'interprète doit lire le fichier de script, car un fichier normal doit être lu.

Arcege
la source
2
Oui mais dans son cas, existe-t-il une solution?
Olivier Pons
13
Une possibilité serait d'avoir un simple programme en C qui incorpore le script et appelle explicitement l'interpréteur. Le programme AC n'a pas besoin d'avoir des autorisations de lecture pour s'exécuter.
Arcege
1
À proprement parler, le noyau ne fait pas de distinction dans ce cas et il exécutera le shell (de la même manière que si le fichier exécutable était un fichier binaire). Cependant, le shell lui-même plantera immédiatement car il ne pourra pas lire le fichier d'entrée (le contenu du fichier de script).
Jozef
34

Ceci est possible uniquement pour les fichiers binaires.

$ chown foo:foo bar
$ chmod 701 bar

En tant qu'utilisateur non privilégié:

$ ls -lha bar
-rwx-----x 1 foo foo 7.0K 2012-03-15 03:06 bar

$ cat bar
cat: bar: Permission denied

$ ./bar
baz

Maintenant, voici le kicker. Bien que le fichier soit illisible par des moyens conventionnels, vous ne pouvez pas empêcher la lecture du fichier. C'est en fait un défi sur http://smashthestack.org/ (niveau 13). Il existe un utilitaire bien connu appelé hktracevous permettant de lire le fichier avec ptrace.

Kwarrick
la source
Très intéressant (hktrace).
fthinker
1
est-il possible de convertir un script shell au format binaire?
ashim
4
En fait, vous pouvez l’empêcher, je pense. Les versions actuelles du noyau Linux définissent le processus comme non-dumpable, ce qui signifie qu'aucun utilisateur normal ne peut plus le ptracer, si l'utilisateur n'est pas autorisé à lire le fichier binaire.
jeudi
6

Ce n'est pas possible, du moins sur Linux (d'autres Unices pourraient le permettre); Pensez-y, lorsque vous exécutez le script, le shell doit le lire pour savoir quoi faire.

Renan
la source
3
C'est certainement possible. OpenBSD permet à tout script d'être exécuté sans autorisation de lecture. Pour ce faire, il crée un duplicata de descripteur de fichier que l'interpréteur utilisera.
eradman
@eradman j'ai mis cela (avec un exemple, une explication et quelques remarques de ma part) dans une réponse .
Mosvy
3

Je pense que vous pouvez le faire avec setuid.

Sauf que vous ne pouvez pas, car la plupart des distributions (apparemment) ont été setuiddésactivées, car c'est un trou de sécurité énorme. C'est désactivé sur le mien, donc je ne sais pas vraiment si cette réponse va marcher, je la poste quand même parce que je pense que ça devrait .

Quoi qu'il en soit, si je voulais faire ce que vous vouliez faire - et j'avais une distribution avec setuidenabled pour les scripts - je ferais quelque chose comme:

$ 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!

Ce qui veut dire que j'écrirais un autre script dont le seul but est d'appeler le script root en lecture seule, de le changer pour qu'il appartienne à root et de lui donner l'autorisation setuid. (Avec le statut non-inscriptible de tous les autres.)

Comme la fonction myscript-nonroot est lisible par tout le monde, elle peut être lue et exécutée. Au moment où vous obtenez deux fois la ligne où vous exécutez votre script ( bash myscript), il est exécuté en tant que root (ou celui que vous voulez, l'utilisateur exact). Peu importe, tant que le fichier wrapper appartient au même utilisateur.)

quodlibetor
la source
Que signifie 4755? Je suis nouvelle dans ce domaine, alors j'aimerais savoir ce que cela signifie. Je comprends la partie 755. Merci
Kevdog777
2
le 4définit le bit setuid . Voir la section Modes de la page de manuel chmod sur manpagez .
quodlibetor
Ok, je ne comprends toujours pas très bien, mais il m'a fallu un certain temps pour comprendre 755.
Kevdog777
oui, chmod 755est en fait identique à 0775 octal. Il y a beaucoup de confusion autour de cela .. Cette page ( manpagez.com/man/1/chmod ) a un parchemin horizontal lugubre et sans bases que je ne comprends pas ...
erm3nda
2

Sur cette situation, j'ai utilisé sudo avec une option NOPASSWD afin que les utilisateurs puissent exécuter le script sans pouvoir le lire.

utilisateur33577
la source
2

Il y a une demi-vérité dans les déclarations précédentes. Vous pouvez configurer un script pour qu'il ne soit pas lisible par l'utilisateur, mais toujours exécutable. Le processus est un peu long, mais c'est faisable en faisant une exception dans / etc / sudoer afin que l'utilisateur puisse exécuter le script temporairement en tant que vous-même sans être invité à entrer un mot de passe. Cette méthode: - contourne le patch setuid pour d’autres distributions. - vous permet de donner temporairement des autorisations élevées pour un script spécifique sans donner à l'utilisateur des droits sudo sur tout.

Suivez les instructions sur ce message: autorisation de fichier exécuter uniquement

Santana
la source
0

Cela fonctionne sur OpenBSD

Comme déjà mentionné dans un commentaire de @eradman, cela est possible sur OpenBSD.

En tant que root:

hzy# cat <<'EOT' >/tmp/foo; chmod 001 /tmp/foo
#! /bin/sh
: this is secret
echo done
EOT

En tant qu'utilisateur régulier:

hzy$ cat /tmp/foo
cat: /tmp/foo: Permission denied
hzy$ /tmp/foo
done

Cela fonctionne en passant /dev/fd/3(ou quel que soit le fd ouvert au script) à l’interprète. Cette astuce ne fonctionnerait pas sous Linux, où il /dev/fd/Nn’ya pas de périphériques à caractères spéciaux qui renvoient un dup(2)fd lorsqu’ils sont ouverts, mais des liens symboliques "magiques" vers le fichier / dentry original, qui ouvre le fichier à partir de zéro [1]. Cela pourrait être implémenté dans Free / NetBSD ou Solaris ...

Mais ce n'est pas ce que ça craint d'être

Donner l’ xautorisation (exécuter), c’est aussi donner l’ rautorisation (lire) sur tout fichier qui a un 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

ktracen'est pas le seul moyen; si l'interpréteur est un exécutable lié dynamiquement comme perlou python, un LD_PRELOADhack ed qui remplace la read(2)fonction pourrait être utilisé à la place.

Et non, le rendre setuid n'empêchera pas un utilisateur régulier de voir son contenu; elle pourrait simplement l'exécuter sous ptrace(2), ce qui ferait ignorer les bits setuid:

En tant que root:

hzyS# cat <<'EOT' >/tmp/bar; chmod 4001 /tmp/bar
#! /bin/sh
: this is secret
id
EOT

En tant qu'utilisateur régulier:

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
       "

(désolé si ce n'est pas la façon la plus directe de le démontrer)

[1] ceci pourrait être émulé sur Linux en utilisant binfmt_misc, mais l'interpréteur devra être modifié ou un wrapper devra être utilisé; Voir la dernière partie de cette réponse pour un exemple délibérément ridiculement incertain.

[2] ou en général, tout fichier qui ne fera pas execve()revenir ENOEXEC.

Mosvy
la source
-2

Oui, si vous êtes utilisateur root, vous pouvez exécuter le fichier sans autorisation de lecture.

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

Mais si vous vous connectez avec un autre utilisateur, vous ne pouvez pas exécuter ce fichier.

$ ./test
-bash: ./test: Permission denied
gaurav goyal
la source
3
Cela ne répond pas vraiment à la question, car root peut toujours lire le fichier même sans autorisation.
Wjandrea
-5

Pour rendre vos scripts illisibles tout en étant exécutables, vous avez 3 options principales:

Première option

Utilisez la commande openssl pour le chiffrer manuellement. Et à l'avenir, lorsque vous souhaitez exécuter le script, vous devrez réexécuter OpenSL manuellement et fournir le mot de passe à déchiffrer.

Cryptage avec openssl:

chat yourscript.sh | openssl aes-128-cbc -a -salt -k votre-mot-de-passe> yourscript.enc

Décryptage avec openssl:

chat yourscript.enc | openssl aes-128-cbc -a -d -salt -k votre mot de passe> yourscript.dec

yourscript.dec sera le même que votre script original yourscript.sh

Deuxième option

Utilisez un site tel que www.Enscryption.com pour chiffrer automatiquement votre script et rendre la version chiffrée du script exécutable. Ce site utilise à la fois les capacités de cryptage d’openssl et certaines autres méthodes d’obscurcissement pour empêcher les intrus de s’emparer de votre script ou de dévoiler les secrets que vous souhaitez cacher. Avec ce site, vous pouvez chiffrer des scripts shell et des scripts perl, python et ruby ​​en ligne de commande. Je pense aussi php.

Troisième option

Utilisez un outil tel que shc . On dirait qu'il n'a pas été mis à jour depuis 2012. Mais je l'ai utilisé dans le passé. Vous devez compiler votre script pour chaque système d'exploitation sur lequel vous souhaitez l'utiliser, si le système d'exploitation est différent de celui que vous avez utilisé pour le compiler.

Sommaire:

Si cacher votre code est d'une grande importance pour vous, le fait de ne compter que sur les autorisations et la propriété va vous aider, car tout utilisateur root peut y accéder. C'est juste un fait. Ce que vous pouvez faire, si vous voulez vraiment empêcher tout le monde de voir votre code sans autorisation, est d'écrire un script autour de la commande openssl. Faites en sorte que, avant que le script ne s'exécute, un mot de passe soit demandé et une fois le mot de passe donné, il sera exécuté sans script, dans un fichier temporaire. Si cela vous semble trop de travail, les options 2 et 3 devraient suffire à vos besoins.

AncientMinds
la source
Le lien "shc" pointe également vers la page précédente. Êtes-vous par hasard affilié à cette page / service?
phk
3
Si vous chiffrez votre script, il ne pourra pas s'exécuter sans clé. Si vous avez envoyé la clé à un utilisateur pour l’exécuter, vous pourrez voir son contenu. Cette anwers est si stupide ...
erm3nda