¿Hay un shell que verifica que el código esté firmado?

19

Estuve jugando con PowerShell esta semana y descubrí que debes firmar tus scripts para que puedan ejecutarse. ¿Existe alguna funcionalidad segura similar en Linux que se relacione con la prevención de la ejecución de scripts bash?

La única funcionalidad similar a esta, que yo sepa, es la de SSH que requiere una determinada clave.

leeand00
fuente
2
Suena un poco como una solución ad-hoc para la firma de paquetes. No sé si Windows tiene un paquete criptográfico firmado como Linux.
Comodín el
66
@ leeand00 Un script es un caso especial de un paquete de software y no veo ningún punto para señalar ese caso.
Gilles 'SO- deja de ser malvado'
2
El mecanismo que más me gusta es la forma en que ChromeOS hace esto: colocando el único sistema de archivos no marcado noexecen una partición de solo lectura en un dispositivo de bloque firmado de dm-verity.
Charles Duffy el
1
source.android.com/security/verifiedboot habla sobre la adopción de Android de esa característica (inicialmente ChromeOS).
Charles Duffy el
1
Puede considerar bash como un conjunto de comandos que se pueden escribir manualmente en la interfaz de línea de comandos. ¿Cuál es el punto de restringir las secuencias de comandos cuando puede escribir el contenido en la línea de comandos de todos modos?
Ding-Yi Chen

Respuestas:

11

Si está bloqueando la capacidad de los usuarios para ejecutar scripts a través de, sudoentonces podría usar la digestfuncionalidad.
Puede especificar el hash de un script / ejecutable en el sudoersque se verificará sudoantes de ejecutarse. Entonces, aunque no es lo mismo que firmar, le brinda una garantía básica de que el script al menos no se ha modificado sin que también se modifiquen los sudoers.

Si el nombre de un comando tiene el prefijo Digest_Spec, el comando solo coincidirá con éxito si se puede verificar utilizando el resumen SHA-2 especificado. Esto puede ser útil en situaciones donde el usuario que invoca sudo tiene acceso de escritura al comando o su directorio padre. Se admiten los siguientes formatos de resumen: sha224, sha256, sha384 y sha512. La cadena se puede especificar en formato hexadecimal o base64 (base64 es más compacto). Existen varias utilidades capaces de generar resúmenes de SHA-2 en formato hexadecimal, como openssl, shasum, sha224sum, sha256sum, sha384sum, sha512sum.

http://www.sudo.ws/man/1.8.13/sudoers.man.html

Batfastad
fuente
Eso me detendrá hasta que lea sobre SE Linux y lo haga bien.
leeand00
13

Si y no.

La distribución de software de Linux funciona de manera algo diferente a la distribución de software de Windows. En el mundo Linux (no integrado), el método principal para distribuir software es a través de una distribución (Ubuntu, Debian, RHEL, Fedora, Arch, etc.). Todas las distribuciones principales han estado firmando sus paquetes sistemáticamente durante aproximadamente una década.

Cuando el software se distribuye de forma independiente, depende del proveedor decidir cómo enviarán su software. Los buenos proveedores proporcionan fuentes de paquetes que son compatibles con las principales distribuciones (no existe un mecanismo de distribución unificado para todo Linux: la distribución de software es uno de los principales puntos de diferenciación entre las distribuciones) y que se firman con la clave del proveedor. Las distribuciones de Linux rara vez actúan como una autoridad de firma para proveedores externos (Canonical hace esto con los socios de Ubuntu, pero eso cubre muy pocos proveedores), y creo que todas las distribuciones principales usan la red de confianza PGP en lugar de la infraestructura de clave pública TLS, por lo que depende del usuario determinar si desea confiar en una clave.

No existe un mecanismo especial que destaque los paquetes de software que consisten en un solo script de paquetes de software que consisten en un archivo ejecutable nativo, un archivo de datos o varios archivos. Tampoco se incluye ninguna verificación de firma en ningún intérprete de script común, porque verificar un paquete de software es una preocupación completamente ortogonal al ejecutar un script.

Creo que Windows anota los archivos con su origen y requiere la confirmación del usuario para ejecutar un archivo cuyo origen se "descargue" en lugar de "local". Linux realmente no tiene un mecanismo similar. Lo más cercano es el permiso de ejecución: un archivo descargado no tiene permiso de ejecución, el usuario debe habilitarlo explícitamente ( chmod +xen la línea de comando o la acción equivalente en un administrador de archivos).

