주요글: 도커 시작하기
반응형
안전한 코드를 위한 보안 정책에 대해서 살펴본다.

코드의 보안 강화 방법

지난 '안전한 코드를 위한 보안 정책: Part 1'에서는 안전한 코드를 위한 정책으로서 제품의 요구 사항과 위험관리, 에러 처리, 객체에 대한 접근 규약, 접근과 승인 등에 대한 내용을 살펴보았다. 이번 Part 2에서는 계속해서 안전한 코드를 위한 보안 정책에 대해서 살펴보도록 하자.

코드의 구분

여러분은 어플리케이션에 알맞은 컴포넌트 또는 객체를 사용함으로써 보안 구멍에 따른 피해를 최소화할 수 있다. 코딩할 때는 가능한 한 많이 고룁된 유닛(즉, 다른 요소와의 연관성이 매우 적은 컴포넌트나 객체)을 사용해야 한다. 특히, 보안과 관련된 코드는 어플리케이션에 알맞게 설계된 보안 API를 사용해야 하며, 그렇게 함으로써 여러분은 보안 정책을 틈새없이 제어할 수 있다. 예를 들어, 불필요하게 다양한 기능을 제공하는 보안 API를 사용할 경우에는 필요로 하지 않는 기능에 의한 보안 구멍이 생길 수 있으며, 또한 너무 적은 기능을 제공하는 보안 API를 사용할 경우에는 어플리케이션에서 필요로 하는 보안 기능을 충족시킬 수 없게 된다.

또한, 인증된 코드를 하나의 아카이브 파일에 넣어야 한다. 예를 들어, 보안 구멍을 노리고 있는 공격자들은 인증된 클래스를 연결하는 새로운 애플릿이나 라이브러리를 생성할 수도 있다. 비록 인증된 코드를 하나의 아카이브 파일에 넣는 것이 이러한 문제를 완벽하게 해결하지는 못하지만, 문제를 해결하는 데 도움을 줄 수는 있을 것이다.

암호화

여러분이 작성한 코드는 매우 깨기 어려운 코드일 수도 있지만, 그 코드에 있는 문제점은 항상 공격의 대상이 될 수 있다. 특히 네트워크를 통해서 데이터를 주고 받는 경우에는 더더욱 그렇다. 예를 들어, POP3를 생각해보자. POP3는 메일 서버로부터 메일을 읽어올 때 사용되는 프로토콜이다. POP3는 사용자를 인증하기 위해서 사용자 아이디와 암호를 입력하도록 하고 있다. 하지만 이 때 입력하는 아이디와 암호는 어떤 처리도 되지 않은 평범한 텍스트로 전송되기 때문에 중간에서 누구든지 손쉽게 그 내용을 훔쳐볼 수 있는 가능성이 있다.

텔넷 역시 이러한 보안 문제를 갖고 있으며, 오늘날 가장 많이 사용되는 HTTP 프로토콜 역시 같은 보안 문제를 안고 있다. 이러한 문제점을 해결할 수 있는 가장 간단한 방법은 주고 받는 데이터를 암호화하는 것이다. 예를 들어, 텔넷의 경우 SSH을 사용하여 데이터를 암호화하고 있고, HTTP 프로토콜의 경우는 HTTPS를 통해서 암호화를 할 수 있게 되어있다. 여러분이 작성하는 어플리케이션 역시 네트워크를 통해서 보안을 유지해야 하는 데이터를 주고 받을 경우 암호화하는 것을 고려해봐야 한다. 암호화를 할 때의 주의점은 암호화 기법이 노출되어서는 안 된다는 점이다. 예를 들어, 비밀키/공개키를 사용하는 경우 비밀키가 노출될 경우 암호화하여 주고 받는 모든 데이터를 매우 간단하게 분석할 수 있게 된다.

주고 받는 데이터 뿐만 아니다. 회원이 입력하는 기밀 정보-예를 들어, 암호나 신용카드 번호-를 데이터베이스나 파일에 저장해야 하는 경우 암호화하는 것이 좋다. 비록 특정 사용자만 기밀 데이터에 접근할 수 있도록 보안 장치를 했다 하더라도 보안 장치는 언제든지 깨질 수 있으며, 따라서 기밀 데이터는 암호화하여 저장하는 것이 안정성을 더욱 높이는 방법이다.

입력 검사와 클라이언트 콜

입력의 검사는 매우 중요하다. 클라이언트는 변경될 수 있고, 쿠키 역시 변경될 수 있으며, DNS와 IP 주소는 스푸핑 될 수 있다. 공격자는 여러분이 작성한 바이너리 데이터를 변경할 수도 있다. 여러분이 사용하는 표준 라이브러리나 운영 체제가 안전하다고 가정해서는 안 된다.

가능하다면 이러한 종류의 모든 외부 데이터 입력은 피해야 한다. 항상 모든 클라이언트의 보안 검사를 해야 하며, 에러 검사는 필수적이다. 또한 입력 가능한 값의 집합을 정의해야 하며, 가능하다면 운영 체제까지 이어지는 하위 레벨 호출은 피해야 한다.

디컴파일러에 대한 방어

기계어를 디컴파일하여 프로그래밍 언어로 변환하는 일은 좀처럼 쉬운 일이 아니다. 예를 들어, 어셈블리어를 C/C++ 언어나 또는 델파이에서 사용하는 오브젝트 파스칼로 변환하려고 시도하는 것 자체가 고통스러운 일이다. 하지만, 자바의 경우는 얘기가 좀 다르다. 자바의 클래스 파일 포맷을 살펴보면 컨스턴트 풀(constant pool)이라는 것이 있는데 이것은 소스 코드에 대한 많은 정보를 포함하고 있으며, 디컴파일러는 이 정보를 이용하여 클래스 파일로부터 원본에 가까운 소스 코드를 추출해내기도 한다.

특히 최근에는 순수하게 자바로만 구현되는 제품이 증가하면서 디컴파일에 대한 방어를 할 수 있도록 코딩을 해야 할 필요성이 증가하고 있다. 디컴파일에 대한 내용은 IBM의 Developerworks에 있는 How to lock down your Java code 를 참조하기 바란다.

오픈 소스의 검토

최근 많은 프로젝트가 오픈소스로 진행되고 있다. 오픈 소스로 프로젝트를 진행할 경우 해커들이 매우 간단하게 어플리케이션의 약점을 발견할 수 있다는 단점이 있지만, 그와 함께 많은 사람들에 의해 보안 구멍을 빠르게 보완할 수 있다는 장점도 있다. 센드메일의 경우 초기 버전은 보안에 많은 문제점이 있었지만 지금은 많은 부분에서 문제점이 해결되었다. 이는 모두 센드메일의 소스 코드가 공개되었기 때문에 가능한 것이었을 것이다.

결론

Part 2에서는 지난 Part 1에서 언급하지 않았던 몇 가지 보안 정책에 대해서 추가적으로 살펴보았다. 개발자들은 항상 머리속에 자신이 개발한 어플리케이션에 보안 문제가 발생할 수 있다는 것을 염두해두어야 하며, 따라서 어플리케이션 개발할 때에는 먼저 보안 정책을 세워둠으로써 보다 안전한 어플리케이션을 개발할 수 있는 토대를 만들어야 할 것이다.

관련링크:

+ Recent posts