본문 바로가기

Let's Study/Vulnerability

Poodle [padding oracle on downgraded legacy encryption]

이걸 전주에서 발표한 지 2달쯤 지난 것 같은데 그 후로 너무 바빠서 지금 포스팅을 하게 되네요.






 10월에 잠깐 이슈가 되었던 푸들어택은 POODLE(Padding Oracle On Downgraded Legacy Encryption)의 약자로  TLS 프로토콜을 SSLv3로 다운그레이드시켜 패딩오라클 어택을 합니다.


 사실상 이 공격은 2011년의 BEAST(Browser Exploit Against SSL/TLS) 어택과 비슷하다고 보면 됩니다. 결국은 패딩을 이용한 공격으로 사용자의 정보를 가로채는 기술이니까요. 푸들은 2014년 10월 14일, 구글보안팀의 Bodo moller, Thai duong, Krzytof kotowicz가 공개했습니다. TLS 프로토콜을 사용하는 클라이언트와 서버의 핸드쉐이크 과정에 끼어들어 TLS가 아닌 SSL 3.0으로 다운그레이드시켜 통신데이터의 일부를 해커가 해독하는데 이 취약점을 이용할 수 있습니다.


 푸들과 비슷한 예로 BEAST attack과 Lucky 13 attack이 있는데 이 공격들도 마찬가지로 서버를 리모트하는 공격은 아니고 CBC 블럭암호 구조를 이용해 공격합니다.


 TLS는 SSL를 표준화하는 과정에서 지어진 새로운 이름인데, 이 TLS는 SSL을 사용하는 시스템과의 연동을 위해 SSLv3을 지원합니다. 그렇기 때문에 TLS는 SSL과 하위호환이 되어 TLS도 푸들어택에서 결코 안전하지 않습니다.

 *SSLv3에서 TLS1.0으로 새로 명명됬을 뿐 구조는 비슷합니다. 그래서 하위호환이 된다는 표현을 썼습니다.




 푸들은 HeartBleed나 ShellShock에 비하면 상대적으로 덜 위험하지만 사용자 브라우저에서 쿠키 정보 등을 빼낼 수 있는 공격으로 이어질 수 있는 만큼 주의가 요망되고 있습니다. 그림에 보여지는 숫자는 위험도 수준을 나타내고 있습니다. 6이어도 무시를 할 수 없는건 , 일단 SSL은 18년 전에 최초로 개발되었다는 점에서 브라우저나 서버, 인터넷 상거래 등 다방면으로 사용되고 있습니다. 근데 SSL은 지불카드 트랜잭션을 위해 특별히 만들어진 게 아니라 클라이언트와 서버 간의 포괄적인 안전한 통신을 위해 개발된 겁니다.


 푸들어택은 사용자의 컴퓨터를 해킹하는 것은 아니고 암호를 크랙하는 데, 예를 들어서, 어떤 사용자가 페이팔(해외온라인 결제대행 서비스를 해주는 사이트)을 이용할 때 아이디와 패스워드를 입력하는데 악의를 품은 공격자가 페이팔 사용자의 쿠키를 가로채서 그 사람의 아이디를 쓸 수 있습니다. 아이디를 쓸 수 있다는 건 그 사람의 카드를 마음대로 긁을 수 있다는 뜻이 됩니다.

 아무튼, 푸들어택으로는 이런 걸 할 수 있고


 요즘에는 "SSL은 죽었다" 는 표현을 쓰면서 SSL을 안 쓰려고 하죠. 예전 사례로 SSL Strip, THC-SSL-DOS, 500개가 넘는 가짜 SSL 인증서가 탄생해서 최상위 보안인증 기관이 파산했던 디지노타 유출사건, openssl 취약점인 HeartBleed, 그리고 이번엔 공개된 Poodle. 이것들 외에도 SSL 취약점은 여러개가 있겠지만 이제 SSL을 이용하는 건 더이상 안전하지 않다고 여러 측에서 생각을 하고 있습니다. 




 모 사이트에서는 sha1 알고리즘을 2로 바꾼다는 공지도 있고 파이어폭스, 마소, 구글같은 경우는 SSL 인증서 지원을 중지하는 계획이 있습니다. sha1 알고리즘이 SSL 인증서의 98%를 차지하고 있어서인지 더는 손놓고 볼 수 없다는 것 같습니다.


 그럼, SSL이 뭘까요? SSL은 인터넷 내에서 가장 중요한 보안 프로토콜입니다. 서버와 클라이언트 사이에서 암호화 연결을 사용하고 있는데 푸들어택은 SSL에서 일어나는 버그입니다. 불행하게도, 많은 사용자와 서버가 가장 일반적으로 지원하는 게 SSLv3입니다. SSL은 네트워크 내에서 메시지 전송의 안전을 관리하기 위해 넷스케이프에 의해 만들어진 프로그램 계층입니다. 




 그림을 보시면 HTTP와 TCP 사이에 SSL이 있는데 간단하게 설명하자면 레코드 프로토콜은 데이터를 압축해서 안전하게 tcp패킷으로 변환하고 데이터 암호화 및 무결성을 위한 메시지 인증을 하는 프로토콜입니다. 이걸로 handshake, change cipher, alert, application protocol을 감싸주고 나머지 4개의 프로토콜은 그냥 handshake로 어떤 프로토콜을 쓸 지, 예를 들어 SSLv3이라거나 TLS1.0 ~ 1.2 같은 거, 그리고 암호화 알고리즘을 결정하고 change cipher 프로토콜로 이 결정된 것들을 쓰겠다 라고 알립니다.


 


 위 그림은 앞에서 설명드렸던 handshake부터 change cipher 프로토콜 과정을 보여줍니다. 근데 위의 client hello 과정에서 SSL 버전번호와 암호 선호 사항 등 클라이언트가 사용할 수 있는 조합리스트를 서버로 제시하는데 해커는 여기서 정보를 가로채서 Downgrade Dance를 시도합니다.




 Downgrade dance 과정은 일단, 클라이언트가 서버에게 client hello에 최신 프로토콜인 TLS 1.2를 보내는 데 중간에 해커가 그 정보를 가로채서 패킷을 드랍시키고 서버에게 현재 연결을 종료시키는 패킷을 보냅니다. 클라이언트 쪽에서는 TLS 1.2가 서버에서 지원이 안되나보다 하고 한단계 낮은 TLS 1.1을 날립니다. 이것도 해커가 가로채서 패킷을 드랍시킵니다. 이렇게 한 단계씩 내리다보면 SSLv3까지 내려오게 되는데 그제서야 해커는 서버에게 이 패킷을 날려서 SSLv3을 사용하도록 유도합니다.

