Alpine Linux OpenSSH 서버, 비밀번호 없이 로그인되는 인증 우회 공개 (musl crypt() 오류값이 원인)
- musl libc의 crypt()가 256바이트를 넘는 키에 오류 표시로 별표 문자를 반환하는데, 비밀번호 없는 계정의 shadow 비밀번호 필드 값도 같은 별표라 해시 비교가 통과해 비밀번호 없이 로그인이 성립함. 공격자는 257~1024바이트 비밀번호를 한 번 보내면 되고 재시도도 필요 없음
- openssh-server를 PAM 없이 빌드해 쓰거나 UsePAM no인 openssh-server-pam을 쓰고, PasswordAuthentication이 기본값 yes이며, 비밀번호 필드가 별표인 계정 하나와 또는 해시 계정 하나가 있으면 영향받음. 확인한 Alpine 3.16~3.24와 edge 전부 해당
- openssh-server-pam에 UsePAM yes를 쓰거나 PasswordAuthentication no이거나, 잠긴 계정(비밀번호 필드 !)만 있거나 $ 해시 계정이 하나도 없으면 안전함. cloud-init으로 설정한 클라우드 이미지와 컨테이너 안에서 sshd를 안 돌리는 Docker 사용자도 영향 없음
- 공식 tiny-cloud 이미지 3.18.11~3.24.3은 비밀번호 필드가 별표인 alpine 사용자와 비밀번호 없는 doas를 넣어 배포했고, 관리자가 콘솔 비밀번호를 정하는 등 해시가 생기는 순간 공격자가 alpine 셸에서 doas로 root까지 올라감
- edge 10.6_p2-r0부터 3.16의 9.0_p1-r6까지 수정 패키지가 나왔고 apk upgrade -U -a 뒤 rc-service sshd restart로 데몬을 다시 시작해야 함. 패키지만 올리면 실행 중인 sshd가 그대로 남고, CVE 번호는 아직 부여되지 않음
Hacker News 의견들
musl crypt()가 키가 256바이트 넘으면 오류 표시로 별표 문자를 반환하는데, 비밀번호 없는 계정 shadow 필드도 똑같이 별표라서 해시가 맞아버림. POSIX는 실패하면 NULL을 반환하고 errno를 설정하라고 하는데, POSIX 준수로 유명한 musl이 왜 이랬는지 모르겠음.
이 버그가 수십 년에 걸쳐 어떻게 만들어졌는지 sshhole.com에 추적이 자세히 나와 있음.
솔직히 스펙에서 위험하게 벗어난 그냥 버그임.
NULL 체크를 안 해서 크래시 나는 코드 때문에 그렇게 했다는 얘기가 있음. 남의 잘못된 코딩을 스펙 이탈로 감싸주는 건 이상한 선택이지.
2026년에 아직 C 쓰는 게 이해 안 됨. 이 정도면 Rust 같은 걸로 옮겨야 하는 거 아님?
언어를 바꾸면 이게 어떻게 해결됨? 이건 순수 로직 버그라서 Rust로 짜도 Go로 짜도 crypt가 별표를 반환하면 똑같음.
Rust의 Result도 못 막음. 에러 타입을 String으로 만들면 그냥 끝이고, sentinel 값 실수는 Rust에서도 충분히 나옴.
musl 개발자들이 언어를 바꾸게 만들 그 압력이 정확히 뭐임? 그런 게 있음?
예전엔 NULL을 반환했는데 편의를 위해 바꿨다는 얘기가 있더라.
Alpine이랑 musl은 쓰면 안 된다고 계속 말하는데, 사람들은 정적 링크가 좋다고 답하고 끝임.
Docker 생태계에서 Alpine이 워낙 널리 쓰여서 많은 사람이 맞을 거임. 그래도 컨테이너 안에서 sshd 돌리면서 비밀번호 인증 켜둔 사람은 별로 없긴 함.
컨테이너에서 SSH를 밖으로 노출하는 경우가 거의 없어서 체감 타격은 생각보다 작을 수도 있음.
Alpine 기본 이미지가 root에 별표를 달고 오는데, 기본 PermitRootLogin prohibit-password라 root 자체는 막힘. 문제는 doas로 root가 될 수 있는 다른 계정임.
Docker 컨테이너 앱들은 베이스 이미지 업데이트가 느려서 이게 진짜 아픔.
글 문장이 AI 티가 난다는 지적도 있었음. Either one closes the hole 같은 표현이나 공격자를 자랑하는 듯한 어조가 그렇다고 함.
나는 SSH 인증서만 써서 이번엔 안 걸렸음.
하드웨어에 Alpine 쓰는데 키 로그인만 쓰고 비밀번호 없는 계정이 없어서 영향 없었음.