comportamiento extraño de zsh con sudo --stdin y contraseña con caracteres aleatorios

comportamiento extraño de zsh con sudo --stdin y contraseña con caracteres aleatorios

Esta es una publicación que no comienza como cabría esperar o ver todos los días, aquí está mi contraseña de root: :4\g&8n:6_F[`9Touc8Ls+L'8)>6!3,nNmUzR&Ub~w7NTd'^Lb0]`0`."u>tP\>XAspMLTt!@}=F6CP)NsSMYY7*xm'A!7`!n'tmAaGWoBhS|u4{k$*v/o|'%)mbXMw
Difícil de recordar, ¿verdad? Bueno, ese no es el problema. Y antes de que me grites, sí, lo cambié. Ahora tengo un dummy_rootusuario con esa contraseña para las pruebas.

TL;DR

Rompí zsh al pasar esta contraseña a sudo en stdin

Versión (muy) larga

Así que esto es lo que está mal: lo uso sudocon la targetpwbandera, lo que significa que la contraseña solicitada por sudo es la contraseña del usuario objetivo, no la mía. Yo uso el passadministrador de contraseñas (sitio) para todo, incluida la contraseña de root de todas mis computadoras/servidores. Por razones obvias de seguridad, esta contraseña se genera aleatoriamente mediante un pase de 128 caracteres (porque por qué no). Como persona vaga (estoy seguro de que tú también lo eres), quiero usar el siguiente alias:

alias sudo='pass mydomain.tld/hostname/users/root/password | sudo --stdin'

Para aquellos de ustedes que no están familiarizados con pass, básicamente cifra las contraseñas en un árbol de directorios con GnuPG y, al invocarlo, pass directory/subdirectory/passworddescifra la contraseña y la imprime en la salida estándar (por supuesto, los directorios son opcionales, puede almacenar todo en desorden en la raíz). sin embargo, eso no se recomienda). El objetivo del alias es evitar hacer esto decenas de veces al día:

$ pass --clip root_password #Copy root password to clipboard 
$ sudo command
[sudo] password for root: paste
#command output (if the password is right of course)

Pero al probar el comando alias, esto sucede:

$ pass root_password | sudo --stdin --shell
[sudo] password for root: %
$

Aquí, el %signo tiene el color invertido: mi terminal tiene texto blanco sobre fondo negro, es %negro sobre fondo blanco, está resaltado en blanco y se imprime después de descifrar la contraseña. Entre la impresión de [sudo] password for root:y la impresión de este %, GPG solicita mi contraseña de clave privada. Ya me di cuenta en alguna ocasión del signo de porcentaje invertido, y de dónde y cuándo lo vi, creo que es para imprimir EOF(ojo, no estoy nada seguro de esto, mira al final del post un método para imprimir esto %). Fíjate que después de esta extraña señal, no soy root, pero echo $?vuelve 0...

Así que descarté hexadecimalmente el resultado de pass root_passwordpara ver si puedo obtener más información sobre ese personaje. Aquí está el resultado:

