보안정보

[CVE-2017-7546] PostgreSQL non-libpq Client Policy

침해사고분석팀 2017.09.01

개요


PostgreSQL Database에 보안 우회 취약점이 존재한다. 해당 취약점은 libpq를 사용하지 않는 사용자 계정에 빈 패스워드가 있는 경우를 제대로 검증하지 않아 발생한다.
 
 
[CVE 정보]
CVE-2017-7546
 
[취약한 버전]
PostgreSQL PostgreSQL 9.6.x prior to 9.6.4
PostgreSQL PostgreSQL 9.5.x prior to 9.5.8
PostgreSQL PostgreSQL 9.4.x prior to 9.4.13
PostgreSQL PostgreSQL 9.3.x prior to 9.3.18
PostgreSQL PostgreSQL 9.2.x prior to 9.2.22
 
[취약한 함수]
md5_crypt_verify()
 
 
 

확인 내역

 
해당 취약점은 사용자 계정에 빈 패스워드가 존재함으로 발생한다. 이를 확인 하기 위해선, PostgreSQL 통신 절차를 살펴 볼 필요가 있다.
 
 
1. Client -> Server : Startup Message
 
먼저, PostgreSQL 세션을 맺기 위해선 클라이언트에서 Startup Message를 보냄으로 세션이 처음 시작되게 된다. Startup Message 구조 및 예제는 다음과 같다.
 
[Startup Message]

Offset Length Description 
(Bytes) (Bytes)
 -------------------------------------- 
0x00 0x04 Length 
0x04 0x04 Protocol Version 
0x08 N Parameter1 Name 
0x08+N 0x01 Delimiter (0x00) 
0x08+N+1 M Parameter1 Value 
0x08+N+M+1 0x01 Delimiter, (0x00) 
... ... ... 
Length-1 0x01 Final Delimiter (0x00) 


[예제]
x00x00x00x00 
x00x03x00x00 
userx00example_userx00 
databasex00example_databasex00 
application_namex00psqlx00 
client_encodingx00UTF8x00x00 
 
 
Startup Message 바로 뒤에 나오는 Message 구조는 다음과 같다.
 
[Subsequent Message]

Offset Length Description 
(Bytes) (Bytes) 
-------------------------------------- 
0x00 0x01 Message Type 
0x01 0x04 Message Length 
0x05 N Message Contents
 
 
 
 
2. Server -> Client : Authentication Request Message
 
 
Startup Message 를 받은 서버에서는 Authentication Request Message를 클라이언트에 보내게 된다. 
 
[Authentication Request Message]

Offset Length Description 
(Bytes) (Bytes) 
-------------------------------------- 
0x00 0x01 0x52 ("R") 
0x01 0x04 Message Length 
0x05 0x04 Authentication Method 
0x09 N Additional Parameters (optional)
 
여기에서 Authentication Method 필드는 클라이언트를 인증하기 위해 사용되는 것으로, 이번 취약점과 관련된 Method는 2가지가 존재한다.
 
1) Plaintext password(0x00000003)  2) MD5 password (0x00000005)
 
Authentication Method가 MD5 password로 설정 된 경우, Additional Parameters 필드에 무작위로 생성된 4byte salt 값이 포함 된다.
 
 
 
3. Client -> Server : Password Message
 
Authentication Request 메시지를 받은 클라이언트는, 이에 해당하는 Response Message를 보내게 된다. 여기에서 Method 필드가 위에서 설명한 2개 중 하나가 설정 되어 있는 경우 응답 메시지로 Password Message를 보내게 된다.
 
[Password Message]

Offset Length Description 
(Bytes) (Bytes) 
-------------------------------------- 
0x00 0x01 0x70 ("p") 
0x01 0x04 Message Length 
0x05 N Passowrd 
0x05+N 0x01 Delimiter (0x00) 
 
Password 필드 값은 클라이언트의 plaintext password 또는 이전에 전송 된 salt 값, 사용자 이름, 사용자 비밀번호를 사용하여 계산 된 MD5 hash 값으로 구성된다.
 
여기에서 MD5 hash 값을 구하는 계산 절차는 다음과 같다.
 
initial_hash = md5(password + username).hexdigest() 
final_hash = 'md5' + md5(initial_hash + salt).hexdigest() 
 
 
통신 절차를 확인 하였으므로, 이제 실제로 공격 패킷을 통해 취약점이 어떻게 발생하는지 살펴보도록 하자.
공격 예시는 Plain Text password의 경우에 대해서만 살펴보도록 하겠다.
 
 
[그림1] Plain Text Password의 경우
 
위 패킷의 파란색 부분을 Password Message 구조에 맞춰서 작성해보면 다음과 같다.
x70
x00x00x00x05
x00
 
여기에서 우리는 패스워드 값이 설정되어 있지 않는 것을 확인 할 수 있다. 
 
 
 
 

대응방안

 
해당 벤더사에서 제공한 보안 권고문을 참고하여, 취약한 버전에 대해 패치를 진행 한다.
https://www.postgresql.org/about/news/1772/
 
 

 

참고

https://www.postgresql.org/about/news/1772/

http://www.securityfocus.com/bid/100278

http://securitytracker.com/id?1039142