하루가 멀다 하고 해킹 사고가 뉴스에 오르내리고 있습니다. 최근에는 숙박 앱이 해킹되어 개인 정보와 숙박 기록까지 유출된 것으로 추정되어 한바탕 소동이 일고 있습니다. 또 중국에서는 최근의 국내 군사 움직임을 문제 삼아 보복성 해킹 공격을 예고하고 또 실행하기도 했습니다. 이러한 환경에서 과연 우리의 IT 시스템은 얼마나 안전할 수 있을까요? 전문가들은 보안은 100% 안전할 수 없다고 말합니다. 그래서 기업의 보안담당자들은 치솟아만 가는 해킹의 위협 속에서 “제발 우리 회사는 공격 대상이 안됐으면 좋겠다”라든지, “설마, 우리 회사를 공격하겠어?”라는 기대와 희망이 교차하리라 생각됩니다. 물론 이미 다양한 방법으로 해킹 공격에 대응을 하는 회사도 있습니다. 또는 열심히 기도를 하고 있을 수도 있겠네요. 그래서 지금부터는 해킹 공격에 대응할 수 있는 방법 중 가장 근본적인 방법인 시큐어 코딩(Secure Coding)에 대해 이야기를 해보겠습니다. 본격적으로 이야기를 시작하기에 앞서, 이번 글에서 다루는 해킹 공격의 유형에 대해서 간단하게 짚고 넘어가겠습니다. 해킹에는 다양한 방법과 기법이 있습니다. ‘어디를 공격 대상으로 삼는가?’로 분류할 수도 있고, 공격 대상을 어떠한 경로로 해킹을 시도하는지, 즉 침투 경로로 분류할 수도 있습니다. 이렇게 분류한다면 네트워크 해킹, 시스템 해킹, 애플리케이션 해킹, 하드웨어 해킹, 심지어는 사람을 속이는 사회공학까지 너무나도 다양한 경로로 해킹 시도가 가능한 것을 알 수 있습니다. 이번 글에서는 ‘시큐어 코딩’에 대한 이야기인 만큼, 소프트웨어 해킹에 초점을 맞춰서 어떻게 하면 보다 안전한 소프트웨어를 개발하여 다양한 해킹 공격에 대비할 수 있을지 고민해 보겠습니다. 그럼 시큐어 코딩이 무엇인지부터 알아보겠습니다. 시큐어 코딩이란 안전한 소프트웨어 개발을 위해 소스 코드 등에 존재할 수 있는 잠재적인 보안 취약점을 제거하고, 보안을 고려하여 기능을 설계 및 구현하는 등 소프트웨어 개발 과정에서 지켜야 할 일련의 보안 활동을 말합니다. 이런 정의를 놓고 보면 ‘시큐어 코딩’은 IT 분야에서는 소프트웨어로 구현되는 모든 곳에 적용이 가능합니다. 비단 웹 애플리케이션뿐만이 아니라, 네트워크 장비, 네트워크 프로토콜을 구현하는 개발자들도 시큐어 코딩에 따라 개발을 해야 하고, 시스템 개발자들, OS(운영체제)를 개발하는 분들도 모두 해당이 되겠네요. 그 유명한 SDL(Secure Development Lifecycle)로 시큐어 코딩을 주창한 회사도 운영체제(Operating System, OS)를 개발하는 마이크로소프트였습니다. 그리고, 흔히 시큐어 코딩이라는 용어에서 발생하는 오해가 하나 있는데, 바로 ‘코딩’이라는 단어 때문에 발생하는 오해입니다. 마치 코딩을 하는 개발자만 알아서 안전하게 잘 하면 된다는, 책임을 개발자에게 지우는 생각을 하는 경우가 많습니다. 하지만 앞서 살펴본 정의에서 보듯 시큐어 코딩은 ‘지켜야 할 일련의 보안 활동’을 의미합니다. 즉, 소프트웨어를 개발하는데 있어서 코드를 안전하게 할 수 있는 절차상의 다양한 보안 활동들 전부를 포함합니다. 분석•설계 단계에서는 실제 개발, 즉 코딩이 포함되지 않기 때문에 보안과 관련된 활동이 없다고 생각하는 경우가 많습니다. 하지만 그렇지 않으며, 소프트웨어 개발이 분석•설계에 좌우되는 만큼 소프트웨어의 보안 수준도 분석•설계 단계에서 얼마나 보안을 고려했느냐가 관건이 됩니다. 우선 분석•설계 시점에 발생하고 있는 알려진 위협들을 파악을 해야 합니다. 이때 가장 많이 활용하는 기준은 OWASP (Open Web Application Security Project)의 Top 10 취약점이나, SANS (Server Application Network Security)의 Top 25 같이 흔하게 발생되는 보안 위협 또는 보안상 오류를 참고합니다. 이러한 위협에 대응하기 위해서 설계에 어떠한 요소들을 반영하고, 필요한 경우 애플리케이션 프레임워크를 결정하거나 애플리케이션 프레임워크에서 사용할 공통 모듈(공통 함수들의 집합)을 식별할 수 있습니다. 이는 일반적으로 다양한 고객 요구 사항을 소프트웨어에 효과적으로 반영해야 하는 역할을 가진 소프트웨어 아키텍트(Software Architect)가 주도하게 됩니다. 그리고 이 단계에서는 앞으로 본격적인 개발에 들어갈 개발자들에게 시큐어 코딩 가이드와 필요한 공통 모듈의 사용방법을 함께 교육을 시켜야 합니다. 보안뿐만이 아니라 일반적인 개발 과정에서 유지 보수성을 향상시키기 위해서라도 코딩 표준이나, 애플리케이션 프레임워크 사용 방법에 대해서는 교육을 시켜야 하기 때문에 이러한 과정에 보안과 관련된 내용을 포함시킵니다. 또 한가지 덧붙이자면, 아직 국내에서는 적용되는 사례가 많지는 않지만 설계서(또는 화면 설계서) 내에 보안 관련 요구 사항들을 명시하는 것입니다. 예를 들어 화면에 입력 값을 받는 곳에 SQL Injection 예방을 위한 입력 값 검증을 수행하도록 명시를 한다면 개발 시 개발자가 굳이 보안에 대해서 별도의 고민을 하지 않아도 되는 효과가 있습니다. 물론 보다 좋은 방법은 개발자가 아예 고민을 하지 않도록 애플리케이션 프레임워크 단에서 알아서 검증이 되도록 아키텍처를 설계하는 것이겠지만요. 실제 위와 같이 설계문서에 보안 요구 사항들을 반영을 하였을 경우, 그렇지 않았을 경우와 비교했을 때 모의해킹(취약점 점검)을 수행하면 발견되는 보안 취약점의 개수는 보안 요구 사항이 설계에 반영되었을 경우 현저하게 적습니다. 이제 본격적으로 소프트웨어 개발에 들어갑니다. 설계서에 보안 요건이 제대로 반영이 되었다면 이 단계에서의 작업도 무난하게 진행되겠죠? 하지만 안심할 수 없습니다. 일반적으로 소프트웨어에서는 항상 많은 오류 가능성을 내포하고 있습니다. 오류 가능성을 줄이기 위해 다양한 소프트웨어 품질관리 기법들이 등장했습니다. 테스트 주도 개발(Test-driven development, TDD) 등도 이런 상황에서 등장한 개발 방식 중 하나입니다. 그렇다면 보안 측면에서는 개발 단계에서 어떠한 검증 방법을 사용할 수 있을까요? 국내에서는 흔히 소스 코드 취약점 점검 도구라고 부르는 정적 소프트웨어 취약점 점검 도구를 많이 활용하고 있으며 실제 공공기관에서도 개발 시 소스 코드 취약점 점검이 의무화되어 있습니다. 정적 소프트웨어 취약점 점검 도구는 개발 중인 소스 코드를 분석하여 알려진 취약한 패턴을 찾아줍니다. 예를 들어 사용자로부터 입력 값을 받은 변수를 별도의 검증 절차 없이 바로 메모리에 복사를 하는 등의 행위를 할 경우 입력 값 검증을 하지 않았다는 오류를 발생시킵니다. 또한 사용하는 곳에 따라서 개발이 완료된 후에 점검을 하기도 하지만 가장 바람직한 형태는 개발자의 개발 환경에 유기적으로 포함되는 것입니다. 즉, 컴파일 시에 자동으로 소프트웨어 취약점 점검이 이루어지는 형태입니다. 물론 이렇게 할 경우 개발자가 많은 환경에서는 적용이 어려울 수도 있어 소스 코드 형상관리 도구와 연계하여 적용 시 점검하도록 구현할 수 있습니다. 그리고 도구를 활용하는 방법 외에 마이크로소프트에서 활용하는 것으로 알려진 방법은 짝 프로그래밍(Pair Programming)입니다. 개발자 두 명이 나란히 앉아서 개발을 함께 진행하는 것입니다. 두 명이 함께 개발을 진행하게 되면 서로 놓치는 부분을 보완해주는 효과가 있습니다. 결국 소스 코드의 ‘품질’을 높이는데 활용되는 다양한 방법들이 동일하게 보안을 높이는데도 사용되는 것을 알 수 있습니다. 보안도 결국은 품질의 한 요소이니까요. 시험 단계에서는 개발된 코드가 실제 요구 사항에 맞도록 동작하는지 확인합니다. 이때 보안 측면에서는 앞서 분석•설계 단계에서 정의했던 보안 위협들이 제대로 차단이 되는지를 검증하게 됩니다. 이때도 성능 시험을 위해 별도의 도구를 이용하는 것과 같이, 보안을 위한 도구도 존재합니다. 개발 단계에서는 ‘정적’ 소프트웨어 취약점 점검 도구를 이용했다면, 시험 단계에서는 ‘동적’ 소프트웨어 취약점 점검 도구를 이용합니다. 대표적인 예로는 웹 애플리케이션 스캐너가 있습니다. 실제 동작하는 소프트웨어에 알려진 다양한 공격을 자동화하여 시도하고 발생되는 취약점을 식별하여 알려주게 됩니다. 이러한 동적 소프트웨어 취약점 점검 도구에도 한계가 있습니다. 알려진 취약점에 대해서는 짧은 시간 안에 사람보다 훨씬 더 다양한 공격들을 시도하여 많은 취약점을 찾아내지만, 사람이 수행해야만 알 수 있는 비즈니스적인 취약점들을 발견하기 어렵습니다. 예를 들어, 입력 값 검증을 하지 못해 발생하는 SQL Injection의 경우는 사람보다는 자동화된 점검 도구가 훨씬 더 손쉽게 취약점을 발견하지만, 일반 사용자는 특정 권한을 가진 화면을 볼 수 없다는 권한 관리 요건을 점검할 때는 아직까지는 사람이 조금 더 손쉽게 점검을 할 수 있습니다. 따라서 보통 수작업이 포함되는 모의해킹(또는 취약점 점검)을 별도로 수행합니다. 대규모 회사의 경우는 이러한 모의해킹을 전담하여 수행하는 별도의 조직을 운영하기도 합니다. 흔히 Red Team으로 부르는 이러한 조직은 기업•기관의 다양한 소프트웨어에 대해 상시적으로 취약점 점검을 수행하는 역할을 갖습니다. 이 과정을 거쳐서 개발된 안전한 소프트웨어가 세상에 나오게 되면 모든 것이 완료되었다고 생각하기 쉽습니다. 하지만 그렇지 않습니다. 고객의 요구 사항은 지속적으로 바뀌기 때문에 소프트웨어도 그에 따라 진화를 해나갑니다. 새로운 기능을 넣기도 하고, 기존의 기능을 보완하기도 합니다. 이렇게 조금씩 계속 바뀌어 나가는 소프트웨어는 다시 보안 위협에 직면하게 되고, 새로운 형태의 공격 기법들이 등장하기도 합니다. 따라서 운영 단계에서는 주기적으로 새로운 보안 위협을 식별하고, 식별된 보안 위협이 기존의 소프트웨어에 미치는 영향을 분석하여 보완하는 작업을 끊임없이 수행해야 합니다. 이런 작업을 가장 손쉽게 알게 해주는 사례가 바로 윈도우 보안 업데이트입니다. 마이크로소프트에서도 새로운 보안 위협이나 취약점이 발견이 되면 지속적으로 보안 업데이트를 제공하여 기존의 소프트웨어에 패치를 진행하고 있습니다. 모 기업의 경우는 운영 단계로 넘어간 소프트웨어에 대해서 다음과 같은 절차를 운영하고 있습니다. 우선 수정, 추가되는 기능이 있을 경우 해당 코드에 대해서 정적 소프트웨어 취약점 점검 도구로 점검을 수행하고, 사람이 직접 수정된 화면•모듈에 대해 취약점 점검을 한 뒤 운영 환경으로 이관하는 절차를 두었습니다. 그리고 주기적으로 해당 소프트웨어에 대해서 모의해킹도 수행을 합니다. 이렇게 수많은 과정을 거쳐서 소프트웨어를 개발하는데 그만큼의 비용이 발생하기 마련입니다. 정적, 동적 소프트웨어 취약점 점검 도구를 구매하는 것은 물론이고, 이 모든 과정에는 추가적인 노력이 들어가게 됩니다. 추가적인 노력은 우리가 흔히 말하는 MM(Man Month)를 증가시켜 비용 상승의 주범이 됩니다. 그렇다고 하더라도 시큐어 코딩은 과연 효과가 있는 것일까요? 차라리 서둘러서 개발을 완료하여 제품 출시를 하고 유지 보수를 하면서 수정하는 것이 더 효과•효율적이지 않을까라는 고민이 있을 수 있을 것입니다. 물론 이윤을 추구하는 기업이라면 당연히 그런 생각을 하는 것이 맞습니다. 하지만 아래 연구 결과를 살펴보면 소프트웨어의 결함을 수정하는데 소요되는 비용은 해당 결함을 개발 초기 단계에서 발견할수록 미미하고, 제품이 출시된 이후에 발견을 하게 될 경우 약 30배의 비용이 소요된다고 합니다. 이 연구 결과를 놓고 보면, 개발 초기 단계에서부터 안전한 소프트웨어를 위해 투자하는 비용은 전체적으로 봤을 때 오히려 비용을 절감하는 효과를 가져옵니다. 최근에 발생하는 각종 해킹 관련된 사고들을 돌이켜보면, 비단 비용만의 문제가 아님을 느낄 수 있습니다. 기업의 존폐가 결정될 수도 있는 이용자 대거 이탈과 더불어 법적인 처벌까지 받을 수 있는 최근의 환경에서는 보다 안전한 소프트웨어 개발은 선택이 아닌 필수가 되어가고 있습니다. 앞서 설명한 내용은 가장 일반적인 개발 절차를 따랐습니다. 세상에는 다양한 개발 방법론이 있으며 절차대로 개발이 되지 않는 소프트웨어도 많이 있습니다. 하지만 한가지 분명한 것은, 보안을 개발 과정에 녹여내지 못하고 별도로 떼어놓고 고민을 하고 있다면 그 고민은 영원히 풀리지 않는 숙제가 될 것입니다. 품질 결함이 있으면 당연히 제품 출시를 못하는 것처럼 보안도 품질의 한 부분이 되어야 합니다. 보안을 소프트웨어 품질의 한 요소로 명확히 인지하고 전반적인 품질관리 체계 안으로 녹여서 관리를 해야 합니다. 그렇게 해서, 보안 취약점(품질 결함)이 있을 경우 제품 출시를 못하게 되는 것을 당연한 것으로 인식하게 되어야 할 것입니다.