Gilles 'SO- deja de ser malvado'
fuente
2
FWIW, además de este PowerShell, se puede configurar (mediante la configuración de la política) para ejecutar solo scripts firmados y esta política se puede configurar de modo que todos los scripts deben estar firmados o solo los scripts de "origen remoto", o sin scripts. Funciona mejor en un entorno AD con administración de claves y administración central de políticas. Se puede omitir :-)
Stephen Harris
@StephenHarris Bueno, sí, si lo configuras para evitar ...
leeand00
@ leeand00 - Aparentemente, la codificación base64 también funciona como un bypass, pero no sé si eso se ha cerrado en las versiones más recientes de PowerShell.
Stephen Harris el
1
@ leeand00 - visita darkoperator.com/blog/2013/3/5/… para divertirte :-) Básicamente, pasa el script codificado en base64 como parámetro en la línea de comando :-) ¡Suficientemente fácil de envolver!
Stephen Harris el
2
SeLinux anota archivos con su origen. Es una de sus premisas principales.
loa_in_
10

Linux no proporciona la capacidad de limitar la ejecución de scripts bash basados ​​en firmas digitales.

Hay algo de trabajo en la autenticación de ejecutables binarios. Consulte https://lwn.net/Articles/488906/ para obtener información.

Quentin Fennessy
fuente
Vota por una respuesta directa sin sugerir una solución alternativa de hackey.
user394
8

En una palabra, "no".

Linux realmente no diferencia entre ejecutables y scripts; el #!al principio es una forma de decirle al núcleo qué programa se ejecute para evaluar la entrada pero no es la única forma en que un script puede ser ejecutado.

Entonces, por ejemplo, si tengo un script

$ cat x
#!/bin/sh 
echo hello

Entonces puedo ejecutar esto con el comando

$ ./x

Eso hará que el núcleo intente ejecutarlo, detecte #!y luego se ejecute efectivamente /bin/sh x.

Sin embargo, también podría ejecutar cualquiera de estas variantes:

$ sh ./x
$ bash ./x
$ cat x | sh
$ cat x | bash
$ sh < x

o incluso

. ./x

Entonces, incluso si el núcleo intentó imponer la firma en la execcapa, podemos evitar esto ejecutando solo el intérprete con el script como parámetro.

Esto significa que el código de firma debería estar en el propio intérprete. ¿Y qué impediría a un usuario compilar su propia copia de un shell sin el código de cumplimiento de firma?

La solución estándar para esto no es usar la firma, sino usar los Controles de acceso obligatorios (MAC), como SELinux. Con los sistemas MAC puede especificar exactamente lo que cada usuario puede ejecutar y hacer la transición de capas. Entonces, por ejemplo, puede decir "los usuarios normales pueden ejecutar cualquier cosa menos que el servidor web y los procesos CGI solo puedan acceder a cosas del /var/httpddirectorio; todo lo demás se rechaza".

Stephen Harris
fuente
1
This means that signing code would have to be in the interpreter itself. And what would stop a user from compiling their own copy of a shell without the signing enforcement code?No permitir la ejecución de ningún ejecutable sin firmar lo haría, si el usuario no tiene la clave de firma. Ya hay varios proyectos * nix para esto.
alzee
2

Las distribuciones de Linux generalmente tienen gnupg . Me parece que todo lo que desea es un simple contenedor de bash que verifique una firma de GPG separada contra el script de argumento y solo proceda a ejecutar el script si la verificación tiene éxito:

#!/bin/sh
gpgv2 $1.asc && bash "$@"
PSkocik
fuente
Lo único que esto no presenta es ejecutar un script que alguien acaba de hacer ... solo ...
leeand00
2

