오래전 이야기/Open Tools

nmap 한글 번역 메뉴얼

리눅스 엔지니어였던 2008. 9. 15. 17:28

Remote OS detection via TCP/IP Stack FingerPrinting
by Fyodor <
fyodor@dhp.com> (www.insecure.org)

Translated by Ji-ho Noh(
admin@nohjeeho.com)

다음 문서는 자유롭게 배포해도 좋습니다.
영문 최신판은 아래의 링크에서 얻을 수 있습니다.
http://www.insecure.org/nmap/nmap-fingerprinting-article.html


개요

다음 문서는 어느 특정 호스트의 TCP/IP 스택에 query를 던짐으로써. 그 호스트의 정보를 알아내는 방법에 대해 다룰 것이다. 먼저, 예전에 쓰이던 테크닉으로 호스트의 운영체제를 알아내는 방법(스택 Fingerprinting을 사용하지 않는 방법)을 말하고, 그 다음으로 현재 쓰이는 스택 Fingerprinting에 대해 설명하겠다. 이어서 원격호스트가 정보를 흘리도록 만드는 다양한 방법들에 대해 소개하겠다. 마지막으로 nmap에 대해 알아보고, nmap으로 다른 유명한 호스트에 대한 정보를 어떻게 얻는지 실례를 보도록 하겠다.

먼저 생각하기

많은 보안상의 문제들이 운영체제의 버전에 의존하기 때문에, 해커가 특정 호스트의 운영체제 정보를 알게 되는 것은 매우 위험한 일이다. 예를 들어, 당신이 어떤 특정 호스트를 검사하여 53번 포트가 열려 있다는 사실을 알게 되었다고 하자. 만약에 그 포트가 공격받기 쉬운 버전의 Bind라고 하자. 그렇다면 당신은 한 방에 그 컴퓨터의 데몬을 망쳐놓을 수가 있다. 그리고 TCP/IP Fingerprinter를 통해, 그 컴퓨터가 “솔라리스 2.51” 또는 “리눅스 2.0.35”가 돌아가는 컴퓨터임을 알 수 있고, 그에 맞춰서 당신의 쉘 프로그램(어떤 목적으로 쓰여진 쉘 프로그램이든 간에..)을 수정할 수가 있는 것이다.

더 나아가 당신은 500,000대의 컴퓨터를 검사하여, 어떤 컴퓨터가 어떤 운영체제를 쓰고 있는지, 어떤 포트가 열려 있는지를 알아낼 수 있다는 것이다. 만약에 보안 전문가들이 솔라리스 컴퓨터의 comsat 데몬을 통해 루트 권한을 얻을 수 있는 헛점이 있음을 발표했다고 가정하자. 우리의 호기심 많은 cracker는 바로 미리 정리해 둔 리스트에서 솔라리스 2.6를 쓰고, 루트권한 탈취가 가능한 컴퓨터 목록을 찾을 수 있을 것이다. 물론 아이들 장난하는 것으로 생각될 수 있다. 그 cracker는 아무런 기술도 쓰지 않았고, 또한 누구도 그 cracker가 패치가 되지 않은 .ac.kr 컴퓨터의 헛점을 찾을 수 있다고 하여 신기해 할 사람도 없다. 그 cracker가 어느 부서의 홈페이지에 자기가 얼마나 똑똑한지, 시스템 관리자가 얼마나 무식인지 떠들어대도 신기해 할 사람은 더더욱 없는 것이다.

이러한 호스트의 정보는 대인관계를 이용해 공격할 수도 있다. 예를 들어, 어떤 해커가 어느 회사의 네트워크를 스캔하였다고 치자. 그리고 nmap이 다음과 같은 메시지를 출력한다.
“Datavoice'Datavoice TxPORT PRISM 3000 T1 CSU/DSU 6.22/2.06'.
그 해커는 바로 그 회사에 전화를 걸어 Datavoice사의 고객지원팀인척 하며 다음과 같이 말한다. “Datavoice 고객지원팀입니다. PRISM 3000에 보안상의 문제가 있습니다. Datavoice에서는 이에 대해 바로 인터넷상에 문제점을 제기할 예정입니다. 그 전에 고객님의 컴퓨터에 패치를 해야 할 것 같습니다. 제가 막 패치 파일을 이메일로 보내드렸는데, 해커들의 타겟이 되지 않으려면 그 파일을 오늘 이내로 실행을 하셔야 할 것 같습니다.” 초짜 시스템 관리자들은 이러한 전화내용에 바로 그 파일을 실행할 것임이 틀림없다.

Nmap의 또 다른 이용가치가 있다. 당신이 거래를 하고 싶어하는 회사의 네트워크 구조를 살필 수가 있는 것이다. 당신은 DSL을 깔기 위해 돈을 지불하기 전에, 회선제공업체의 컴퓨터들에 대한 사전 조사를 할 수 있는 것이다. 예를 들어, 그 회사가 폐기처분 직전의 라우터와 Windows가 깔린 컴퓨터들로 이루어진 회사임을 알게 된다면, 일년에 10만원씩 돈을 내며 그 회사의 DSL 라인을 신청할 필요는 없는 것이다.


고전적 방법들

스택 Fingerprinting은 운영체제를 알아내는 유일한 방법이다. 이 방법이 가장 확실한 방법이라 생각하지만 그 외의 방법이 없는 것은 아니다. 불행히도 다음에 소개할 방법이 가장 효율적인 방법이다.

playground~> telnet hpux.u-aizu.ac.jp
Trying 163.143.103.12 ...
Connected to hpux.u-aizu.ac.jp.
Escape character is '^]'.

HP-UX hpux B.10.01 A 9000/715 (ttyp2)

login:

