목차12개 항목
출처와 참고
ByteByteGo의 System Design 101 가이드 「What is DevSecOps?」, 「Top 4 Forms of Authentication Mechanisms」를 바탕으로 재구성한 노트다. 클라우드의 보안 위협과 대응, 보안 솔루션 배치는 고려사이버대학교 「클라우드 컴퓨팅」(2023-2학기) 강의 내용으로 보강했다. 취약점 대응의 운영 부담은 GeekNews Weekly의 「취약점은 쏟아지는데, 방어하는 사람은 지쳐갑니다」(2026.10)로 보강했다. 공급망 공격 사례와 감염 대응은 「NIKKE PC launcher compromise」(2026.11) 분석 문서로 보강했다.
DevSecOps란
DevSecOps는 개발(Dev)·보안(Sec)·운영(Ops)을 한 흐름으로 묶어, 보안을 소프트웨어 수명 주기 전 단계에 넣는 방식이다. DevOps가 개발과 운영 사이의 벽을 허문 것처럼, 보안팀이 출시 직전에 한 번 검사하던 관문을 없애고 검사를 파이프라인 곳곳에 자동으로 심는다.
문제는 늦게 발견할수록 고치는 비용이 커진다는 것이다. 그래서 검사를 왼쪽(앞 단계)으로 당기는 시프트 레프트(shift left) 가 핵심 원칙이다.
단계별로 넣는 것
flowchart LR a["설계"] --> b["코드"] --> c["빌드"] --> d["테스트"] --> e["배포"] --> f["운영"] a -.- a1["위협 모델링"] b -.- b1["시크릿 스캔<br/>리뷰"] c -.- c1["SCA<br/>SAST<br/>이미지 스캔"] d -.- d1["DAST<br/>QA 연동"] e -.- e1["IaC 검사<br/>서명 검증"] f -.- f1["모니터링<br/>취약점 관리<br/>사고 대응"]
| 개념 | 하는 일 | 예 |
|---|---|---|
| 위협 모델링 | 설계 단계에서 "누가 무엇을 어떻게 노릴까"를 따져 방어를 정한다 | STRIDE로 데이터 흐름도 점검 |
| 자동 보안 검사 | 정적 분석(SAST)으로 코드의 취약 패턴을, 동적 분석(DAST)으로 실행 중인 앱을 검사한다 | PR마다 SAST, 스테이징에서 DAST |
| 의존성 분석(SCA) | 오픈소스 의존성의 알려진 취약점과 라이선스를 찾는다 | Dependabot, npm audit, SBOM 생성 |
| CI/CD 자동화 | 위 검사를 파이프라인 단계로 넣고, 기준을 넘으면 빌드를 막는다 → CI/CD | 심각도 높음 이상이면 머지 차단 |
| 코드형 인프라(IaC) | 인프라 정의도 코드로 리뷰·검사한다 | 공개 버킷, 0.0.0.0/0 보안 그룹 탐지 |
| 컨테이너 보안 | 최소 베이스 이미지, 루트 아닌 사용자, 이미지 취약점 스캔과 서명 | Dockerfile 작성과 컨테이너의 PID 1 |
| 비밀 관리 | 비밀을 코드 밖에서 주입하고 짧게 발급한다 (아래) | Vault, 클라우드 시크릿 매니저 |
| 지속 모니터링 | 운영 중 이상 징후와 새로 공개된 취약점을 감시한다 | 로그·감사 추적, 런타임 탐지 |
| 취약점 관리 | 발견 → 우선순위 → 수정 → 확인의 흐름을 기한과 함께 돌린다 | 심각도별 수정 기한 |
| QA 연동 | 보안 테스트 케이스를 일반 테스트와 함께 돌린다 | 인가 우회 회귀 테스트 |
| 협업 | 보안을 별도 팀의 일이 아니라 모든 팀의 책임으로 둔다 | 팀마다 보안 챔피언 |
기계가 쓰는 자격 증명
사람의 로그인 말고도 시스템끼리는 여러 형태의 비밀로 서로를 확인한다.
| 형태 | 쓰임 | 주의 |
|---|---|---|
| SSH 키 | 서버·Git 원격 접속 → SSH의 동작 | 사람·용도별로 따로, 퇴사 시 회수 |
| OAuth 토큰·API 키 | 서드파티 API, 서비스 간 호출 → OAuth 2.0 | 최소 scope, 짧은 수명 |
| TLS 인증서 | 서버 신원 증명, 서비스 간 상호 TLS(mTLS) → HTTPS와 TLS | 만료 전 자동 갱신 |
| 자격 증명(아이디·비밀번호, DB 접속 정보) | DB·내부 시스템 접속 | 공유 계정 금지, 정기 교체 |
비밀 관리 원칙
- 비밀은 Git 저장소에 넣지 않는다. 비공개 저장소도 마찬가지다. 한 번 커밋되면 히스토리에 남고, 저장소가 복제·공개되는 순간 퍼진다.
- 커밋 전 훅과 CI에서 비밀 스캔을 돌리고, 유출되면 히스토리 삭제보다 키 폐기·교체가 먼저다.
- 비밀은 비밀 관리 도구에 두고 실행 시점에 환경 변수나 파일로 주입한다 → NestJS 설정과 환경 변수
- 가능하면 오래 사는 키 대신 짧게 발급되는 자격 증명을 쓴다. 예: CI가 클라우드에 접근할 때 저장된 액세스 키 대신 OIDC 연동으로 실행마다 임시 자격 증명을 받는다.
- 누가 언제 어떤 비밀을 읽었는지 감사 로그를 남긴다.
- 사람끼리 비밀을 건넬 때도 도구를 쓴다. API 키를 메신저 DM이나 메일로 보내면 대화 기록에 평문으로 남는다. 1Password 같은 팀용 비밀번호 관리자의 공유 금고를 쓰고, 직접 운영해야 하면 Bitwarden 호환 서버를 셀프 호스팅한다.
침해를 전제로 설계한다
AI를 이용한 자동화 공격이 늘면서 규모와 상관없이 대부분의 조직이 공격 대상이 된다. 완벽한 방어를 목표로 하기보다 「털려도 피해가 어디까지인가」를 설계 질문으로 둔다.
| 원칙 | 내용 |
|---|---|
| 최소 수집 | 쓰지 않을 개인정보는 처음부터 받지 않는다. 없는 데이터는 유출되지 않는다 |
| 분리 보관 | 식별 정보와 민감 정보를 다른 저장소·키로 나눠 한 번의 침해로 다 드러나지 않게 한다 |
| 최소 권한 | 사람·서비스·AI 에이전트 모두 일에 필요한 권한만 준다. 이메일·결제·기기 제어 권한을 가진 에이전트는 탈취됐을 때 피해도 그만큼 크다 |
| 결합 위험 | 여러 곳에서 따로 유출된 정보가 나중에 합쳐지면 더 큰 피해가 된다. 「이것만으로는 누군지 모른다」는 판단을 과신하지 않는다 |
클라우드의 보안 위협
클라우드 보안은 공동 책임이다. 사업자가 물리 시설·하드웨어·가상화 계층을 맡고, 그 위는 서비스 모델에 따라 사용자 몫이다(서비스 모델). 여러 고객이 큰 인프라와 중앙의 데이터를 나눠 쓰는 멀티테넌트 환경이라, 위협은 사람·절차 쪽(관리적)과 시스템 쪽(기술적)으로 나눠 본다.
| 관리적 위협 | 내용 | 대응 |
|---|---|---|
| 클라우드 남용 | 누구나 큰 계산 자원을 쉽게 빌리므로 공격자도 비밀번호 크래킹·채굴·공격 기지로 쓴다. 같은 호스트 VM끼리의 트래픽은 기존 네트워크 장비가 못 보는 경우가 많다 | 가입 시 신원 검증, 이용 행태 모니터링 |
| 악의적인 내부자 | 퇴사자 계정이 남아 있거나 부서를 옮긴 뒤 옛 권한이 살아 있는 것이 전형. 협력사 사용자도 있다 | 계정·권한의 지속적인 검토와 감사, 권한 분산 |
| 불투명성 | 클라우드의 잠재 위협이 다 알려지지 않았고 사업자 내부가 보이지 않는다 | 로그·인프라 정보 공개 요구, 모니터링 보완 |
| 이해 부족 | 서버 기반에서 가상화 기반으로 옮기며 생긴 구조 차이를 모른 채 같은 방식으로 운영 | 교육, 표준 아키텍처 |
| 부실한 식별·권한 관리 | 쓰는 SaaS가 많아져 담당자도 일부만 안다(섀도 IT). 외부로 공유된 문서 속 기밀이 사각지대에 남는다(섀도 데이터) | 통합 인증(SSO), 최소 권한, SaaS 목록 관리 |
| APT(지능형 지속 위협) | 오래 잠복하며 여러 기법을 섞는 표적 공격. 원격 접속과 데이터 집중으로 침투 경로가 많다 | 기술적 탐지와 관리적 대응을 함께 |
| 기술적 위협 | 내용 | 대응 |
|---|---|---|
| 안전하지 않은 API | 모든 것을 API로 조작하므로, 인증 우회나 권한 밖 데이터 접근을 허용하는 API 취약점은 곧 유출과 장악이다 | 안전한 API 설계, 앞단 웹 방화벽(API 보안) |
| 가상화 취약점 | 하이퍼바이저·가상 네트워크의 결함이 그 위 모든 VM으로 번진다. 가상 스위치에서 이웃 VM 패킷 엿보기(ARP 스푸핑), 게스트에서 호스트로 탈출해 다른 VM 장악 | 하이퍼바이저 패치, 테넌트 격리, 가상 네트워크 모니터링 |
| 계정·트래픽 탈취 | 털린 계정으로 기밀을 보고, 관리자 계정이면 다른 계정과 계약까지 바꾼다. XSS 같은 웹 취약점이 통로가 된다 | 입출력 검증, 보안 라이브러리, 2단계 인증 |
| 데이터 유출 | 접근 경로가 넓고, 다들 비슷하게 쓰므로 한 회사에 통한 공격이 다른 회사에도 통한다. 주로 읽기에서 생긴다 | 암호화, 접근 통제 |
| 데이터 손실 | 동시 편집 같은 편리함의 반대편. 악의든 실수든 지우거나 덮어쓰면 사라진다. 주로 쓰기에서 생긴다 | 수정·삭제 권한 관리, 버전 관리와 백업 |
| 서비스 거부(DoS) | 자원을 소진시켜 가용성을 무너뜨린다. 자동 확장이 켜져 있으면 비용 폭탄이 된다 | DDoS 방어 서비스, 확장 상한과 비용 알림 |
취약점: CVE와 CCE
알려지지 않은 취약점 공격은 시점에 따라 부른다. 제로데이는 아직 공개·패치되지 않은 취약점이라 드물지만 막기 어렵고, 원데이는 공개 직후 패치가 퍼지기 전을 노리고, 올드데이는 패치가 나온 지 한참 됐는데 적용하지 않은 시스템을 노린다. 가장 흔한 것은 비용이 싼 올드데이라서, 패치를 제때 하는 것만으로 상당수를 막는다.
시스템 취약점은 두 갈래로 점검한다.
| CVE 점검 | CCE 점검 | |
|---|---|---|
| 대상 | 소프트웨어 자체의 알려진 결함(OpenStack, Xen·KVM·QEMU 같은 플랫폼 포함) | 설정 미흡(약한 비밀번호 정책, 과한 파일 권한, 필요 없는 서비스) |
| 누가 만들고 고치나 | 벤더가 만들고 벤더가 패치 | 사용자가 만들고 사용자가 고친다 |
| 관점 | 알려진 취약 버전이 돌고 있나 | 내부 정책과 규제를 지키나 |
병목은 패치가 아니라 운영이다
AI가 취약점을 찾고 악용하는 비용을 낮추면서, 공격자와 방어자가 같은 속도로 결함을 찾아 공개 건수가 한꺼번에 몰린다. 메인테이너 쪽에서는 하위 호환을 깨지 않는 수정안을 찾기 어렵고, 재현되지 않거나 중복된 제보를 걸러 내는 일도 쌓인다. 운영 쪽의 부담은 패치를 쓰는 일보다 영향받는 구성 요소가 어디에 숨어 있는지 찾고(라이브러리 안, 프로그램별 인증서 저장소까지), 우리 환경이 실제로 노출되는지 판단하고, 업데이트를 테스트하는 일에 있다. 이 일은 시스템을 가장 잘 아는 소수에게 몰려 번아웃으로 이어진다.
| 대응 | 내용 |
|---|---|
| 인벤토리 | 서버·컨테이너·구성 요소 버전 목록(SBOM 포함)을 늘 최신으로 둔다. 「어디에 쓰고 있나」에 바로 답할 수 있어야 한다 |
| 분류(triage) | 모든 권고를 같은 긴급도로 다루지 않는다. 외부 노출 여부, 실제 악용 확인 여부, 공격 조건이 우리 환경에 맞는지로 순서를 매긴다 |
| 리허설 | 패치 테스트와 배포 절차를 평소에 연습해 둔다 |
| 패치 전 완화 | 필요 없는 관리 인터페이스를 닫고, 최소 권한을 적용하고, 망을 나눠 한 곳이 뚫려도 퍼지지 않게 한다 |
| 점검 창구 | 재부팅이 필요한 패치를 넣을 정기 점검(PM, Preventive Maintenance) 시간을 서비스 담당 조직과 미리 합의해 둔다 |
커널 패치의 병목은 배포가 아니라 다운타임이다. 전체 서버에 패키지 업데이트와 재부팅 명령을 내리는 일은 Ansible 같은 구성 관리 도구로 금방 끝난다. 어려운 것은 커널 교체에 따르는 재부팅과 그동안의 서비스 중단을 서비스 담당 조직과 조율하는 일이다. 중단을 이유로 패치를 미루면 그 기간만큼 알려진 취약점을 안고 운영하게 되므로(위의 올드데이), 취약점이 나올 때마다 일정을 협상하지 말고 정기 점검 창구를 미리 확보해 둔다. RHEL 같은 유료 배포판은 패치 지원을 계약으로 보장받는다는 장점이 있지만, 새 취약점이 계속 나오고 그때마다 재부팅 일정을 잡아야 하는 사정은 같다.
노출 여부는 공격을 재현하지 않고 판단한다. 웹 서버 취약점(예: HTTP/2 처리 모듈의 레이스 컨디션으로 인한 원격 코드 실행)이 공개됐을 때, 공격 코드를 돌려 보지 않아도 아래 항목으로 영향 여부를 가릴 수 있다.
| 확인 항목 | 보는 것 |
|---|---|
| 기능 활성화 | 취약한 기능(예: HTTP/2)이 설정에서 켜져 있는가. 꺼져 있으면 공격 조건이 성립하지 않는다 |
| 버전 | 서버 버전이 권고문의 영향 범위에 드는가 |
| 패치 상태 | 수정 버전이나 배포판의 보안 업데이트가 적용됐는가 |
| 응답 헤더 | 외부에서 보이는 서버 종류·버전·프로토콜이 무엇인가 |
| 로그 | 워커 프로세스의 비정상 종료, 오류 급증 같은 이상 징후가 있는가 |
실제 공격 코드로 검증해야 한다면 본인 소유이거나 명시적으로 허가받은, 운영과 분리된 테스트 환경에서만 한다.
규모가 크고 정책이 복잡한 클라우드는 CCE 쪽에 특히 약하다. 공개된 버킷, 0.0.0.0/0으로 열린 보안 그룹, 꺼진 로깅 같은 설정 오류를 계속 검사하는 도구(CSPM, Cloud Security Posture Management)를 쓰는 이유이고, 같은 검사를 배포 전 IaC 단계로 당긴 것이 위 표의 「코드형 인프라」 검사다.
보안 솔루션 배치
클라우드에서 보안 솔루션은 서비스와 함께 늘어날 수 있는지를 먼저 본다. 보안 장비가 확장을 막으면 결국 교체하거나 구조를 다시 짜야 한다.
| 방식 | 구조 | 주의 |
|---|---|---|
| 네트워크 기반 | 구간마다 가상 보안 어플라이언스를 두고 트래픽을 통과시킨다 | 대량 트래픽에 여러 대가 필요하고 영역마다 따로 둔다. 자동 확장·HA가 안 되는 제품이 많다 |
| 호스트 기반 | 서버마다 에이전트를 설치한다 | 서버와 함께 늘어나 확장성이 중요하면 이쪽이 맞다. OS 호환성은 확인한다 |
flowchart TB
user["사용자"] -->|"HTTPS"| waf["WAF / DDoS 방어"] --> lb["로드 밸런서"]
subgraph pub["퍼블릭 서브넷"]
web["웹 서버들<br>(보안 그룹, 호스트 IPS)"]
end
subgraph priv1["프라이빗 서브넷"]
app["앱 서버들<br>(보안 그룹)"]
end
subgraph priv2["프라이빗 서브넷"]
db["DB<br>(보안 그룹: 앱 서버에서만)"]
end
lb --> web --> app --> db
office["사무실"] -->|"VPN·전용선"| adm["관리 접근<br>(접근 제어, 디렉터리 인증)"]
layers["모든 계층"] -->|"로그"| mon["모니터링·탐지"]온프레미스가 경계 방화벽 장비로 막았다면, 클라우드는 보안 그룹처럼 API로 설정하는 자원 단위 접근 제어가 기본이라 더 세밀하고 코드로 관리된다. 망 구성은 AWS VPC 네트워크 구성에 있다.
공급망 공격: 배포 파일이 변조될 때
소프트웨어 공급망 공격(supply chain attack) 은 목표 시스템을 직접 뚫지 않고, 그 시스템이 믿고 받아 쓰는 코드·파일을 변조한다. 사용자가 공식 앱을 정상적으로 실행하기만 해도 감염된다. 의존성 패키지(npm 설치 스크립트 → npm install이 하는 일), 남의 도메인에서 불러오는 스크립트(polyfill.io 사례 → ECMAScript 표준과 TC39 프로세스), 배포 CDN의 파일이 모두 통로가 된다.
2026년 11월 공개된 한 PC 게임 런처 사고가 전형적인 모양이다. 퍼블리셔 CDN에 올라간 공식 JavaScript 파일 네 개에 짧은 로더가 끼워졌고, 런처의 내장 브라우저가 이 파일을 불러 외부 서버에서 원격 제어 에이전트를 받아 실행했다. 에이전트는 임의 명령 실행, 저장된 로그인·브라우저 비밀번호·쿠키 수집, SSH 키·개발자 토큰 읽기, 암호화폐 지갑 확장 데이터 수집까지 했다. 런처가 관리자 권한을 요구하는 탓에 에이전트도 높은 권한으로 돌았다. Linux의 Proton(Wine) 환경도 안전하지 않았다. Wine이 Linux 홈 폴더를 그대로 보여 주기 때문이다.
막는 쪽: 배포하는 입장
| 원칙 | 하는 일 |
|---|---|
| 무결성 검증 | 클라이언트가 불러오는 스크립트·파일을 해시나 서명으로 확인한다. 웹은 SRI(integrity 속성 → HTML 기초와 HTML5), 바이너리·이미지는 코드 서명 |
| 배포 경로 최소 권한 | CDN·스토리지에 쓸 수 있는 자격 증명을 줄이고, 쓰기 이벤트를 감사 로그로 남겨 알림을 건다 |
| 앱 최소 권한 | 관리자 권한이 꼭 필요하지 않으면 요구하지 않는다. 권한이 높을수록 변조된 코드도 높은 권한으로 돈다 |
| 캐시 무효화 | 원본을 고쳐도 CDN 엣지와 클라이언트 캐시에 변조본이 남는다. 사고 대응 절차에 캐시 퍼지를 넣는다 |
| 나가는 트래픽 감시 | 앱이 평소와 다른 도메인으로 큰 데이터를 올리면 탐지한다 |
당한 쪽: 감염이 의심되는 PC
- 증거부터 남긴다. 앱을 다시 실행하거나 재설치하기 전에 로그·캐시 폴더를 확인하거나 복사한다. 재설치하면 흔적이 지워져 감염 여부를 알 수 없다. 흔적이 없다는 것이 안전하다는 뜻은 아니다.
- 격리한다. 의심되는 앱을 닫고 그 PC의 네트워크를 끊는다. 공개된 악성 도메인·IP는 hosts 파일·공유기·방화벽에서 막는다.
- 깨끗한 다른 기기에서 계정을 정리한다. 감염된 PC에서 바꾼 비밀번호는 다시 새어 나갈 수 있다. 주요 계정(이메일, 금융, 브라우저에 저장된 사이트) 비밀번호를 바꾸고, 2단계 인증을 켜고, 로그인된 세션을 모두 끊는다. 세션 쿠키가 털렸다면 비밀번호만 바꿔서는 막히지 않는다.
- 기계용 비밀을 교체한다. API 토큰, SSH 키, 개발 도구 자격 증명을 폐기하고 새로 발급한다(위 「기계가 쓰는 자격 증명」). 지갑은 새 시드로 옮긴다.
- 시스템을 복구한다. 지속성(자동 실행 등록, 레지스트리 키, 심어진 DLL)을 지우거나, 가장 확실하게는 OS를 다시 설치한다. 백신이 놓치는 경우도 있다.
정리
- DevSecOps는 보안 검사를 마지막 관문에서 파이프라인 전체로 옮기고 자동화한다.
- 설계는 위협 모델링, 코드는 SAST·시크릿 스캔, 빌드는 SCA·이미지 스캔, 배포는 IaC 검사, 운영은 모니터링과 취약점 관리가 맡는다.
- 기계용 자격 증명(SSH 키, 토큰, 인증서, 접속 정보)은 저장소 밖에서 주입하고, 짧게 발급하고, 유출되면 즉시 교체한다.
- 공급망 공격은 믿고 받는 파일을 변조한다. 배포하는 쪽은 무결성 검증과 배포 경로 최소 권한으로 막고, 당한 쪽은 증거 보존 → 격리 → 깨끗한 기기에서 비밀번호·세션·토큰 교체 순서로 대응한다.
- 클라우드 사고 대부분은 설정 오류와 권한 관리 실수에서 나온다. 관리적 위협과 기술적 위협을 나눠 대응하고, 패치(CVE)와 설정 점검(CCE)을 계속 돌리고, 보안 솔루션은 확장성을 먼저 본다.
관련 노트: CI/CD, 보안 시스템 설계: 원칙과 민감 데이터 관리, API 보안 체크리스트, Dockerfile 작성과 컨테이너의 PID 1, SSH의 동작: 전송·인증·연결 계층, 클라우드 기초와 AWS, 쿠버네티스 보안, AWS VPC 네트워크 구성