오늘 아침에 보니 어제 올린 TCP 스택 취약점 이슈를 다룬 글이 insecure.org에 올라와있더군요. Nmap을 개발한 Fyodor 씨가 쓴 글인데, 자기 생각으로는 별 새로울 것도 없는 오래된 취약점이라고 하면서 아주 상세하게 글을 올렸습니다. 읽어보니 확실히 지금까지 올라왔던 모호한 기술들이 다 들어맞더군요. 이 글이 이번에 Louis 씨가 주장하는 취약점을 정확하게 설명한다고 확신할 수는 없겠지만, 명쾌하게 쓴 글이고 그냥 읽어보는 것도 TCP 스택을 이해하는데 도움이 될 것이라 번역해서 소개합니다. 그나저나 Fyodor 씨는 "세부 사항은 나중에 발표하겠다"는 식의 미디어 장난질을 상당히 싫어하는 것 같네요.

설명

여러분은 아마 Nmap Security Scanner 개발자로 저를 잘 알고 있을 겁니다. 2002년에 저는 TCP 서비스를 대상으로  DoS 공격을 수행하는 Ndos ("Network Denial of Service") 라는 이름의 유틸리티를 만든 적이 있습니다. 이 유틸리티는 TCP를 사용하는 어플리케이션이나 OS 커널의 리소스를 고갈시키도록 만들어졌습니다. 리소스 고갈시키는 방법이야 여러가지가 있을 수 있겠지만, 제가 썼던 방식은 어플리케이션과 TCP 스택의 한계치까지 소켓을 열어버리는 것이었죠. 그러니까 커널 안에 존재하는 TCP 전송 버퍼와 동시 프로세스 제한 같은 것들 말입니다. 이 프로그램을 컨설팅할 때 썼었는데, 뭐 고객이 입금을 미뤘다거나 해서 썼던 것은 아니고 :) , DoS 공격을 얼마나 잘 견딜 수 있는지 테스트하길 원하는 고객이 있어서 만들었던 겁니다. Robert와 Jack처럼 저도 얼마나 이 기법들이 서비스 다운시키는데 효과적인가를 보고 놀랐었죠. 이 간단한 공격만으로도 웹 서버가 정상적으로 서비스를 수행하지 못하도록 만들 수 있습니다. 약간만 더 꼬아놓으면 운영체제 자체를 맛이 가게 할 수 있었죠.

기본적인 아이디어는 이렇습니다. iptables 등을 이용하여 여러분의 IP 주소를 방화벽에서 막아버립니다. (아래 2번에서 이유를 설명합니다.) 그 다음에 아래와 같이 작업해서 수백 개나 수천 개 정도의 TCP 연결을 만들어냅니다:

  1. 공격자는 자신의 IP 주소를 출발지에 써넣은 정상적인 TCP SYN 패킷을 목표에게 전송합니다.
  2. 목표하는 포트가 열려 있으면 SYN/ACK 패킷을 응답하겠죠. 공격자가 SYN 패킷을 raw 소켓을 써서 전송한 상태라고 하면, 공격자의 운영체제 입장에서는 예기치 못한 SYN/ACK 패킷을 받은 것이므로 자연스레 RST 패킷을 보내면서 연결을 끊어버리게 됩니다. 이런 원하지 않는 동작을 막기 위해 방화벽에서 자신의 IP가 목적지로 된 패킷을 차단합니다. 대신에 libpcap 등을 써서 패킷 스니핑으로 데이터를 읽고 raw 응답 패킷을 만들어 전송하면 됩니다.
  3. SYN/ACK 패킷에 포함된 정보를 이용하여 ACK 패킷을 보내면서 접속을 완료합니다.

