메뉴 바로가기 검색 및 카테고리 바로가기 본문 바로가기

한빛출판네트워크

IT/모바일

자바 보안 구조의 10 가지 팁

한빛미디어

|

2001-07-24

|

by HANBIT

11,586

by 스콧 옥스, Java Security, 2nd Edition의 저자 보안은 자바 플랫폼을 디자인할 때 여러 가지 영향을 미친다. 물론 보안을 관리하는 사람이 따로 있고, 핵심 J2SE(Java 2, Standard Edition) 플랫폼에서 디지털 사인을 만들기 위한 클래스를 포함하고 있다. 그리고 Java 2, version 1.3에서는 세 가지 중요한 보안 확장이 있다. 게다가 보안 문제는 자바의 클래스 로더 및 언어 규칙(배열 bounds 체킹 등), 그리고 클래스의 구현(java.lang.String 클래스 등)에까지 영향을 미친다. 그러면 보안 문제에 대해 어떻게 시작해야 할까? Java Security 2nd Edition에서는 자바 보안 인프라(infrastructure)를 개략적으로 살펴보는 것으로 시작해서 URL 클래스 로더를 사용하여 그것이 로드하는 클래스에 부가적인 퍼미션을 설치하기 위한 세부사항, P와 Q(DSA 키를 계산할 때 사용하는 파라미터) 등 특정 값을 사용하여 DSA 키를 만드는 것까지 다루고 있다. 이 글에서는 보안에 입문할 때 가장 중요한 점을 간추려 볼 것이다. 자바 보안 구조로 작업할 때 가장 중요한 10 가지 팁을 제시하겠다. 1. 모든 것을 보안 관리자로 실행하라. 자바 보안에서 가장 잘 알려진 점은 애플릿이 특정 연산을 수행하는 데에 제한을 받는다는 것이다. 보안 관리자가 이러한 제한을 한다. 하지만 보안 관리자가 애플릿에만 적용되는 것은 아니다. RMI 서버 등의 애플리케이션에도 올바르게 연산이 일어나기 전에 보안 관리자를 설치해야 하는 경우도 있다. 그러나 모든 애플리케이션은 보안 관리자의 혜택을 받을 수 있다. Acme Software에서 방금 자바 애플리케이션을 받았다고 하자. Acme은 믿을만한 소프트웨어 회사이므로 소프트웨어에 바이러스를 집어넣지는 않았을 것이다. 하지만 Acme에서 주의를 충분히 기울이지 않아서 소프트웨어에 바이러스가 침입했을 수도 있다. 아무리 좋은 소프트웨어 회사라도 모르는 사이에 바이러스가 침입한 소프트웨어를 배포할 수도 Acme의 소프트웨어가 C++로 작성되었다면, 사용자는 Acme에서 그것을 보내기 전에 바이러스를 치료했기만을 바라야 할 것이다. 사용자가 할 수 있는 일은 별로 없다. 하지만 자바로 작성되었다면, 보안 관리자의 보호 아래 실행할 수 있다. 그래서 소프트웨어가 중요한 시스템 파일이나 다른 문서에 접근하거나 그것을 삭제하지 못하게 할 수 있다. 모든 자바 프로그램에서 보안 관리자는 선택적이다. 애플릿을 실행하는 컨테이너(appletviewer나 자바를 사용할 수 있는 브라우저)는 자동으로 보안 관리자를 설치하지만 그 외의 경우에는 보안 관리자를 설치하는 것은 선택에 달려있다. 만약 애플리케이션을 작성하고 있다면, 프로그램적으로 이것이 가능하다. 하지만 자바를 시작할 때 명령 행에 "Djava.security.manager"라는 플래그(flag)를 포함하는 것이 훨씬 간단하다. 자바가 처음 생겼을 때에는 자바 보안 모델에 "심각한 결점"이 있었다. 명령 행에서 실행되는 애플리케이션은 파일을 읽을 수 있거나, 네트워크에 접속할 수 있었다. 지금까지, 대부분의 사람들은 애플리케이션과 애플릿이 이런 점에서 차이가 있다고 이해하고 있다. 애플리케이션이 보안 관리자와 함께 실행될 수 있게 만들어야 한다는 점을 인식하는 사람은 매우 적다. 2. 인증을 얻어라. 자바 보안 구조의 많은 부분이 디지털 인증(정확히 말하자면, X509 인증)에 의존한다. .jar 파일에 있는 코드가 더 많은 허가를 얻을 수 있게 하기 위해 .jar 파일에 사인하는 데에 디지털 인증을 사용한다. SSL(Security Socket Layer)을 사용하는 서버를 셋업할 때, 특정 형식으로 암호화할 때 등의 경우 디지털 인증을 사용할 수 있다. 이상적으로는 모두에게 디지털 인증이 있고 그것을 단순하게 사용할 수 있어야 할 것이지만, 실제로는 그렇지 않다. 디지털 인증은 관리하기 힘들고, 자바 관련 툴은 특정 워크그룹(엔터프라이즈는 말할 것도 없다)에서 사용하는 디지털 인증에 딱 들어맞는 것은 아니다. 게다가 자바 애플리케이션과 다른 애플리케이션에서 디지털 인증을 공유하기도 힘들다. 하지만 디지털 인증을 지원하기 위한 구조는 지난 몇 년간 발전되어 왔다. 사실 개인이 디지털 인증을 얻기는 정말 쉬워졌다. Thawte 웹사이트를 방문해서 "personal certificate"를 클릭하기만 하면 된다. 웹사이트의 개인 인증 프로그램을 일단 등록하기만 하면, 모든 자바 애플리케이션에서 사용할 수 있는 인증을 얻을 수 있다. 이것은 무료이며, 사용하기도 쉽다. 자바에서 가장 중요한 보안 특성을 이용할 때 인증이 꼭 필요한 것은 아니다. 특히 부가적인 허가를 얻기 위해 코드에 사인할 필요가 없다. 연산을 수행하기 위한 허가는 코드가 로딩된 장소와 누가 코드에 사인했는지의 결합에 기반하여 자바 코드에 주어진다. 이 결합의 두 부분 모두 선택적이다. 만약 oreilly.com에 있는 코드에서 당신의 시스템에 있는 파일을 읽기 위해 허가를 받기를 원한다면, java.policy 파일에 다음 엔트리를 만들면 된다.
grant codebase "http://www.oreilly.com/" {
    permission java.io.FilePermission "<>", "read";
};
만약 네임 서버를 믿을 수 없는(인터넷 등) 네트워크에 있다면, 오직 URL에 기반하여 승인하는 것은 위험한 일이다. 하지만 보호 받는 네트워크에 있거나 파일 시스템에서 클래스를 로딩하고 있다면, 상관 없다. 만약 자바 애플리케이션을 배포하고 있다면, 사용자가 애플리케이션을 http를 통해 내려받고, 애플리케이션을 .jar 파일에 로컬로 설치하게 하고, 사용자가 적절한 허가를 적절한 파일 기반의 URL에 주도록 하라. 3. 자바 플러그 인과 RSA 인증을 사용하라.
 소프트웨어가 자바로 작성되었다면, 보안 관리자의 보호 아래 실행할 수 있다. 그래서 소프트웨어가 중요한 시스템 파일이나 다른 문서에 접근하거나 그것을 삭제하지 못하게 할 수 있다.
