요즘 노트북은 모두 내장 보안 토큰을 갖고 있다

3 hours ago 2
  • 보안 토큰은 개인키를 장치 밖으로 내보내지 않고 장치 안에서 서명하며, 사용자의 물리적 동작을 요구해 원격 공격자가 임의 서명을 만들기 어렵게 함
  • SSH 인증, U2F, 비밀번호 없는 로컬 로그인, sudo, git 커밋 서명에 쓸 수 있고, 최신 노트북·스마트폰의 내장 보안 장치가 YubiKey를 대체할 수 있음
  • ssh-keygen -t ed25519-sk로 만든 “개인키” 파일은 실제 개인키가 아니라 토큰 안 키를 가리키는 핸들이며, 같은 토큰으로 다른 컴퓨터에서도 같은 SSH 키 파일 생성 가능함
  • MacBook에서는 secure element를 SSH 키로 설정해 Touch ID 기반 SSH 로그인이 가능했고, git 커밋 서명에는 파일 경로 대신 ssh-agent와 key:: 형식의 user.signingKey 설정이 필요했음
  • 보안 토큰은 분실 시 개인키를 복구할 수 없고 반복 터치에 익숙해지는 사용성 위험이 있으며, Windows 노트북에서는 Windows Hello가 얼굴 인식·지문·PIN으로 SSH 키 사용을 확인할 수 있었음

보안 토큰의 장점과 한계

  • 원격 공격을 막는 핵심 구조

    • 보안 토큰은 개인키/공개키 쌍을 장치 안에 두고, 공개키는 쉽게 꺼낼 수 있지만 개인키는 장치 밖으로 나가지 않게 만드는 장치임
    • 서명할 데이터 패킷을 장치에 보내면 개인키로 장치 안에서 서명되며, 보통 깜박이는 터치 버튼을 누르는 같은 물리적 사용자 동작이 필요함
    • 원격 공격자가 컴퓨터에 접근해도 사용자가 실제 세계에서 동작하지 않으면 보안 토큰이 임의의 서명을 해주지 않으므로, ~/.ssh 디렉터리에 전체 SSH 개인키/공개키 쌍을 파일로 두는 방식보다 나아 보임
    • SoloKeysNitrokeys처럼 FOSS 펌웨어를 원하는 선택지도 있음
    • 더 고급형 보안 토큰은 내장 지문 리더 같은 생체 인증 기능을 더하지만, 핵심은 개인키를 장치 밖으로 내보내지 않는 구조임
  • 사용성에서 생기는 위험

    • 사용자가 보안 토큰이 깜박일 때마다 누르는 데 익숙해지면, 악의적인 요청에도 무심코 응답할 수 있음
    • 연속 서명 작업 중 토큰을 반복해서 누르는 상황에서는 한 번 더 깜박이는 요청을 실제로 알아차리기 어려울 수 있음
    • Apple과 Microsoft는 스마트폰의 인증 앱에서 접근 요청마다 무작위 숫자 코드를 붙여 사용자가 입력하게 하는 방식을 쓰지만, 이는 번거롭고 TOTP를 쓰는 Authy나 Google Authenticator 앱 대비 보안 토큰의 사용성 이점을 줄임
  • 분실과 백업 문제

    • 보안 토큰을 잃어버리면 해당 개인키는 영구히 사라지고 백업할 방법이 없음
    • 여러 계정에서 잠기는 위험을 피하려면 보안 토큰을 살 때 최소 2개를 사서 같은 서비스에 등록해야 함
    • 대안으로 BIP 39처럼 개인키를 사람이 읽을 수 있는 단어 목록으로 바꿔 적어두는 백업·복원 방식이 있음
    • 개인키가 보안 엔클레이브 밖으로 나갈 수 있으면 사용자가 단어 목록을 잘못된 곳에 쓰도록 유도하는 피싱 공격도 가능해짐
    • 모든 보안 토큰을 잃을 가능성이 크게 걱정된다면 BIP 39 단어 목록이 시스템 접근을 되찾기 위한 최후 수단이 될 수 있음

