프로그램이 아니라 “과정”을 공격하는 시대

소프트웨어 보안에 대해 이야기할 때 사람들은 대개 프로그램 내부의 취약점을 떠올린다. 버퍼 오버플로우, 인증 우회, SQL 인젝션 같은 것들이 대표적이다. 오랫동안 보안 연구와 공격의 중심에는 이런 취약점들이 있었다. 공격자는 프로그램의 내부 구조를 분석하고, 예상하지 못한 입력을 만들어 시스템을 무너뜨리거나 권한을 탈취하려고 시도했다. 보안 역시 그런 취약점을 찾아내고 패치하는 방식으로 발전해 왔다.

그러나 지난 몇 년 동안 등장한 여러 사건들은 이 전통적인 관점이 더 이상 충분하지 않다는 사실을 보여주었다. 공격자는 반드시 프로그램 자체를 해킹할 필요가 없다는 것이다. 오히려 더 효율적인 방법이 존재한다. 프로그램이 만들어지고 배포되는 과정 전체를 공격하는 것이다.

이 접근 방식은 생각보다 단순하다. 프로그램이 배포되기 전에 그 과정 어딘가에 악성 코드를 삽입하면 된다. 업데이트 서버를 장악하거나, 빌드 시스템을 조작하거나, 개발 도구에 악성 코드를 넣는 방식이다. 이렇게 하면 공격자는 단 하나의 프로그램이 아니라 그 프로그램을 사용하는 모든 사람을 동시에 공격할 수 있다.

이것이 바로 최근 몇 년 동안 급격히 증가한 소프트웨어 공급망 공격의 본질이다.

공격의 목표가 바뀌고 있다

전통적인 해킹은 특정 시스템을 목표로 한다. 서버 하나, 기업 하나, 혹은 특정 조직의 네트워크가 공격의 대상이 된다. 이런 공격은 위험하지만 동시에 범위가 제한적이다. 공격자가 성공하더라도 피해는 비교적 특정한 영역 안에 머무르는 경우가 많다.

하지만 공급망 공격은 전혀 다른 방식으로 작동한다. 공격의 대상은 더 이상 최종 사용자가 아니다. 대신 그 사용자들에게 소프트웨어를 전달하는 과정이 목표가 된다.

이 차이는 생각보다 매우 크다. 만약 공격자가 어떤 프로그램의 업데이트 서버를 장악한다면 그 프로그램을 사용하는 수많은 컴퓨터에 동시에 악성 코드를 배포할 수 있다. 사용자는 평소와 똑같이 업데이트를 설치했다고 생각하지만, 실제로는 공격자가 심어 놓은 코드를 실행하게 되는 것이다.

이 구조에서는 공격의 효율이 극단적으로 높아진다. 공격자는 수많은 개별 시스템을 해킹할 필요가 없다. 대신 하나의 중심 지점을 장악하면 된다. 그 지점은 보통 개발 환경, 빌드 시스템, 배포 서버, 혹은 개발 도구 같은 곳이다.

그리고 바로 이 지점에서 공격의 대상이 조금 더 흥미로운 방향으로 이동하기 시작했다.

왜 개발 도구가 공격의 목표가 되는가

소프트웨어는 코드로 만들어지지만, 그 코드는 언제나 도구를 통해 작성된다. 텍스트 에디터, IDE, 컴파일러, 빌드 시스템, 패키지 매니저 같은 것들이 그 대표적인 예다. 개발자는 이런 도구들을 사용해 프로그램을 작성하고, 빌드하고, 배포한다.

이 말은 곧 하나의 중요한 사실을 의미한다. 개발 도구는 수많은 소프트웨어의 출발점이라는 것이다.

만약 공격자가 개발자가 사용하는 도구를 침해한다면 그 개발자가 만드는 모든 프로그램에 영향을 줄 수 있다. 단순히 하나의 프로그램을 공격하는 것이 아니라, 그 프로그램을 만드는 과정 자체를 공격하는 셈이다.