만약 인터넷에서 애플리케이션을 배치하고 있고, 부가적인 허가를 얻고 싶다면, 그 애플리케이션을 포함하는 .jar 파일에 사인하고 사용자에게 사인된 .jar 파일에 부가적인 허가를 요청하는 수밖에 없다. 자바 2 보안 모델을 지원하는 브라우저는 별로 없다. 넷스케이프 6(Netscape 6)과 오페라(Opera)에서는 지원이 된다. 넷스케이프의 초기 버전이나 인터넷 익스플로러(Internet Explorer)에서는 자바 2 보안 모델을 Java Plug-in을 통해서만 지원한다. 이 브라우저에 구축된 자바 가상 머신은 자바 2 보안 모델을 지원하지 않는다. 따라서 Java Plug-in(넷스케이프 6과 오페라에서는 자동으로 사용한다)을 사용하는 것이 제일 좋을 것이다. 그렇게 하면 추가로 얻을 수 있는 이점이 있다. 사용자는 보통 policytool을 실행하고 특정 장소에서 로딩되고(되거나) 특정 기관에서 사인된 코드에만 허가를 주는 한 가지 이상의 java.policy 파일을 수정함으로써 코드에 허가를 준다. 하지만 만약 애플릿에 RSA 인증으로 서명하고 그것을 Java Plug-in 1.3이나 그 이후 버전을 통해 실행한다면, 사용자는 policy 파일을 수정할 필요가 없다(심지어는 policy 파일이 뭔지 몰라도 된다). 자바 플러그 인이 RSA 인증으로 사인된 애플릿과 만나면, 사용자에게 애플릿이 보안 관리자가 애플릿에 설정해 놓았을 모든 제약을 무시해야 하는지를 물을 것이다. 사용자는 애플릿이 현재 세션에서나, 항상, 자유롭게 실행되도록 할 수 있다(자유롭게 실행되지 못하게 설정할 수도 있다). policy 파일도 없고 특정한 허가도 없다. 사용자는 단지 간단한 대화 상자만 다루면 된다. 4. 보안 확장을 얻어서 설치하라. 자바 보안 구조에서 세 가지 중요한 확장이 있다. JCE(Java Cryptography Extension)를 사용하면 다양한 알고리즘을 수행하여(보안 키 교환 등 다른 일도 수행한다) 강하게 암호화하는 코드를 허용한다. 그리고 JSSE(Java Secure Sockets Extension)을 사용하면, SSL에 자바 인터페이스를 제공한다. JAAS(Java Authentication and Authorization Service)를 사용하면 코드를 실행하는 최종 사용자의 신원을 확인할 수 있으며, 특정한 최종 사용자가 특정 작업을 하는 것(만)에만 권한을 부여할 수도 있다. 이것은 현재 자바 2 플랫폼의 버전 1.3에 대한 확장이다. 따라서 이 프로그램은 별도로 내려받아서 꾸러미나 꾸러미가 아닌 확장으로서 사용해야 한다. 이 경우에 .jar 파일을 $JAVAHOME/lib/ext에 설치하고 설정한다. 아니면 애플리케이션에서 .jar 파일을 포함하도록 클래스패스(classpath)를 설정할 수도 있다. 설치 방법에 상관없이 이러한 확장에 대해 알아야 할 사항이 있다. 개발자를 위해 확장에서는 자바에 맞는 유용한 보안 API를 포함하고 있다. 핵심 플랫폼 API에서는 메시지 다이제스트와 디지털 서명을 만드는 것을 허용하지만, 많은 개발자들은 데이터를 암호화하고 사용자 인증을 하는 데에 관심이 있다. 이러한 확장은 자바 1.4의 핵심 배포에 포함될 지도 모른다. 1.4로 업그레이드하면 이런 기능을 사용하라.
 지금까지, 대부분의 사람들은 애플리케이션과 애플릿이 이런 점에서 차이가 있다고 이해하고 있다. 애플리케이션이 보안 관리자와 함께 실행될 수 있게 만들어야 한다는 점을 인식하는 사람은 매우 적다.