* 이 방법 외에도 다운그레이드 하는 방법은 몇 가지 더 되고, 제가 적은 건 다운그레이드 방법의 한 예입니다.




 SSLv3으로 내려가면 패딩오라클 어택을 시도할 수 있습니다. 위 그림은 CBC mode encryption을 나타냈는데 평문 한 블록을 임의의 초기벡터와 xor 연산을 해서 나온 임의의 값을 특정 키값과 블럭암호화를 합니다. 생성된 암호문 1을 다음 평문과 xor하여 또 다른 암호를 2를 만들고.. 이렇게 블록암호화 하면서 암호문을 생성하는 게 cbc encryption인데, 블럭암호화를 하면 패딩ㅇ값이 무조건 1바이트 이상 나오게 됩니다.




 예를 들어 표현한 건데 블럭암호화를 하지 않았을 경우와 암호화를 했을 때를 나타내는 표입니다. 1번은 Shayete라는 7바이트 값이 블럭에 들어가 있습니다. 근데 블럭암호를 했을 때 블럭의 마지막 1바이트에 패딩값이 채워지게 됩니다. 마찬가지로 4바이트 값이 들어가 있다면 패딩값 4바이트가 채워지게 되고 블럭에 8바이트 꽉꽉 채워져있으면 그 다음 블럭에 8바이트의 패딩값이 들어갑니다. 8바이트 이상의 값이 있어도 그 다음 블럭에서 똑같이 패딩값이 생성되고요. 이 패딩으로 어떻게 값을 알아낼 수 있냐고요?




 cbc decryption마저 보고 설명드리겠습니다. 복호화는 암호화와 반대로 진행됩니다. 암호문을 특정 키값과 블럭암호화해서 생성된 임의의 값과 임의의 초기벡터를 xor연산해서 평문으로 복호화합니다. 처음의 암호문1로 다음 임의의 값과 xor연산해서 다음 평문을 복호화시키고요. 이 과정이 cbc decryption입니다. 지금까지 encryption, decryption을 설명드렸는데 이걸로 뭘 할 수 있을까요. 패딩값을 이용하는 것과 cbc mode의 구조의 결함을 가지고 공격을 하게 됩니다. 평문을 얻어내려면 초기벡터값과 임의의 값 intermediary값이 필요한데, 




 공격자는 중간에 빼온 값들을 xor 연산해서 intermediary 값을 얻게 되는데 이 과정에서 암호문이 옳다면 서버는 200ok 표시되고 패딩값은 맞는데 잘못된 값을 받았을 경우 200ok custom error를, 그리고 패딩값이 잘못된 값을 받았을 땐 500 에러가 뜹니다. 초기벡터값을 브루트포싱으로 진행하다보면 올바른 intermediary 값을 얻게 되는데 이걸 이용해서 평문을 복호화시킵니다. 위 그림을 보면 예를 들어 패딩값이 1개 있을 때 브루트포싱으로 쭉 돌리다가 초기벡터가 0x36일 때 서버에서 200ok를 보내 패딩값을 알아낸 것을 볼 수 있고 2번째는 패딩값이 4개일 때, 마지막은 패딩값이 8개일 때 올바른 intermediary값을 찾은 걸 볼 수 있습니다.




 패딩오라클의 전체적인 모습을 그림으로 표현해봤습니다. A의 값과 B를 xor하면 intermediary C가 나오게 되는데 이것이 Original 값의 D와 일치하다고 판단하여 평문인 E를 얻게 됩니다. 이런식으로 브루트포스를 진행해서 완벽한 평문을 얻어내는 게 패딩오라클 어택입니다. 



푸들어택에 대한 대처방안은,


 크롬에서는  --ssl-version-min=tls1 을 이용해서 버전이 내려가는 걸 막는 방법이 있습니다. IE에서는 인터넷 옵션에서 ssl3.0으로 내리는 것을 막을 수 있고요. 공용 와이파이를 쓰지 않는 것과 TLS_FALLBACK_SCSV 옵션을 사용하는 방법이 있습니다. 그리고 마소에서 푸들을 막기 위해 임시용 프로그램을 만들어 둔 것 같은데 그것도 방법 중의 하나입니다.


--ssl-version-min=tls1 이건 인터넷 검색해보면 여러 군데에서 설명을 해뒀으니 따로 적지 않겠습니다.


TLS_FALLBACK_SCSV는 



만약 프로토콜이 내려가는 것을 감지하면 inappropriate_fallback 경고 메세지를 보내서 다운그레이드를 방지할 수 있는 방법입니다.

(위 코드는 어느분 자료에서 긁은 건데 무단으로 사용해서 죄송합니다.)



여기까지 푸들어택에 대한 글을 마칩니다.