La contrapregunta que viene a la mente de inmediato es: "¿Por qué querrías evitar que los usuarios ejecuten programas que escribieron? " Existen varias posibilidades:

  1. Es literalmente imposible detectar quién creó el código en primer lugar. El propietario del archivo de script es el que realmente guardó el contenido de ese archivo, independientemente de su origen. Por lo tanto, hacer cumplir una firma es solo un sustituto complicado para un cuadro de diálogo de confirmación: "¿Está seguro de que desea hacer esto?" En Linux, parte de este problema se resuelve de forma transparente con paquetes firmados y se mitiga por el hecho de que los usuarios tienen acceso limitado de forma predeterminada. También se espera que el usuario sepa que ejecutar el código de otros puede ser peligroso *.
  2. En la misma línea, firmar un script es una operación mucho más compleja que guardar un archivo. En el mejor de los casos, esto lleva al usuario a darse cuenta de que está realizando una acción similar a la firma de un documento, y debe inspeccionar lo que dice antes de continuar. Lo más probable es que simplemente garantice un nivel muy mínimo de competencia técnica por parte del usuario para poder ejecutar el script. En el peor de los casos, demuestra la voluntad de saltar a través de una larga serie de aros para ejecutar lo que querían. Se asume competencia técnica en Linux *.
  3. Es más probable que las personas detecten código obviamente malicioso al escribir / pegar una serie de comandos en su línea de comandos. Los fragmentos de texto sin formato destinados a ser copiados y pegados generalmente son más pequeños que la serie de comandos necesarios para hacer algo propiamente infame. El usuario también puede copiar y pegar cuidadosamente cada línea por separado, entendiendo lo que sucede a medida que sucede. Con un script es posible que el usuario nunca haya mirado el código. Esta puede ser una aplicación útil de scripts firmados, a un costo demasiado común de complacencia después de la 12a vez que tiene que hacerlo.

* Esto probablemente se está volviendo cada vez menos cierto a medida que más personas comienzan a usar Linux

l0b0
fuente
1

La razón por la cual los sistemas han evolucionado de manera diferente es que Linux tiene el atributo de archivo 'exec' y Windows usa extensiones de archivo para determinar la ejecubilidad.

Por lo tanto, en Windows es fácil engañar al usuario para que descargue un archivo con la extensión ".exe", ".bat", ".scr", que estará oculto de forma predeterminada . Hacer doble clic en ese archivo le daría ejecución de código arbitrario. Por lo tanto, se creó un gran mecanismo de seguimiento de origen y firma ejecutable / script para mitigar este riesgo.

En Linux, es posible que pueda obtener un archivo para el usuario, pero no puede forzar fácilmente la configuración del bit 'exec'. Además, es posible crear sistemas de archivos completos 'noexec'.

En cualquier caso, puede ejecutar un script explícitamente invocando al intérprete. Incluso puede crear scripts de shell en tiempo de ejecución y canalizarlos a "sh", o ejecutar "sh -c".

pjc50
fuente
0

Por costumbre, muchos programas de archivo no conservan el bit de ejecución en archivos contenidos. Esto hace que sea imposible ejecutar ejecutables arbitrarios. Bueno, casi.

El punto es que lo que se describió en otra respuesta es que la falta de bit de ejecución no le impide pasar dicho script directamente bash. Si bien es discutible que la mayoría de estos scripts sean bashscripts, el shebang puede especificar cualquier programa como intérprete. Esto significa que depende del usuario ejecutar el intérprete apropiado si decide ignorar la semántica ejecutable.

Si bien esto no es mucho, cubre la prevención de ejecutar ejecutables no confiables en * nixes con solo kernel y shell .

Como mencioné en uno de los comentarios, hay otra capa de protección SeLinux, que rastrea el origen de los archivos en función de un conjunto de reglas. Una configuración SeLinuxno permitiría, por ejemplo, que la raíz ejecute un ejecutable con un conjunto de bits ejecutable que se descargó de Internet, incluso si copia y mueve el archivo. Se puede agregar una regla de que dichos archivos solo se pueden ejecutar a través de otro binario que verifique la firma, no muy diferente de lo que mencionó en su pregunta.

Entonces, al final es una cuestión de configuración de herramientas preinstaladas comúnmente, y la respuesta es .

loa_in_
fuente
muchos programas de archivo no conservan el bit de ejecución en archivos contenidos ... bueno, eso es una desventaja cuando realmente quieres usarlo para archivar. Afortunadamente tar no preservar el bit de ejecución.
pjc50
Tienes que usar la tar -p fuente
loa_in_
-p, --preserve-permissions, --same-permissionssignifica extraer información sobre los permisos de archivos (predeterminado para superusuario)
loa_in_
No, NO necesitas -p. Veo lo que dice la página del manual, pero no es lo que sucede. touch permtest; chmod +x permtest; tar cf permtest.tar.gz permtest; rm permtest; tar xf permtest.tar.gz; ls -l permtest- Es ejecutable aquí, y no soy root.
Domen
Intentaré mejorar mi respuesta entonces.
loa_in_