$ pass root_password
:4\?g&8n:6_F[`9Touc8Ls+L'8)>6!3,nNmUzR&Ub~w7NTd'^Lb0]`0`."u>tP\>XAspMLTt!@}=F6CP)NsSMYY7*xm'A!7`!n'tmAaGWoBhS|u4{k$*v/o|'%)mbXMw
$ pass root_password | hexdump -C
00000000  3a 34 5c 3f 67 26 38 6e  3a 36 5f 46 5b 60 39 54  |:4\?g&8n:6_F[`9T|
00000010  6f 75 63 38 4c 73 2b 4c  27 38 29 3e 36 21 33 2c  |ouc8Ls+L'8)>6!3,|
00000020  6e 4e 6d 55 7a 52 26 55  62 7e 77 37 4e 54 64 27  |nNmUzR&Ub~w7NTd'|
00000030  5e 4c 62 30 5d 60 30 60  2e 22 75 3e 74 50 5c 3e  |^Lb0]`0`."u>tP\>|
00000040  58 41 73 70 4d 4c 54 74  21 40 7d 3d 46 36 43 50  |XAspMLTt!@}=F6CP|
00000050  29 4e 73 53 4d 59 59 37  2a 78 6d 27 41 21 37 60  |)NsSMYY7*xm'A!7`|
00000060  21 6e 27 74 6d 41 61 47  57 6f 42 68 53 7c 75 34  |!n'tmAaGWoBhS|u4|
00000070  7b 6b 24 2a 76 2f 6f 7c  27 25 29 6d 62 58 4d 77  |{k$*v/o|'%)mbXMw|
00000080  0a                                                |.|
00000081

0aes NLsegún man ascii. Puede notar aquí que el %signo no está aquí y que el carácter de nueva línea que necesita sudo (ver man sudo) está aquí.

Pero espera, ahora comienza la diversión: cuando ejecuto el comando dos veces en una ventana terminadora o tty recién iniciada, esto es lo que sucede:

$ pass root_password | sudo --stdin --shell
[sudo] password for root: %
$ pass root_password | sudo --stdin --shell
zsh: parse error near `)'
$

Y a partir de entonces, zsh parece estar roto. Parece que quiere ejecutar el resultado del primer comando, pero solo sudoes el segundo comando. A continuación se muestran algunos ejemplos con este shell "roto":

$ echo testpw | sudo --stdin --shell
zsh: command not found: testpw
$ echo testpw | cat
testpw
$ echo testpw | wc --bytes
11
$ echo anothertestpw | sudo --stdin --shell
zsh: command not found: anothertestpw
$ pass root_password | sudo --stdin --shell
zsh: parse error near `)'
$ exec zsh
$ echo testpw | sudo --stdin --shell
zsh: command not found:testpw

¿Que esta pasando aqui? Como se muestra, incluso reemplazar la instancia zsh con otra ( exec zsh) no soluciona este problema. ¿Qué es lo que realmente está roto aquí? pasar, zsh o sudo?

Así que continuemos, probemos más, hagamos otro volcado hexadecimal en una nueva ventana de terminal (porque obviamente no sé cómo devolver zsh a su estado "normal"):

$ pass root_password | sudo --stdin --shell 2>&1 | hexdump -C
00000000  5b 73 75 64 6f 5d 20 70  61 73 73 77 6f 72 64 20  |[sudo] password |
00000010  66 6f 72 20 72 6f 6f 74  3a 20                    |for root: |
0000001a
$

¿A dónde se fue este signo de porcentaje? Ni idea. Simplemente no está aquí y todavía no soy root, pero el shell ahora está en su estado roto (definitivamente no sé cómo nombrar correctamente este "estado roto"). Al ejecutar el pass root_password | sudo --stdin --shellcomando después de este, aparece el mismo mensaje de error que antes. Cabe señalar que todo es igual en un tty y en terminator, incluso este %personaje malvado.

Aquí está toda la información que se me ocurre y que podría necesitar para ayudarme. Estoy en Arch Linux y todos los paquetes mencionados están actualizados a partir de hoy (2017-04-16 o 15, dependiendo de dónde se encuentre en el planeta, actualmente a las 4 a. m. en Francia), lo que significa ( pacman -Qsalida):

  • núcleo: 4.10.9-1
  • zsh: 5.3.1-2
  • sudo: 1.8.19.p2-1
  • pasar: 1.7.1-1
  • grupo: 2.1.20-1
  • terminador: 1,91-5

Aquí hay unenlacea mi .zshrc, también podría ayudar.

Y como prometí, aquí hay algunos pasos para eliminar este %signo malicioso pass. Simplemente cree una contraseña de varias líneas y presione Ctrl+ Dpara finalizar la contraseña sin agregar una nueva línea al final, se imprimirá este carácter. Noto aquí que presionar Ctrl+ Dno es suficiente al final de una línea con texto, hay que hacerlo dos veces. Pero si agrega una línea final a esta contraseña de varias líneas, presionarla una vez finalizará la entrada de la contraseña sin mostrarla.

$ pass insert --multiline test_evil_percent
Enter contents of test_evil_percent and press Ctrl+D when finished:
fooReturn
barCtrl+DCtrl+D%
Ahí está !

Pero con una línea final, no aparece y recuperamos nuestro mensaje al presionar Ctrl+ Dsolo una vez.

$ pass insert --multiline test_evil_percent
Enter contents of test_evil_percent and press Ctrl+D when finished:
fooReturn
barReturn
Ctrl+D
$

Entonces la pregunta primordial es: ¿cómo hacer que mi alias funcione? Para aquellos que se lo preguntan, acabo de escribir un script de una línea en mi directorio de scripts personalizados invocando pass root_passwordy configurando la variable de entorno SUDO_ASKPASSpara pasar este script en mi .zshrcarchivo. Otra pregunta puede ser: ¿qué diablos está pasando con zsh y sudo aquí?


Editar 2017-04-16: Solución

Gracias amiguel homeroElegí esta solución para mi problema:

  • Escriba un script de una línea llamado askpass-sudoque invoquepass root_password
  • Establezca la SUDO_ASKPASSvariable de entorno en my .zprofileen la ruta de este script
  • Agregué la línea alias sudo='sudo -A'a mi.zshrc

¡Y voilá! La invocación sudo commandahora solicita, como quería, mi frase de contraseña de clave GnuPG para descifrar la contraseña de root, y sudo --shellobtengo correctamente un shell de root.

Respuesta1

pass root_password | sudo --stdin --shelltuvo éxito. passimprimió la contraseña, sudola leyó e inició un shell; la salida de passterminó, lo que significa que la secuencia utilizada para la salida passy la entrada del shell estaba cerrada; el shell salió exitosamente en EOF.

Ejecuciones posteriores dentro delsudoventana de tiempo de esperano requería autenticación, por lo que el shell recibió la contraseña e intentó ejecutarla como un comando, dando ese error.


Su alias no puede funcionar si desea un shell o ejecutar alguna lectura de comandos desde la entrada estándar (pero sí lo hace para los comandos que no lo hacen). Puede configurar un alias que se ejecute pass root_password | sudo --stdin truesi lo desea y luego confiar en el tiempo de espera para ejecutar comandos sin contraseña.

También podría crear algún tipo de ayuda de Askpass que le brinde el comportamiento que desea. Proporcionaría la contraseña a través de passcuandopreguntópara ello por sudo.

información relacionada