만약에 위와 같이 ‘이 컴퓨터는 어떤 운영체제가 돌아가는 컴퓨터요~”라고 인사를 한다면, 스택 Fingerprinting이고 뭐고 할 필요도 없는 것이다.
불행히도, 많은 컴퓨터 제조회사들은 위와 같이 세팅을 해 놓은 채로 컴퓨터를 판매하고, 또한 많은 관리자들이 이러한 세팅을 끌 생각을 하지 않는다. 호스트의 운영체제를 알아낼 수 있는 방법(스택 Fingerprinting과 같은 기법들)이 많이 있다고 해서, “내 컴퓨터는 무엇이요”라고 외치며 어중이 떠중이들까지 당신의 컴퓨터를 해킹의 대상으로 만들게 할 필요는 없는 것이다.

문제는, 더 이상 이러한 테크닉에 의존할 수는 없다는 것이다. 이유인즉. 위와 같이 컴퓨터의 정보가 담긴 초기화면을 띄우는 경우는 많이 줄어들고 있고, 컴퓨터의 정보가 초기화면에 뜬다 하더라도, 거짓정보를 올리는 경우가 대세이기 때문이다.

초기화면을 띄우지 않는다 하여도 다른 곳에서 비슷한 헛점을 찾을 수 있다. 상당수의 어플리케이션들이 이러한 종류의 정보를 흘리는 것이 사실이다. 예를 들어 FTP 서버를 보자.

payfonez> telnet ftp.netscape.com 21
Trying 207.200.74.26 ...
Connected to ftp.netscape.com.
Escape character is '^]'.
220 ftp29 FTP server (UNIX(r) System V Release 4.0) ready.
SYST
215 UNIX Type: L8 Version: SUNOS

제일 먼저 받는 메시지가 시스템의 정보인 것이다. 만약 우리가 ‘SYST’라는 명령을 보내면, 더 많은 양의 시스템 정보를 볼 수가 있다.

만약 그 시스템이 anonymous FTP를 지원한다면, 우린 /bin/ls와 다른 몇몇 바이너리 파일들은 내려받을 수가 있고 그 시스템이 어떠한 구조를 하고 있는지 알아낼 수가 있다.

다른 많은 어플리케이션들도 마찬가지이다. 웹서버를 한번 보자.

playground> echo 'GET / HTTP/1.0\n' | nc hotbot.com 80 | egrep '^Server:'
Server: Microsoft-IIS/4.0
playground>

하….마이크로소프트 IIS/4.0이라…


이러한 종류의 방법에는 DNS 호스트 정보를 이용하는 방법(그다지 효율적이지는 않지만), 대인관계를 이용하는 방법도 포함된다. 만약 시스템이 161/udp (snmp)가 열려 있다면, CMU SNMP 툴의 ‘snmpwalk’을 이용하여 시스템의 세세한 정보를 얻는 것은 너무나 쉬운 일이다.

현재의 Fingerprinting 프로그램

Nmap이 TCP/IP Fingerprinting 기법을 사용하여 운영체제를 판별하는 최초의 프로그램은 아니다. Johan이 만든 IRC spoofer sirc는, 버전 3 (또는 그 이전)부터 기본적인 Fingerprinting 기법을 사용하여 왔다. IRC spoofer sirc는 몇 개의 간단한 TCP 플래그 검사를 통해 호스트를 “리눅스", “4.4GSD”, “Windows 95”, 도는 “미상(Unknown)”등으로 분류를 할 수가 있었다. 비슷한 프로그램으로 checkos라는 것이다. Shok이라는 사람이 「Confidence Remains High Issue #7」을 통해 올해 1월 공개하였다.

Fingerprinting 기법은 SIRC와 거의 비슷하다. 심지어 프로그램 코드의 많은 부분은 완전히 일치한다. Checkos는 일반 공개하기 오래전부터 암암리에 사용되어 왔기 때문에. Checkos의 코드를 누가 어디서 배껴 왔는지는 알 수가 없다. 하지만 분명한 것은 누구도 저작권에 대해 왈가왈부하고 싶어하지는 않는다는 것이다. Checkos에 추가된 점은 텔넷 초기화면을 검사할 수 있다는 것이지만, 위에서도 말했듯이 전적으로 텔넷 초기화면에 의존할 수는 없다. [덧글: Shok이 말하기를 chekos는 일반에 공개되어질 목적으로 만들어진 것이 아니기 때문에, SIRC 저작권에 대해 우려할 필요가 없었다고 한다.]

Su1d라는 사람 또한 운영체제를 검사하는 프로그램을 만들었었다. SS라고 불리는 프로그램으로 12개의 OS 종류를 분류할 수 있다. 사실 Su1d가 nmap의 네트워킹 코드 일부를 빌려쓰고 내 이름을 적어주었기 때문에, 이 프로그램에 나도 조금은 기여했다고 말할 수 있겠다.  

다음으로 queso라는 프로그램이 있다. 가장 최근의 것으로 다른 프로그램들에 비해 상당히 발전한 프로그램이다. 새로운 검사 방법 몇 가지를 더 추가했을 뿐만 아니라, 내가 본 프로그램 중에 처음으로, 운영체제 Fingerprints를 코드 밖으로 빼냈다. (역주, ‘지문’처럼 이러이러한 특징을 만족시키면 누구이구나 하며 알 수 있듯이, 호스트의 TCP 정보를 종합해서 ‘아! 무슨 컴퓨터구나’라고 판단할 수가 있는 것이다. 그러한 과정을 fingerprinting이라고 하고, 수집된 정보를 비교하기 위해 만들어 놓은 데이터를 fingerprints라고 한다.) 다른 프로그램들은 다음과 같은 코드를 포함한다.

/* from ss */
if ((flagsfour & TH_RST) && (flagsfour & TH_ACK) && (winfour == 0) &&
  (flagsthree & TH_ACK))
      reportos(argv[2],argv[3],"Livingston Portmaster ComOS");

