비밀번호의 진화

비밀번호의 진화과정을 한번 정리해 봅니다.

저장형태

비밀번호를 시스템에 저장하는 형태의 변천을 알아봅니다.

평문 저장

근래에도 아직 소규모 조직에서는 사용하는 방법입니다. RDBMS에 아이디, 비밀번호 컬럼을 두거나, 일반 텍스트 파일에 아이디, 비밀번호를 저장하는 형태입니다.

이 경우는 보안 대책으로는 해당 DB나 비밀번호 파일에 대한 접근 권한을 제어하는 정도로만 관리하였습니다.

crypt 혹은 PBE기법

오래된 버전의 UNIX에서는 현재도 볼 수 있습니다. UNIX에서는 기본적으로 crypt라는 비밀번호 암호화 함수를 제공하였습니다. 참고 Crypt_(UNIX) crypt함수는 비밀번호의 길이가 8자리로 제한이 있으며, passwd파일에 저장된 경우, 파일이 유출되면 쉽게 패스워드를 찾아낼 수 있습니다. 물론, passwd파일은 OS에서 일반 사용자가 내용을 볼 수 있게 되어 있습니다. ( 추후, shadow파일로 비밀번호를 따로 저장하는 강화 방법이 나왔습니다. ) 간단히, a-z0-9{8}조합으로 짧은 시간에 알아낼 수 있겠습니다. 참고 brute force 공격 물론, 영대소문자, 특수문자를 조합하면 조금 더 걸리긴 하겠지만, 8자리 이하에서는 요즘 시스템으로 얼마 안걸립니다.

다른 형태로 개발자가 간단한 대칭키 암호화 기법을 쓰는 경우도 있습니다. 대칭키를 통해 암호화를 하면, 저장된 비밀번호는 사람이 알아보기는 어렵지만, 암호화에 사용되는 대칭키가 노출되면 마찬가지로 쉽게 복호화가 가능할 것입니다.

비밀번호를 저장할 때, 쉽게 알아낼 수 없는 방법이 도입되었습니다. 하지만, 컴퓨터의 연산능력 향상에 따라 지금은 사용하지말아야할 방법입니다.

MD5

이제, 비밀번호를 암호화할 때, 단방향 함수 해시 방식을 쓰기 시작합니다. crypt에 비하여 향상된 보안성을 가집니다. 사용자가 입력한 비밀번호를 단방향 함수를 사용해 나온 결과값을 저장합니다. 사용자가 입력한 비밀번호를 일정 길이로 맞게 자른후(crypt같이 8자리 이후를 무시하는 형태가 아님), 그 값을 단방향 함수를 써서 다시 암호화를 합니다. 그 결과 값은 의미있는 길이를 가집니다.

메시지 요약과정과 단방향 함수의 실행에 따른 연산 증가로 crypt 시절과 같은 brute force형태의 비밀번호 찾기는 어려워 집니다.

하지만, 마찬가지로 노출되면 현재 연산능력으로 비밀번호를 찾을 수 있으며, 해시값을 찾는데는, brute force에서 사용하던 무작위 입력값에 대한 해시를 미리 쌓아두고, 비밀번호 찾기에서는 해당 해시를 비교하여 역으로 비밀번호를 찾을 수 있습니다.

SHA1, SHA2

MD5가 현대 연산능력으로 쉽게 생성 가능하자, 좀더 길이가 긴 값(물론 알고리즘도 강화했겠지요?)을 가지는 SHA1이 나옵니다. ( MD5의 길이나, SHA1, SHA2의 길이나 산술적 안전성은 따로 찾아 보세요 ) 현재 나오는 많은 소프트웨어 들이 SHA1을 지원하고 있습니다. SSL에 사용되는 인증서의 경우도 SHA1이 대부분입니다. 올해 내년을 기하여 SHA1이 저물고 SHA2로 넘어가려고 합니다. SHA2 알고리즘의 경우, 윈도우의 경우 XP는 서비스팩3에서 탑재되었습니다. Oracle Application Server 10g의 경우, SHA2인증서를 지원하지 않습니다.

