IT_Server/네트워크 · 보안

[프로그래머가 알아야 할 보안] HTTPS를 뚫는 자전거 공격

JJun ™ 2016. 1. 15. 06:48



 출처: http://echopedia.tumblr.com/post/프로그래머가-알아야-할-보안-https를-뚫는-자전거-공격




개발자들 중에는 HTTPS/TLS로 암호화된 컨텐츠는 안전하다고 믿는 이가 많을 것이다.
그래서 ID/암호를 평문으로 실어 보내는 사람도 있을 것이고. (과거의 나…;;)

최근 자전거 공격이라는 이름을 붙인 한 페이퍼[1]가 공개되어 궁금증을 참지 못하고 실험해 보았다.
결론적으로 이는 스트림 기반 HTTPS/TLS 암호화의 취약성을 이용하고 있다.
이는 예전부터 보고된 내용[2]으로, 새로운 발견은 아닐테지만 웹어플리케이션에서 어떻게 이용될 수 있는지를
실제로 보여주는 유용한 연구라 말할 수 있다.


스트림 기반 암호화와 블록 기반의 차이는?


먼저 스트림 사이퍼와 블록 사이퍼의 차이점을 알아보자. 스트림은 이름에서 알 수 있듯이 연속적인 비트를 입력받아
대응하는 암호화 비트를 생성하는 방식이다. 함수 f(x)의 형태나, 자판기를 연상하면 쉽게 이해될 것이다.
이에 반해 블록 암호화는 정해진 길이(블록) 단위로 처리한다는 점이 다르다.

<원본 이미지>

<암호화된 이미지>


위 그림을 보면, 암호화가 된 이후에도 대략적인 그림의 형태는 파악할 수 있다.
이를 텍스트라고 가정하면 암호가 유출될 수도 있을 것. 스트림 사이퍼의 특성은 낮은 확산성(Diffusion)을 가진다고 말한다.
하지만 블록 기반의 방식도 블록 길이가 충분히 크지 않다면 일련의 경향성이 드러나는 것을 피할 수는 없을 텐데,
또 이를 해결하기 위한 다른 방법들이 있다고 한다.

원래의 연구 이야기로 돌아가 보면, 널리 사용되는 보편적인 스트림 기반의 방식으로 HTTPS/TLS 통신을 할 경우 각 구성요소의 길이를
따져서 특정 인자의 길이를 유추할 수 있다고. 같은 길이의 컨텐츠에서 항상 같은 갈이로 암호화된 결과가 나온다면 이를 역으로 계산하여
특정 구성 요소의 원래 길이를 찾아낼 수 있지 않을까? 그게 만일 사용자의 암호라면 어떻게 되는 것일까?
소개된 실험은, 이러한 물음에서 시작된 것이었다.


왜 자전거 공격이라 이름 지었나?

위 그림에서 본 것처럼, 암호화를 해 놓아도 모양 판독이 가능하다.
마찬가지로, 자전거는 포장을 해 놓아도 자전거라고 식별할 수 있을테니 이를 빗대어 듣기 좋게 자전거 공격이라 칭한 것이다… 라고
원문 필자가 이야기하고 있다.


어떻게 공격이 이루어지나?


페이퍼에 소개된 내용대로, 가상머신에 워드 프레스를 띄우고, 일련의 로그인 과정을 BurpSuite 도구로 캡처했다.
아래 그림과 같이, HTTP/S 통신 내용을 편리하게 갈무리할 수 있다.

<그림: HTTP/S 통신을 기록하기 위한 프록시 도구 BurpSuite>


많은 이들이 사용하는 Wireshark를 이용하면 아래 그림에서처럼 네트워크 패킷 송수신 상황을 캡처할 수 있는데,
이를 통해 주고 받은 컨텐츠의 순서, 크기 등을 파악할 수 있다.


<그림: 네트워크 패킷 캡처하는 Wireshark>


자, 만일 위 그림과 같이 공격 대상의 패킷 덤프를 확보했다면 로그인 때 ID/암호를 담은 POST 요청이 어떤 것인지 찾아야 한다.
위 그림에서 중간 쯤에 보이는 1212바이트짜리 요청, 바로 저 것인데, BurpSuite에서 확보한 로그인 시의 Request 길이 정보를 가지고
피어슨 상관 계수를 이용, 해당 POST 요청을 찾아낼 수 있다. (각 요청은 암호화할 때 일정한 비율로 크기가 증가한다)

페이퍼에 파이썬 소스가 들어있으니, 데이터 넣고 한번 돌려보면,
Access to wp-login.php detected at element 23 in sequence S

이런식으로 해당 POST 요청을 찾아낼 수 있는 것이다.
그 다음부터는 그냥 더하기 빼기해서 암호의 길이를 알아내는 것. 만약 다섯 글자라고 해보자. 

나처럼 그냥 숫자 12345를 암호로 썼으면 위에 보는 바와 같이, 초당 1,000번의 Brute-force 공격으로 2분 내에 뚫린다.
만약 “자주 쓰이는 암호 100,000개" 등의 사전 데이터로 공격하면 더 빨리 뚫릴 것이다.
이처럼, 암호의 길이만 노출된다고 해도 위험한 일이 아닐 수 없다.


얻을 수 있는 교훈


1. 일단 사용하는 암호는 길면 길수록 좋다. 

2. 개발자라면, 암호를 그냥 네트워크로 흘려보내지 말지어다.
    패딩값을 주던가 고정길이로 해싱을 해서, 혹은 암호화시켜서 원래 암호의 길이를 알 수 없게 해야 한다.

3. 보안은 목적지가 아닌 여정, 영어로 “Security is a journey, not a destination”라고 하더라.
    모든 조직과 사람이 그렇듯이, 보안도 지속적으로 개선해나가야 한다는 말일 것이다.


참고자료

[1] http://blogs.websense.com/security-labs/https-bicycle-attack-obtaining-passwords-tls-encrypted-browser-requests

[2] https://www.ietf.org/archive/id/draft-pironti-tls-length-hiding-02.txt