2011년 1월 2일 일요일

PASSWORD()와 OLD_PASSWORD() 함수 그리고 old_passwords 설정


MySQL에서 사용자의 로그인 보안 수준을 높이기 위해서,
MySQL 4.0.x 이하 버전과 MySQL 4.1.x 이상 버전의 PASSWORD() 함수의 구현 알고리즘이 달라졌다.
사실 아주 오래전 이야기이지만, 아직도 MySQL 4.0.x를 사용하는 사이트가 많고,
최근 들어서 MySQL 5.1이나 5.5 버전으로 업그레이드를 준비하면서 이런 내용이
업그레이드에 걸림돌이 되는 경우가 많은 것으로 보인다.



MySQL 4.0.x 이하 버전
  - PASSWORD()
  - OLD_PASSWORD() 함수는 없음


  mysql> SELECT PASSWORD('mypass');
  +--------------------+
  | PASSWORD('mypass') |
  +--------------------+
  | 6f8c114b58f2ce9e   |
  +--------------------+


MySQL 4.1.x 이상 버전
  - PASSWORD()         ==> 버전업된 암호화 함수
  - OLD_PASSWORD()     ==> 기존 암호화 (MySQL 4.0.x의 PASSWORD()와 동일)


  mysql>select PASSWORD('mypass');
  +-------------------------------------------+
  | password('mypass')                        |
  +-------------------------------------------+
  | *6C8989366EAF75BB670AD8EA7A7FC1176A95CEF4 |
  +-------------------------------------------+
  
  mysql>select OLD_PASSWORD('mypass');
  +------------------------+
  | old_password('mypass') |
  +------------------------+
  | 6f8c114b58f2ce9e       |
  +------------------------+


위 결과를 보면, 새로운 암호화 알고리즘에 의해서 암호화된 내용은 암호 제일 앞에 "*" 마크가 붙게 되므로, 새로운 암호인지 예전 암호인지 쉽게 구분할 수 있다.


그런데, old_passwords=1로 설정하게 되면, MySQL 4.1.x 이상 버전에서도 아래와 같이 MySQL 4.0.x와 같은 결과를 보여주게 된다.
MySQL 4.1.x 이상 버전에서도, 이전 버전과 동일하게 짧은 암호화 문장으로 변환됨
  root@localhost:(none)>select PASSWORD('mypass');
  +--------------------+
  | PASSWORD('mypass') |
  +--------------------+
  | 6f8c114b58f2ce9e   |
  +--------------------+
  
  root@localhost:(none)>select OLD_PASSWORD('mypass');
  +------------------------+
  | OLD_PASSWORD('mypass') |
  +------------------------+
  | 6f8c114b58f2ce9e       |
  +------------------------+


MySQL 4.1.x 이상 버전에서 old_passwords=0 (기본 설정값)인 경우에는, mysql.user 테이블의 비밀번호가 
예전 버전에서 생성된 짧은 비밀번호라면 로그인할 수 없게 된다.


하지만, MySQL 4.1.x 이상 버전에서도 mysql.user 테이블에 사용자의 비밀번호가 예전 버전인 경우 로그인할 수 있도록 
해주기 위해서 old_passwords 라는 옵션을 1로 설정할 수 있도록 해둔 것이다.


근본적인 원인은 MySQL이 업그레이드되면서 기존 비밀번호의 암호화 수준을 보완하여 더 보안 수준을 높이면서 
이런 문제가 야기되었다는 것이며, 가능하다면 업그레이드된 긴 암호를 사용하는 것이 좋아 보인다.


더 중요한 것은
MySQL의 PASSWORD() 함수는 MySQL의 사용자 자체의 계정 및 비밀번호를 관리하기 위한 함수이지
일반 서비스용 계정및 암호를 관리하는 용도로는 적합하지 않다는 것이다.


예를 들어서 MySQL 4.0.x 버전의 회원정보가 예전 방식의 PASSWORD() 함수로 암호화되어서 저장되어져 있다면,
MySQL 4.1.x 이상의 PASSWORD() 함수로는 로그인이 되지 않게 될 것이다. (이 경우에는 OLD_PASSWORD()를 사용해야만 로그인을 할수 있게 된다.)
하지만, 이 경우 예전 버전의 PASSWORD()함수의 암호화 내용을 새로운 버전의 PASSWORD() 함수로 대체할 수 없다.
(한번 암호화된 문장은 다시 풀어낼 수 없는 형태 - 비대칭형 암호화 - 이기 때문)
서비스용 계정이 MySQL의 사용자 계정 암호화 방식에 의존하게 되면 이런 문제가 야기될 수 있으므로 
필요시에는 MD5와 같은 알고리즘을 사용할 것을 추천한다.


또한, 이렇게 두개 버전의 암호화 방식이 존재하는 상태에서
서비스용 MySQL의 버전 업그레이드와 연관되어서 명확히 해결하지 않고 업그레이드를 진행하게 되면,
일부 사용자의 암호는 예전 버전이고, 또 일부 사용자는 새로운 암호화 버전을 사용하도록 되어버리면
걷잡을 수 없는 혼란에 빠져들고, 이를 처리하기 위해서 또 한번 쿼리와 IF ~ ELSE가 필요해질 수도 있다는 것이다.

댓글 1개:

  1. 아... 덕분에 궁금하던 것이 해결되었습니다. 감사합니다.

    답글삭제