이제 많은 사람들이 개발할 때, SHA1 정도는 기본적으로 사용하기 시작했습니다. 일부에서 SHA2를 사용하는 곳도 있습니다. SHA2는 512bit도 있네요.

그리고, 앞으로는 SHA3도 개발하고 있나 봅니다.

SHA1, SHA2(보편적인 256이라면)도 MD5시절의 공격에서는 자유롭지 못합니다.

이제는 저장방식보다는 사용자가 실제 사용하는 비밀번호를 복잡하게 사용할 때가 되었습니다. 8자리이상으로 쓰고, 문자조합을 좀더 복잡하게 하면, 해시DB에서 발견될 확률이 좀더 낮아지겠지요?

SSHA(Salted SHA1)

해시값을 비밀번호로 저장하는데, 무작정 긴출력값을 가지는 것으로 가는 것보다, 알고리즘은 SHA1정도로 하되, 해시DB에는 쉽게 노출될 수 없는 방법을 강구하였습니다.

Salted SHA1인데, 해시를 치기 전에 소금을 뿌린다? 간단하게 생각하면, 사용자가 입력한 비밀번호에 시스템에서 임의의 값을 추가로 넣어버리는 것입니다. 그러면, 사용자가 ‘hackernono’같은 비밀번호를 사용하면, SHA1에서는 4ee0d16a918d8f95f5b2027d38c57c9c76094a51 값인데, hackernono에 salt ‘dgkim’을 넣으면 아래와 같은 값이 나오지요. ( dgkimhackernono ) ‘f6b19f964a78bb35ddf12b72c3c8e20ffeeebbb3’ 이 값과 ‘dgkim’을 같이 저장하면, 향후 비밀번호 검증시에는 검증이 가능하지만, 위 값으로는 원래 비밀번호인 hackernono를 찾을 수 없게 됩니다.

salt값을 복잡하고 어느 정도 길이를 가지면, 해시DB에 있을 확률을 확 줄일 수 있겠습니다.

OpenLDAP에서 비밀번호를 저장할 때, SSHA를 사용하고 있습니다.

여기까지가 제가 알고 있는 비밀번호의 진화과정입니다.

인증의 수행

사용자가 입력한 아이디 비밀번호를 확인하는 과정

비밀번호 평문 비교

가장 단순한 형태로, 비밀번호가 평문으로 저장된 경우, SQL에서 아이디 비밀번호를 WHERE조건으로 비교합니다.

비밀번호 해시값 비교

비밀번호 해시 연산을 프로그램에서 수행하는 형태입니다. 개발한 프로그램에서 해시 알고리즘을 정의하고, 인증 및 관리를 하는 형태입니다. 현재 많은 프로그램에서 이런 방식을 사용하고 있습니다.

LDAP Bind 형태

아이디 비밀번호를 사용자가 개발한 프로그램에서 수행하는 것이 아닌, 인증 서버를 통한 방식입니다. Microsoft AD가 대표적인 형태입니다. AD는 사용자 비밀번호 속성의 값을 LDAP인터페이스를 통해 제공하지 않습니다. 그러므로, 비밀번호가 저장된 형태(해시인지 Salt는 있는지)를 AD에서 관리하고, 프로그램에서는 알 수 없게 됩니다. 아이디 비밀번호 인증 부분을 인증서버로 위임할 수 있습니다.

아이디 비밀번호 확인은 LDAP에 두고, LDAP에 인증주체를 Bind하는 방법이 가장 이상적이라 생각합니다.

인증 수단 다양화

kerberos SSO 등

기본적으로 사용자 인증을 위해서는 해당 시스템에 아이디 비밀번호를 관리하는 것이 기초적입니다. 이에서 나아가, 인증정보를 중앙 관리를 하고, 인증 시스템을 통한 인증을 하는 방식입니다. 이럴 경우, 중앙 집중된 인증 서버를 안전하게 관리하고, 정책을 일원화 하며, 개별 시스템의 인증이 쉽게 침입당하지 않도록 합니다.

kerberos는 많이 들어보았는데, 운이 없어서 아직 구현해 보지는 못했습니다.

