Kann ein Skript ausführbar, aber nicht lesbar sein?

65

Ist es möglich, ein Skript auszuführen, wenn keine Berechtigung zum Lesen vorhanden ist? Im Root-Modus habe ich ein Skript erstellt und möchte, dass der andere Benutzer dieses Skript ausführt, aber nicht liest. Ich habe chmoddas Lesen und Schreiben verboten, aber die Ausführung zugelassen. Im Benutzermodus wurde jedoch die Meldung angezeigt, dass die Berechtigung verweigert wurde.

wie er
quelle

Antworten:

68

Das Problem ist , dass das Skript ist nicht das, was läuft, aber der Dolmetscher ( bash, perl, python, etc.). Und der Dolmetscher muss das Skript lesen. Dies unterscheidet sich von einem "normalen" Programm dadurch, lsdass das Programm wie der Interpreter direkt in den Kernel geladen wird. Da der Kernel selbst Programmdateien liest, muss er sich keine Gedanken über den Lesezugriff machen. Der Interpreter muss die Skriptdatei lesen, so wie eine normale Datei gelesen werden müsste.

Arcege
quelle
2
Ja, aber in seinem Fall gibt es eine Lösung?
Olivier Pons
13
Eine Möglichkeit wäre ein einfaches C-Programm, das das Skript einbettet und den Interpreter explizit aufruft. Das AC-Programm muss keine Leseberechtigung haben, um ausgeführt zu werden.
Arcege
1
Streng genommen ist der Kern in diesem Fall nicht diskriminieren und es wird in der Tat läuft die Schal (die gleiche Art und Weise , als ob die ausführbare Datei ein binäres war). Die Shell selbst stürzt jedoch sofort ab, da sie die Eingabedatei (den Inhalt der Skriptdatei) nicht lesen kann.
Jozef
34

Dies ist nur für Binärdateien möglich.

$ chown foo:foo bar
$ chmod 701 bar

Als nicht privilegierter Benutzer:

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

$ cat bar
cat: bar: Permission denied

$ ./bar
baz

Hier ist der Kicker. Obwohl die Datei auf herkömmliche Weise nicht lesbar ist, können Sie das Lesen der Datei nicht verhindern. Dies ist tatsächlich eine Herausforderung auf http://smashthestack.org/ (Level 13). Es gibt ein bekanntes Hilfsprogramm hktrace, mit dem Sie die Datei lesen können ptrace.

kwarrick
quelle
Sehr interessant (hktrace).
Fthinker
1
Kann ich ein Shell-Skript in ein Binärformat konvertieren?
Ashim
4
Eigentlich kann man das verhindern, denke ich. Aktuelle Linux-Kernel-Versionen setzen den Prozess auf nicht abspeicherbar, was bedeutet, dass kein normaler Benutzer mehr darauf zugreifen kann, wenn der Benutzer die Binärdatei nicht lesen darf.
Thejh
6

Dies ist zumindest unter Linux nicht möglich (andere Unices könnten dies zulassen). Denken Sie darüber nach, wenn Sie das Skript ausführen, muss die Shell es lesen, um zu wissen, was zu tun ist.

Renan
quelle
3
Es ist sicherlich möglich; OpenBSD erlaubt es, jedes Skript ohne Leseberechtigung auszuführen. Unter der Haube wird dazu ein doppelter Dateideskriptor erstellt, den der Interpreter verwenden kann.
Eradman
@eradman Ich habe das (zusammen mit einem Beispiel, einer Erklärung und einigen meiner Bemerkungen) in eine Antwort geschrieben .
Mosvy
3

Du kannst das, denke ich, mit machen setuid.

Abgesehen davon, dass dies nicht möglich ist, da die meisten Distributionen (anscheinend) setuiddeaktiviert wurden, da dies eine massive Sicherheitslücke darstellt. Es ist bei mir deaktiviert, daher weiß ich nicht, ob diese Antwort funktioniert. Ich poste sie trotzdem, weil ich denke, dass es das sollte .

Wie auch immer, wenn ich tun wollte, was Sie tun wollten - und ich hatte eine Distribution mit setuidaktivierten Skripten - würde ich Folgendes tun:

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

