블로그 이미지
키에티스트
그냥 저냥 이거 저거

calendar

1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31

Tag cloud

Tistory Cumulus Flash tag cloud by BLUEnLIVE requires Flash Player 9 or better.

2012. 11. 14. 15:48 개발

SSL 통신을 캡처하기위한 Tomcat 구성


보안 통신 디버깅하기

Dominic Tulley, Leading Architect, DOORS Development Lab, IBM  

요약:  클라이언트와 서버 간의 통신 문제를 조사하는 과정은 가장 좋은 때에도 성가신 일이며 SSL로 통신을 보호하면 이 과정은 더욱 어려워집니다. 이 튜토리얼에서는 캡처한 통신을 Wireshark의 SSL Dissector가 복호화할 수 있도록 Tomcat과 Wireshark를 구성하는 단계를 살펴봅니다. 이렇게 하고 나면 마치 SSL이 관련되지 않은 것처럼 조사할 수 있습니다.

개인 키와 인증서를 작성한다.

먼저, openssl을 사용하여 개인 키를 새로 작성하는 방법을 살펴보자. Cygwin을 시작하고 다음 명령을 실행한다.

openssl genrsa -des3 -out ./serverkey.pem 2048 
            

생성된 pem 파일에 해당하는 암호구를 입력하라는 메시지가 표시된다. 이 튜토리얼 뒷부분에서는 이 암호구를 <서버 키 암호구>로 참조한다. 이 암호구를 입력하여 확인이 되면 명령이 완료되고 개인 키가 새로 생성되어 serverkey.pem 파일에 저장된다.

이제 다음과 같은 명령을 실행한다. (튜토리얼 템플릿에 제한되어 한 행에 입력하지 못했지만, 이 명령은 모두 한 행에 입력해야 한다는 점에 주의하자.)

openssl req -new -x509 -key ./serverkey.pem -out ./servercert.pem -subj 
'/C=GB/ST=XX/O="My Org"/CN="Wireshark dissectable Cert"'

이 명령을 실행하면 암호구를 입력하라는 메시지가 표시된다. 그러면 앞서 선택한 <서버 키 암호구>를 입력해야 한다. 이렇게 하면 앞서 생성한 개인 키에 대응하는 서버 인증서가 servercert.pem 파일에 저장된다.

인증서를 JKS 키 저장소로 변환

불행히도 앞 단계에서 생성된 서버 인증서는 Tomcat에 필요한 형식이 아니다. 따라서 이 인증서를 JKS 키 저장소에 적합한 형식으로 변환해야 한다. 첫 번째 단계에서는 Cygwin에서 실행되는 다음 명령을 사용하여 인증서를 PKCS12 형식으로 변환한다.

openssl pkcs12 -export -in ./servercert.pem -inkey ./serverkey.pem  
-certfile ./servercert.pem -out ./servercert.p12 -name "cert-name"
            

이 시점에서 암호구를 입력하라는 메시지가 다시 표시되면 <서버 키 암호구>를 입력한다. 그러면  암호구를 입력하라는 메시지가 표시된다. 이 암호구는 이 튜토리얼 뒷부분에서 <서버 p12 암호구>로 참조하게 된다. 이 새 암호구를 입력하고 확인이 되면 명령이 완료되고 servercert.p12 파일이 새로 작성된다.

다음에는 Jetty 배포판에 포함된 유틸리키를 사용하여 이 인증서를 JKS 키 저장소로 변환한다. 이 클래스는 Jetty 버전마다 다른 jar 파일 안에 있거나 배포판의 다양한 패키지 아래에 있다. Jetty 6.1.21 배포판에서는 필수 클래스가 org.mortbay.jetty.security 패키지에 있는 기본 jetty-6.1.21 jar 파일에 존재한다. 이 jar 파일이 현재 디렉토리에 있다고 가정할 때, 실행할 명령은 다음과 같다.

java -classpath ./jetty-6.1.21.jar org.mortbay.jetty.security.PKCS12Import 
./server.p12 ./dissectable.keystore
            