알다시피 모든 TCP 연결은 시스템에서 중요한 자원을 사용합니다. (커널 TCP 스택의 상태 정보들, 응용 프로그램 메모리, 소켓 디스크립터 등) 게다가 많은 서버들은 TCP 연결이 들어올 때마다 프로세스를 하나씩 fork 하게 되어있죠. 공격자 측은 상대적으로 리소스를 별로 소모하지 않습니다. 서버에서 리소스가 다 고갈될 때까지 계속 연결을 만들어내기만 해도 됩니다. 공격자 입장에서는 연결 하나에 소스 포트 하나를 매핑해야 하니까 대충 IP 하나로 6만 5천 개 정도의 연결을 만들어 낼 수 있죠.

이렇게 수천개 정도의 연결을 만들어 놓은 상태에서 목표하는 서비스에 맞게 커스터마이즈된 악성 데이터 페이로드를 실어보내면 공격 효과가 훨씬 좋아집니다. 예를 들면 웹 서버에 연결된 상태에서 커다란 파일을 요청한다고 생각해봅시다. 서버의 운영체제 TCP 스택에서는 파일의 첫번째 부분을 커널 메모리에 버퍼링한 상태에서 네트워크를 통해 데이터를 전송하겠죠. 그런데 공격자가 ACK 패킷을 안 보내면 이 버퍼를 회수할 길이 없게 됩니다. 요청 한 번 보낼 때마다 커널 메모리라는 중요한 리소스가 줄줄 새는거죠. 저는 많은 운영체제들이 이 공격으로 인해 메모리가 고갈되면서 재부팅되는 것을 보았습니다. 저는 고객들에게 커널 maxusers 변수 값을 늘리라고 조언합니다. 공격자가 TCP 윈도우 사이즈를 늘리면 공격이 더 효과적일 겁니다. 공격자의 대역폭이 얼마 안 된다면 이렇게 하기 힘들테니, 이 경우에는 작은 윈도우 사이즈로 목표 시스템에 자주 전송하는 편이 낫겠죠.

이 공격을 살짝 바꾸면 다른 종류의 리소스도 고갈시킬 수 있습니다. 가령 웹페이지를 동적으로 만들어 내는 경우 이 페이지를 요청하면 CPU가 소모되겠죠. 이런 것들은 그냥 기본적인 공격에 약간 변화를 준 것에 불과합니다.

FAQ

이게 정말 새로운 발견인가요?

Robert와 Jack이 이전 레퍼런스를 못 봤던 것 같습니다. 제가 처음으로 만들어 낸 공격 기법도 아닙니다. 사실 TCP/IP 네트워킹을 잘 알고 있는 사람이라면 아주 당연한 얘기죠. PoC 코드는 2000년 4월 Stanislav Shalunov 씨가 Bugtraq에 포스팅했었고요. 같은 해 12월에 이를 더 심도있게 조사한 "Naptha" 연구가 있었어요. Robert와 Jack이 한 일은 이 오래되고 심각한 문제에 관심을 일으킨 것이죠. 뭐 저는 이게 인터넷에 아주 심각한 위협이라고 생각하지는 않지만, 해결해야 할 문제라고 생각하고 있습니다.

이게 어떻게 Robert와 Jack이 찾은 것과 같은 버그라는 것을 아셨나요?

전 모릅니다. 아직 전말을 공개하지도 않았는데 알 수가 없죠. 하지만 저는 지금까지 공개된 이야기와 완벽하게 일치하기 때문에 이게 맞을거라고 생각하고 있습니다. Robert와 Jack은 똑똑한 친구들이니까 이 버그를 써먹는 방법을 몇 가지 더 찾아냈다고 해도 뭐 별로 놀라지 않을 겁니다. 하지만 위에 설명한 것만으로도 이미 충분히 위협적이죠.

완전히 다른 버그를 찾아냈을 가능성도 있긴 합니다만, 어쨌든 위에 설명한 버그들은 고쳐져야 합니다.

Robert는 자기 블로그에서 이 공격 기법은 다르다고 주장했는데요.

