웹 소켓 API를 이용한 터널링과 캐시 포이즈닝 학술

이 문서에서는 Talking to Yourself for Fun and Profit 논문에서 언급된 공격 벡터들을 다룬다. 최근까지 HTML5 WebSocket 명세가 계속해서 심하게 바뀌어왔는데, 특히 웹소켓 드래프트 구현체에서 발견된 네트워크 우회 공격 벡터가 큰 영향을 미쳤다. 이 때문에 한 때 Firefox 4.0에서는 웹소켓 구현을 기본적으로 비활성화하기도 하였으나, 최종적으로 표준으로 제안된 RFC6455 명세가 Firefox 11과 크롬 16 버전에서 지원되는 것으로 알려져있다.

자바 애플릿이나 플래시, 실버라이트와 같은 RIA 애플리케이션들은 모두 소켓 API를 지원한다. 웹소켓은 별도의 플러그인으로 제공되던 소켓 API를 웹 브라우저에 표준적으로 내장하려는 시도이다. 플러그인들이 소켓 API를 제공할 때에는 보안 문제를 야기하지 않도록, 컨텐츠를 다운로드한 서버로만 접속 가능하게 하거나 (자바 애플릿), 별도의 크로스도메인 정책 파일(crossdomain.xml 또는 clientaccesspolicy.xml)을 먼저 다운로드하여 허용된 위치로만 소켓으로 접속할 수 있도록 하는 방식(플래시, 실버라이트)으로 접근 제한을 수행한다. 게다가 실버라이트의 경우에는 TCP 4502-4532 범위로 포트 접속을 제한하고 있다.

이러한 접근제한 방식이 완전한 것은 아니어서, 예전에 DNS Rebind가 이슈가 되었던 적이 있다. 가령, 공격자의 웹사이트에서 내려받은 RIA 컨텐츠를 실행할 때 TCP 소켓 접속을 시도하면서 액세스 정책을 내려받은 시점에 DNS 캐시가 만료되고, 다시 DNS 조회하게 될 때 공격자가 방화벽으로 보호되는 내부 서버의 IP를 반환하여 일종의 터널을 만들 수 있다. 이 이슈는 정책을 내려받은 시점의 DNS 조회 결과를 사용하게 함으로써 해결할 수 있었다.

이 논문에서 제기한 취약점은 투명 프록시의 동작을 악용하는 것이다. 웹 캐싱/가속이나 L7 트래픽 필터링을 수행하는 네트워크 장비가 트래픽 관문에서 동작하는 경우가 많은데, 이런 류의 장비는 사용자가 존재유무를 인식할 수 없도록 투명하게 동작하기 때문에 투명 프록시(Transparent Proxy)라 불린다.

논문에서 가져온 아래 도식을 살펴보자.


그림 1은 IP 하이재킹의 과정을 나타낸 것이다. 만약 중간에 위치한 프록시가 Host 헤더를 기반으로 라우팅을 수행한다면 아래와 같은 순서대로 공격 가능하다.
  1. 공격자는 attacker.com:843으로 플래시 소켓 정책 서버를 운영하는데, 이 서버는 출발지에 관계없이 임의의 포트로 접근 가능한 액세스 정책을 반환한다.
  2. 공격자의 SWF가 IP 2.2.2.2를 가진 attacker.com:80으로 소켓 연결을 시도한다.
  3. 플래시 플레이어는 액세스 허용 여부를 결정하기 위해 먼저 공격자의 정책 서버에 접속하여 정책을 다운로드하고 정책에 따라 attacker.com:80에 대한 소켓 접속을 허용한다.
  4. 공격자의 SWF는 아래와 같이 HTTP 헤더 바이트를 쓴다:
    GET / HTTP/1.1
    Host: target.com
  5. 투명 프록시는 이를 HTTP로 해석하고 목적지 IP가 아닌 Host 헤더에 따라 라우팅을 수행한다. 즉, 요청이 1.1.1.1 IP를 가진 target.com:80으로 전달된다.
  6. 내부 클라이언트 IP 주소로부터 요청이 왔기 때문에 target.com 서버는 정상적으로 요청에 대한 응답을 반환한다. 내부 정보가 프록시를 거쳐 공격자의 SWF로 전달된다.
Host 헤더가 목적지 IP와 일치할 것이라는 가정이 깨졌기 때문에 이와 같은 공격이 가능하다. 만약 GET 대신 CONNECT를 쓴다면 방화벽을 우회하여 터널링도 가능해진다. 내부 클라이언트의 IP를 이용하기 때문에 내부망 출발지를 신뢰하는 보안 정책은 무용지물이 된다.


그림 2는 프록시의 캐시를 오염시키는 과정을 나타낸 것이다. 위의 경우에는 Host 헤더에 따라 라우팅한다고 가정했지만, 여기에서는 프록시가 경로 결정 과정에서 Host 헤더를 무시하고 원래의 목적지 IP에 따라 라우팅하는 경우를 상정한다. 이 경우에 IP 하이재킹으로부터는 안전하지만, 공격자가 의도한 임의의 URL로 프록시의 캐시를 오염시킬 수 있다.
  1. 공격자의 자바 애플릿이 attacker.com:80으로 연결을 시도한다.
  2. 이전 예와 마찬가지로 HTTP 요청을 전송한다. 
    GET /script.js HTTP/1.1
    Host: target.com
  3. 투명 프록시는 이를 HTTP 요청으로 해석하고 원래 목적지 IP로 라우팅한다. 즉, 공격자의 서버로 HTTP 요청이 전달된다.
  4. 공격자는 Expires 헤더를 매우 길게 잡아서 악성 스크립트 파일을 반환한다.
  5. 프록시는 Host 헤더를 기준으로 캐시하기 때문에 원래 http://attacker.com/script.js 이지만 프록시에 http://target.com/script.js로 캐시된다.
  6. 이제 해당 프록시를 통과하는 모든 클라이언트가 악성 스크립트를 받게 된다.
이전 HTML5 웹소켓 드래프트 명세들도 위의 모든 문제들을 가지고 있었으며, 최종 버전에서는 XOR 마스킹을 이용하여 공격자가 제어 가능한 바이트 영역을 없애버렸다. 자세한 내용은 RFC 6455를 참고하기 바란다.

트랙백

이 글과 관련된 글 쓰기 (트랙백 보내기)
TrackbackURL : http://www.xeraph.com/tb/5590591 [도움말]

덧글

댓글 입력 영역