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

보안 정책

오늘날, 웹 어플리케이션을 포함한 대부분의 소프트웨어에서 보안은 반드시 제공해야 하는 기능으로 자리잡고 있다. 안전한 네트워크와 운영체제를 위한 검사 목록이 있으며, 보안 검사를 전문적으로 하는 기업에 의뢰를 맡기기도 한다.

하지만, 보안을 위한 검사 목록을 작성하고 다른 기업에 의뢰를 맡긴다 해도 보안 문제의 근본적인 원인은 해결할 수 없게 된다. 왜냐면 보안 문제의 근본적인 원인은 소프트웨어에 있기 때문이다. 실제로 외부에서 보안의 구멍을 뚫고 둘어오는 경우는 대부분 소프트웨어의 약점을 통해서 이루어진다. 모든 해커는 소프트웨어의 문제점을 이용하여 보안에 구멍을 뚫을 수 있고, 그러한 구멍은 모든 소프트웨어에서 발생할 수 있다. 예를 들어, 리눅스나 유닉스 시스템에서 SMTP 프로토콜을 이용하여 메일을 주고 받을 때 많이 사용되는 센드메일은 예전부터 보안에 많은 문제점이 있었으며, 이를 이용하여 시스템을 해킹한 사례가 많았다.

해커들의 공격으로부터 소프트웨어를 방어할 수 있는 유일한 방법은 방어 프로그래밍을 비롯한 소프트웨어 개발 보안 정책을 정의하는 것이다. 하지만, 아쉽게도 보안 문제를 고려한 개발 프로세스와 좋은 제품을 위한 개발 프로세스는 서로 상충하는 경우가 많다. 보안을 고려하여 설계된 소프트웨어는 소수에 불과하며, 대부분의 제품은 보안을 고려하지 않은 채로 개발이 시작되는 경우가 허다하다. 실제로, 오늘날에 충분한 시간을 갖고서 소프트웨어를 개발하는 것은 무리가 있으며, 이 때문에 제품을 빨리 만들려고 하는 프로그래머와 시간과 비용이 많이 드는 견고한 보안 정책을 세우는 설계자 사이에 심각한 딜레마를 유발하기도 한다.

이 글에서는 2회에 걸쳐 소프트웨어를 개발할 때 필요한 보안 정책에 대해서 살펴보기로 하자.

정책

소프트웨어에서의 보안은 보안 정책(policy)을 정하는 것에서부터 시작한다. 보안 정책은 개발자가 제품의 요구 사항을 따르는 데 도움을 주며, 코딩 표준과 개발 지침을 따르게끔 만들어준다. 특히, 이제 간신히 개발할 수 있을 정도의 실력을 가진 초보 프로그래머나 코더들에게 있어 안전한 코딩 정책은 매우 유용하다.

보안 정책은 모든 개발자들이 숙지해야 하는 것으로서, 모든 제품에 있어서 근본적인 요소이다. 개발자들은 보안 정책을 학습함으로써 제품에 표준적인 보안 체계를 제공할 수 있게 된다. 비록 코드 보안 정책이 작성할 제품에 따라서 크게 다르지만, 일반적으로 다음에 제시할 내용을 바탕으로 제품의 코드에 추가적인 보호 계층을 제공할 수 있을 것이다.

1. 제품의 요구 사항과 위험 관리

모든 소프트웨어 제품은 보안 요구 사항을 갖고 있다. 따라서 제품을 개발할 때에는 항상 제품의 보안과 관련된 부분을 염두해야 한다. 실제 프로젝트에서 보안과 비용은 동전의 양면에 비유할 수 있다. 보안에 신경을 쓰면 비용이 증가하게 되고, 비용을 줄이다 보면 보안이 허술해지는 트레이드 오프가 존재하는 것이다. 때때로, 제품의 보안 구멍을 남겨둬야 하는 경우도 발생하며, 이에 따라 비즈니스에 위험 부담을 허용하기도 한다.

일반적으로, 처음부터 보안을 염두해두고 시스템을 설계해야한다. 예를 들어, e-커머스에서 데이터를 주고 받는 데 초점을 둘 경우, 주고 받는 데이터를 암호화 할 것을 고려해야 한다. 또한 사용자가 웹을 통해서 입력한 신용카드 번호를 단순히 HTTP 프로토콜을 사용하여 입력 받을 지, 또는 HTTPS 프로토콜을 사용하여 암호화해서 입력 받을지를 프로젝트 초기에 결정하는 것이 좋다.

2. 에러 처리, 실패, 버그, 에러 상태

코딩 정책에 있어서 또 하나 중요한 것이 있다면 에러 처리에 대한 전략을 포함하고 있어야 한다는 점이다. 예를 들어, 자바는 예외(exception)를 지원하고 있다. 정책에는 예외가 어떻게 어디서 발생하는 지에 대한 목록이 포함되어 있어야 한다. 프로그램을 어떻게 테스트 할 것인지 그리고 실제로 어떻게 예외를 방어할 것인지에 대한 내용도 문서에 포함되어야 한다. 기타 try/catch 블럭에서 finally를 어떻게 구현할 지에 대한 표준도 정의되어 있어야 한다.