예를 들어 IDE나 컴파일러가 악성 코드를 삽입하도록 조작되었다고 상상해 보자. 개발자는 정상적인 코드를 작성하고 있다고 생각할 것이다. 하지만 실제로 빌드된 프로그램에는 공격자가 넣어 둔 코드가 함께 포함될 수 있다. 그리고 그 프로그램이 사용자에게 배포되면, 공격은 자연스럽게 확산된다.

이런 구조에서는 개발자가 공격의 피해자가 되는 동시에 공격의 전달자가 되는 상황이 발생한다. 공격자는 개발자를 직접 해킹하지 않아도 된다. 대신 개발자가 사용하는 도구를 장악하면 된다.

보이지 않는 전쟁

이런 공격이 특히 위험한 이유는 대부분의 사용자들이 그 존재조차 인식하지 못한다는 점이다. 프로그램 내부의 취약점은 종종 눈에 보이는 결과를 남긴다. 시스템이 비정상적으로 동작하거나, 데이터가 유출되거나, 서비스가 중단되는 식이다.

하지만 공급망 공격은 훨씬 더 조용하게 진행된다.

사용자는 정상적인 업데이트를 설치한다. 개발자는 정상적인 도구를 사용한다. 프로그램도 정상적으로 실행되는 것처럼 보인다. 그러나 그 내부에는 공격자가 삽입한 코드가 숨어 있을 수 있다. 그리고 그 코드는 때로는 수개월, 혹은 수년 동안 발견되지 않을 수도 있다.

이러한 공격은 기술적으로도 매우 복잡하다. 공격자는 단순히 취약점을 찾는 것이 아니라 소프트웨어 개발과 배포 과정 전체를 이해해야 한다. 빌드 시스템, 업데이트 메커니즘, 코드 서명 체계, 패키지 관리 구조 같은 것들이 모두 공격의 대상이 될 수 있다.

하지만 바로 그 복잡함 때문에 공격이 성공했을 때의 파급력은 상상 이상으로 커진다.

왜 이 이야기를 살펴볼 필요가 있는가

오늘날 우리가 사용하는 대부분의 소프트웨어는 거대한 공급망 위에 존재한다. 하나의 프로그램은 수십 개의 라이브러리를 사용하고, 그 라이브러리는 또 다른 프로젝트에 의존한다. 개발 도구와 패키지 저장소, 빌드 시스템, CI/CD 환경이 서로 연결되어 거대한 생태계를 형성하고 있다.

이 구조는 소프트웨어 개발을 놀라울 정도로 빠르게 만들었다. 그러나 동시에 새로운 공격 표면을 만들어 냈다. 공격자는 더 이상 프로그램의 내부를 파고들 필요가 없다. 대신 그 프로그램이 만들어지는 과정을 공격하면 된다.

최근 몇 년 동안 발생한 여러 사건들은 이 사실을 매우 명확하게 보여주었다. 업데이트 시스템이 공격당해 수많은 사용자에게 악성 코드가 배포된 사건도 있었고, 개발 도구 자체가 악성 코드의 전달 통로가 되었던 사건도 있었다. 심지어 국가 단위의 공격이 소프트웨어 공급망을 통해 진행된 사례도 등장했다.

이 시리즈는 바로 그런 사건들을 하나씩 살펴보려고 한다.

개발 도구를 둘러싼 새로운 위협

다음 글에서는 실제로 발생했던 대표적인 공급망 공격 사건들을 살펴볼 것이다. 어떤 사건에서는 프로그램 자체가 아니라 업데이트 시스템이 공격당했고, 어떤 사건에서는 개발 도구 자체가 악성 코드를 배포하는 통로가 되었다. 또 어떤 사건에서는 빌드 시스템이 침해되면서 전 세계 수많은 조직이 동시에 공격을 받았다.

이 사건들은 단순한 보안 사고가 아니다. 그것들은 소프트웨어 세계에서 공격의 방식이 어떻게 변화하고 있는지를 보여주는 신호이기도 하다.

과거의 해커들은 프로그램을 공격했다. 그러나 이제 공격자들은 프로그램을 만드는 과정을 공격한다.

그리고 그 과정의 가장 중심에는 언제나 개발 도구가 존재한다.