보안 취약점이 발견되면 누구나 자연스럽게 묻는다. “이게 왜 지금껏 발견되지 않았을까?” 혹은 “누구의 실수일까?” 하지만 이 질문들은 문제를 잘못 짚고 있다. 진짜 질문은 이것이다. 우리가 지금껏 쌓아온 시스템의 신뢰는 얼마나 허술한 기초 위에 세워졌는가?
소프트웨어 개발에서 기술 부채(technical debt)라는 개념은 익숙하다. 당장 기능 구현에 급급해 임시방편으로 짠 코드, 미뤄둔 리팩토링, 미완성의 아키텍처가 쌓여 미래의 개발자에게 부담을 지우는 현상이다. 그런데 보안 부채(security debt)는 이보다 더 교묘하다. 기술 부채가 “미래의 내가 해결할 문제”라면, 보안 부채는 “미래의 누군가가 감당할 재앙”에 가깝다. 그리고 그 누군가는 종종 개발자가 아니다. 사용자일 수도, 전혀 관계없는 제3자일 수도 있다.
문제는 이 보안 부채가 의도적인 선택의 결과만은 아니라는 점이다. 원문에서 지적하듯, 우리가 “만든 적 없는” 보안 부채가 존재한다. 예를 들어, 20년 전에는 안전하다고 믿었던 암호화 알고리즘이 시간이 지나면서 취약해지는 경우다. MD5나 SHA-1이 대표적이다. 당시에는 최신 기술이었고, 누구도 이 알고리즘들이 수십 년 후 해시 충돌 공격에 취약해질 거라고 예상하지 못했다. 하지만 기술은 진화하고, 공격자의 능력도 발전한다. 우리가 쌓아올린 시스템은 마치 모래 위에 지은 성처럼, 시간이 흐를수록 그 기반이 약해진다.
더욱 우려스러운 것은 이 부채가 시스템의 복잡성 속에서 은밀하게 자란다는 사실이다. 현대 소프트웨어는 수많은 의존성으로 얽혀 있다. 한 프로젝트가 수십, 수백 개의 오픈소스 라이브러리에 의존하고, 그 라이브러리들은 또 다른 라이브러리에 의존한다. 이 거대한 의존성 트리 어딘가에 숨어 있는 취약점 하나가 전체 시스템을 위험에 빠뜨릴 수 있다. 2021년 로그4j 취약점(Log4Shell)이 전 세계를 발칵 뒤집어놓은 사건을 기억하는가? 당시 많은 개발자가 “우리가 왜 이 라이브러리를 쓰고 있었지?”라는 질문을 던졌다. 하지만 그 질문은 이미 늦었다. 시스템은 이미 취약했고, 공격자들은 그 틈을 파고들었다.
여기서 핵심은 책임 소재가 아니다. 누구의 잘못도 아니라는 말이다. 문제는 우리가 시스템을 설계하고 운영하는 방식 그 자체에 있다. 보안은 종종 기능 구현 이후에 “추가되는” 요소로 여겨진다. “일단 돌아가게 만들고, 나중에 보안을 강화하자”는 접근은 보안 부채를 쌓는 가장 빠른 길이다. 하지만 보안은 시스템의 DNA에 새겨져야 한다. 설계 단계부터, 코드 한 줄 한 줄부터, 심지어 팀 문화와 프로세스까지 보안은 스며들어야 한다.
보안은 시스템의 속성이 아니라, 시스템을 만드는 모든 과정의 속성이다.
그렇다면 우리는 어떻게 이 문제를 해결할 수 있을까? 첫째, 보안에 대한 인식을 바꿔야 한다. 보안은 개발자의 책임이 아니라, 모든 이해관계자의 책임이다. 경영진은 보안 투자를 “비용”이 아니라 “필수”로 여겨야 하고, 개발자는 보안을 “제약”이 아니라 “기능”으로 인식해야 한다. 둘째, 시스템의 복잡성을 통제해야 한다. 의존성을 최소화하고, 사용하지 않는 라이브러리는 과감히 제거해야 한다. 마지막으로, 지속적인 모니터링과 업데이트가 필요하다. 보안은 한 번의 노력으로 끝나는 일이 아니다. 끊임없이 진화하는 위협에 맞서 시스템도 끊임없이 진화해야 한다.
우리가 몰랐던 보안 부채는 어쩌면 우리가 시스템을 너무 쉽게 믿었기 때문에 생긴 것일지도 모른다. 기술은 완벽하지 않고, 인간은 실수를 한다. 하지만 그 사실을 인정하는 순간, 우리는 더 나은 시스템을 만들 수 있다. 보안 부채는 피할 수 없는 운명이 아니다. 우리가 어떻게 대응하느냐에 따라 그 무게는 달라질 수 있다.
이 글은 Security Debt We Never Created를 바탕으로 작성되었습니다.
이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.