¿Puede un script ser ejecutable pero no legible?

65

¿Es posible ejecutar un script si no hay permiso para leerlo? En modo raíz, hice un script y quiero que el otro usuario ejecute este script pero no lo lea. Hice chmodpara prohibir la lectura y escritura, pero permitir la ejecución, sin embargo, en el modo de usuario, vi el mensaje que dice: permiso denegado.

como él
fuente
Relacionado: Ejecute scripts sin descifrarlos .
Scott

Respuestas:

68

La cuestión es que el guión no es lo que se está ejecutando, pero el intérprete ( bash, perl, python, etc.). Y el intérprete necesita leer el guión. Esto es diferente de un programa "regular", ya lsque el programa se carga directamente en el núcleo, como lo haría el intérprete. Como el núcleo mismo está leyendo el archivo del programa, no necesita preocuparse por el acceso de lectura. El intérprete necesita leer el archivo de script, ya que un archivo normal necesitaría ser leído.

Arcege
fuente
2
Sí, pero en su caso ¿hay alguna solución?
Olivier Pons
13
Una posibilidad sería tener un programa C simple que incorpore el script y llame al intérprete explícitamente. El programa de CA no necesita tener permisos de lectura para ejecutarse.
Arcege
1
Estrictamente hablando, el núcleo no discrimina en este caso y , de hecho, ejecutará el shell (de la misma manera que si el archivo ejecutable fuera un binario). Sin embargo, el propio shell se bloqueará inmediatamente porque no puede leer el archivo de entrada (el contenido del archivo de script).
Jozef
34

Esto es posible solo para binarios.

$ chown foo:foo bar
$ chmod 701 bar

Como usuario no privilegiado:

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

$ cat bar
cat: bar: Permission denied

$ ./bar
baz

Ahora, aquí está el pateador. Si bien el archivo es ilegible por medios convencionales, en realidad no puede evitar leer el archivo. Esto es realmente un desafío en http://smashthestack.org/ (nivel 13). Existe una utilidad conocida hktraceque le permite leer el archivo usando ptrace.

kwarrick
fuente
Muy interesante (hktrace).
fthinker
1
¿Es posible convertir el script de shell a formato binario?
ashim
44
En realidad, puedes evitarlo, creo. Las versiones actuales del kernel de Linux configuran el proceso como no volátil, lo que significa que ningún usuario normal puede seguirlo, si el usuario no tiene permiso para leer el binario.
thejh
6

Esto no es posible, al menos en Linux (otros Unices podrían permitirlo); piénselo, cuando ejecuta el script, el shell debe leerlo para saber qué hacer.

Renan
fuente
3
Ciertamente es posible; OpenBSD permite ejecutar cualquier script sin permiso de lectura. Debajo del capó lo hace creando un descriptor de archivo duplicado para que el intérprete lo use.
eradman el
@eradman He puesto eso (junto con un ejemplo, una explicación y algunos comentarios míos) en una respuesta .
mosvy
3

Puedes, creo, hacer esto con setuid.

Excepto que no puedes porque la mayoría de las distribuciones (aparentemente) se han setuiddeshabilitado porque es un agujero de seguridad masivo. Está deshabilitado en el mío, por lo que no sé si esta respuesta funcionará, de todas formas la publicaré porque creo que debería .

De todos modos, si quisiera hacer lo que tú quisieras, y tuviera una distribución setuidhabilitada para scripts, haría algo como:

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

Es decir, escribiría otro script cuyo único propósito es llamar al script de solo lectura de root, cambiarlo para que sea propiedad de root y darle el permiso setuid. (Junto con el estado de asistente no escribible por todos los demás).

Dado que la función myscript-nonroot es legible por todos, puede leerse y ejecutarse, y para el momento en que obtiene dos la línea donde realmente ejecuta su script ( bash myscript) se está ejecutando como root (o quien quiera, el usuario exacto no importa, siempre que el archivo contenedor sea propiedad del mismo usuario).

quodlibetor
fuente
¿Qué significa 4755? Soy nuevo en esto, así que me gustaría saber qué significa. Entiendo la parte 755. Gracias
Kevdog777
2
los 4conjuntos del setuid bits. Consulte la sección Modos en la página de manual de chmod en manpagez .
quodlibetor
Ok, todavía no lo entiendo, pero me tomó un tiempo entenderlo 755.
Kevdog777
Sí, en realidad chmod 755es lo mismo que 0775 octal. hay una gran confusión en torno a ese .. Esta página ( manpagez.com/man/1/chmod ) tiene un desplazamiento horizontal y terrible unneded que no puedo entender ...
erm3nda
2

En esta situación, utilicé sudo con una opción NOPASSWD para que los usuarios puedan ejecutar el script sin poder leerlo.

usuario33577
fuente
2