지금까지는 JCE와 JSSE는 확장으로서 사용 가능했지만 이제는 미국 정부가 수출을 제한하지 않을 것이라는 점에서 중요하다. 확장의 이전 버전은 미국과 캐나다 내에서만 사용하고 배치할 수 있었다. 개발 제한이란 그러한 확장을 사용하는 프로그램을 인터넷에 배치할 수 없다는 것을 의미한다. 미국 정책의 변화로 썬 마이크로시스템에서 세계로 확장을 배포할 수 있게 되었다. 어떤 나라에서는 이러한 패키지를 수입하는 데 제한이 있을 수도 있다. 자세한 사항은 Java Secure Socket Extension을 참고하라. 5. SSL 서버 네임을 검증하라. JSSE에서는 SSL을 사용하기 위한 API를 제공한다. SSL은 소켓 프로토콜이므로, API는 자바의 표준 소켓 의미론을 따르는 클래스를 공급한다. SSLSocket 클래스는 Socket 클래스를 확장하고 SSLServerSocket 클래스는 ServerSocket 클래스를 확장한다. 이것은 평범한 SSL 소켓을 상호 교환 가능하게 사용할 수 있게 한다. 사실 JSSE는 이 추상화에 소켓 팩토리를 공급한다. 하지만 여기에는 복잡한 것이 있다. SSL과 평범한 소켓은 호스트와 포트에 접속함으로써 생성되며, 이것은 소켓 팩토리가 공급하는 인터페이스이다. 하지만 안전성을 최대화하기 위해, SSL 소켓은 부가적으로 초기화 단계를 거쳐야 한다. SSL 클라이언트가 SSL 서버에 연결될 때 서버가 클라이언트에 인증을 보내고, 클라이언트는 인증을 확인하고, 어떤 암호화 알고리즘을 사용할 지 결정하는 등 많은 단계를 거친다. SSLSocket 객체가 생성되면 모든 것이 종료된다. 하지만 클라이언트가 서버에서 보낸 인증의 유효성을 확인하는 동안, 서버의 신원을 확인하지 못한다. 클라이언트에서는 단지 인증을 발행한 기관을 신뢰하며, 그 기관에서 유효한 인증이 생겼다는 것을 알 뿐이다. 애플리케이션 개발자는 한 걸음 더 나아가서 애플리케이션이 올바른 서버에 접속되었는지 확인해야 한다. 이것을 확인하려면 인증에 이식된 이름이 인증에 있는 사이트 이름과 일치하는지 검사하면 된다. 만약 www.sun.com에 있는 SSL 서버에 접속한다면, 당신에게 되돌아오는 인증 안에 있는 이름도 www.sun.com이어야 한다. 그리고 애플리케이션 개발자는 코드를 공급해야 한다. 애플리케이션 개발자는 인증에 있는 이름을 보기 위해 코드를 공급해야 하며, 그것이 애플리케이션에서 접속하고자 하는 호스트 네임과 같은지 확인해야 한다. 다양한 환경에서 이름이 모두 일치하지 않는 경우도 자주 있다. 애플리케이션에서는 호스트 네임이 아니라 특정 IP 주소를 표시할 수도 있으며, 어떤 사이트에서는 이름이 잘못된 채로 인증이 되었을 수도 있다. 그래서 확인 과정을 거쳐야 하는 것이다. IP 주소를 복구하고, 그것을 비교하며, 애플리케이션에서 사용자에게 이름이 서로 일치하지 않을 경우 그것을 받아들일 것인지의 여부를 묻는다. 어떻게 확인할 것인지는 애플리케이션에 따라 다르다. 이 단계가 중요하지만, 소켓 API의 프로토콜 독립적인 요소 때문에 수행하기 힘들 수도 있다. 6. 구현을 엔터프라이즈에 맞추어라. 자바의 핵심 보안 구현은 단일 사용자나 단일 플랫폼에 좋다. 하지만 다른 솔루션이 필요할 경우에는 어떻게 해야 하는가? 인증은 키툴(keytool)이 관리하는 파일에 담겨 있다. 로컬 워크그룹에서는 파일을 공유할 수 있겠지만, 도쿄와 뉴욕 사무실에서 공유하려면 어떻게 해야 하는가? 다양한 java.policy 파일에 있는 엔트리에 있는 코드에 기반하여 허가가 주어지지만, 이것을 한 군데에 모아서 보관하고 싶다면 어떻게 해야 하는가? JAAS는 그것이 확인한 허가를 사용자에게 인증을 주기 위해 셋업된다. 하지만 임시적으로 만들어진 기준에서 정의된 허가가 정의되어야 할 때에는 어떻게 해야 하는가? 사용자 이름에 기반하여 정의되어야 하는 경우도 있을 것이다.
 자바가 얼마나 안전한지, 혹은 자바 애플리케이션에 얼마나 많은 보안을 설정하였는지는 상관이 없다. 환경에서 나머지 부분이 안전하지 않으면, 자바의 장점은 큰 도움이 되지 않는다.