반면 queso는 위와 같은 코드를 설정파일로 이동시켰기 때문에, 확장성이 많이 좋아졌다. 판별하고 싶은 운영체제를 추가하려면, 설정 파일에 몇줄의 코드만 더 추가시키면 되는 것이다.

Queso는 Savage(Apostols.org에서 일하는 괜찮은 놈)이 만들었다.

지금까지 언급한 프로그램들은 Fingerprinting 테스트의 수가 매우 제한되어 있어서, 대상 시스템의 운영체제에 대한 자세한 정보를 알기가 어려웠다. 내가 원했던 것은 “이 시스템이 OpenBSD, FreeBSD, 또는 NetBSD이다”라고 하는 대략적인 정보뿐만이 아니라, 할 수 있다면 릴리즈등과 같이 좀더 세부적인 정보였다. 같은 맥락으로 ‘솔라리스를 쓰는 컴퓨터이다’보다는 ‘솔라리스 2.6을 쓰는 컴퓨터이다’라는 대답을 얻고 싶었다. 그렇게 하기 위해서 몇 가지 Fingerprinting 기법을 변형, 추가시켰다. 다음 장에서 이러한 기법들을 설명하겠다.

Fingerprinting 방법

네트워킹 스택을 Fingerprinting하는 방법은 수없이 많다. 기본적으로 운영체제마다 가지고 있는 고유한 특성들, 즉, 다른 운영체제와 구별되는 특성들을 찾아내고, 그 차이점을 판단기준(프로브 Probe)으로 정하는 것이다. 이러한 차이점을 많이 확보하면 할수록, 더 정확히 그 시스템의 운영체제를 알아낼 수 있다. 예를 들어, nmap은 더욱 세세하게 기술된 판단기준을 통해, 솔라리스 2.4, 솔라리스 2.5-2.51, 솔라리스 2.6등을 가려낼 수 있다. 또한 리눅스 커널 2.0.30, 2.0.31-34, 2.0.35간의 구별도 가능하다. 밑에서 그 방법을 설명하겠다.

FIN 프로브 &#8211; FIN 패킷 (혹은 ACK나 SYN플래그를 제외한 패킷)을 열려있는 포트에 보내고 응답을 기다린다. RFC 793에 따르면 응답하지 않는 것이 정상이지만, 이를 제대로 수행하지 못하는 시스템들은(예를 들어 MS Windows, BSDI, CISCO, HP/UX, MVS, 그리고 IRIX) RESET을 돌려 보낸다. 지금 사용되는 대부분의 툴은 이러한 차이점을 이용하고 있다.

거짓 플래그 프로브 &#8211; 이 방법을 쓰는 스캐너는 Queso가 처음이라고 생각된다. 기본적인 아이디어는 다음과 같다. SYN 패킷의 TCP 헤더에 위치하는 정해지지 않은 TCP 플래그(왼쪽에서부터 7번째 또는 8번째 비트)를 설정하는 것이다. 버전 2.0.35 이전 리눅스는 위의 TCP 플래그를 건드리지 않고 다시 보낸다. 다른 운영체제에서는 이러한 버그를 본 적이 없지만, 어떤 운영체제는 거짓플래그가 포함된 SYN패킷을 받게 되면 접속을 다시 시도하는 것도 같다. 이러한 현상은 위의 운영체제를 분별하는데 도움이 된다. (덧글: 현재 8번째 비트와 9번째 비트는 “ECN 영역”으로 사용된다.)

TCP ISN(초기 일련 번호) 샘플링 &#8211; 접속 개설을 신청할 때, 응답으로 보내는 메시지의 ISN 패턴을 통해 판별하는 것이 핵심이다. 이러한 패턴을 통해 여러가지 그룹으로 분류할 수 있다. 예를 들어, 전형적인 64K 패턴(오래된 UNIX 시스템들), 난수를 증가시키는 패턴(새로운 버전의 솔라리스, IRIX, FreeBSD, Digital UNIX, Cray 등등), 제대로 된 난수 패턴 (리눅스 2.0.*, OpenVMS, 신형 AIX 등등). Windows는 시간차에 따라 작은 양의 일정 상수를 ISN에 더하는, 시간에 의존하는 패턴을 사용한다(Windows와 몇몇 다른 기종들). 더 말할 필요도 없이, 이러한 방법은 오래된 64K 시스템의 동작보다도 더 간단하여 쉽게 찾아낼 수 있다. 물론 내가 가장 좋아하는 패턴은 “상수”를 이용하는 것이다. 어떤 컴퓨터들은 항상 같은 ISN을 보낸다. 몇몇 3Com사의 허브들(0x803를 사용한다), 그리고 애플 LaserWriter printers (0xC7001를 사용한다)도 항상 같은 ISN을 보낸다.

위의 분류 방법뿐만 아니라, 컴퓨터내의 변수, 최대공약수, 그 외의 일련번호 집합과 일련번호들간의 차이를 다루는 함수들을 통한 난수 증가 방법에 따라서 더 세부적으로 분류할 수 있다. 알아두어야 할 것은, ISN을 만드는 과정이 보안상으로 상당히 중요한 부분이라는 것이다. 내가 알고 있는 프로그램 중에 nmap은 ISN을 만드는 과정의 차이점을 이용하여 OS를 구분하는 최초의 프로그램이다.