이 명령을 실행하면 먼저, 입력 키 저장소 암호구를 입력하라는 메시지가 표시된다. 이 암호구는 앞서 선택한 <서버 p12 암호구>이다. 그러면 새 키 저장소에 맞는 새로운 암호구를 선택하라는 메시지가 표시된다. 나중에는 이 암호구를 <서버 jks 암호구>로 참조한다. 이 암호구를 확인하라는 메시지는 표시되지 않으므로 주의해서 올바르게 입력해야 한다.

참고: PKCS12Import 클래스는 버전마다 다른 jar 파일 안에 있거나 다른 패키지 아래에 있기도 하므로 동일한 Jetty 버전을 명확하게 사용하지 않으면 안 된다.

개인 키 보호 해제

openssl과 관련하여 마지막으로 해야 할 작업은 개인 키를 보호하는 데 사용할 암호구를 제거하는 일이다. Wireshark가 이 키 파일을 올바르게 읽을 수 있도록 하려면 이 작업을 반드시 수행해야 한다. Cygwin에서 다음 명령을 실행하면 키 파일에서 암호구가 보호되지 않는다.

openssl rsa –in ./serverkey.pem –out ./open-private-key.pem

이 명령을 실행하면 암호구를 입력하라는 메시지가 표시된다. 앞서 선택한 <서버 키 암호구>를 입력한다. 이 명령이 완료되면 보호되지 않은 개인 키 사본이 포함된 open-private-key.pem 파일이 새로 작성된다.


출처 : http://www.ibm.com/developerworks/kr/web/tutorials/wa-tomcat/section2.html#ibm-pcon



Tomcat 구성

이제까지 필요한 암호화 아티팩트를 살펴보았으므로 이 아티팩트를 사용할 Tomcat을 구성하자. 다음과 같은 세 가지 구성 단계를 완료해야 한다.

  • dissectable.keystore를 Tomcat 루트 디렉토리에 복사한다.
  • 생성한 서버 인증서를 사용하도록 Tomcat에 명령한다.
  • 암호 세트를 Wireshark에서 처리할 수 있는 암호로 제한한다.

마지막 두 가지 조치는 동일한 파일을 편집하는 과정을 통해 이루어진다. Tomcat 설치판에서 conf 디렉토리를 탐색하여 server.xml파일을 편집한다. 이 파일에서 목록 1과 같은 SSL 커텍터 정의 섹션을 찾는다.


목록 1. 기본 SSL 커넥터 정의
    <!-- Define a SSL HTTP/1.1 Connector on port 8443 -->
    <!--
    <Connector port="8443" 
        maxHttpHeaderSize="8192"
        maxThreads="150"
        minSpareThreads="25" 
        maxSpareThreads="75"       
        enableLookups="false" 
        disableUploadTimeout="true"          
        acceptCount="100" 
        scheme="https" secure="true"           
        clientAuth="false" 
        sslProtocol="TLS" />
    -->

이 XML 코드가 목록 2에 있는 코드와 같아지도록 두 번째 행과 마지막 행을 제거한다.


목록 2. 주석을 제거한 SSL 커텍터 정의
    <!-- Define a SSL HTTP/1.1 Connector on port 8443 -->
    <Connector 
        port="8443" 
        maxHttpHeaderSize="8192"      
        maxThreads="150" 
        minSpareThreads="25" 
        maxSpareThreads="75"     
        enableLookups="false" 
        disableUploadTimeout="true"        
        acceptCount="100" 
        scheme="https" 
        secure="true"       
        clientAuth="false" 
        sslProtocol="TLS" 
    />

그런 다음, 아래에 굵은체로 된 텍스트를 포함하도록 커넥터 요소를 수정한다. 여기에서는 dissectable.keystore 파일을 Tomcat 설치판 루트 디렉토리(LICENSE 및 NOTICE 파일이 있는 디렉토리)에 복사한다고 가정한다. 아래 예제의 "password here" 부분에 앞서 선택한 <jks 서버 암호구>를 입력해야 한다.