Hay una verdad a medias en las declaraciones anteriores. Puede configurar un script para que el usuario no pueda leerlo, pero aún sea ejecutable. El proceso es un poco prolongado, pero se puede hacer haciendo una excepción en / etc / sudoer para que el usuario pueda ejecutar el script como usted temporalmente sin que se le solicite una contraseña. Este método: - evita el parche setuid para otras distribuciones. - le permite otorgar permisos elevados temporalmente para un script específico sin otorgarle al usuario derechos de sudo sobre todo.

Siga las instrucciones de esta publicación: solo se ejecuta permiso de archivo

santana
fuente
0

Funciona en OpenBSD.

Como ya se mencionó en un comentario de @eradman, esto es posible en OpenBSD.

Como root:

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

Como usuario habitual:

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

Eso funciona al pasar /dev/fd/3(o lo que sea el fd abierto al script) al intérprete. Ese truco no funcionaría en Linux, donde /dev/fd/Nno hay dispositivos de caracteres especiales que devuelven una dup(2)de las fd cuando se abren, sino enlaces simbólicos "mágicos" al archivo / dentry original, que abren el archivo desde cero [1]. Se podría implementar en Free / NetBSD o Solaris ...

Pero no es lo que parece ser

Básicamente, otorgar el xpermiso (ejecutar) significa también otorgar el rpermiso (lectura) en cualquier archivo que tenga 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

ktraceno es el único camino; si el intérprete es ejecutable vinculado dinámicamente como perlo python, en su lugar, se podría usar un LD_PRELOADhack ed que anula la read(2)función.

Y no, hacer que sea setuid no impedirá que un usuario normal vea su contenido; ella simplemente podría ejecutarlo ptrace(2), lo que hará que los bits setuid sean ignorados:

Como root:

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

Como usuario habitual:

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
       "

(perdón si esta no es la forma más directa de demostrarlo)

[1] esto podría emularse en Linux mediante el uso binfmt_misc, pero el intérprete tendrá que modificarse o se deberá usar un contenedor; vea la última parte de esta respuesta para ver un ejemplo deliberadamente hecho ridículamente inseguro.

[2] o en general, cualquier archivo que no hará que se execve()devuelva ENOEXEC.

Mosvy
fuente
-2

Sí, si es usuario root, puede ejecutar el archivo sin permiso de lectura

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

Pero si inicia sesión con cualquier otro usuario, no puede ejecutar este archivo

$ ./test
-bash: ./test: Permission denied
gaurav goyal
fuente
3
Esto realmente no responde la pregunta, porque la raíz aún puede leer el archivo incluso sin permiso.
wjandrea
-5

Para hacer que sus scripts sean ilegibles pero ejecutables, tiene 3 opciones principales:

Primera opción

Use el comando openssl para cifrarlo manualmente. Y en el futuro, cuando desee ejecutar el script, deberá ejecutar openssl manualmente nuevamente y proporcionar la contraseña para descifrar.

Cifrado con openssl:

gato yourscript.sh | openssl aes-128-cbc -a -salt -k yourpassword> yourscript.enc

Descifrado con openssl:

gato yourscript.enc | openssl aes-128-cbc -a -d -salt -k su contraseña> yourscript.dec

yourscript.dec será el mismo que el script original yourscript.sh

Segunda opción

Use un sitio como www.Enscryption.com para cifrar automáticamente su secuencia de comandos y hacer que la versión cifrada de la secuencia de comandos sea ejecutable. Este sitio utiliza las capacidades de cifrado de openssl y algunos otros métodos de ofuscación para dificultar que los intrusos se entrometan en su script o revelen los secretos que desea ocultar. Con este sitio, puede encriptar scripts de shell y scripts de línea de comando perl, python, ruby. Creo que php también.

Tercera opción

Use una herramienta como shc . Parece que no se ha actualizado desde 2012. pero lo he usado en el pasado. Debe compilar su script para cada sistema operativo en el que desea utilizarlo, si el sistema operativo es diferente del que utilizó para compilarlo.

Resumen:

Si ocultar su código es de gran importancia para usted, dependerá únicamente de los permisos y la propiedad, ya que cualquier persona con root puede acceder a él. Eso es solo un hecho. Lo que puede hacer, si realmente quiere evitar que alguien vea su código sin autorización es escribir un script alrededor del comando openssl. Asegúrese de que, antes de que se ejecute el script, solicite una contraseña Y después de que se le proporcione la contraseña, ejecutará el script sin escribirlo en un archivo temporal. Si esto parece demasiado trabajo, las opciones 2 y 3 deberían ser suficientes para sus propósitos.

AncientMinds
fuente
El enlace "shc" también apunta a la página anterior. ¿Está por casualidad afiliado a esta página / servicio?
phk
3
Si cifra su script, no podrá ejecutarse sin clave. Si envió la clave a un usuario para que la ejecute, podrá ver su contenido. Esta respuesta es tan estúpida ...
erm3nda