위에서 언급한 모든 문제는 여러 가지 중요한(그리고 핵심적인) 자바 클래스의 구현을 공급하면 해결된다. 보안 구조는 그런 식으로 정의되기 때문에, 클래스를 로컬 사용자 기반으로 구현하는 것은 환경에 따라 커스터마이즈(customize)되는 구현으로 쉽게 대체될 수 있다. 그것은 Policy 클래스(각 클래스에 주어지는 허가를 결정한다)의 디폴트 구현을 대체하는 것이 급진적으로 보일 수도 있지만, 사실 그렇지도 않다. 많은 환경에서 이런 일이 가능하며, 보안 API에 의해 정의되는 기본적인 연산이다. 이런 식으로, 자바의 기본적인 보안 클래스로 확장할 수 있는 제 3의 패키지가 점점 늘어나고 있다. 더 많은 솔루션을 살펴 보려면 Solutions Marketplace를 참고하라. 7. 올바른 암호 파라미터를 사용하라. JCE를 사용하면 API에서 DES, DESede(triple DES), Blowfish 등 다양한 알고리즘을 사용하여 암호화를 할 수 있다. 하지만 알고리즘이 실행될 모드도 알고리즘 만큼 중요하다. 암호화 하려는 데이터 타입에 맞는 모드를 선택해야 한다. 암호화의 디폴트 모드는 ECB(Electronic CookBook)이다. 이 모드는 데이터 블록(8 바이트)을 한 번에 암호화한다. 만약 사이퍼텍스트가 재정렬되면, 암호가 해독되어 있을 것이다(비록 평문(plain text)은 어지럽혀질 테지만). 패턴을 찾게 되면 ECB 모드는 공격 받을 수 있다. 그래서 텍스트로 된 데이터를 암호화하는 데에는 알맞지 않으며, 바이너리 데이터에만 사용해야 한다. 어떤 텍스트 타입은 CBC(Cipher Block Chaining) 모드를 사용하는 암호화에 적당하다. 이 모드는 패턴이 텍스트의 시작 부분에 있지 않다면(이 메일(e-mail) 헤더처럼) 텍스트 데이터에 있는 패턴을 숨길 수 있다. 이 모드는 몇몇 키 교환 기술에서 사용되는 PBEWithMD5AndDes 등과 같은 특정 알고리즘에서 사용할 때 가장 좋다. 텍스트는 OFB 모드(Output Feedback)나 CFB(Cipher FeedBack)에서 암호화가 더 잘 된다. 이 모드에서는 텍스트에 있는 패턴을 모두 숨길 수 있다. OFB는 모뎀 등 시끄러운 전송 선을 위해 설계되었다. 만약 다른 모드로 암호화된 데이터가 조금이라도 있다면 전체 8바이트(byte) 블록이 없어지지만, OFB 모드에서는 1비트(bit)만 없어진다. 만약 자동으로 데이터를 암호화하거나 암호를 푸는 인풋(input)이나 아웃풋 스트림(output stream)을 사용할 것이라면, 8번에 덧붙인 모드 중 하나를 사용해야 한다. 이것을 사용하면 데이터가 8비트 블록으로 처리된다. 그렇지 않을 경우, 스트림은 데이터를 처리하기 전에 64 비트 데이터로 버퍼될 것이다. 8. 외부 환경을 이해하라. 나는 최근 근무 중에 종종 접근하던 웹사이트를 자동화하는 프로그램을 작성하였다. 이 웹사이트에는 사용자 이름과 패스워드가 필요하고, 특정 형식에 맞추어야 하며, 그리고 나서 어떤 형식에 맞게 기입하고, 도큐먼트를 받을 것이다. 하지만 자동 프로그램을 사용하면 문서를 얻기 위해 단지 스크립트를 실행하기만 하면 된다. 패스워드를 어떻게 다룰 지에 대해서는 크게 논쟁이 되었다. 우리는 스크립트가 특정 시점에서 자동으로 실행되기를 원했기 때문에, 그것이 더 빨리 일어나게 할 수가 없었다. 그리고 동료 몇 명은 보호 받지 않는 패스워드를 스크립트에 남겨두는 것이 마음 편하지 않다고 하였다. 그래서 패스워드는 스크립트에 저장하기 전에 암호화되어야 한다. 여기서 해야 할 일은 물론 JCE로부터 강한 암호화 API를 사용하는 것이다. 이상적으로 이것은 모든 사람의 개인적인 인증에 기반할 수 있다. 나는 그렇게 하지 않았다. 나는 내 동료가 금방 알아낼 수 있도록 암호화를 약하게 구현했다(일단 알기만 하면 가능하다).
 자바 보안에 관심이 있다면, 자바계에서 일어나는 일에 계속 관심을 가져야 한다.