목록 3. 수정된 SSL 커넥터 정의
    <!-- Define a SSL HTTP/1.1 Connector on port 8443 -->
    <Connector 
        port="8443" 
        maxHttpHeaderSize="8192"      
        maxThreads="150" 
        minSpareThreads="25" 
        maxSpareThreads="75"     
        enableLookups="false" 
        disableUploadTimeout="true"        
        acceptCount="100" 
        scheme="https" 
        secure="true"       
        clientAuth="false" 
        sslProtocol="TLS" 
 keystoreFile="dissectable.keystore"
        keystorePass="password here"
        ciphers="SSL_RSA_WITH_RC4_128_SHA,
 TLS_RSA_WITH_AES_128_CBC_SHA, 
 SSL_RSA_WITH_3DES_EDE_CBC_SHA"
    />
           

Tomcat 구성 확인

이제 Tomcat이 올바르게 구성되었는지 확인한다. 이렇게 하려면 bin 디렉토리에서 startup.bat 스크립트를 실행하면 된다. 모든 것을 올바르게 구성했고 dissectable.keystore 파일을 올바른 위치에 복사했으면 Tomcat이 아무런 오류 없이 시작된다.

Tomcat이 올바르게 시작하지 않고 화면에 오류가 표시되거나 단순히 시작에 실패하면 XML 코드를 편집하는 과정에서 오자가 입력되지 않았는지, 그리고 키 저장소 파일이 올바른 위치에 있는지 재확인해야 한다.

일단 Tomcat이 시작되면 웹 브라우저에서 https://localhost:8443/ URL을 탐색하여 SSL 연결이 작동하는지 확인할 수 있다. 이렇게 하면 처음에는 서버 인증서에 대해 문제를 제기하면서 이 서버를 신뢰할 것인지 묻는 메시지가 표시된다. (정확한 용어는 사용하는 브라우저에 따라 다르다.) 이러한 현상은 앞서 작성한 자기 서명 인증서로 인한 것이므로 해당 서버를 믿는다고 응답해야 한다. 그러면 Tomcat 시작 페이지가 표시된다. 이렇게 되면 보안 연결을 지원하도록 Tomcat을 올바르게 구성한 것이다.


출처 : http://www.ibm.com/developerworks/kr/web/tutorials/wa-tomcat/section2.html


'개발' 카테고리의 다른 글

SSL 패킷 캡처를 위한 wireshark 설정  (0) 2012.11.14
winapi wininet 사용하여 https post 날리기  (0) 2012.11.13
PostgreSQL ALTER TABLE  (0) 2010.11.02
posted by 키에티스트
2012. 11. 14. 15:46 개발

Wireshark 구성

이제까지 Tomcat을 구성했으므로 이제는 Wireshark를 구성해야 한다. 이렇게 하려면 Tomcat을 실행한 시스템에서 Wireshark를 시작하고 해당 메뉴에서 Edit --> Preferences(Ctrl-Shift P)를 선택해야 한다.


그림 1. Wireshark 환경 설정 화면
Wireshark 애플리케이션 환경 설정 화면 스크린샷 

왼쪽에 있는 Protocols 항목을 펼치고 표시된 목록에서 SSL을 선택한다.


그림 2. Wireshark SSL 구성 대화 상자
Wireshark SSL 구성 대화 상자의 스크린샷 

옵션 상자

옵션 상자를 둘 다 선택해야 한다.

RSA 키 목록

RSA keys list 필드는 대화에 사용하는 IP 주소와 포트에 따라 대화를 디코드하는 데 사용할 개인키를 Wireshark에게 알려주는 역할을 한다. 형식은 다음과 같다.

IPAddress,Port,Protocol,PrivateKey 
           

여기에서와 같이 목록을 쉼표로 분리하여 다수의 항목을 입력할 수 있지만 이 튜토리얼에서는 단지 하나의 항목만 입력한다.

IPAddress1,Port1,Protocol1,PrivateKey1; IPAddress2,Port2,Protocol2,PrivateKey2

