
컨테이너 탈출 탐지의 현실
컨테이너 탈출은 “하나의 이벤트”가 아니라 “행위 조합”
컨테이너 탈출 시도는 보통 다음 요소들이 연속적으로 나타납니다.
- 격리 경계 접근:
/proc,/sys,/dev, namespace 조작 - 권한 상승 시도:
CAP_SYS_ADMIN,setcap, SUID,unshare,nsenter - 호스트 제어면 접근: Docker 소켓(
/var/run/docker.sock), kubelet API, container runtime socket - 호스트 지속성: cron/systemd 변조, ssh key 추가, 바이너리 드롭
👉 따라서 실무에서는 “A 단독이면 경고”, “A+B면 중간”, “A+B+C면 고위험” 같은 스코어링/상관분석이 맞습니다.
osquery의 강점/한계
- 강점: 프로세스/권한/마운트/소켓/유저/파일 상태를 일관되게 수집, 규칙화 쉬움
- 한계: 커널 익스플로잇 자체(시스템콜 레벨)는 정밀하게 못 봄(이벤트 백엔드에 따라 다름)
- 결론: osquery는 “관측(telemetry) + 룰 + 상관”의 기반이며, 필요시 auditd/eBPF/Falco와 조합이 베스트
런타임 구조 이해: Docker / containerd / CRI-O / Kubernetes가 뭐가 다르나
공통점 (중요)
모두 결국 리눅스에서 아래를 씁니다.
- cgroup(자원/격리/계층)
- namespace(pid/net/mnt/user 등 격리)
- runc/crun(OCI 런타임)
👉 그래서 osquery는 “Docker냐 CRI-O냐”보다 cgroup_path / namespace / mount / socket을 보면 됩니다.
차이점 (탐지에서 실제로 영향을 주는 부분)
- Docker: 도커 데몬과 도커 소켓이 핵심(탈출·장악 루트가 명확)
- containerd/CRI-O: Kubernetes에서 흔하며, kubelet + CRI 소켓 + kubepods cgroup이 핵심
- Kubernetes: “컨테이너 자체의 이상행위” + “클러스터 설정(권한/hostPath/privileged)”이 결합됨
→ osquery는 노드(호스트)에서 관측하는 데 강함.
K8s 설정 점검은 별도의 정책 검사(OPA, kube-bench, API audit)가 필요.
컨테이너 “식별”이 1번 과제: 런타임별로 어떻게 컨테이너 프로세스를 구분하나
osquery에서 가장 실용적인 방법은 processes.cgroup_path 기반입니다.
통합 컨테이너 판별 규칙(추천)
- Docker 계열:
cgroup_path에docker문자열 또는 container-id 흔적 - Kubernetes:
kubepods포함 - containerd: 환경에 따라
containerd/cri-containerd흔적 - CRI-O:
crio흔적 - Podman(참고):
libpod흔적
예시: “컨테이너 프로세스만 뽑기(통합)”
SELECT pid, name, cmdline, uid, cgroup_path
FROM processes
WHERE
cgroup_path LIKE '%kubepods%'
OR cgroup_path LIKE '%docker%'
OR cgroup_path LIKE '%containerd%'
OR cgroup_path LIKE '%cri-containerd%'
OR cgroup_path LIKE '%crio%'
OR cgroup_path LIKE '%libpod%';
운영 팁
배포판/시스템드 구성에 따라 cgroup_path 문자열 형태가 다릅니다.
- 먼저 위 쿼리를 돌려서 내 환경에서 실제로 어떤 패턴이 보이는지를 “환경별 베이스라인”으로 잡아야 합니다.
탐지 전략의 뼈대: “행위 카테고리 6종”으로 나누면 체계가 잡힙니다
컨테이너 탈출/격리우회 탐지를 아래 6개 축으로 설계하면 운영이 쉬워집니다.
- 컨테이너 프로세스의 위험 도구 실행
- 컨테이너 프로세스의 namespace 조작/진입
- 컨테이너 프로세스의 민감 마운트/호스트 경로 접근
- 런타임/제어면 소켓 접근 (docker.sock, CRI 소켓, kubelet 등)
- 권한 상승 흔적 (capabilities, SUID, setcap)
- 호스트 지속성/변조 (cron/systemd/ssh keys/새 바이너리)
각 축마다 “단일 이벤트 경고” + “상관 룰(스코어)”을 운영합니다.
osquery 테이블(무엇을 보나) – 실전 핵심만
환경에 따라 이벤트 테이블 지원이 다르지만, 아래는 거의 항상 유용합니다.
- processes: 현재 프로세스 스냅샷(핵심)
- process_envs: 환경변수(악성 PATH/LD_PRELOAD 흔적 등)
- process_open_sockets / listening_ports: 소켓/포트 사용
- mounts: 마운트 상태(호스트 경로 노출/이상 마운트)
- file / hash / yara(가능 시): 파일 변조·드롭 탐지
- users / user_groups / sudoers(환경 따라 다름): 권한 관련
이벤트 기반(가능할 때)
- process_events / socket_events / file_events: “실행 순간” 포착(백엔드 설정 필요)
런타임별 핵심 “공격 표면”과 osquery 탐지 포인트
Docker (가장 대표적)
공격 표면
/var/run/docker.sock접근 = 사실상 호스트 장악 가능- privileged / CAP_SYS_ADMIN 컨테이너에서
nsenter,mount등 실행
탐지 포인트(우선순위 매우 높음)
- 컨테이너 프로세스가
docker.sock에 접근 - 컨테이너 프로세스가
nsenter/unshare/mount/chroot/setcap실행
containerd / CRI-O (K8s 노드의 런타임)
공격 표면
- 런타임 소켓 접근 (환경마다 위치 다름)
- containerd:
/run/containerd/containerd.sock(예시) - CRI-O:
/var/run/crio/crio.sock(예시)
- containerd:
- kubelet 제어면 접근 (노드 내부 네트워크/소켓)
- hostPath/privileged가 열려 있으면 내부에서 호스트로 바로 접근
탐지 포인트
- 컨테이너 프로세스의 런타임 소켓 접근 흔적
- 컨테이너 프로세스의 “호스트 민감 경로” 접근/마운트
Kubernetes (운영 관점에서 제일 중요)
K8s는 “노드에서 관측되는 행위” + “클러스터 설정 취약”이 겹칩니다.
설정(정책) 측면의 핵심 위험(보안 점검 체크포인트로 배포 추천)
privileged: trueallowPrivilegeEscalation: truehostPID: true,hostNetwork: truehostPath로/,/proc,/sys,/var/run등 노출- 과도한 capabilities (
SYS_ADMIN,SYS_PTRACE,NET_ADMIN등)
osquery는 “설정값 자체”를 Kubernetes API로 직접 읽는 게 목적이 아니고,
노드에서 “그 결과로 나타난 행위”를 잡는 데 강합니다.
설정 점검은 별도 파이프라인(예: kube-bench, OPA, API audit)과 병행이 베스트입니다.
실전 쿼리 팩(핵심 예시) – Docker/containerd/CRI-O/K8s 공통 운영형
아래 쿼리들은 “컨테이너 프로세스인지”를 cgroup_path로 먼저 제한하는 게 핵심입니다.
컨테이너 프로세스 필터(공통 WHERE 절로 재사용)
-- 이 WHERE를 각 쿼리에 공통으로 붙여 쓰는 방식 추천
(cgroup_path LIKE '%kubepods%'
OR cgroup_path LIKE '%docker%'
OR cgroup_path LIKE '%containerd%'
OR cgroup_path LIKE '%cri-containerd%'
OR cgroup_path LIKE '%crio%'
OR cgroup_path LIKE '%libpod%')
“위험 도구 실행” 탐지 (주기/이벤트 모두 가능)
SELECT pid, parent, name, path, cmdline, uid, cgroup_path
FROM processes
WHERE
(cgroup_path LIKE '%kubepods%'
OR cgroup_path LIKE '%docker%'
OR cgroup_path LIKE '%containerd%'
OR cgroup_path LIKE '%crio%'
OR cgroup_path LIKE '%libpod%')
AND (
cmdline LIKE '%nsenter%'
OR cmdline LIKE '%unshare%'
OR cmdline LIKE '%mount%'
OR cmdline LIKE '%pivot_root%'
OR cmdline LIKE '%chroot%'
OR cmdline LIKE '%setcap%'
OR cmdline LIKE '%capsh%'
OR cmdline LIKE '%modprobe%'
OR cmdline LIKE '%insmod%'
);
운영 팁(오탐 줄이기)
mount는 정상일 수 있어도, 컨테이너 프로세스에서 mount/unshare/nsenter는 강한 신호입니다.- 부모 프로세스가 웹서버/애플리케이션 런타임(nginx, java, node, php-fpm 등)인데 저 도구가 실행되면 위험도를 크게 올립니다.
런타임 소켓 접근(제어면 장악 루트) 탐지
Docker 소켓(최우선)
SELECT s.pid, p.cmdline, p.uid, p.cgroup_path, s.path
FROM process_open_sockets s
JOIN processes p ON s.pid = p.pid
WHERE s.path = '/var/run/docker.sock';
containerd / CRI-O 소켓(경로는 환경별로 튜닝)
SELECT s.pid, p.cmdline, p.uid, p.cgroup_path, s.path
FROM process_open_sockets s
JOIN processes p ON s.pid = p.pid
WHERE
s.path IN ('/run/containerd/containerd.sock',
'/var/run/crio/crio.sock',
'/run/crio/crio.sock');
보안 가이드 포인트
- “앱 컨테이너 프로세스가 런타임 소켓 접근”은 거의 고위험
- 정상 예외는 노드 관리 에이전트/운영툴로 제한하고, 예외 목록을 최소화
민감 마운트/호스트 경로 노출 상태 점검(주기 수집)
SELECT device, path, type, flags
FROM mounts
WHERE
path IN ('/','/proc','/sys','/dev')
OR path LIKE '%/var/run%'
OR path LIKE '%/run/containerd%'
OR path LIKE '%/var/lib/kubelet%'
OR flags LIKE '%rw%';
해석 팁
- 이 쿼리 하나만으로 “탈출”을 확정하긴 어렵지만,
- 노드에서 위험한 hostPath/바인드 마운트가 실제로 존재하는지 빠르게 점검할 수 있습니다.
호스트 지속성 흔적(변조) – 스냅샷/베이스라인 방식
컨테이너 탈출 성공 이후엔 호스트에 “지속성”을 심는 경우가 많습니다.
cron/systemd 경로 파일 변화 감시(스냅샷 기반)
SELECT path, uid, gid, mode, mtime, size
FROM file
WHERE
path LIKE '/etc/cron%'
OR path LIKE '/etc/systemd/system/%'
OR path LIKE '/root/.ssh/%'
OR path LIKE '/etc/ssh/%';
운영 방식
- 최초 수집을 베이스라인으로 저장
- 이후 수집에서 mtime/size/hash 변화가 있으면 경고
(이 방식이 osquery의 강력한 “구성 변경 탐지” 패턴입니다)
상관분석(스코어링) 설계 예시 – “체계적으로” 운영하려면 꼭 필요
탐지 운영을 쉽게 만들려면, 아래처럼 점수 기반을 추천합니다.
이벤트별 점수 예시
- 컨테이너 프로세스가
nsenter/unshare실행: +60 - 컨테이너 프로세스가
docker.sock또는 CRI 소켓 접근: +80 - 컨테이너 프로세스가
/proc/1/root등 호스트 루트 우회 흔적(환경 따라): +60 - 컨테이너 프로세스가
modprobe/insmod실행: +90 - 호스트에서 cron/systemd 파일 변경 감지: +70
- 부모 프로세스가 웹앱(nginx/java/node)인데 쉘 실행: +40
알림 레벨
- 60점 이상: 의심 (조사 큐)
- 100점 이상: 고위험 (즉시 대응)
- 160점 이상: 침해 강력 의심 (격리/차단 포함)
포인트: 단일 시그널로 “탈출 확정”을 선언하지 않고,
복합 시그널이 쌓일수록 확신도를 올리는 구조가 운영 난이도를 크게 낮춥니다.
Kubernetes에서 “osquery만으로 부족한 영역”과 보완 권장 조합
K8s는 설정/정책이 공격면을 크게 좌우합니다. 그래서 아래 조합이 현실적입니다.
- 노드 행위 탐지: osquery (지금 이야기한 영역)
- K8s 설정 점검: kube-bench / OPA Gatekeeper / Kyverno / PodSecurity(정책)
- 감사 로깅: Kubernetes Audit Log (권한 오남용, exec, port-forward 등)
- 시스템콜 기반 런타임 탐지: Falco(eBPF) 또는 auditd 기반 탐지
osquery는 여기서 “노드에서 벌어진 실제 행위”를 SIEM으로 보내는 표준 센서 역할로 매우 좋습니다.
보안 점검 체크포인트
- 런타임 소켓(docker.sock/CRI 소켓) 컨테이너 노출 금지
- privileged / CAP_SYS_ADMIN 최소화
- hostPID/hostNetwork/hostPath 사용 엄격 통제
- 컨테이너 readOnlyRootFilesystem 권장, 불필요한 쉘/패키지 설치 금지
- 노드에서 nsenter/unshare/mount 같은 위험 도구 실행 모니터링
- cron/systemd/ssh key 등 지속성 경로 변경 모니터링
- 오탐 방지를 위한 예외(Allowlist)는 “운영툴”로만 최소 유지
실행 절차 제안
- 환경 식별
- 위 3.1 쿼리로
cgroup_path패턴을 수집 → “우리 환경 패턴 사전” 만들기
- 위 3.1 쿼리로
- 핵심 탐지 3종 먼저 배포
- 위험 도구 실행
- 런타임 소켓 접근
- 호스트 지속성(변조) 스냅샷
- 오탐 튜닝
- 정상 운영툴/에이전트 예외 최소화
- 부모 프로세스/uid/이미지(가능 시) 기반 조건 추가
- 스코어링 적용
- 단일 경고 폭주 방지, 우선순위 정렬
- K8s 정책 점검 파이프라인 병행
- “설정이 열려있어서 생기는 이벤트”를 근본적으로 줄임
환경별 맞춤 pack
여기서 더 실전으로 가려면, 결국 “당신 환경의 cgroup_path 실물 패턴”과 “이벤트 테이블 사용 가능 여부(process_events/socket_events/file_events)”가 중요합니다.
바로 적용 가능한 최소 세트
processes + process_open_sockets + mounts + file(스냅샷)조합
이벤트 기반이 가능하면
process_events/socket_events/file_events로 “순간 포착”을 강화합니다.
위 내용을 기반으로 (1) Docker 중심 노드, (2) containerd/CRI-O 기반 K8s 노드로 나눠서
- 쿼리 pack 구성(주기/이벤트)
- 점수화 룰
- 오탐 예외 기준(운영툴 allowlist)
- 대응 플레이북(조사 순서: 프로세스→소켓→마운트→파일변조)
댓글