Docker Security
Last updated
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Use Trickest to easily build and automate workflows powered by the world's most advanced community tools. Get Access Today:
Docker 엔진은 리눅스 커널의 네임스페이스와 Cgroups를 사용하여 컨테이너를 격리하여 기본적인 보안 계층을 제공합니다. 추가적인 보호는 권한 제거, Seccomp, 및 SELinux/AppArmor를 통해 제공되어 컨테이너 격리를 강화합니다. 인증 플러그인은 사용자 행동을 추가로 제한할 수 있습니다.
Docker 엔진은 유닉스 소켓을 통해 로컬에서 또는 HTTP를 사용하여 원격으로 접근할 수 있습니다. 원격 접근을 위해서는 HTTPS와 TLS를 사용하여 기밀성, 무결성 및 인증을 보장하는 것이 필수적입니다.
Docker 엔진은 기본적으로 unix:///var/run/docker.sock
에서 유닉스 소켓을 수신 대기합니다. Ubuntu 시스템에서 Docker의 시작 옵션은 /etc/default/docker
에 정의되어 있습니다. Docker API 및 클라이언트에 대한 원격 접근을 활성화하려면 다음 설정을 추가하여 Docker 데몬을 HTTP 소켓을 통해 노출해야 합니다:
그러나 Docker 데몬을 HTTP로 노출하는 것은 보안 문제로 인해 권장되지 않습니다. HTTPS를 사용하여 연결을 보호하는 것이 좋습니다. 연결을 보호하는 두 가지 주요 접근 방식이 있습니다:
클라이언트가 서버의 신원을 확인합니다.
클라이언트와 서버가 서로의 신원을 상호 인증합니다.
서버의 신원을 확인하기 위해 인증서가 사용됩니다. 두 방법에 대한 자세한 예는 이 가이드를 참조하십시오.
컨테이너 이미지는 개인 또는 공용 저장소에 저장될 수 있습니다. Docker는 컨테이너 이미지를 위한 여러 저장 옵션을 제공합니다:
Docker Hub: Docker의 공용 레지스트리 서비스입니다.
Docker Registry: 사용자가 자신의 레지스트리를 호스팅할 수 있도록 하는 오픈 소스 프로젝트입니다.
Docker Trusted Registry: 역할 기반 사용자 인증 및 LDAP 디렉토리 서비스와의 통합 기능을 갖춘 Docker의 상업적 레지스트리 제공입니다.
컨테이너는 기본 이미지 또는 기본 이미지 위에 설치된 소프트웨어로 인해 보안 취약점을 가질 수 있습니다. Docker는 컨테이너의 보안 스캔을 수행하고 취약점을 나열하는 Nautilus라는 프로젝트를 진행 중입니다. Nautilus는 각 컨테이너 이미지 레이어를 취약점 저장소와 비교하여 보안 구멍을 식별합니다.
자세한 정보는 여기에서 읽어보세요.
docker scan
docker scan
명령은 이미지 이름 또는 ID를 사용하여 기존 Docker 이미지를 스캔할 수 있게 해줍니다. 예를 들어, hello-world 이미지를 스캔하려면 다음 명령을 실행하십시오:
Docker 이미지 서명은 컨테이너에서 사용되는 이미지의 보안성과 무결성을 보장합니다. 다음은 간략한 설명입니다:
Docker 콘텐츠 신뢰를 활성화하려면 export DOCKER_CONTENT_TRUST=1
을 설정합니다. 이 기능은 Docker 버전 1.10 이상에서 기본적으로 꺼져 있습니다.
이 기능이 활성화되면 서명된 이미지만 다운로드할 수 있습니다. 초기 이미지 푸시에는 루트 및 태그 키에 대한 비밀번호를 설정해야 하며, Docker는 보안을 강화하기 위해 Yubikey도 지원합니다. 더 많은 세부정보는 여기에서 확인할 수 있습니다.
콘텐츠 신뢰가 활성화된 상태에서 서명되지 않은 이미지를 가져오려고 하면 "No trust data for latest" 오류가 발생합니다.
첫 번째 이후의 이미지 푸시를 위해 Docker는 이미지를 서명하기 위해 리포지토리 키의 비밀번호를 요청합니다.
개인 키를 백업하려면 다음 명령을 사용하세요:
When switching Docker hosts, it's necessary to move the root and repository keys to maintain operations.
Use Trickest to easily build and automate workflows powered by the world's most advanced community tools. Get Access Today:
Namespaces는 커널 리소스를 분할하여 한 집합의 프로세스가 한 집합의 리소스를 보고, 다른 집합의 프로세스가 다른 집합의 리소스를 보는 Linux 커널의 기능입니다. 이 기능은 리소스와 프로세스의 집합에 대해 동일한 네임스페이스를 가지지만, 해당 네임스페이스는 서로 다른 리소스를 참조함으로써 작동합니다. 리소스는 여러 공간에 존재할 수 있습니다.
Docker는 컨테이너 격리를 달성하기 위해 다음 Linux 커널 네임스페이스를 사용합니다:
pid namespace
mount namespace
network namespace
ipc namespace
UTS namespace
네임스페이스에 대한 더 많은 정보는 다음 페이지를 확인하세요:
Linux 커널 기능 cgroups는 일련의 프로세스 간에 cpu, memory, io, network bandwidth와 같은 리소스를 제한할 수 있는 기능을 제공합니다. Docker는 특정 컨테이너에 대한 리소스 제어를 허용하는 cgroup 기능을 사용하여 컨테이너를 생성할 수 있습니다. 다음은 사용자 공간 메모리가 500m로 제한되고, 커널 메모리가 50m로 제한되며, cpu 공유가 512, blkioweight가 400인 컨테이너입니다. CPU 공유는 컨테이너의 CPU 사용량을 제어하는 비율입니다. 기본값은 1024이며 0에서 1024 사이의 범위를 가집니다. 세 개의 컨테이너가 동일한 CPU 공유 1024를 가지면, 각 컨테이너는 CPU 리소스 경합 시 최대 33%의 CPU를 사용할 수 있습니다. blkio-weight는 컨테이너의 IO를 제어하는 비율입니다. 기본값은 500이며 10에서 1000 사이의 범위를 가집니다.
컨테이너의 cgroup을 얻으려면 다음과 같이 할 수 있습니다:
더 많은 정보는 다음을 확인하세요:
능력은 루트 사용자에게 허용될 수 있는 능력에 대한 더 세밀한 제어를 허용합니다. Docker는 Linux 커널 능력 기능을 사용하여 사용자 유형에 관계없이 컨테이너 내에서 수행할 수 있는 작업을 제한합니다.
Docker 컨테이너가 실행될 때, 프로세스는 격리에서 탈출하는 데 사용할 수 있는 민감한 능력을 포기합니다. 이는 프로세스가 민감한 작업을 수행하고 탈출할 수 없도록 보장하려고 합니다:
이것은 Docker가 컨테이너 내에서 사용할 수 있는 시스템 호출을 제한할 수 있게 해주는 보안 기능입니다:
AppArmor는 컨테이너를 제한된 리소스 집합에 프로그램별 프로필로 제한하는 커널 향상 기능입니다.:
레이블링 시스템: SELinux는 모든 프로세스와 파일 시스템 객체에 고유한 레이블을 할당합니다.
정책 집행: 프로세스 레이블이 시스템 내 다른 레이블에서 수행할 수 있는 작업을 정의하는 보안 정책을 집행합니다.
컨테이너 프로세스 레이블: 컨테이너 엔진이 컨테이너 프로세스를 시작할 때, 일반적으로 제한된 SELinux 레이블인 container_t
가 할당됩니다.
컨테이너 내 파일 레이블링: 컨테이너 내의 파일은 일반적으로 container_file_t
로 레이블이 지정됩니다.
정책 규칙: SELinux 정책은 주로 container_t
레이블을 가진 프로세스가 container_file_t
로 레이블이 지정된 파일과만 상호작용(읽기, 쓰기, 실행)할 수 있도록 보장합니다.
이 메커니즘은 컨테이너 내의 프로세스가 손상되더라도 해당 레이블이 있는 객체와만 상호작용하도록 제한되어, 그러한 손상으로 인한 잠재적 피해를 크게 제한합니다.
Docker에서 권한 부여 플러그인은 Docker 데몬에 대한 요청을 허용할지 차단할지를 결정하는 데 중요한 역할을 합니다. 이 결정은 두 가지 주요 컨텍스트를 검토하여 이루어집니다:
인증 컨텍스트: 여기에는 사용자에 대한 포괄적인 정보가 포함되며, 사용자가 누구인지와 어떻게 인증했는지를 포함합니다.
명령 컨텍스트: 이는 요청과 관련된 모든 관련 데이터를 포함합니다.
이러한 컨텍스트는 인증된 사용자로부터의 합법적인 요청만 처리되도록 보장하여 Docker 작업의 보안을 강화합니다.
컨테이너가 사용할 수 있는 리소스를 적절히 제한하지 않으면, 손상된 컨테이너가 실행 중인 호스트에 DoS를 일으킬 수 있습니다.
CPU DoS
대역폭 DoS
다음 페이지에서 --privileged
플래그가 의미하는 바를 배울 수 있습니다:
공격자가 낮은 권한 사용자로 접근할 수 있는 컨테이너를 실행하는 경우, 잘못 구성된 suid 바이너리가 있다면 공격자가 이를 악용하여 컨테이너 내에서 권한을 상승시킬 수 있습니다. 이는 그가 컨테이너에서 탈출할 수 있게 할 수 있습니다.
no-new-privileges
옵션을 활성화하여 컨테이너를 실행하면 이러한 종류의 권한 상승을 방지할 수 있습니다.
For more --security-opt
options check: https://docs.docker.com/engine/reference/run/#security-configuration
비밀을 Docker 이미지에 직접 포함시키거나 환경 변수를 사용하는 것은 피하는 것이 중요합니다. 이러한 방법은 docker inspect
또는 exec
와 같은 명령을 통해 컨테이너에 접근할 수 있는 모든 사람에게 민감한 정보를 노출합니다.
Docker 볼륨은 민감한 정보에 접근하기 위한 더 안전한 대안으로 권장됩니다. 이는 메모리 내에서 임시 파일 시스템으로 활용될 수 있어 docker inspect
및 로깅과 관련된 위험을 완화합니다. 그러나 루트 사용자와 컨테이너에 exec
접근 권한이 있는 사용자는 여전히 비밀에 접근할 수 있습니다.
Docker 비밀은 민감한 정보를 처리하는 더욱 안전한 방법을 제공합니다. 이미지 빌드 단계에서 비밀이 필요한 인스턴스의 경우, BuildKit은 빌드 시간 비밀을 지원하여 빌드 속도를 향상시키고 추가 기능을 제공하는 효율적인 솔루션을 제공합니다.
BuildKit을 활용하려면 세 가지 방법으로 활성화할 수 있습니다:
환경 변수를 통해: export DOCKER_BUILDKIT=1
명령어에 접두사를 붙여: DOCKER_BUILDKIT=1 docker build .
Docker 구성에서 기본적으로 활성화: { "features": { "buildkit": true } }
, 이후 Docker를 재시작합니다.
BuildKit은 --secret
옵션을 사용하여 빌드 시간 비밀을 사용할 수 있게 하여, 이러한 비밀이 이미지 빌드 캐시나 최종 이미지에 포함되지 않도록 합니다.
실행 중인 컨테이너에서 필요한 비밀을 위해, Docker Compose와 Kubernetes는 강력한 솔루션을 제공합니다. Docker Compose는 비밀 파일을 지정하기 위해 서비스 정의에서 secrets
키를 사용합니다. 다음은 docker-compose.yml
예제입니다:
이 구성은 Docker Compose로 서비스를 시작할 때 비밀을 사용할 수 있도록 허용합니다.
Kubernetes 환경에서는 비밀이 기본적으로 지원되며 Helm-Secrets와 같은 도구로 추가 관리할 수 있습니다. Kubernetes의 역할 기반 접근 제어(RBAC)는 Docker Enterprise와 유사하게 비밀 관리 보안을 강화합니다.
gVisor는 Go로 작성된 애플리케이션 커널로, Linux 시스템 표면의 상당 부분을 구현합니다. 이는 애플리케이션과 호스트 커널 간의 격리 경계를 제공하는 runsc
라는 Open Container Initiative (OCI) 런타임을 포함합니다. runsc
런타임은 Docker 및 Kubernetes와 통합되어 샌드박스화된 컨테이너를 쉽게 실행할 수 있게 합니다.
Kata Containers는 경량 가상 머신을 사용하여 안전한 컨테이너 런타임을 구축하기 위해 노력하는 오픈 소스 커뮤니티입니다. 이들은 컨테이너처럼 느껴지고 작동하지만, 하드웨어 가상화 기술을 사용하여 더 강력한 작업 부하 격리를 제공합니다.
--privileged
플래그를 사용하지 않거나 컨테이너 내부에 Docker 소켓을 마운트하지 마십시오. Docker 소켓은 컨테이너를 생성할 수 있게 하므로, 예를 들어 --privileged
플래그로 다른 컨테이너를 실행하여 호스트를 완전히 제어할 수 있는 쉬운 방법입니다.
컨테이너 내부에서 root로 실행하지 마십시오. 다른 사용자 와 사용자 네임스페이스 를 사용하십시오. 컨테이너의 root는 사용자 네임스페이스로 재매핑되지 않는 한 호스트의 root와 동일합니다. 이는 주로 Linux 네임스페이스, 기능 및 cgroups에 의해 약간 제한됩니다.
모든 기능을 제거하십시오 (--cap-drop=all
) 및 필요한 기능만 활성화하십시오 (--cap-add=...
). 많은 작업 부하에는 기능이 필요하지 않으며, 이를 추가하면 잠재적인 공격 범위가 증가합니다.
“no-new-privileges” 보안 옵션을 사용하십시오 프로세스가 더 많은 권한을 얻지 못하도록 방지하십시오. 예를 들어 suid 바이너리를 통해서입니다.
컨테이너에 사용할 수 있는 리소스를 제한하십시오. 리소스 제한은 서비스 거부 공격으로부터 머신을 보호할 수 있습니다.
seccomp 조정하십시오, AppArmor (또는 SELinux) 프로필을 최소한의 요구 사항으로 컨테이너에 대한 작업 및 시스템 호출을 제한하십시오.
공식 Docker 이미지를 사용하고 서명을 요구하십시오 또는 이를 기반으로 직접 빌드하십시오. 백도어가 있는 이미지를 상속하거나 사용하지 마십시오. 또한 루트 키와 비밀번호를 안전한 장소에 보관하십시오. Docker는 UCP로 키를 관리할 계획이 있습니다.
정기적으로 이미지를 재빌드하여 호스트 및 이미지에 보안 패치를 적용하십시오.
비밀을 현명하게 관리하여 공격자가 접근하기 어렵게 하십시오.
Docker 데몬을 노출하는 경우 HTTPS를 사용하십시오 클라이언트 및 서버 인증과 함께.
Dockerfile에서 ADD 대신 COPY를 선호하십시오. ADD는 자동으로 압축된 파일을 추출하고 URL에서 파일을 복사할 수 있습니다. COPY는 이러한 기능이 없습니다. 가능한 한 ADD 사용을 피하여 원격 URL 및 Zip 파일을 통한 공격에 취약하지 않도록 하십시오.
각 마이크로 서비스에 대해 별도의 컨테이너를 가지십시오.
컨테이너 내부에 ssh를 두지 마십시오. “docker exec”를 사용하여 컨테이너에 ssh할 수 있습니다.
더 작은 컨테이너 이미지를 가지십시오.
당신이 docker 컨테이너 내부에 있거나 docker 그룹의 사용자에 접근할 수 있다면, 탈출하고 권한을 상승시키려고 시도할 수 있습니다:
Docker 소켓에 접근할 수 있거나 docker 그룹의 사용자에 접근할 수 있지만 Docker 인증 플러그인에 의해 행동이 제한된다면, 우회할 수 있는지 확인하십시오:
도구 docker-bench-security는 프로덕션에서 Docker 컨테이너를 배포할 때의 수십 가지 일반적인 모범 사례를 확인하는 스크립트입니다. 테스트는 모두 자동화되어 있으며, CIS Docker Benchmark v1.3.1을 기반으로 합니다. 이 도구는 Docker를 실행하는 호스트 또는 충분한 권한을 가진 컨테이너에서 실행해야 합니다. README에서 실행 방법을 확인하십시오: https://github.com/docker/docker-bench-security.
Trickest를 사용하여 세계에서 가장 진보된 커뮤니티 도구로 워크플로우를 쉽게 구축하고 자동화하십시오. 오늘 바로 접근하십시오:
AWS 해킹을 배우고 연습하십시오:HackTricks Training AWS Red Team Expert (ARTE) GCP 해킹을 배우고 연습하십시오: HackTricks Training GCP Red Team Expert (GRTE)