IPID 샘플링 &#8211; 대부분의 운영체제는 각각의 패킷을 보낼 때, 시스템 전체적으로 사용되는 IPID 값을 증가시킨다. OpenBSD같은 경우는 난수를 IPID로 사용하고, 리눅스와 같은 운영체제는 대부분 “Don’t Fragment” 비트가 정해지지 않은 경우에 IPID를 0으로 사용한다. Windows는 네트워크 바이트 순서에 IPID를 아예 사용하지 않는다. 그래서 Windows는 각각의 패킷에 256을 더하여 사용한다. Nmap은 이들 숫자와, 난수, 그리고 unknown sequence class에 따른 구분이 가능하다. IPID 순서를 알 수 있다는 것은 단지 그 운영체제가 무엇이다라는 것뿐만 아니라, 그 이상의 보안상의 문제점도 함께 지니고 있다. Nmap에서 “Idlescan” (-sl)의 기능이 바로 그러한 예 중에 하나이다.

TCP Timestamp -- 운영체제를 알아내기 위해서 사용될 수 있는 또다른 숫자들은 바로 TCP Timestamp 숫자들이다. 어떤 운영체제들은 이러한 기능을 사용하지 않는다. 다른 어떤 운영체제들은 2Hz, 100Hz, 또는 1000Hz 주파수에 맞춰 숫자를 증가시킨다. 또 다른 어떤 운영체제들은 그냥 0을 사용한다. Nmap은 물론 이러한 정보를 사용하여 호스트의 uptime 값을 결정할 수 있는 것이다.

“Don't Fragment bit”의 감시 &#8211; 많은 운영체제들이 밖으로 보내지는 패킷의 일부 중에 IP “Don’t Fragment”비트를 설정하기 시작했다. 이 기능은 성능향상에 많은 도움을 준기는 하지만 때로는 상당히 귀찮은 면도 있다. (Nmap fragment 처리과정이 솔라리스 시스템에는 잘 맞지 않는 이유이기도 하다.) 모든 운영체제가 이 기능을 사용하는 것이 아니고, 또 어떤 경우에는 다른 방법으로 이 기능을 사용하기 때문에, “Don’t Fragment bit”를 유심히 보는 것만으로도 운영체제의 종류뿐만 아니라 그 이상의 정보도 얻어 낼 수 있는 것이다. 이러한 기능도 이전에는 없었다고 본다.

TCP 초기 윈도우 사이즈 -- 이 기능은 돌아오는 패킷에 담겨 있는 윈도우의 사이즈를 확인하는 과정이다. 이전의 스캐너는 단순히 RST 패킷의 윈도우 사이즈가 0이 아니면 “BSD 4.4 계열”이라고 단정하였다. Queso나 Nmap과 같은 최근의 스캐너는 운영체제에 따라 윈도의 사이즈가 일정값으로 정해져 있으므로, 이를 추적해 운영체제의 종류를 구분한다. 사실 어떤 운영체제는 이 윈도우 사이즈 값만으로도 구별이 가능하다. (예를 들어, AIX은 윈도우 사이즈 값으로 0x3F25를 쓰는 유일한 운영체제이다.) NT5의 “완전히 바뀐” TCP 스택은 0x402E값을 쓴다. 흥미로운 점은 이 값이 OpenBSD나 FreeBSD에서 쓰는 값과 완전히 일치한다는 것이다.

ACK 값 &#8211; 사실 이 값을 정하는 데에 기준이 있는 것처럼 생각되기 쉽지만, 기계마다 이 값이 다른 경우가 있다. 예를 들어 닫혀있는 TCP 포트에 당신이 FIN|PSH|URG를 보냈다고 하자. 대부분의 시스템에서는 당신의 보낸 패킷의 ISN (Initial Sequence Number)을 ACK 값에 넣어 보내지만, Windows나 몇몇 바보 같은 프린터는 당신이 보낸 ISN 숫자에 1을 더하여 사용한다. 당신이 만약 SYN|FIN|URG|PSH를 열려있는 포트에 보내면, Windows는 일정하지 않은 값을 보낸다. 때로는 ISN 값을 그냥 보내기도 하고, 때로는 S++를 보내기도 하고, 또 어떤 때는 난수 같아 보이는 값을 보내기도 한다. 당연히, Windows를 만드는 사람들이 어떻게 Windows를 만들었길래, 이런 결과를 보이는지 궁금해 하지 않을 수 없다.

ICMP 에러 메시지 죽이기 --- 일부 똑똑한 운영체제들은 RFC 1812 규제를 따른다. 즉, 다양한 에러 메시지를 보내는 횟수를 제한한다. 예를 들어 리눅스 커널(innet/ipv4/icmp.h)은 목적지에 도달이 불가능한 메시지를 4초에 80개까지 제한하고, 이를 넘기게 되면 1/4초의 패널티 시간을 부여하게 되어있다. 이를 검증하는 방법으로 임의의 high UDP 포트에 패킷을 충분히 많이 보내보고, 도달 불가능 메시지의 수를 세어 보는 것이다. 이러한 테스트 방법을 이전에는 본적이 없으며, 더불어서 nmap에 이러한 기능을 추가시키지는 않았다. (UDP 포트를 스캔하기 위한 기능에만 위의 방법이 사용된다.)  사실 이 방법으로 운영체제를 알아내기 위해서는 어느 정도의 시간이 필요하다. 수많은 패킷을 보내고 또 그 패킷에 대한 응답을 기다려야 하기 때문이다. 또한 네트워크에서 길을 잃어버린 패킷의 경우도 생각해 주어야 하기 때문에 결코 이 방법이 쉬운 일은 아니다.

ICMP 메시지 인용 -- RFC에서는 다양한 에러를 일으키는 ICMP 메시지의 일정 소량을 인용하여 ICMP 에러 메시지를 만들도록 규정하고 있다. 포트 도달 불가능 메시지와 같은 경우, 대부분의 시스템은 꼭 필요한 IP 헤더 + 8 bytes를 돌려 보낸다. 그러나 솔라리스는 한 비트를 더 보내고. 리눅스는 거기서 또 한 비트를 추가하여 보낸다. 아주 훌륭한 점은 이러한 현상을 이용하여 nmap이 리눅스와 솔라리스를 구분할 수 있다는 것 외에도, 이들 시스템에 열려있는 포트가 없는 경우에도 이들 간의 구분이 가능하다는 것이다.  