이 튜토리얼에서는 192.168.45.22 IP 주소에서 Tomcat을 실행 중이고 8443 포트에서 SSL 트래픽을 리스닝 중이라고 가정한다. 트래픽은 HTTP 트래픽이며 앞서 생성된 open-private-key.pem 파일은 C 드라이브의 루트로 복사된다. 이를 위해 RSA keys list 필드에 입력할 문자열은 다음과 같다.

192.168.45.22,8443,http,c:\open-private-key.pem

해당 시스템의 IP 주소를 식별해야 한다. Cygwin에서는 다음 명령을 실행하여 이 작업을 수행할 수 있다.

ipconfig /all
            

참고: 시스템에 다수의 네트워크 어댑터가 있으면 시스템에 둘 이상의 어댑터가 있을 수 있다. 두 번째 시스템에서 이 시스템의 Tomcat 서버에 연결할 수 있는 주소를 선택해야 한다.

SSL 디버그 파일

Wireshark가 디버그 결과물을 작성할 수 있는 파일 이름을 제공해야 한다. 이렇게 하면 Wireshark 구성의 문제점을 해결하는 데 매우 유용하다.

구성 완료

OK를 눌러서 구성을 완료한다.

구성 확인

이제 앞서 선택한 SSL 디버그 로그 파일을 열어야 한다. 구성이 성공적으로 되었으면 Wireshark가 개인 키를 정상적으로 로드했다는 메시지가 표시된다. 아래 목록 4에 있는 예제를 살펴보자.


목록 4. SSL 디버그 로그 내용
ssl_association_remove removing TCP 9443 - http handle 040820A0
ssl_init keys string:
9.175.228.55,8443,http,C:\temp\open-private-key.pem
ssl_init found host entry 9.175.228.55,8443,http,C:\temp\open-private-key.pem
ssl_init addr '9.175.228.55' port '8443' filename 'C:\temp\open-private-key.pem'
 password(only for p12 file) '(null)'
Private key imported: KeyID 0E:BA:EA:08:5D:FA:FB:85:59:4A:7B:A9:B2:56:C3:16:...
ssl_init private key file C:\temp\open-private-key.pem successfully loaded
association_add TCP port 8443 protocol http handle 040820A0
            

이 디버그 로그 파일에서 모든 암호 처리 단계와 Wireshark 구성 단계를 올바르게 수행했다는 사실을 확인할 수 있다. 이 메시지가 표시되지 않으면 관련 단계를 다시 수행해야 한다. 가장 발생하기 쉬운 문제는 RSA 키 목록에 있는 키 파일의 경로나 개인 키 파일을 실제로 생성하는 과정과 관계가 있다.

대화 캡처

Wireshark를 올바르게 구성했으면 이제는 대화를 기록할 준비를 해야 한다. Wireshark의 해당 메뉴에서 Capture --> Interfaces를 선택한다(Ctrl I -- 대문자 i). 그러면 다음과 같은 대화 상자가 표시된다.


그림 3. Wireshark 인터페이스 목록 대화 상자
Start, Options, Details 단추와 함께 다양한 어댑터가 표시된 Wireshark Capture Interfaces 화면의 스크린샷 

목록에 있는 네트워크 인터페이스 중 어느 것이 두 번째 시스템에서 Tomcat에 연결할 인터페이스인지 결정해야 한다. Wireshark 구성 단계에서 올바른 IP 주소를 알아야 했으므로 어떤 인터페이스를 사용할 것인지는 이미 분명하다. 확실하지 않은 경우에는 두 번째 시스템에서 웹 브라우저를 사용하여 Tomcat 서버에 액세스하여 어떤 인터페이스에서 패킷 개수가 증가되는지 확인한다.

리스닝할 인터페이스를 선택했으면 options를 클릭한다. 그러면 다음과 같은 대화 상자가 표시된다.


그림 4. Wireshark Capture Options 대화 상자
Wireshark Capture Options 대화 상자의 스크린샷 

Capture Filter에 다음을 입력하여 캡처한 대화에서 불필요한 데이터를 줄여야 한다.

tcp port 8443
            

