하나의 오픈소스 패키지에 악성 코드 한 줄이 심어지면, 그걸 의존하는 수만 개 프로젝트가 동시에 뚫린다. 이게 공급망 공격의 본질이다. 2020년 SolarWinds 사태가 그랬고, 2021년 Log4Shell이 그랬다. 오픈소스 생태계는 개발 속도를 끌어올리는 엔진이지만, 그 개방성 자체가 공격 벡터다. 공짜 코드엔 공짜 책임도 따라온다는 얘기다.
왜 오픈소스가 표적이 되는가
이유는 단순하다. 효율적이기 때문이다. 공격자 입장에서 보면 널리 쓰이는 npm 패키지 하나를 탈취하면, 그걸 의존하는 프로젝트 전체에 코드를 밀어 넣을 수 있다. 직접 기업 서버를 두드리는 것보다 비용 대비 효과가 훨씬 크다. 누구나 기여하고 누구나 받아 쓸 수 있는 구조가 문제의 핵심이다. 신뢰를 기반으로 돌아가는 생태계라는 점도 걸린다. 검증 없이 믿고 쓰는 습관이 쌓이면, 그 사이 어딘가에 악성 코드가 슬어들 틈이 생긴다.
공급망 공격, 어떻게 작동하나
최종 사용자를 직접 치는 게 아니다. 개발-빌드-배포 파이프라인의 중간 어딘가를 건드린다. 패턴은 크게 셋이다. 첫째, 오픈소스 패키지에 악성 코드를 직접 삽입하는 방식. 둘째, 유지관리자 계정을 탈취해 오염된 버전을 공식 배포 채널에 올리는 방식. 셋째, 원본 패키지와 이름이 비슷한 가짜 패키지를 만들어 혼동을 유도하는 타이포스쿼팅. 개발자가 정상 업데이트인 줄 알고 패키지를 설치하면 악성 코드가 이미 빌드 환경에 들어온다. 탐지가 어렵고 피해 범위가 넓다는 게 이 공격의 진짜 위험성이다.
개발자가 바로 실천할 보안 5단계
- 1. 다단계 인증(MFA) 전면 적용: GitHub, npm, PyPI 등 코드 저장소와 패키지 관리 시스템 모두 MFA를 켜야 한다. 비밀번호만으로 지키는 계정은 사실상 열린 문이다. 권한도 최소화하는 게 맞다. 읽기만 하면 되는 계정에 쓰기 권한을 주는 건 관리 편의 때문인데, 그 편의가 침투 경로가 된다.
- 2. 코드 서명 및 검증: 배포하는 패키지엔 디지털 서명을 붙여라. 사용하는 외부 라이브러리도 서명을 확인하는 게 원칙이다. Sigstore 같은 도구가 이미 있다. 서명이 없거나 검증이 안 되면 쓰지 않는 게 맞다. 불편하더라도.
- 3. 개발 환경 격리: 빌드 서버와 일반 업무 PC는 분리하는 게 기본이다. 개발 머신에 브라우저 확장 프로그램이 잔뜩 깔려 있다면 이미 위험 구역이다. OS 및 보안 패치는 나오는 즉시 적용하고, 정기적인 취약점 점검을 분기 1회 이상 돌려야 한다.
- 4. 의존성 관리 자동화: 프로젝트에 딸린 패키지가 몇 개인지 정확히 아는가. Dependabot, Snyk, OWASP Dependency-Check 같은 도구를 CI/CD 파이프라인에 붙여두면 취약점 발견 시 자동으로 알려준다. 안 쓰면 알 방법이 없다. 아직 붙이지 않았다면 지금 바로 적용해야 한다.
- 5. 시큐어 코딩과 코드 리뷰: 코드를 짤 때부터 보안을 고려하는 게 맞다. 완성 후 보안 검토를 붙이는 방식은 비용도 크고 놓치는 것도 많다. PR 리뷰 단계에서 보안 체크리스트를 의무화하는 팀이 그렇지 않은 팀보다 취약점 발견 속도가 훨씬 빠르다.
오픈소스 고를 때 확인해야 할 것들
GitHub 스타 수만 보고 가져다 쓰는 건 위험하다. 스타가 많아도 마지막 커밋이 2년 전이면 사실상 방치된 프로젝트다. 확인해야 할 건 세 가지다. 첫째, 최근 커밋 이력과 이슈 대응 속도. 오래된 취약점 신고가 방치돼 있다면 패스다. 둘째, 메인테이너가 1명인지 팀인지. 1인 유지관리 프로젝트는 계정 탈취 한 번으로 전체가 무너진다. 셋째, Snyk이나 OSS Review Toolkit 같은 분석 도구로 코드를 직접 검사한 뒤 쓰는 게 맞다. 모든 오픈소스가 검증된 건 아니다. 사전 검증은 선택이 아니라 의무다.
사고 터졌을 때 대응 순서
아무리 준비해도 뚫릴 때는 뚫린다. 그때 중요한 건 속도다. 감염 확인 즉시 해당 시스템을 네트워크에서 끊는다. 내부 확산을 막는 게 첫 번째다. 그다음, 어떤 패키지가 오염됐는지, 어디까지 퍼졌는지 범위를 파악한다. SBOM(소프트웨어 자재 명세서)이 있으면 추적이 훨씬 빠르다. 없다면 이번 사고를 계기로 만들어야 한다. 원인 파악이 끝나면 깨끗한 버전으로 복구하고, 관련 자격증명 전체를 교체한다. 비밀번호, API 키, 인증서 모두. 마지막은 재발 방지 문서화다. 사고 타임라인과 원인, 대응 조치를 기록해두지 않으면 같은 실수가 반복된다.
결국 커뮤니티 차원의 문제다
개인이나 단일 기업이 오픈소스 생태계 전체를 지킬 수는 없다. 구조적으로 불가능하다. CVE 정보를 빠르게 공유하고, 취약점 패치를 신속히 배포하고, 의심스러운 패키지 변경 사항을 커뮤니티가 서로 감시하는 문화가 쌓여야 한다. OpenSSF(Open Source Security Foundation) 같은 이니셔티브가 이 방향으로 움직이고 있다. 개발자 개개인이 할 수 있는 건 결국 자기 코드에 대한 책임이다. 가져다 쓴 패키지도 내 책임이라는 인식, 그게 출발점이다. 기술이 빠르게 진화하는 만큼 공격 기법도 함께 진화한다. 방심하는 순간이 가장 위험하다.
출처: TechCrunch