ICMP 에러 메시지 정합성(Error message integrity) &#8211; 아이디어는 Theo De Raadt(OpenBSD 개발책임자)가 comp.security.unix에 올린 글에서 얻었다. 이전에 말한 것처럼, 컴퓨터는 도달 불가능 에러 메시지에 당신이 보낸 메시지의 일부를 추가하여야 한다. 하지만 일부 컴퓨터는 초기 원본 메시지 처리 과정에서 헤더부분을 “작업 영역”으로 사용하는 경우가 있다. 즉, 되돌아 온 ICMP 에러 메시지의 헤더 내용이 변하기도 한다는 것이다. 예를 들어, AIX와 BSDI에서 되돌아 오는 메시지의 IP ‘전체 길이’ 항목을 보면 통상보다 20 byte 더 많이 적혀 있다. 일부 BSDI, FreeBSD, OpenBSD, ULTRIX, VAXen등은 IP의 ID에 모순이 생기기도 한다.. 사실 변경된 TTL 때문에 어차피 체크섬이 변해야 하기는 하지만, 일부 컴퓨터(AIX, FreeBSD 등등)에서는 일정하지 않은 값이나 0을 체크섬으로 보낸다. UDP 체크섬에도 같은 현상이 일어난다.. 한마디로 말해, nmap은 이러한 ICMP 에러에 대한 9가지의 테스트를 하여 운영체제의 세세한 차이점들을 찾아낸다.

서비스의 종류 (Type of service) -- 되돌아 온 ICMP 포트 도달 불가능 메시지의 서비스 종류 값을 보면, 대부분의 컴퓨터에서는 0을 쓴다. 하지만 리눅스는 0xC0를 쓴다. 이 값은 표준 TOS 값이 아니고, 사용되지 않은 precedence 필드의 값이 그대로 넘어오는 것이다. 왜 0으로 바꿔서 보내지 않는지는 모르겠지만, 훗날 이 값이 0으로 바뀌게 되면, 그 시점을 기준으로 이전의 버전과 이후의 버전을 구별할 수 있는 값이 되리라 생각된다.

Fragmentation 처리 -- 이 방법은 Secure Networks사(지금은 NAI사의 수많은 Windows 사용자들이 접수하기는 했지만)의 Thomas H. Ptacek 이 가장 좋아하는 방법이다. 이 방법은 운영체제마다 IP fragment를 덮어씌우는 방법이 저마다 다르다는 점을 이용하고 있다. 어떤 운영체제는 새롭게 수신된 부분으로 오래된 IP fragment를 덮어 씌우는가 하면. 어떤 운영체제는 반대로 이전에 수신된 내용을 계속 사용한다. 패킷이 어떻게 재구축 되었는지 판단하기 위해서 여러 가지 방법이 사용될 수 있다. 사실 내가 아는 한 IP fragment를 간단하게 보내는 방법이 없기 때문에 이 기능을 nmap에 더하지 않았다. (특히. 솔라리스에 대해서는 도대체 방법이 생각나질 않는다.) IP fragment 오버래핑에 관한 상세 정보는 IDS 논문들을 참조하기 바란다. (www.secnet.com)

TCP 옵션 -- 호스트에서 새어 나오는 정보에 관해서는 이 부분이 최고이다. 왜 멋지냐 하면..
첫째) 말 그대로 옵션이기 때문이다 (헉..) 따라서, 모든 컴퓨터가 이 부분을 건드리지는 않는다는 것이다.
둘째) 옵션에 쿼리를 붙여 보내면 목표 호스트는 그 옵션을 지원하는지 안 하는지를 자상하게 답해 준다.
셋째) 패킷에 여러 가지 옵션을 덧붙여서 한 번에 테스트를 할 수 있다.

nmap은 거의 모든 탐색용 패킷에 이러한 옵션을 붙여 보낸다.

Window Scale=10; NOP; Max Segment Size = 265; Timestamp; End of Ops;

응답이 돌아올 때, 어떠한 옵션이 되돌아 왔는지를 보고 지원이 되는지 안 되는지를 알 수 있다. 최근의 FreeBSD와 같은 시스템은 위의 모든 옵션을 지원한다. 반면에 리눅스2.0.X와 같은 시스템은 거의 지원을 하지 않는다. 최신 리눅스 2.1.X 커널은 위의 모든 옵션을 지원한다. 한편, TCP 일련번호를 추측하기 쉬운 취약점이 있기는 하다. 확인해 보라.

일부 운영체제들은 동일한 옵션만 지원해 주기는 하지만. 때로는 보내지는 옵션의 값을 통해서 그 운영체제들을 구별할 수도 있다. 예를 들어, 당신이 리눅스 머신에 작은 MSS 값을 보내면. 그 MSS 값을 다시 당신에게 보내준다. 다른 호스트에서는, 다른 값을 보내준다.

같은 옵션을 지원하고. 같은 값을 보낸다 하더라도, 옵션이 보내어지는 순서나 패딩의 장소가 어디인지를 통해서도 구별할 수 있다. 예를 들어 솔라리스는 ‘NNTNWME’로 보낸다. 다시 말해 아래와 같은 순서로 보내는 것이다.

<no op><no op><timestamp><no op><window scale><echoed MSS>

한편 리눅스 2.1.122는 ‘MENNTNW’로 보낸다. 같은 옵션을 지원하고, 같은 값을 보내지만, 순서가 다르다.

TCP 옵션을 이용한 운영체제 탐색 툴을 본 적은 없지만, 아주 유용한 테스트 방법이다.