Das heißt, ich würde ein anderes Skript schreiben, dessen einziger Zweck darin besteht, das schreibgeschützte Root-Skript aufzurufen, es so zu ändern, dass es root gehört, und ihm die Berechtigung setuid zu erteilen. (Zusammen mit dem Status der nicht beschreibbaren Begleitperson durch alle anderen.)

Da die myscript-nonroot-Funktion für alle lesbar ist, kann sie gelesen und ausgeführt werden. Sobald Sie zwei Zeilen erhalten bash myscript, wird sie als root ausgeführt (oder wer auch immer Sie möchten, der genaue Benutzer) spielt keine Rolle, solange sich die Wrapper-Datei im Besitz desselben Benutzers befindet.)

quodlibetor
quelle
Was bedeutet 4755? Ich bin neu in diesem Bereich und würde gerne wissen, was es bedeutet. Ich verstehe den 755 Teil. Danke
Kevdog777
2
das 4setzt das setuid- Bit. Weitere Informationen finden Sie im Abschnitt Modi in der Manpage zu chmod auf manpagez .
Quodlibetor
Ok, ich verstehe immer noch nicht ganz, aber es hat eine Weile gedauert, bis ich das 755Stück verstanden habe.
Kevdog777
yep, ist eigentlich chmod 755gleich wie 0775 oktal. Es gibt eine Menge Verwirrung um das. Diese Seite ( manpagez.com/man/1/chmod ) hat eine schreckliche und unbrauchbare horizontale Schriftrolle, die ich nicht verstehen kann ...
erm3nda
2

Es gibt eine halbe Wahrheit zu den vorherigen Aussagen. Sie können ein Skript so einrichten, dass es für den Benutzer nicht lesbar, aber dennoch ausführbar ist. Der Prozess ist etwas langwierig, kann jedoch durch eine Ausnahme in / etc / sudoer ausgeführt werden, sodass der Benutzer das Skript vorübergehend als Sie selbst ausführen kann, ohne zur Eingabe eines Kennworts aufgefordert zu werden. Diese Methode: - umgeht den Setuid-Patch für andere Distributionen. - Ermöglicht es Ihnen, vorübergehend erhöhte Berechtigungen für ein bestimmtes Skript zu erteilen, ohne dem Benutzer Sudo-Rechte für alles zu erteilen.

Befolgen Sie die Anweisungen in diesem Beitrag: Nur Dateiberechtigung ausführen

Santana
quelle
1

In dieser Situation habe ich sudo mit einer NOPASSWD-Option verwendet, damit die Benutzer das Skript ausführen können, ohne es lesen zu können.

user33577
quelle
0

Es funktioniert unter OpenBSD

Wie bereits in einem Kommentar von @eradman erwähnt, ist dies unter OpenBSD möglich.

Als root:

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

Als regulärer Benutzer:

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

Das funktioniert, indem man /dev/fd/3dem Interpreter (oder was auch immer das offene fd zum Skript ist) übergibt . Dieser Trick würde unter Linux nicht funktionieren, wo /dev/fd/Nes keine Sonderzeichengeräte gibt, die dup(2)beim Öffnen einen der fd zurückgeben, sondern "magische" Symlinks zur Originaldatei / zum Originaleintrag, die die Datei von Grund auf öffnen [1]. Es könnte in Free / NetBSD oder Solaris implementiert werden ...

Aber es ist nicht das, was es verspricht

Grundsätzlich bedeutet das Erteilen der x(Ausführungs-) Erlaubnis auch das Erteilen der r(Lese-) Erlaubnis für jede Datei, die einen Shebang hat:

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

ktraceist nicht der einzige Weg; Wenn der Interpreter wie perloder dynamisch mit einer ausführbaren Datei verknüpft ist , kann stattdessen pythonein LD_PRELOADed-Hack verwendet werden, der die read(2)Funktion überschreibt .

Und nein, wenn Sie es setuid machen, wird ein normaler Benutzer nicht daran gehindert, seinen Inhalt zu sehen. sie könnte es einfach unterlaufen lassen ptrace(2), wodurch die setuid-Bits ignoriert werden:

Als root:

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

Als regulärer Benutzer:

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
       "