구현에 몇 가지 덧붙여서 새로운거라고 할 수도 있겠죠. DoS 공격을 효과적으로 하는데 쓰이는 변종 기법이 많이 있습니다. Nmap 만들면서 어려웠던 점 중 하나는 스캔 당하는 쪽이 죽지 않도록 하는 것이었습니다. 중요한 것은 이미 DoS 공격으로 서비스 다운시키는 것 정도야 매우 쉽다는거고, 따라서 별로 "인터넷의 안녕을 위해" 공개를 미룰 하등의 이유가 없다는 겁니다. 그게 그렇게 중요하면 벤더가 움직일 때까지 기다려야지 왜 보도자료 뿌리고 인터뷰 하고 난리칩니까?

이 문제가 얼마나 심각한가요? 이게 잘 알려진 버그라면 공격자는 왜 사용하지 않죠?

DoS 공격자들이 게으르고 멍청한 경우가 많은 것도 하나의 이유라고 할 수 있겠지만, 이렇게 우아한 기법을 쓰는 것보다 그냥 무식하게 패킷 쏟아붓는게 더 좋은 이유가 있거든요. 위에서 설명한대로 공격하려면 TCP 연결을 맺어야 하고 실제 IP가 남기 때문에 추적하거나 방화벽으로 차단하는게 훨씬 쉽습니다. 반면에 패킷 플러딩을 사용하는 경우라면 그냥 IP 위조해서 뿌리면 끝이고 추적하기도 어렵죠. 뭐 어차피 공격할 때 좀비를 쓰긴 하겠지만.

패치나 우회 방안이 전혀 없다는게 사실입니까?

공격이 시작되면 IP 찾아내고 차단하는 것 정도는 아주 쉽습니다. 물론 공격자가 IP를 다른 걸로 바꿀 수도 있겠지만 말이죠. 인라인 IDS/IPS에서 공격 패턴을 찾아서 자동으로 차단하는 것도 가능하고요. 물론 정상 트래픽을 차단하지 않도록 주의를 기울여야 할 것입니다. 운영체제나 응용 프로그램 단에서도 가급적 적게 리소스를 사용하도록 튜닝할 필요가 있겠죠. 만병통치약은 없지만 적어도 공격 영향을 줄일 방법은 많이 있습니다. (역주: 개인적으로는 트래픽 패턴 찾는 것은 상당히 어려울 것 같군요. 특히 대형 네트워크인 경우에는 단순 계산만 해봐도 아시겠지만 통계 유지하는 것도 쉬운 일이 아닙니다.)

Ndos 툴은 어디서 받을 수 있나요?

아 그거는 배포하지 않을 겁니다. 대충 만든거라서 공개할 수준이 아니기도 하고 악용할 소지가 많아서요. 2004년에 저술한 책 Stealing the Network: How to Own a Continent에 Ndos를 언급한 적이 있습니다. 아래 인용문을 참고하세요:

“Web sites are taken down by attackers daily, usually using a brute packet flood from many source machines (known as a distributed denial of service attack). Sendai realizes that much more elegant and effective attacks are possible by exploiting weaknesses in TCP protocol implementations rather than raw packet floods. Sendai has taken down much bigger Web sites than Fiasco's from a simple modem connection.”

SYN 쿠키나 SYN 플러딩은 왜 언급된거죠?

SYN 플러딩 공격은 정말 간단하고 아주 잘 알려진 TCP 공격 기법입니다. 이 공격에서는 TCP 연결을 맺을 필요가 없습니다. SYN 쿠키는 10년 전에 SYN 플러딩 공격을 막기 위해 개발된 것인데, 이걸로는 이번 새로운 이슈에 대응할 수 없다는 점을 설명하기 위해 언급했을 겁니다.

Robert는 이를 "클라이언트 사이드 SYN 쿠키"라고 불렀는데 별로 중요한 얘기가 아닙니다. 공격하는데 필요하지도 않고요. 그런데 일부 언론이나 커뮤니티에서는 이를 잘못 받아들이고는 심지어 SYN 쿠키를 끄라고 권고하기도 하더군요. 이는 SYN 플러딩 공격에 취약하게 만들 뿐 아무런 도움이 되지 않습니다. (역주: 저도 삽질했네요.)

더 질문하고 싶으면 어떻게 해야 하나요?

fyodor@insecure.org로 메일 보내세요.