나중에 사용하게 될지도 모르는 아주 유용한 옵션들이 있긴 하다. 예를 들어, T/TCP를 지원하는지 또는 선택적인 ACK를 지원하는지를 검사할 수도 있다.

Exploit 연대기 -- 위에 열거된 수많은 검사 방법을 다 사용해도 nmap은 Win95, WinNT, Win98간의 TCP 스택을 구별하지 못한다. Win98이 Win95가 나오고 4년이 지난 뒤에 나왔다는 것을 생각하면 더 놀라운 일이다. 적어도 4년이면 스택의 어느 부분이라도 개선할 생각을 해야 정상이 아닌가? (지원하는 TCP 옵션을 더 늘린다든지..) 또한 그래야 우리가 변화된 점을 확인하고 Windows 운영체제간의 구별도 쉽게 할 수 있는 것이 아닌가? 불행히도 Windows는 전혀 바뀌지 않았다. NT에서 사용하는 TCP 스택은 Windows95에서 사용되었던 썩기 직전의 스택을 그대로 사용하고 있다. 물론 Windows98도 바뀐 것은 하나도 없다.

하지만 희망을 버리지는 말자. 해결책이 있다. 예전에 만들어졌던 DOS attack (Ping of Death, Winnuke, 등등)로 먼저 공격을 하고, 차츰 이후에 만들어진 공격책 (Teardrop and Land등등)으로 공격을 한다. 공격을 하고 Ping을 때려 살았는지 죽었는지 확인한다. 어느 공격으로 뻗었는지 확인이 가능하면, 어떤 운영체제가 돌아가고 있었는지 확인할 수 있을 것이다. (역주. 저자가 얼마나 M$를 싫어하는지 대목에 알 수 있는 단락. 밑줄 쫙~)

위의 공격 방법을 통한 검사를 nmap에 담고 싶은 마음이야 굴뚝같지만, 그렇게 하지는 않았다.

대량의 SYN 보내기 -- 어떤 운영체제들은 위조된 SYN 패킷이 무작위로 쏟아져 들어오면 더 이상의 새로운 접속을 받아들이지 않는다. (패킷을 위조해서 보내야 당신 컴퓨터의 커널이 하나하나의 접속을 리셋트하는 수고를 덜 수 있다.) 대부분의 컴퓨터는 8개의 패킷까지 다룰 수 있다. (다른 운영체제들 중에) 최근의 리눅스 커널은 SYN cookies와 같은 다양한 방법으로 이러한 현상이 큰 문제가 되지 않도록 막고 있다. 즉, 열려있는 포트에 송신원 주소를 위조한 패킷을 8개 보내고, 그 후에 그 포트로 접속이 가능한지 확인하여 보면, 목표 호스트의 운영체제에 대한 정보를 알 수 있는 것이다. 이 기능은 nmap에 담지 않았다. 사실, 대량의 SYN을 호스트에 보내면 좋아할 사람은 아무도 없기 때문이다. 목표 호스트의 운영체제가 무엇인지 알고자 이 방법을 사용하였다고 해명한다 하더라도, 그 사람들을 진정시키기는커녕, 맞지 않으면 다행일 것이다.

NMAP의 실행과 결과

위에서 열거한 운영체제 판별 방법들을 실행해 보았다. (nmap에 포함시키지 않았다고 언급한 내용은 제외한다.)  그리고 위에 개괄적으로 말했던, 각 운영체제들간의 세세한 차이점은 따로 만들어 놓았기 때문에, nmap은 이미 어떤 시스템은 어떤 포트가 열려있고 어떤 포트가 닫혀 있는지 자동으로 조사해준다. Linux, *BSD, 솔라리스 2.51, 2.6, 그리고 다른 운영체제에서도 잘 작동함을 알린다.

새로운 버전의 nmap은 아래와 같은 간단한 문법으로 쓰여진 Fingerprint templates를 참조한다.

FingerPrint  IRIX 6.2 - 6.4 # Thanks to Lamont Granquist
TSeq(Class=i800)
T1(DF=N%W=C000|EF2A%ACK=S++%Flags=AS%Ops=MNWNNT)
T2(Resp=Y%DF=N%W=0%ACK=S%Flags=AR%Ops=)
T3(Resp=Y%DF=N%W=C000|EF2A%ACK=O%Flags=A%Ops=NNT)
T4(DF=N%W=0%ACK=O%Flags=R%Ops=)
T5(DF=N%W=0%ACK=S++%Flags=AR%Ops=)
T6(DF=N%W=0%ACK=O%Flags=R%Ops=)
T7(DF=N%W=0%ACK=S%Flags=AR%Ops=)
PU(DF=N%TOS=0%IPLEN=38%RIPTL=148%RID=E%RIPCK=E%UCK=E%ULEN=134%DAT=E)

첫째 줄을 보자.

> FingerPrint  IRIX 6.2 - 6.3 # Thanks to Lamont Granquist

보는 바와 같이, IRIX 시스템 6.2에서 6.3에 대한 Fingerprint 임을 나타내고 있다. Lamont Granquist씨가 친절하게도 검증에 사용된 호스트의 IP 주소와 Fingerprint를 보내주었다.  

> TSeq(Class=i800)

둘째 줄은 ISN 샘플링을 “i800 class”로 사용함을 말한다. 이는. 다음 일련번호가 이전번호에 800의 배수값을 더한 것임을 나타낸다.  

> T1(DF=N%W=C000|EF2A%ACK=S++%Flags=AS%Ops=MNWNNT)