(Entschuldigung, wenn dies nicht der einfachste Weg ist, es zu demonstrieren)

[1] Dies könnte unter Linux mithilfe von emuliert werden binfmt_misc, der Interpreter muss jedoch geändert oder ein Wrapper muss verwendet werden. Im letzten Teil dieser Antwort finden Sie ein Beispiel, das absichtlich lächerlich unsicher gemacht wurde.

[2] oder generell jede Datei, die nicht execve()zur Rückkehr führt ENOEXEC.

Mosvy
quelle
-2

Ja, wenn Sie Rootbenutzer sind, können Sie Dateien ohne Leseberechtigung ausführen

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

Wenn Sie sich jedoch mit einem anderen Benutzer anmelden, können Sie diese Datei nicht ausführen

$ ./test
-bash: ./test: Permission denied
gaurav goyal
quelle
3
Dies beantwortet die Frage nicht wirklich, da root die Datei auch ohne Erlaubnis lesen kann.
wjandrea
-5

Um Ihre Skripte unlesbar und dennoch ausführbar zu machen, haben Sie drei Hauptoptionen:

Erste Wahl

Verwenden Sie den Befehl openssl, um ihn manuell zu verschlüsseln. Wenn Sie das Skript in Zukunft ausführen möchten, müssen Sie openssl erneut manuell ausführen und das zu entschlüsselnde Kennwort eingeben.

Verschlüsselung mit openssl:

Katze yourscript.sh | openssl aes-128-cbc -a -salt -k deinpasswort> yourscript.enc

Entschlüsselung mit openssl:

cat yourscript.enc | openssl aes-128-cbc -a -d -salt -k deinpasswort> yourscript.dec

yourscript.dec entspricht dem ursprünglichen Skript yourscript.sh

Zweite Option

Verwenden Sie eine Site wie www.Enscryption.com , um Ihr Skript automatisch zu verschlüsseln und die verschlüsselte Version des Skripts ausführbar zu machen. Diese Site verwendet sowohl die Verschlüsselungsfunktionen von openssl als auch einige andere Verschleierungsmethoden, um es Eindringlingen recht schwer zu machen, in Ihr Skript einzudringen oder Geheimnisse zu enthüllen, die Sie verbergen möchten. Mit dieser Site können Sie Shell-Skripte und Befehlszeilen-Perl-, Python- und Ruby-Skripte verschlüsseln. Ich denke auch php.

Dritte Option

Verwenden Sie ein Werkzeug wie shc . Sieht so aus, als ob es seit 2012 nicht mehr aktualisiert wurde. Ich habe es jedoch in der Vergangenheit verwendet. Sie müssen Ihr Skript für jedes Betriebssystem kompilieren, auf dem Sie es verwenden möchten, wenn sich das Betriebssystem von dem unterscheidet, mit dem Sie es kompiliert haben.

Zusammenfassung:

Wenn es für Sie von großer Bedeutung ist, Ihren Code zu verbergen, können Sie sich nur auf Berechtigungen und Eigentumsrechte verlassen, da jeder mit Root-Rechten darauf zugreifen kann. Das ist nur eine Tatsache. Was Sie tun können, um das unbefugte Anzeigen Ihres Codes durch irgendjemanden zu verhindern, ist, ein Skript um den Befehl openssl zu schreiben. Stellen Sie sicher, dass Sie vor der Ausführung des Skripts zur Eingabe eines Kennworts aufgefordert werden, und führen Sie das Skript nach der Eingabe des Kennworts aus, ohne es in eine temporäre Datei zu schreiben. Wenn dies nach zu viel Arbeit klingt, sollten die Optionen 2 und 3 für Ihre Zwecke ausreichen.

AncientMinds
quelle
Der "shc" -Link verweist auch auf die eine Seite von zuvor. Sind Sie zufällig mit dieser Seite / diesem Service verbunden?
Phk
3
Wenn Sie Ihr Skript verschlüsseln, kann es ohne Schlüssel nicht ausgeführt werden. Wenn Sie den Schlüssel an einen Benutzer gesendet haben, um ihn auszuführen, wird dessen Inhalt angezeigt. Diese Antwort ist so dumm ...
erm3nda