SSO는 꼭 필요한 것 같기도 한데, 솔루션들에서는 SSO를 아직 지원하지 않고 있습니다.

NPKI

국내에서는 NPKI라는 것을 만들어, 국민에게 개인 인증서를 발급하고, 시스템에서 그 개인 인증서를 통해 인증할 수 있도록 하였습니다.

국가에서 개인에게 부여한 인증서이므로, 내부 통제에는 적절하지 않고, 주민등록번호 시스템과 긴밀하게 연결되어 있고, 그 외 다른 시스템적 연계가 어려우며, 인증기관 특징적인 인증 체계를 가질 수 없게 되어 있습니다.

또한, OS, HTTPS, SMIME등 인프라에 적용할 수 없는 것이 한계입니다. ( 물론, 플러그인 프로그램으로 비슷한 흉내를 내긴합니다. )

ssh-key, SSL Client Cert

원래 UNIX에서는 rsh, telnet등의 명령이 있었으며, 하나의 시스템에서 다른 시스템으로 접근을 하게 되면, 시스템 식별과 사용자 식별로 인증을 수행하여 접근을 허가하였습니다.

rsh가 보편적이지 않고, telnet을 사용할 때는 해당 시스템의 아이디 비밀번호가 인증 수단이며, rsh는 시스템과 아이디만으로 식별 인증하여 사용할 수 있습니다.

ssh는 rsh에 보안성을 강화하고 확장한 프로그램이며, ssh에서는 ssh-keygen을 통해서 비밀번호를 대신하여 개인키를 사용할 수 있습니다.

https에서도 역시 개인인증서를 통해 인증을 할 수 있습니다.

하지만, 윈도우에서는 아직도 비밀번호를 대체하는 수단이 기본 제공되지 않는 것 같습니다. ( AWS에서 linux는 ssh-key가 기본인데, 윈도우는 비밀번호를 줍니다. )

비밀번호를 넘어

개인의 비밀번호 관리 방법 개선

brute force공격이나, 해시DB를 통한 비밀번호 유추를 방지하기 위하여, 개인에게는 아래와 같은 개선 사항이 떨어졌습니다.

  1. 조금더 긴 비밀번호 사용( 4자리 -> 6자리 -> 8자리 -> 이상 )
  2. 복잡한 문자 조합 사용( 숫자 -> 영문숫자 -> 영문숫자특수문자 -> 영대소문자숫자특수문자 )

일부 기관에서는 영대소문자숫자 조합을 강제하는 경우도 있지요.

현 시점에서는 영문 숫자 특수문자 조합으로 8자리 정도면 기본적인 안전성을 가지지 않겠나 생각합니다.

또한, 주기적인 변경을 요구하기도 하지요. 하지만, 비밀번호 정책의 경우는 특정 시스템에서만 가능한 정책보다는, 전체 시스템에 일괄적으로 적용할 수 있는 정책이 우선이라 생각합니다.

인증서 비밀번호도 주기적으로 변경하는 것이 좋긴한데, 잘 바꾸지 않지요.

비밀번호의 변경은 가능하면, 개인의 판단에 맡겨주세요.

보안카드

일반적으로 비밀번호라고하면, 로그인시 사용하는 비밀번호를 얘기하는데, 보안성을 강화한다면, 로그인 비밀번호 뿐 아니라, 추가 보안이 필요한 경우 다른 비밀번호를 추가로 입력받던가, 은행과 같이 ‘이체’와 같은 보안이 더 필요한 작업에 ‘보안카드’와 같은 추가 수단을 사용할 수 있습니다. 전자결재시스템의 경우, ‘결재 비밀번호’를 따로 사용하기도 합니다.

로그인 비밀번호를 통해 한번 인증되면 끝이 아니라, 보안이 필요한 부분에서는 비밀번호를 한번 더 넣게 하던가, 추가적인 보안 요소를 고려합시다.

OTP

현재 가장 안전하다고 생각하는 인증 수단입니다. 일회용 비밀번호. 기술적으로 완전한 보안은 없겠지만, 아직까지는 (보편적인)‘비밀번호’보다는 안전해 보입니다.