T1은 테스트1이다. T1에서는 SYN 패킷에 여러 TCP 옵션을 더하여 열려있는 포트로 보냈다. DF=N은 되돌아온 패킷의 “Don’t fragment”비트를 건드리지 않았다는 뜻이다. W=C000|EF2A는 우리가 받는 윈도우 통지(Windows Adertisement)가 0xC000 또는 EF2A임을 나타낸다.. ACK=S++는 우리가 받는 ACK가 ISN + 1, 즉 하나씩 증가했다는 것을 나타내고, Flags = AS는 ACK와 SYN 플래그가 응답으로 보내졌다는 것을 말한다. Ops = MNWNNT는 옵션이 다음의 순서로 나열되어 있다는 뜻이다.

<MSS (not echoed)><NOP><Window scale><NOP><NOP><Timestamp>

> T2(Resp=Y%DF=N%W=0%ACK=S%Flags=AR%Ops=)

테스트2는 같은 옵션에, 각각의 값을 NULL로 하여 열린 포트에 보낸다. Resp=Y는 응답을 반드시 수신함을 말하고, Ops= 는 응답 패킷에 어떠한 옵션도 포함되지 않음을 나타낸다. '%Ops=’을 빼면, 모든 옵션이 다 매치될 것이다.

> T3(Resp=Y%DF=N%W=400%ACK=S++%Flags=AS%Ops=M)

Test 3은 SYN|FIN|URG|PSH에 옵션을 붙여서 열린 포트에 보낸다.

> T4(DF=N%W=0%ACK=O%Flags=R%Ops=)

이것은 열린 포트에 보내는 ACK이다. 여기서는 Resp=이 없음을 주의해라. 이것은 다른 테스트에 대한 결과가 있는 한, 응답이 없는 경우 (예를 들어 패킷이 네트워크 상에서 Drop되거나 Firewall에 의해 사라져 버린 경우)로 인해 검증을 무효화 시키지는 않는다는 뜻이다. 우리가 이것을 실행하는 이유는 궁극적으로 모든 호스트는 응답을 해야 하기 때문이다. 응답이 없는 경우는 거의 네트워크 상의 문제 때문이지, 운영체제 자체의 문제에 의한 것은 아니기 때문이다. 테스트 2번과 3번에서 Resp를 사용한 이유는, 종종 일부의 컴퓨터는 응답을 보내지 않고 우리의 패킷을 무시해 버리기 때문이다.

> T5(DF=N%W=0%ACK=S++%Flags=AR%Ops=)
> T6(DF=N%W=0%ACK=O%Flags=R%Ops=)
> T7(DF=N%W=0%ACK=S%Flags=AR%Ops=)

위의 테스트들은 각각 SYN, ACK, FIN|PSH|URG를 닫힌 포트에 보내는 테스트이다. 이전과 같은 옵션도 들어가 있다. 물론 각각의 이름은 T5, T6, T7이다.

> PU(DF=N%TOS=0%IPLEN=38%RIPTL=148%RID=E%RIPCK=E%UCK=E%ULEN=134%DAT=E)

위의 장황하게 늘어놓은 줄은, 도달 불가능 메시지에 대한 검증이다. 이제 DF=N이 무엇을 의미하는지는 알 것이다. TOS=0는 IP 서비스 종류가 0이라는 뜻이고. 다음 2 항목은 메시지 IP 헤더의 IP ‘총 길이’ 값과, 되돌아온 메시지의 IP ‘총 길이’ 값을 16진수로 나타낸 것이다. RID=E는 우리가 다시 받는 UDP 패킷의 복사본에서 RID 값이 기대된다는 것이다. (예로 보낸 값과 같은 값이 들어올 수 있다). RIPCK=E는 대상 호스트에서 체크섬을 건드리지 않았다는 말이다. (만약에 대상 호스트에서 체크섬을 건드리게 되면 RIPCK값이 F로 나온다.) UCK=E는 UDP 체크섬 또한 맞다는 것이다. 다음으로 UDP 길이가 0x134이고, DAT=E는 우리가 보낸 UDP data를 정확하게 다시 보내주었음을 보여준다. 대부분의 운영체제들은 (위의 운영체제도 포함해서) 우리가 보낸 UDP data의 어느 부분도 다시 보내주지 않는다. 그래서 DAT=E를 Default로 받는다.

이러한 기능들을 실행할 수 있는 nmap 버전은 다음 링크에서 받을 수 있다.
http://www.insecure.org/nmap/.


유명한 사이트들에 대한 검증 결과

이제 우리의 노력으로 얻는 재미있는 결과들을 보자. 이제 우리는 임의 인터넷 사이트들을 정하고 그 사이트가 어떠한 운영체제로 돌아가고 있는지 확인할 수 있다. 많은 사이트들이 자기들의 컴퓨터가 무엇으로 돌아가고 있는지를 숨기기 위해 텔넷의 초기화면 등을 없앴다. 하지만 우리의 새로운 Fingerprinter를 이용하면 다 알 수 있는 것들. 또한 당신이 공격하기에 가장 좋은 OS를 돌리고 있는 컴퓨터도 찾을 수가 있는 것이다.

아래의 예들은 다음의 명령을 수행했을 때의 결과들이다.
: nmap &#8211;sS &#8211;p 80 &#8211;O &#8211;v <host>

또한 알아두어야 할 것은 다음의 스캔들은 98년 10월 18일 이루어진 것이다. 몇몇 사이트들은 그 이후로 컴퓨터를 업그레이드 하였거나 아예 바꾼 경우도 있을 것이다.

또 하나 알아둘 것은 밑에 열거된 사이트들은 내가 싫어하는 사이트들 이라는 점.

# 해커들의 사이트 또는 그렇게 생각하는 사람들이 만든 사이트들.
www.l0pht.com        => OpenBSD 2.2 - 2.4
www.insecure.org     => Linux 2.0.31-34
www.rhino9.ml.org    => Windows 95/NT     # No comment :)
www.technotronic.com => Linux 2.0.31-34
www.nmrc.org         => FreeBSD 2.2.6 - 3.0
www.cultdeadcow.com  => OpenBSD 2.2 - 2.4
www.kevinmitnick.com => Linux 2.0.31-34  # Free Kevin!
www.2600.com         => FreeBSD 2.2.6 - 3.0 Beta
www.antionline.com   => FreeBSD 2.2.6 - 3.0 Beta
www.rootshell.com    => Linux 2.0.35  # Changed to OpenBSD after
                                     # they got owned.