나는 게으른 프로그래머이며, 내가 제시한 구현은 저항이 가장 적은 경로이다. 하지만 위에서 언급한 방법은 다른 관점에서도 이치에 맞다. 우리가 접속하는 웹사이트는 http를 사용하지 않는다. 그래서 어떤 사람이 내 패스워드를 훔치고 싶다면, 내 스크립트를 위치시키고 나의 암호화 기술을 해킹할 것이다. 하지만 네트워크를 기웃거리다가 웹 서버에 패스워드가 깔끔하게 텍스트로 전송될 때 패스워드를 훔치는 것이 훨씬 쉽다. 자바 사용자는 보안을 중요하게 생각하며, 자바에서 보안과 관련된 것들은 다른 환경 요인보다 얼마나 감시를 잘 하는가에 달려 있다. 하지만 가끔 자바가 얼마나 안전한지, 혹은 자바 애플리케이션에 얼마나 많은 보안을 설정하였는지는 상관이 없다. 환경에서 나머지 부분이 안전하지 않으면, 자바의 장점은 큰 도움이 되지 않는다. (이것을 구실로 사용하지는 말기를 바란다. 언젠가 내 친구와 내가 접근한 웹사이트에서는 방법이 바보같다는 것을 알아챌 것이고, http를 사용하기 시작할 것이다. 그 다음에 나는 프로그램을 고칠 수밖에 없다. 그러므로 처음부터 제대로 일을 하는 것이 낫다) 9. 최종 사용자 보호 6번 팁에서 설명한 것처럼, 자바의 보안 구조는 매우 유연하다. 자신이 하고 있는 일에 대해 이해하는 사람들에게는 매우 좋다. 하지만 때때로 사용자가 보호 받아야 할 필요가 있는 환경에 있을 수도 있다. 내가 그렇게 거만한 관리자라는 것은 아니다. 사용자가 직면할 수 있는 가장 큰 위험은 허용될 수 없는 연산을 수행하기 위해 신뢰할 수 없는 코드를 따르는 정책 파일에 엔트리를 배치하는 것이다. 디폴트에 의해, 각 사용자는 그러한 허용의 목록을 볼 수 있는 파일($HOME/.java.policy)을 가진다. 그러한 허용은 사용자가 명령 행에 지시한 파일(-Djava.policy 인자와 함께) 뿐 아니라 $JAVAHOME/lib/security/java.policy 파일에 나온 목록에 더해진다. $JAVAHOME/lib/securtiy/java.security 파일을 편집하고 다음 두 가지를 바꾸어서 이러한 보안 구조 특성을 사용할 수 없게 할 수도 있다.
   Delete the line that reads
   policy.url.2=file:${user.home}/.java.policy

   Comment out the line that reads
   policy.allowSystemProperty=true
이렇게 바꾼 후에 $JAVAHOME/lib/security/java.policy 파일에 열거된 허가는 자바 애플리케이션이 실행될 때 효과가 있을 것이다. 사용자는 자바 클래스에 부가적인 허가를 줄 수 없다. 이것이 효과적으로 작용하려면, 물론 최종 사용자는 $JAVAHOME/lib/security 디렉토리에 있는 edit 파일에 접근할 수 없어야 하다. 10. 정보를 계속 수집하라. 자바 보안에 관심이 있다면, 자바계에서 일어나는 일에 계속 관심을 가져야 한다. 특히 java.sun.com에는 자바 보안 구조에서 중요한 점을 알 수 있는 링크가 많이 있다. 자바 보안 모델을 구현하다가 버그를 발견하면, 이 사이트에도 게재된다.
스콧 옥스는 썬 마이크로시스템에서 1987년부터 일한 자바 기술자이다. 썬에서 근무하면서, 그는 SunOS 커널에서 네트워크 프로그래밍과 RPC 등 다양한 기술을 담당했다. 1995년 이후에는 자바에만 전념하였고, 자바 기술을 최종사용자가 사용할 수 있게 하였다.
TAG :
댓글 입력
자료실

최근 본 책0