그런 다음, Start를 클릭하여 트래픽 캡처를 시작한다. 이 시점에서는 캡처되는 패킷이 표시되지 않는다. 두 번째 시스템으로 이동하여, https://192.168.45.22:8443/ URL을 사용하되, Tomcat이 설치된 시스템의 IP 주소나 호스트 이름을 삽입하여 Tomcat을 액세스한다. 이렇게 하면 인증서에 문제가 있다는 메시지가 표시되고 서버를 신뢰할 것인지 묻는 메시지가 표시된다. 앞서와 마찬가지로 서버를 신뢰한다고 확인한다. 그러고 나면 브라우저에 Tomcat 시작 페이지가 표시되고 많은 데이터 행이 Wireshark에 표시된다. 이제 메뉴에서Capture --> Stop을 선택하여 캡처를 중지한다.

이 작업을 올바르게 완료하면 다음과 같이, 복호화되었다는 것을 나타내는 몇 개의 녹색 행이 있는 화면이 표시된다.


그림 5. 성공적인 캡처 결과물
올바르게 복호화되었다는 것을 표시하기 위해 몇 개의 데이터 행을 녹색으로 강조한 Wireshark 패킷 캡처 결과의 스크린샷 

그러면 보통 때와 같이 Wireshark를 자유롭게 사용하여 HTTP 대화를 분석하고 문제점 조사를 시작할 수 있다.

여기서 마지막으로 알아야 할 점은 일반적으로 follow tcp stream을 사용하여 HTTP 대화를 확인할 경우에도 이제는 follow ssl stream을 사용해야 한다는 점이다. 이렇게 하면 HTTP 대화가 평문으로 표시된다.


그림 6. SSL 스트림 이해하기
 패킷이 하나로 일관되게 통합된 SSL 스트림을 추적하는, 헤더와 HTML 코드가 표시된 Wireshark 세부사항의 스크린샷이다. 'Host:'로 시작하는 행과 'Cookie:'로 시작하는 행부터 다음 마지막 다섯 행이 지워졌다. 

손상된 패킷

캡처하는 과정에서 다음과 같이 패킷이 손상될 수 있다.


그림 7. Wireshark에 표시된 손상된 패킷
일부 패킷이 손상된 상태로 수신되었다는 것을 나타내기 위해 이 패킷을 검정색 배경으로 강조한, Wireshark 패킷 캡처 결과 화면의 스크린샷 

패킷이 손상되면 SSL Dissector가 부분적으로 실패할 수 있다. 아래쪽에 녹색 행이 있지만, 이 행에서는 GET에 대한 응답이 복호화되지 않았다. 이 문제를 수정하려면 File --> Save As를 사용하여 이 캡처를 저장해야 한다. 그런 다음, Cygwin에서 editcap –d capture.pcap fixed.pcap을 실행해야 한다. 여기서 editcap은 Wireshark 설치판에 포함되어 있으며 capture.pcap은 저장된 캡처 파일이다. 그리고 fixed.pcap은 이 명령을 실행한 후에 수정된 캡처 파일이다. 이 명령을 실행하고 나면 수정된 패킷 캡처 파일을 Wireshark로 로드할 수 있다. 그러면 예상하는 바와 같이 복호화된 패킷이 표시된다.

녹색 행이 전혀 없는 경우

전체 SSL 대화를 캡처해야 Wireshark가 제대로 작동한다. 이 튜토리얼을 수행하는 과정에서 브라우저를 통해 다수의 요청을 하는 경우, 설정된 보안 연결 중 일부가 캐시되어 캡처된 대화에는 설정된 전체 보안 연결 중 일부만 포함된다. 이렇게 되면 SSL Dissector가 작업을 수행할 수 없게 된다. 캡처를 시작하는 시점에서 Info 행에 "Server Hello, Certificate, Server Hello Done"으로 된 항목이 있는지 살펴보자. 이 항목이 없으면 브라우저는 이전에 설정된 연결의 일부를 다시 사용하고 있는 것이다. 브라우저를 다시 시작하고 재시도하면 이 문제가 수정된다.