# 보안 회사, 보안 상담회사 등등
www.repsec.com       => Linux 2.0.35
www.iss.net          => Linux 2.0.31-34
www.checkpoint.com   => Solaris 2.5 - 2.51
www.infowar.com      => Win95/NT

# 리눅스 회사들
www.li.org           => Linux 2.0.35 # Linux International
www.redhat.com       => Linux 2.0.31-34 # I wonder what distribution :)
www.debian.org       => Linux 2.0.35
www.linux.org        => Linux 2.1.122 - 2.1.126
www.sgi.com          => IRIX 6.2 - 6.4
www.netbsd.org       => NetBSD 1.3X
www.openbsd.org      => Solaris 2.6     # Ahem :) (its because UAlberta
                                       # is hosting them)
www.freebsd.org      => FreeBSD 2.2.6-3.0 Beta

# 아이비 리그 학교들
www.harvard.edu      => Solaris 2.6
www.yale.edu         => Solaris 2.5 - 2.51
www.caltech.edu      => SunOS 4.1.2-4.1.4  # Hello! This is the 90's :)  
www.stanford.edu     => Solaris 2.6
www.mit.edu          => Solaris 2.5 - 2.51 # Coincidence that so many good
                                          # schools seem to like Sun?
                                          # Perhaps it is the 40%
                                          # .edu discount :)
www.berkeley.edu     => UNIX OSF1 V 4.0,4.0B,4.0D  
www.oxford.edu       => Linux 2.0.33-34  # Rock on!

# 보안상태 엉망인 사이트들.
www.aol.com          => IRIX 6.2 - 6.4  # No wonder they are so insecure :)
www.happyhacker.org  => OpenBSD 2.2-2.4 # Sick of being owned, Carolyn?
                                       # Even the most secure OS is
                                       # useless in the hands of an
                                       # incompetent admin.

# 기타
www.lwn.net          => Linux 2.0.31-34 # This Linux news site rocks!
www.slashdot.org     => Linux 2.1.122 - 2.1.126
www.whitehouse.gov   => IRIX 5.3
sunsite.unc.edu      => Solaris 2.6

주석: 마이크로소프트의 기술서를 보면 그들의 보안상의 나태함을 지적하는 부분이 있다. “최근 몇 년간 Windows NT의 보안에 대한 평가가 좋아지면서 이러한 가정이 변했다”라고 한다. 음..내 견해로는. 보안을 다루는 사람들 사이에서. 내가 본 보안을 다루는 그룹 전체를 통틀어서 Windows는 딱 2대를 봤다. 그리고 Windows는&#61514;Windows는 그다지 인기가 없다.  nmap로 찾아내기 너무 쉽다. 왜냐? 물론 너무 엉성하게 만들었기 때문이다.

그리고 우리가 꼭 확인해야 할 사이트가 하나 더 있다. Transmeta사의 초극비 사이트이다. 흥미로운 점은 이 회사가 마이크로소프트사의 Paul Allen으로부터 엄청난 규모의 자금을 지원받는다는 사실. 하지만 이 회사는 Linus Torvalds를 고용했다. 그러면 이 회사는 과연 Paul에 기대서 NT를 쓰고 있을까? 아니면 리눅스 혁명에 동참하며 Paul을 배신할까? 한 번 보자.

사용한 명령어:
nmap -sS -F -o transmeta.log -v -O www.transmeta.com//24

위의 명령은 기존에 알려진 포트에 대해서 SYN 스캔을 한다. 그리고 결과를 transmeta.log로 출력한다. 그리고 OS 스캔을 하고, www.transmeta.com가 설치된 네트워크를 class ‘C’로 스캔한다. 스캔 결과를 정리하면 다음과 같다.

neon-best.transmeta.com (206.184.214.10) => Linux 2.0.33-34
www.transmeta.com (206.184.214.11) => Linux 2.0.30
neosilicon.transmeta.com (206.184.214.14) => Linux 2.0.33-34
ssl.transmeta.com (206.184.214.15) => Linux unknown version
linux.kernel.org (206.184.214.34) => Linux 2.0.35
www.linuxbase.org (206.184.214.35) => Linux 2.0.35 (possibly the same
                                     machine as above )

내가 생각하기에 아까 의문을 가졌던 점에 대한 확실한 답이 되리라 생각한다.


사례

Nmap이 현재 많은 종류의 운영체제를 판별할 수 있었던 유일한 이유는, 새롭고 재밌는 운영체제들의 Fingerprints를 찾으려고 애쓰는 많은 사람들의 노력 덕분이라 생각한다. 특별히 Jan Koum, van Hauser, Dmess0r, David O'Brien, JamesW. Abendschan, Solar Designer, Chris Wilson, Stuart Stock, Mea Culpa, Lamont Granquist, Dr. Who, Jordan Ritter, Brett Eldridge, 그리고 Pluvius는 통상 인터넷으로 접하기 힘든 시스템들의 IP 주소 또는 그 시스템들의 Fingerprints를 무지하게 많이 보내주어 고맙게 생각한다.

Nmap에 대해 질문하고 싶으면 Fyodor@insecure.org로 (단, 영어로)
번역문에 수정할 점이 있다면 노지호(
admin@nohjeeho.com)에게 메일을 보내면 된다.
Nmap을 구하고 싶다면
http://www.insecure.org/nmap에서 얻을 수 있다.

=======================


< 출처: 해커레온 (http://hackerleon.cybersoldier.net/) >