1 puntos por GN⁺ 4 시간 전 | 1 comentarios | Compartir por WhatsApp
  • Los tokens de seguridad firman dentro del dispositivo sin exportar la clave privada fuera de él, y además requieren una acción física del usuario, lo que dificulta que un atacante remoto genere firmas arbitrarias
  • Se pueden usar para autenticación SSH, U2F, inicio de sesión local sin contraseña, sudo y firma de commits de git, y los dispositivos de seguridad integrados en laptops y smartphones modernos pueden sustituir a YubiKey
  • El archivo de “clave privada” creado con ssh-keygen -t ed25519-sk no es la clave privada real, sino un handle que apunta a la clave dentro del token, por lo que es posible generar el mismo archivo de clave SSH en otra computadora usando el mismo token
  • En una MacBook fue posible configurar el secure element como clave SSH para habilitar el inicio de sesión SSH con Touch ID, y para firmar commits de git fue necesario usar ssh-agent y un user.signingKey con formato key:: en lugar de una ruta de archivo
  • Los tokens de seguridad no permiten recuperar la clave privada si se pierden y tienen un riesgo de usabilidad porque el usuario puede acostumbrarse a tocar repetidamente; en laptops con Windows, Windows Hello podía confirmar el uso de la clave SSH con reconocimiento facial, huella o PIN

Ventajas y límites de los tokens de seguridad

  • La estructura clave para detener ataques remotos

    • Un token de seguridad mantiene el par de clave privada/pública dentro del dispositivo; la clave pública se puede extraer fácilmente, pero la clave privada no sale del dispositivo
    • Si se envía al dispositivo el paquete de datos a firmar, este lo firma internamente con la clave privada y normalmente exige alguna acción física del usuario, como pulsar un botón táctil parpadeante
    • Incluso si un atacante remoto obtiene acceso a la computadora, el token de seguridad no realizará firmas arbitrarias si el usuario no actúa físicamente en el mundo real, por lo que parece mejor que guardar el par completo de claves SSH privada/pública como archivos en el directorio ~/.ssh
    • También hay opciones para quienes prefieren firmware FOSS, como SoloKeys y Nitrokeys
    • Los tokens de seguridad más avanzados añaden autenticación biométrica, como un lector de huellas integrado, pero lo esencial es que la clave privada no pueda salir del dispositivo
  • Riesgos derivados de la usabilidad

    • Si el usuario se acostumbra a pulsar el token de seguridad cada vez que parpadea, puede terminar respondiendo sin pensar incluso a solicitudes maliciosas
    • Durante tareas de firma continuas en las que hay que tocar repetidamente el token, puede ser difícil notar de verdad una solicitud adicional que parpadee una vez más
    • Apple y Microsoft usan en las apps de autenticación del smartphone un método que muestra un código numérico aleatorio por cada solicitud de acceso para que el usuario lo introduzca, pero esto es engorroso y reduce la ventaja de usabilidad de los tokens de seguridad frente a apps TOTP como Authy o Google Authenticator
  • Pérdida y respaldo

    • Si se pierde un token de seguridad, esa clave privada desaparece para siempre y no hay forma de respaldarla
    • Para evitar el riesgo de quedarse fuera de varias cuentas, al comprar un token de seguridad conviene adquirir al menos 2 y registrarlos en el mismo servicio
    • Como alternativa, existen métodos de respaldo y recuperación como BIP 39, que convierten la clave privada en una lista de palabras legibles por humanos para anotarla
    • Si la clave privada pudiera salir del secure enclave, también serían posibles ataques de phishing que induzcan al usuario a anotar esa lista de palabras en un lugar incorrecto
    • Si realmente preocupa mucho la posibilidad de perder todos los tokens de seguridad, una lista de palabras BIP 39 puede ser el último recurso para recuperar el acceso al sistema

