El escenario:
En un script bash, tengo que verificar si una contraseña dada por un usuario es una contraseña de usuario válida.
Supongo que tengo un usuario A con contraseña PA .. En el script le pedí al usuario A que ingrese su contraseña, entonces, ¿cómo verificar si la cadena ingresada es realmente su contraseña? ...

expecten stackoverflow.com/a/1503831/320594 .Respuestas:
Como desea hacer esto en un script de shell, ¿hay un par de contribuciones en Cómo verificar la contraseña con Linux? (en Unix.SE , sugerido por AB ) son especialmente relevantes:
/etc/shadowda parte de la solución.mkpasswdcomando presente en Debian (y Ubuntu).Para verificar manualmente si una cadena es realmente la contraseña de algún usuario, debe hacer un hash con el mismo algoritmo hash que en la entrada de sombra del usuario, con la misma sal que en la entrada de sombra del usuario. Luego se puede comparar con el hash de contraseña almacenado allí.
He escrito un guión completo y funcional que demuestra cómo hacer esto.
chkpass, puede ejecutarlo y leerá una línea de entrada estándar y comprobará si es la contraseña.chkpass userusermkpasswdutilidad de la que depende este script.Notas de seguridad
Puede que no sea el enfoque correcto.
El hecho de que un enfoque como este se considere seguro y apropiado depende de los detalles sobre su caso de uso que no haya proporcionado (a partir de este escrito).
No ha sido auditado.
Aunque he tratado de tener cuidado al escribir este script, no ha sido auditado adecuadamente por vulnerabilidades de seguridad . Se pretende que sea una demostración, y sería un software "alfa" si se lanza como parte de un proyecto. Además...
Otro usuario que está "mirando" puede descubrir la sal del usuario .
Debido a las limitaciones en la forma en que
mkpasswdacepta los datos de sal, este script contiene una falla de seguridad conocida , que puede considerar aceptable o no según el caso de uso. Por defecto, los usuarios de Ubuntu y la mayoría de los otros sistemas GNU / Linux pueden ver información sobre los procesos ejecutados por otros usuarios (incluida la raíz), incluidos sus argumentos de línea de comandos. Ni la entrada del usuario ni el hash de contraseña almacenado se pasan como argumento de línea de comandos a ninguna utilidad externa. Pero la sal , extraída de lashadowbase de datos, se proporciona como un argumento de línea de comandosmkpasswd, ya que esta es la única forma en que la utilidad acepta una sal como entrada.Si
www-data) ejecutar su código, o/proc)es capaz de verificar los argumentos de la línea de comandos
mkpasswdsegún lo ejecuta este script, luego pueden obtener una copia de la sal del usuario de lashadowbase de datos. Es posible que tengan que ser capaces de adivinar cuándo se ejecuta ese comando, pero eso a veces es posible.Un atacante con su sal no es tan malo como un atacante con su sal y hachís , pero no es lo ideal. La sal no proporciona suficiente información para que alguien descubra su contraseña. Pero sí permite que alguien genere tablas de arco iris o hash de diccionario precalculados específicos para ese usuario en ese sistema. Inicialmente, esto no tiene valor, pero si su seguridad se ve comprometida en una fecha posterior y se obtiene el hash completo, se podría descifrar más rápidamente para obtener la contraseña del usuario antes de que tenga la oportunidad de cambiarla.
Por lo tanto, esta falla de seguridad es un factor exacerbador en un escenario de ataque más complejo en lugar de una vulnerabilidad totalmente explotable. Y podría considerar la situación anterior exagerada. Pero soy reacio a recomendar cualquier método para uso general en el mundo real que filtre cualquier información no pública de
/etc/shadowun usuario no root.Puede evitar este problema por completo:
Ten cuidado con cómo llamas a este script.
Si permite que un usuario no confiable ejecute este script como root o ejecute algún proceso como root que llame a este script, tenga cuidado . Al cambiar el entorno, pueden hacer que este script, o cualquier script que se ejecute como root, haga cualquier cosa . A menos que pueda evitar que esto ocurra, no debe permitir a los usuarios privilegios elevados para ejecutar scripts de shell.
Ver 10.4. Lenguajes de secuencias de comandos de Shell (derivados de sh y csh) en la programación segura de David A. Wheeler para Linux y Unix HOWTO para obtener más información al respecto. Si bien su presentación se centra en los guiones setuid, otros mecanismos pueden ser víctimas de algunos de los mismos problemas si no desinfectan correctamente el medio ambiente.
Otras notas
Solo admite hashes de lectura de la
shadowbase de datos.Las contraseñas deben estar sombreadas para que este script funcione (es decir, sus hashes deben estar en un
/etc/shadowarchivo separado que solo la raíz pueda leer, no en/etc/passwd).Este siempre debería ser el caso en Ubuntu. En cualquier caso, si es necesario, el script se puede extender trivialmente para leer hashes de contraseñas
passwdy tambiénshadow.Tenga
IFSen cuenta al modificar este script.Lo configuré
IFS=$al principio, ya que los tres datos en el campo hash de una entrada de sombra están separados por$.$, por lo que el tipo de hash y la sal son"${ent[1]}"y en"${ent[2]}"lugar de"${ent[0]}"y"${ent[1]}", respectivamente.Los únicos lugares en este script donde
$IFSdetermina cómo el shell divide o combina palabras soncuando estos datos se dividen en una matriz, inicializándolos desde la
$()sustitución del comando sin comillas en:cuando la matriz se reconstituye en una cadena para compararla con el campo completo
shadow, la"${ent[*]}"expresión en:Si modifica la secuencia de comandos y hace que divida las palabras (o la combinación de palabras) en otras situaciones, deberá establecer
IFSdiferentes valores para diferentes comandos o diferentes partes de la secuencia de comandos.Si no tiene esto en cuenta y asume que
$IFSestá configurado en el espacio en blanco habitual ($' \t\n'), podría terminar haciendo que su script se comporte de maneras bastante extrañas.fuente
Puedes hacer un mal uso
sudode esto.sudotiene la-lopción, para probar los privilegios de sudo que tiene el usuario y-Spara leer la contraseña de stdin. Sin embargo, no importa qué nivel de privilegio tenga el usuario, si se autentica correctamente,sudoregresa con el estado de salida 0. Por lo tanto, puede tomar cualquier otro estado de salida como indicación de que la autenticación no funcionó (suponiendosudoque no tenga ningún problema, como errores de permiso osudoersconfiguración no válida ).Algo como:
Este script depende bastante de la
sudoersconfiguración. He asumido la configuración predeterminada. Cosas que pueden hacer que falle:targetpworunaspwestá configuradolistpwesneverOtros problemas incluyen (gracias Eliah):
/var/log/auth.logsudodebe ejecutarse como el usuario para el que se está autenticando. A menos que tengasudoprivilegios para poder ejecutarsudo -u foo sudo -lS, eso significa que tendrá que ejecutar el script como el usuario objetivo.Ahora, la razón por la que usé aquí-docs es para obstaculizar las escuchas. Una variable que se utiliza como parte de la línea de comandos es más fácilmente reveló mediante el uso
topopsu otras herramientas para inspeccionar los procesos.fuente
sudoconfiguraciones poco comunes (como usted dice) y desorden/var/log/auth.logcon registros de cada intento, esto es rápido, simple y utiliza una utilidad existente, en lugar de reinventar la rueda (por así decirlo). Sugiero ajusteIFS=pararead, para evitar falsas éxitos para la entrada del usuario por espacios en blanco acolchado y contraseñas no acolchada, así como fallos falsos para la entrada del usuario por espacios en blanco acolchado y contraseñas acolchadas. (Mi solución tenía un error similar). También puede explicar cómo debe ejecutarse como el usuario cuya contraseña se está verificando.sudo -lhace que una entrada se escriba con "COMMAND=list". Por cierto (no relacionado), aunque no es objetivamente mejor hacerlo, el uso de una cadena here en lugar de un documento here logra el mismo objetivo de seguridad y es más compacto. Dado que el script ya usa los bashismosread -sy&>, el usoif sudo -lS &>/dev/null <<<"$PASSWD"; thenno es menos portátil. No estoy sugiriendo que debas cambiar lo que tienes (está bien). Más bien, lo menciono para que los lectores sepan que también tienen esta opción.sudo -ldeshabilitado algo, tal vez informaba cuando un usuario intentaba ejecutar un comando que no tenía permitido.Otro método (probablemente más interesante por sus contenidos teóricos que por sus aplicaciones prácticas).
Las contraseñas de los usuarios se almacenan en
/etc/shadow.Las contraseñas almacenadas aquí están encriptadas, en las últimas versiones de Ubuntu usando
SHA-512.Específicamente, después de la creación de la contraseña, la contraseña en texto claro es salada y encriptada
SHA-512.Una solución sería entonces sal / cifrar la contraseña dada y compararla con la contraseña del usuario cifrado almacenada en la
/etc/shadowentrada del usuario dado .Para obtener un desglose rápido de cómo se almacenan las contraseñas en cada
/etc/shadowentrada de usuario , aquí hay una/etc/shadowentrada de muestra para un usuariofoocon contraseñabar:foo: nombre de usuario6: tipo de cifrado de contraseñalWS1oJnmDlaXrx1F: sal de cifrado de contraseñah4vuzZVBwIE1Z6vT7N.spwbxYig9e/OHOIH.VDv9JPaC3.OtTusPFzma7g.R/oSZFW5QOI7IDdDY01G0zTGQE/:SHA-512contraseña salada / encriptadaPara coincidir con la contraseña dada
barpara el usuario dadofoo, lo primero que debe hacer es obtener la sal:Entonces uno debe obtener la contraseña completa salada / encriptada:
Luego, la contraseña dada puede ser salada / encriptada y comparada con la contraseña del usuario salado / encriptado almacenada en
/etc/shadow:¡Ellos coinciden! Todo puesto en un
bashguión:Salida:
fuente
sudo getent shadow>>sudo grep .... De lo contrario, bien. Esto es lo que pensé originalmente, luego me volví demasiado flojo.getent+grep+cut>grep+cutgetentpuede hacer la búsqueda por ti. Me tomé la libertad de editar.mkpasswdgenerar un hash a partir de la entrada del usuario y la sal existente (e incluía características y diagnósticos adicionales), en su lugar codificó un programa simple de Python que implementamkpasswdla funcionalidad más importante y lo usé. Te recomiendo que estableceIFS=la lectura de introducción de contraseña, y la cita${password}con", por lo que los intentos de contraseña con un espacio en blanco no rompen la secuencia de comandos.