SSH와 git에서 보안 토큰 쓰기

  • SSH 개인키를 보안 토큰에 두기

    • 일반적으로 ssh-keygen을 실행하면 전체 개인키가 포함된 파일 쌍이 만들어짐
    • 보안 토큰에 개인키를 두려면 Yubico의 FIDO/U2F 지침에 따라 libfido2를 설치하고, 보안 토큰을 꽂은 상태에서 ssh-keygen -t ed25519-sk를 실행함
    • 이때도 파일 쌍이 생성되지만, “개인키” 파일은 실제 개인키가 아니라 보안 토큰 안에 있는 개인키를 가리키는 핸들임
    • 같은 보안 토큰으로 ssh-keygen -t ed25519-sk를 다시 실행하면 어느 컴퓨터에서든 같은 개인키/공개키 파일을 만들 수 있어, SSH 접근 권한이 특정 컴퓨터의 특정 파일이 아니라 보안 토큰과 함께 이동함
  • git 인증과 커밋 서명

    • 보안 토큰을 누르는 상황의 약 90%는 git 사용 때문임
    • git forge들은 push와 pull 작업을 위한 SSH 인증을 구현하고, 위에서 생성한 id_ed25519_sk.pub 파일을 올리면 보안 토큰 키 쌍을 허용할 수 있음
    • git은 커밋 서명에도 SSH 키를 지원하며, GitHub 문서의 SSH 키로 서명 키 설정하기를 따른 뒤 git config --global commit.gpgsign true를 실행하면 모든 커밋이 자동 서명됨
    • git forge가 커밋을 본인 서명으로 인식하려면 공개키를 다시 업로드해야 하며, 이 필드는 보통 SSH 인증용 필드와 별도임
  • 커밋 서명의 불편함

    • 긴 커밋 목록을 rebase할 때는 모든 커밋을 다시 서명해야 함
    • 지문 리더가 있는 YubiKey는 수십 개 커밋을 연속 서명하기에는 지문 인식 실패율이 너무 높아 사용을 중단하게 됨
    • git의 “rebase/amend 중심” 래퍼인 jujutsu에는 push 시점에만 커밋에 서명하는 방법이 있음
  • Linux 로컬 로그인과 sudo

MacBook의 secure element를 SSH 키로 쓰기

  • USB-C 포트에 보안 토큰을 계속 꽂아두면 잘못 떨어뜨리거나 부딪혔을 때 포트와 토큰을 망가뜨릴 수 있는 작은 지렛대처럼 튀어나와 있음
  • 2020년형 M1 MacBook Air에서 Arian van Putten의 지침을 따라 내장 보안 요소를 SSH 키로 설정함
sc_auth create-ctk-identity -l ssh -k p-256-ne -t bio ssh-keygen -w /usr/lib/ssh-keychain.dylib -K -N ""
  • 이 명령은 id_ecdsa_sk_rk 개인키/공개키 파일 쌍을 만들고, 이 파일들을 ~/.ssh 디렉터리로 옮김
  • 여기서도 개인키 파일은 실제 개인키가 아니라 장치 안 키에 대한 핸들이므로 공개적으로 붙여 넣을 수 있는 형태임
  • 홈랩 서버에 공개키를 authorized key로 추가하려면 다음처럼 실행함
ssh-copy-id -i ~/.ssh/id_ecdsa_sk_rk.pub <server nickname>
  • 이후 ~/.ssh/config에 다음 설정을 추가함
Host * IdentityFile ~/.ssh/id_ecdsa_sk_rk SecurityKeyProvider=/usr/lib/ssh-keychain.dylib
  • ssh <server nickname>을 실행하면 로그인 전에 macOS가 지문 요청을 자동으로 띄우고, 이후 SSH 로그인이 정상적으로 진행됨

MacBook secure element로 git 커밋 서명하기

  • git config --global user.signingKey /Users/ahelwer/.ssh/id_ecdsa_sk_rk를 설정하고 .ssh/allowed_signers 파일을 갱신해도 git 커밋 서명은 바로 동작하지 않음
  • git은 커밋 서명에 실패하며, 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
  • 해결책은 ~/.ssh 디렉터리의 파일을 직접 가리키는 대신 ssh-agent를 쓰는 것임
  • 위의 튜토리얼에 따라 다음 명령으로 키 쌍을 ssh-agent에 등록함
ssh-add -K -S /usr/lib/ssh-keychain.dylib
  • 이후 user.signingKey에는 파일 경로가 아니라 ~/.ssh/id_ecdsa_sk_rk.pub 내용 앞에 key::를 붙인 키 자체를 ~/.gitconfig에 넣음
[user] name = Andrew Helwer signingKey = "key::sk-ecdsa-sha2-nistp256@openssh.com AAAAInNrLWVjZHNhLXNoYTItbmlzdHAyNTZAb3BlbnNzaC5jb20AAAAIbmlzdHAyNTYAAABBBGxFEdnIg6ppz+pQCdd1eisjOV4gxrjMv1Y4SbtdLoSm6CJCgPZ6q7lnNyuQQsdnS4/Tllsc656AQL7BO3OS47cAAAAEc3NoOg== ssh:"
  • 이 설정 뒤 MacBook의 secure element에 있는 키로 파일을 서명하고 GitLab Pages 사이트에 push할 수 있었음

Windows와 Linux에서 해본 결과

  • 회사 지급 Windows 노트북에서도 빠른 실험을 진행함
winget install Microsoft.OpenSSH.preview ssh-keygen -t ecdsa-sk
  • 이 명령도 개인키/공개키 파일 쌍을 생성했고, SSH 접속 시 Windows Hello의 표준 로그인 흐름을 통해 얼굴 인식, 지문, PIN 중 하나를 받아들였음
  • Linux에서는 비슷한 실제 사용자 존재 확인 뒤에 secure element가 걸려 있는 노트북에 접근할 수 없어 데모하지 못함
Read Entire Article