한 가지 일반적인 문제점인 프로그램의 실행이 실패할 때 어떤 상황이 발생하느냐에 관한 것이다. 만약 프로그램이 실패 이후에 불안전한 상태로 빠지게 된다면, 해커들은 실패가 발생하는 순간을 기다릴 것이다. 예를 들어, 버퍼 오버 플로우를 이용하여 해킹한 사례도 있다. 따라서 프로그램은 실행이 올바르게 되지 않고 실패할 경우에 시스템이 불안전한 상태로 빠지지 않는 방법을 갖고 있어야 한다.

3. 객체에 대한 접근 규약

보안 정책에는 언제 어떻게 객체를 사용할 지에 대한 내용도 정의되어 있어야 한다. private이 아닌 모든 클래스, 메소드, 객체 또는 변수는 공격을 위한 진입 지점이 된다. 따라서 기본적으로 모든 것들을 private으로 작성해야 한다. 만약 클래스, 메소드, 변수 또는 객체가 private이 아닐 경우, 왜 그렇게 했는지에 대한 내용을 정책 문서에 기록해야 한다.

자바 컴파일러는 이너 클래스(inner class)를 일반적인 클래스로 변환하며 따라서 이너 클래스 역시 보안 정책에서 다뤄야 하는 항목중의 하나이다. 일반적으로 이너 클래스는 같은 패키지에서 접근할 수 있으며, 또한 이너 클래스는 그 이너 클래스를 포함하고 있는 클래스의 모든 필드/메소드(심지어 포함하고 있는 클래스의 필드와 메소드가 private 이라 하더라도)에 접근할 수 있다. 따라서 이너 클래스에 대한 접근 정도를 알맞게 정해야 한다.

논-파이날(non-final) 클래스 역시 위험하다. 왜냐면 언제든지 알 수 없는 방법으로 그 클래스들을 상속할 수 있기 때문이다. 만약 논-파이날 클래스가 필요하다면 왜 그렇게 했는지에 대한 내용을 문서화해야 한다.

4. 민간함 정보

패스워드, 알고리즘, 암호화 키와 같은 정보는 유출되서는 안 되는 정보이다. 이러한 정보는 하드 코딩 되어서는 안 되며, 영구 메모리나 관리자 이외에는 접근할 수 없는 설정 파일에 저장하는 것이 좋다. 예를 들어, JDBC URL의 사용자 이름과 암호 부분을 하드 코딩했다고 해 보자. 이러한 정보는 자바 디컴파일러를 통해서 매우 손쉽게 유추해낼 수 있게 되며, 이 경우 데이터베이스에 저장되어 있는 데이터의 값이 원하지 않는 상태로 변경될 수 있게 된다.

5. 기존 소프트웨어와의 연동

필요할 경우 기존 소프트웨어와의 연동에 대한 표준을 정해야 한다. 만약 기존 소프트웨어가 다른 인크립션을 지원하거나 또는 더 적은 보안 표준을 지원할 경우 이것은 특히 중요하다. 기존 제품과 새로운 제품 사이의 신뢰도 정도를 반드시 언급해야 한다.

6. 접근(Access)과 승인(Authentication)

일반적으로, 퍼미션(permission)은 절대적으로 필요한 경우에만 부여해야 한다. 퍼미션을 부여할 때는 항상 최소한의 권한부터 부여해야 하며, 작업을 마칠 수 있는 시간 동안만 권한을 유지해야 하며, 또한 작업이 끝나면 그 권한을 다시 반환해야 한다.

퍼미션 승인은 주로 사용자 체크를 통해서 이루어지며, 사용자 체크의 대부분은 암호 기반의 메커니즘을 사용하고 있다. 따라서 프로그래머는 암호화 키나 암호를 코드내에 남겨두어서는 안 되며, 사용이 끝난 이후에은 그러한 정보를 메모리나 임시 저장 매체로부터 삭제해야 한다.

7. 문서화

문서화는 코딩, 디버깅을 위해서 중요하며, 특히 나중에 발생할지도 모를 법정 솟ㅇ이나 저작권 보호에 있어서 매우 유용하다. 예를 들어, 아파치 그룹에서 나오는 모든 제품은 비록 무료이긴 하지만 각 코드마다 저작권 정보를 표시하고 있으며, 이를 통해 저작권 보호를 받고 있다.

결론

Part 1에서는 코드를 보호하기 위한 보안 정책을 살펴보았다. 2부에서는 계속해서 안전한 코드를 작성하기 위한 몇 가지 코딩 보안 정책에 대해서 더 살펴보도록 하자.

+ Recent posts