출처 : http://www.ibm.com/developerworks/kr/web/tutorials/wa-tomcat/section4.html

'개발' 카테고리의 다른 글

SSL 통신을 캡처하기위한 Tomcat 구성  (1) 2012.11.14
winapi wininet 사용하여 https post 날리기  (0) 2012.11.13
PostgreSQL ALTER TABLE  (0) 2010.11.02
posted by 키에티스트
2012. 11. 13. 17:32 개발

Flag 값을 중간중간 갱신해주는게 포인트


플래그 값 하나로 막 쓰다 보니 ssl 이 안붙거나 개인 인증서라서 에러 발생


귀차나서 중간중간 값 찍어보려고 막 해놓은게 있긴 하지만 잘 작동하는 소스


    int nResult=0;

    HINTERNET   hInternet, hHttpSession, hHttpRequest;

    DWORD dwError = 0;

DWORD dwFlags = INTERNET_FLAG_SECURE |

INTERNET_FLAG_RELOAD |

INTERNET_FLAG_DONT_CACHE |

INTERNET_FLAG_NO_COOKIES;

    // set up connection

    if ( (hInternet=InternetOpen("test", INTERNET_OPEN_TYPE_PRECONFIG, 0, 0, 0)) )

    {

        // set up session

        if ( (hHttpSession=InternetConnect(hInternet, "IP_ADDR", INTERNET_DEFAULT_HTTPS_PORT, 0, 0, INTERNET_SERVICE_HTTP, 0, 0)) )

        {

            // open site

            if ( (hHttpRequest=HttpOpenRequest(hHttpSession, "POST", "/test", 0, 0, 0, dwFlags, 0)) )

            {

dwFlags = SECURITY_FLAG_IGNORE_UNKNOWN_CA |

SECURITY_FLAG_IGNORE_REVOCATION |

SECURITY_FLAG_IGNORE_REDIRECT_TO_HTTP |

SECURITY_FLAG_IGNORE_REDIRECT_TO_HTTPS |

SECURITY_FLAG_IGNORE_CERT_DATE_INVALID |

SECURITY_FLAG_IGNORE_CERT_CN_INVALID;


InternetSetOption(hHttpRequest, INTERNET_OPTION_SECURITY_FLAGS, &dwFlags, sizeof(dwFlags));

dwError = GetLastError();

/*

//헤더 추가하고 포스트 작성하는 부분인데 귀차나서 주석

char szPostData[2048] = {0};

lstrcpy(szPostData, "test");


char szLen[MAX_PATH] = {0};

char szHeader[2048] = {0};


wsprintf(szLen, "%d", lstrlen(szPostData));

lstrcpy(szHeader, "Accept: text/*\r\n");

lstrcat(szHeader, "User-Agent: Mozilla/4.0 (compatible; MSIE 5.0;* Windows NT)\r\n");

lstrcat(szHeader, "Content-type: application/x-www-form-urlencoded\r\n");

lstrcat(szHeader, "Content-length: ");

lstrcat(szHeader, szLen);

lstrcat(szHeader, "\r\n\n");


dwFlags = HTTP_ADDREQ_FLAG_REPLACE | HTTP_ADDREQ_FLAG_ADD;

 HttpAddRequestHeaders(hHttpRequest, szHeader, -1L, dwFlags);

dwError = GetLastError();

*/

                // send request for login server

                if ( HttpSendRequest(hHttpRequest, 0, 0, 0, 0) )

                {

                    // TODO

                    nResult=1;

                }

else

{

dwError = GetLastError();

}

            }

else

{

dwError = GetLastError();

}

InternetCloseHandle(hHttpRequest);

        }

        InternetCloseHandle(hHttpSession);

    }

    InternetCloseHandle(hInternet);

'개발' 카테고리의 다른 글

SSL 통신을 캡처하기위한 Tomcat 구성  (1) 2012.11.14
SSL 패킷 캡처를 위한 wireshark 설정  (0) 2012.11.14
PostgreSQL ALTER TABLE  (0) 2010.11.02
posted by 키에티스트