Uso de tokens de seguridad con SSH y git

  • Guardar la clave privada SSH en un token de seguridad

    • Normalmente, al ejecutar ssh-keygen se crea un par de archivos que incluye la clave privada completa
    • Para guardar la clave privada en un token de seguridad, se instala libfido2 siguiendo la guía FIDO/U2F de Yubico, y luego se ejecuta ssh-keygen -t ed25519-sk con el token conectado
    • También en este caso se genera un par de archivos, pero el archivo de “clave privada” no es la clave privada real, sino un handle que apunta a la clave privada almacenada en el token de seguridad
    • Si se ejecuta de nuevo ssh-keygen -t ed25519-sk con el mismo token de seguridad, se pueden generar los mismos archivos de clave privada/pública en cualquier computadora, de modo que el acceso SSH se mueve con el token y no depende de un archivo específico en una máquina específica
  • Autenticación en git y firma de commits

    • Aproximadamente el 90% de las veces que hay que tocar el token de seguridad es por usar git
    • Los forges de git implementan autenticación SSH para operaciones de push y pull, y al subir el archivo id_ed25519_sk.pub generado arriba pueden aceptar el par de claves del token de seguridad
    • git también admite claves SSH para firma de commits; si se sigue la documentación de GitHub para configurar una clave de firma con una clave SSH y luego se ejecuta git config --global commit.gpgsign true, todos los commits se firman automáticamente
    • Para que el forge de git reconozca los commits como firmados por la misma persona, hay que volver a subir la clave pública, y este campo normalmente está separado del campo usado para autenticación SSH
  • Lo incómodo de la firma de commits

    • Al hacer rebase de una lista larga de commits, hay que volver a firmarlos todos
    • En una YubiKey con lector de huellas, la tasa de fallos del reconocimiento era demasiado alta para firmar decenas de commits seguidos, así que se dejó de usar
    • jujutsu, un wrapper de git centrado en “rebase/amend”, tiene una forma de firmar commits solo al hacer push
  • Inicio de sesión local en Linux y sudo

Usar el secure element de una MacBook como clave SSH

  • Si se deja siempre conectado un token de seguridad al puerto USB-C, queda sobresaliendo como una pequeña palanca que puede dañar tanto el puerto como el token si se golpea o se tira por accidente
  • En una MacBook Air M1 de 2020 se configuró el elemento de seguridad integrado como clave SSH siguiendo la guía de Arian van Putten
sc_auth create-ctk-identity -l ssh -k p-256-ne -t bio
ssh-keygen -w /usr/lib/ssh-keychain.dylib -K -N ""
  • Este comando creó el par de archivos de clave privada/pública id_ecdsa_sk_rk, y luego esos archivos se movieron al directorio ~/.ssh
  • También aquí el archivo de clave privada no es la clave privada real, sino un handle de la clave dentro del dispositivo, así que tiene una forma que se puede pegar públicamente
  • Para agregar la clave pública como authorized key en un servidor del homelab, se ejecuta lo siguiente
ssh-copy-id -i ~/.ssh/id_ecdsa_sk_rk.pub <server nickname>
  • Después se añade esta configuración a ~/.ssh/config
Host *
  IdentityFile ~/.ssh/id_ecdsa_sk_rk
  SecurityKeyProvider=/usr/lib/ssh-keychain.dylib
  • Al ejecutar ssh <server nickname>, macOS muestra automáticamente una solicitud de huella antes del inicio de sesión, y luego el acceso por SSH continúa normalmente

Firmar commits de git con el secure element de la MacBook

  • Aunque se configure git config --global user.signingKey /Users/ahelwer/.ssh/id_ecdsa_sk_rk y se actualice el archivo .ssh/allowed_signers, la firma de commits de git no funciona de inmediato
  • git falla al firmar commits y muestra errores como device not found?
