비밀번호를 안전하게 저장하는 현실적인 아키텍처

2011-08-10

이번에 네이트(싸이월드) 해킹 사건을 계기로 주민등록번호나 비밀번호와 같은 것을 안전하게 저장하는 방법에 대해서 생각 해보았습니다. 물론 완전히 안전하게라는 것은 불가능한 이야기입니다. 상대적으로 안전하게 저장하는 방법만을 고민 해 볼 수 있겠습니다.

규모가 있는 업체라면 HSM과 같은 물리적인 보안 장치를 이용 할 수도 있겠지만, 비용을 절감해야 하는 대부분의 스타트업에서는 선택 할 수 없는 해결책입니다. 그렇다면 제일 손쉽게 선택 할 수 있는 것은 소프트웨어적으로 암호화 해서 저장하는 것일겁니다.

우선 복호화가 필요한 데이터라면 AES와 같은 방식을 사용하고 키를 안전하게 보관하는 것이 좋겠지만, 이 경우는 키가 털릴 경우 모든 데이터가 그 즉시 풀리는 문제가 있습니다. 주민등록번호나 패스워드는 사실 복호화 할 필요가 없는 데이터이므로 AES와 같은 암호화는 오히려 보안에 더 안 좋다고 생각됩니다.

다른 방법으로 MD5SHA-1과 같은 단방향 해쉬 함수를 사용하는 방법이 있는데, 이 둘 다 오래된 것이고 이미 취약점이 많이 알려진 상태입니다. 그러므로 현재로서는 SHA-2를 사용하는 것이 낫습니다. 또한 현재 SHA-3가 준비 중이고, 충분히 사용 할만한 구현이 시장이 나온다면 이것을 사용해야 할 것입니다.

이제 SHA-2와 같은 단방향 해쉬 함수를 사용하는 것으로 충분한가라는 의문이 남습니다.

비밀번호는 조금 낫지만 주민등록번호는 워낙 형식이 고정되어 있어 무작위 대입 공격(Brute-force attack)이 쉽게 통합니다. 아무리 복잡한 단방향 해쉬 함수를 사용해도 이 부분은 피할 수 없습니다. 그러므로 적절한 값을 더한 후 해쉬 함수를 적용시켜 무작위 대입 공격에 좀 더 잘 견딜 수 있도록 해야 합니다. 물론 이 값(Salt)은 사용자별로 할당된 무작위 값이어야 합니다. 안 그렇다면 값이 유출 됐을 때 키가 유출됐을 때처럼 쉽게 무너질 수 있습니다.

그렇다면 사용자별로 무작위로 생성된 값을 어떻게 관리해야 할까요?

우선 온라인으로 접근이 불가능한 서버를 한 대 마련합니다. 이 서버는 SSH 데몬조차 띄워놓지 않고 직접 콘솔로만 접근하도록 합니다. 그리고 https 프로토콜을 통해서 사용자별 값을 생성하고, 가져가고, 삭제하는 기능만을 제공하도록 합니다. RESTful 하게 만든다면 깔끔 할 것 같습니다. 물론 IP를 통한 접근 제어는 방화벽과 로직 레벨에서 완전히 최소화 하여 운영합니다. 거기에 특정 계정에 대한 접근 빈도 등에 대한 제한이나 경보를 할 수 있는 로직을 추가적으로 달아주는 것도 고민 해 볼만 합니다.

이렇게 키와 같은 값을 관리하는 서버를 물리적으로 분리하여 접근을 어렵게 하는 것은 어떤 암호화 방식을 사용하더라도 해커들이 데이터를 해석하는 것을 어렵게 합니다. 서버 값이 많이 저렴해졌으니 보안을 위해 별도의 서버 한대 정도 마련하는 것은 대부분 가능하리라 여겨집니다.

완벽한 보안이란 존재하지 않습니다. 그러므로 데이터건 키건 유출될 수 있다고 가정을 하고, 유출 후에 해독을 어렵게 하거나 유출되는데 시간이 오래걸리도록 만들어 그 사이에 탐지될 확율을 높이는 것이 현실적인 대안책이라고 생각합니다.