error: Signing file /var/folders/l5/5wqvq2l10p96wtdtfr6lvrvw0000gn/T//.git_signing_buffer_tmpc4uQgO
Confirm user presence for key ECDSA-SK SHA256:oQDA2SNYb2MoSQcxJVSmWyAeAWPqMp7rxliBRfi87as
Couldn't sign message: device not found?
Signing /var/folders/l5/5wqvq2l10p96wtdtfr6lvrvw0000gn/T//.git_signing_buffer_tmpc4uQgO failed: device not found?

fatal: failed to write commit object
  • La solución es usar ssh-agent en lugar de apuntar directamente a los archivos del directorio ~/.ssh
  • Siguiendo el tutorial anterior, el par de claves se registra en ssh-agent con este comando
ssh-add -K -S /usr/lib/ssh-keychain.dylib
  • Después, en user.signingKey no se pone una ruta de archivo, sino la propia clave con el prefijo key:: delante del contenido de ~/.ssh/id_ecdsa_sk_rk.pub, dentro de ~/.gitconfig
[user]
	name = Andrew Helwer
	signingKey = "key::sk-ecdsa-sha2-nistp256@openssh.com AAAAInNrLWVjZHNhLXNoYTItbmlzdHAyNTZAb3BlbnNzaC5jb20AAAAIbmlzdHAyNTYAAABBBGxFEdnIg6ppz+pQCdd1eisjOV4gxrjMv1Y4SbtdLoSm6CJCgPZ6q7lnNyuQQsdnS4/Tllsc656AQL7BO3OS47cAAAAEc3NoOg== ssh:"
  • Después de esta configuración, fue posible firmar archivos con la clave del secure element de la MacBook y hacer push al sitio de GitLab Pages

Resultados en Windows y Linux

  • También se hizo una prueba rápida en una laptop Windows entregada por la empresa
winget install Microsoft.OpenSSH.preview
ssh-keygen -t ecdsa-sk
  • Este comando también generó un par de archivos de clave privada/pública y, al conectarse por SSH, aceptó reconocimiento facial, huella o PIN mediante el flujo estándar de inicio de sesión de Windows Hello
  • En Linux no se pudo hacer una demo porque no había acceso a una laptop con secure element que permitiera confirmar de forma similar la presencia real del usuario

1 comentarios

 
GN⁺ 4 시간 전
Opiniones en Lobste.rs
  • Es un gran artículo, y solo mostrar que esto es posible ya resulta muy útil
    En lo personal, no logré encontrar la versión correcta de la biblioteca para hacer que esto funcionara, pero descubrí que 1Password 8 almacena claves SSH de forma segura y que el agente permite desbloquear la clave con autenticación biométrica
    Así que ahora puedo trabajar con git e iniciar sesión en hosts SSH con solo poner el dedo
    Guía: https://developer.1password.com/docs/ssh/get-started/

  • Esto parece ser solo para Mac

    • En el trabajo puedo usar una laptop Windows reciente, así que hice que OpenSSH se integrara con Windows Hello de esta manera
      winget install Microsoft.OpenSSH.preview  
      ssh-keygen -t ecdsa-sk  
      
      Después de eso funcionó como siempre, y cada vez que me conectaba por SSH a cualquier lugar con la clave, pasaba por el flujo estándar de Windows Hello, pudiendo usar lector de huellas, reconocimiento facial o PIN
      No he podido probar un sistema Linux con ese tipo de elemento de seguridad, y aunque mi estación de trabajo Linux tiene un TPM V1, no conozco una forma clara de garantizar que las operaciones de firma solo se ejecuten después de confirmar presencia real del usuario
      Tal vez alguien con una laptop Linux como Framework podría intentarlo. Quizá incluso funcione de verdad en Asahi
    • Yo diría que sí, casi seguro. No sé si existe una capa de emulación FIDO de TPM2 en Linux o Windows
  • Entonces, ¿qué contiene exactamente el archivo de clave privada que se proporciona?

    • @wrs ya respondió antes, pero la parte ssh:, es decir, la aplicación, corresponde al origin del passkey y es útil al crear una resident key por host o dominio
      Por ejemplo, yo la uso para separar claves por propósito incluso dentro de la misma Yubikey física
      flags especifica cómo el hardware debe tratar la clave [1]. El agente también puede agregar sus propias restricciones
      Técnicamente, también se pueden guardar otros blobs o extensiones en una clave FIDO, y en un trabajo anterior lo usamos para pasar credenciales auxiliares junto con la autenticación, como una clave pública X.509. Es una forma bastante elegante de hacerlo
      [1]
      #define SSH_SK_USER_PRESENCE_REQD  0x01  
      #define SSH_SK_USER_VERIFICATION_REQD  0x04  
      #define SSH_SK_FORCE_OPERATION    0x10  
      #define SSH_SK_RESIDENT_KEY    0x20  
      
    • Según Claude, y verificándolo con openssh_key_parser, la estructura es la siguiente
      El envoltorio externo tiene el valor mágico openssh-key-v1\0, cipher=none, kdf=none, así que no está cifrado
      El blob de clave pública de 74 bytes contiene el tipo de clave sk-ssh-ed25519@openssh.com, el punto Ed25519 de 32 bytes fdcce889…03e7852b, y la aplicación ssh:, que separa por namespace las credenciales FIDO de SSH y WebAuthn
      La sección privada tiene 248 bytes y, como cipher=none, está en texto plano. Incluye el valor aleatorio checkint1 == checkint2 == 0x46744267, el tipo de clave repetido y la clave pública, la aplicación ssh:, y flags: 0x01
      Ese flag significa USER_PRESENCE_REQUIRED, así que requiere toque pero no PIN ni verificación del usuario, y es una clave no residente
      key_handle es un ID opaco de credencial de 128 bytes que se pasa a authenticatorGetAssertion, y el dispositivo lo resuelve internamente para recuperar la semilla Ed25519
      Además de eso, hay un reserved vacío, el comentario ahelwer@ah-mbair.local, y relleno 01 02 03
    • Si lo metes en un decodificador base64, sale esto

      openssh-key-v1����none���none����������J���sk-ssh-ed25519@openssh.com��� 盘˪<F$KW+���ssh:���FtBgFtBg���sk-ssh-ed25519@openssh.com��� 盘˪<F$KW+���ssh:���fІpF$D8"&0[X 'L=Ev ')BjM]$}rTv6Z+p9O8ݹ%V* f.|қ.%I{9 .W !D"8N ai*W�y53 �������ahelwer@ah-mbair.local
      Aquí aparecen la versión estándar de la clave v1, el tipo de clave sk-ssh-ed25519@openssh.com, que por alguna razón se repite, y también un nombre de clave legible por humanos, ahelwer@ah-mbair.local
      El resto probablemente sean flags de OpenSSH, por ejemplo si se requiere PIN o presencia del usuario, y un GUID de handle que OpenSSH puede enviar junto con el desafío a la API FIDO/U2F
      OpenSSH puede inferir, por el tipo de clave y en particular por sk, que esta no es una clave privada real sino que debe invocar el elemento de seguridad
      Luego revisa la configuración SecurityKeyProvider o la variable de entorno SSH_SK_PROVIDER para ver desde dónde cargar la biblioteca dinámica que permite comunicarse con ese elemento de seguridad

  • Este artículo parece tratar solo sobre SSH, pero ¿hay alguna forma de usar el Secure Enclave o el TPM de mi computadora como clave FIDO2 o U2F?

    • Claro que sí, y debería funcionar prácticamente con la configuración predeterminada
      Los passkeys también son una forma de este enfoque, usando una clave privada distinta para cada sitio web
  • Viendo esto, se siente raro que no sea más común el soporte para claves API asimétricas o HMAC que puedan vincularse al hardware
    Me alegra ver que van apareciendo más especificaciones que empujan en esa dirección, como WebAuthn, DBSC (Device-Bound Session Credentials) y OAuth2 DPOP