Docker có thực sự an toàn?

15 tháng 4, 2021 By DEVERA ACADEMY

Trong những năm trở lại đây, công nghệ ảo hóa ngày càng phát triển mạnh mẽ kéo theo những yêu cầu ngày càng cao về tính hiệu quả và khả năng bảo mật. Giữa 2 công nghệ ảo hóa đang được sử dụng nhiều nhất hiện tại là Container-based và Hypervisor-based thì Container-based  được đánh giá là nhẹ hơn và có thể tạo ra môi trường ảo một cách hiệu quả. Thế nhưng, Container-based vẫn còn tồn tại một vài vấn đề về bảo mật.

Trong bài viết này, chúng ta sẽ cùng phân tích mức độ bảo mật của Docker - một nền tảng khá nổi tiếng đại diện cho Container-based, thông qua những mối đe dọa có thể xảy ra bên trong một Container.

1. Docker là gì?

Docker là một nền tảng phần mềm ảo hóa hệ điều hành (OS virtualization) được sử dụng để tạo, triển khai và chạy ứng dụng thông qua Docker container. Nhẹ hơn so với các máy ảo hiện tại cùng với khả năng đóng gói ứng dụng vào các container kèm theo cả thư viện và các dependencies, Docker giúp ứng dụng của bạn giảm bớt sự phụ thuộc vào hệ thống đồng thời cũng giúp quá trình làm việc của bạn trở nên đơn giản và nhanh hơn.

Thực ra có thể nói Docker cũng chỉ là một môi trường nơi chúng ta có thể chạy code nhưng nó chạy một cách độc lập - điều mà các máy tính cá nhân không thể thực hiện. Ví dụ, khi chúng ta đang thực hiện một dự án trên hệ thống A và muốn chạy dự án đó trên hệ thống B thì chương trình của chúng ta rất có thể bị crash bởi rất nhiều lý do như: sử dụng compiler khác nhau, không cùng version của phần mềm hay package hoặc là sử dụng khác hệ điều hành. Và Docker chính là giải pháp cho hàng tá vấn đề đó, nó giữ tất cả mọi thứ cho ứng dụng của bạn trong một package và khi chúng ta cần chuyển dự án sang một hệ thống khác thì Docker hoàn toàn có thể đem theo cả môi trường cần thiết cho dự án đó.


2. Các thành phần chính của Docker:

Docker Image là một read-only template giúp bạn tạo một container có thể chạy được trên nền tảng Docker. Template này giúp bạn dễ dàng hơn trong việc đóng gói ứng dụng và cấu hình sẵn môi trường cho server để có thể sử dụng hoặc là chia sẻ cho những người dùng Docker khác.

Image là một package chứa tất cả mọi thứ phục vụ cho việc chạy ứng dụng bao gồm code, runtime, thư viện, các biến môi trường và các file cấu hình.

Docker Container cho phép chúng ta đóng gói code và tất cả những gì cần thiết của phần mềm thành một package, giúp cho ứng dụng có thể chạy một cách nhanh chóng khi bạn chuyển dự án từ máy tính này sang máy tính khác. 

Nhiều người nhầm lẫn giữa Docker container và máy ảo nhưng thật sự giữa chúng có một sự khác biệt rất lớn. Đối với một máy ảo, chúng ta cần phải cài đặt hệ điều hành + kernel + drivers, còn với Docker nó sử dụng hệ thống + kernel + drivers được chia sẻ từ host nên có phần nhẹ và chiếm ít dung lượng. Ngày nay, Docker container được sử dụng ngày càng nhiều bởi sự linh hoạt, nhẹ, dễ dàng chia sẻ và mở rộng.

3. Tính độc lập của Docker

Linux Cgroups là một trong những tính năng được cung cấp bởi Linux giúp cho Docker có khả năng tự cô lập. Cgroups cho phép chúng ta nhóm những tiến tình liên quan lại với nhau và quản lý các nhóm tiến trình đó trong quá trình chúng sử dụng CPU, bộ nhớ hay là I/O. Cgroups có quyền kiểm soát việc phân bổ, quản lý và giám sát tài nguyên hệ thống, phân chia tài nguyên phần cứng cho các tác vụ và người dùng để tăng hiệu quả.


Một kernel khác nữa là Namespaces cho phép xem hệ thống dưới chế độ hạn chế. Khi bạn đăng nhập vào một máy Linux, bạn sẽ thấy hệ thống tệp, tiến trình, giao diện mạng của nó. Sau khi tạo container, Docker sẽ tạo một tập các namespaces với hệ thống tệp, quy trình và giao diện mạng riêng khác với máy chủ đang chạy. Mỗi container nhận được một bộ tài nguyên kernel riêng biệt để không tiến trình nào có thể sử dụng tài nguyên được cấp cho các tiến trình khác.

4. Docker có an toàn không?

Hầu hết các newbie developer đều cho rằng Docker tuyệt đối an toàn, họ có thể pull Docker image từ DockerHub và chạy nó mà không cần quan tâm rằng ai là người push image đó lên hoặc không quan tâm đến tính xác thực của image. Docker không bảo mật giống như máy ảo, bởi chúng ta không thể tương tác trực tiếp với kernel, không có quyền truy cập vào các file hệ thống như /sys và sys/fs,proc/*.


Việc cấu hình Docker dễ xảy ra sai sót hơn so với cấu hình một máy ảo. Tính linh hoạt trong việc chia sẻ tài nguyên của Docker cũng có thể gây ra các lỗi khi thực hiện cấu hình. Tuy nhiên, nếu bạn có thể cài đặt cấu hình đúng cách và không có lỗi gì xảy ra bên trong kernel thì Docker có thể cung cấp cho bạn một khả năng bảo vệ tổng thể, thậm chí còn tốt hơn so với việc sử dụng máy ảo. Bên trong máy ảo, khí bị tấn công thì trình ảo hóa sẽ bị tấn công trước chứ không phải kernel.

Docker Security: https://docs.docker.com/engine/security/


5. Tấn công bề mặt Docker container:

  • Nếu kẻ tấn công là người có thể khởi động container (có quyền truy cập tới Docker API) thì ngay lập tức hắn ta có quyền của một root để truy cập tới host.

  • Nếu kẻ tấn công có được quyền quản lý bên trong container thì bạn sẽ gặp rắc rối, bởi hắn ta có thể thực hiện các lệnh làm ảnh hưởng đến host kernel. Nhưng thật không may là rất nhiều Docker image cho phép chạy dưới quyền root mà bỏ qua việc sử dụng User trong Dockerfile. Đây là một vấn đề bảo mật không thuộc về phía Docker mà thuộc về phía người dùng.

  • Các lỗ hổng bảo mật trên container máy chủ được chia sẻ cùng với kernel host, nó có thể khiến kẻ tấn công phá vỡ container đẻ xâm nhập vào kernel của host. 

  • Đôi khi cấu hình Container tệ cũng khiến bạn có được đặc quyền truy cập vào máy chủ bên dưới. 

  • Nếu bạn có một Container mount với hệ thống tệp trên máy chủ, bạn có thể sửa đổi những thứ trong hệ thống tệp đó để nâng cấp đặc quyền.

Gắn Docker socket bên trong một container để cho phép container hiểu trạng thái của daemon Docker (deamon giúp build, run và quản lý các thành phần trong Docker) là một thực tiễn tương đối phổ biến (nhưng nguy hiểm) trong các container Docker.

6. Thoát khỏi container dùng docker.sock:

Docker.sock là socket duy nhất được xem như là xương sống của việc quản lý các container. Khi bạn dùng các lệnh docker để sử dụng docker client, docker client của bạn sẽ tương tác với docker.sock để quản lý container.


Các lệnh của Docker khi được chạy trên máy chủ, API sẽ gọi Docker daemon thông qua non-networked UNIX socket được đặt ở at/var/run/docker.sock. Socket file này là API chính trong việc điều khiển các Docker container hoạt động trên máy.


Tuy nhiên đa số các container và cả những hướng dẫn yêu cầu bạn hiển thị socket file như một Docker volume bên trong container (hoặc là trên cổng TCP ở một vài trường hợp).


Docker container để lộ ra /var/run/docker.sock dù là local hay remote đều có thể dẫn đến việc toàn bộ môi trường bị chiếm đoạt. Bởi truy cập bằng đường dẫn đó tương đương với quyền của một root.


Cùng xem ví dụ về cách một kẻ tấn công xâm nhập vào một container được mount với docker.sock. Đầu tiên chúng ta giả lập môi trường bằng cách tạo một container với docker.sock được mount với nó.


  • Tạo một alpine container tên là sock từ alpine image bằng lệnh sau:


  • Mở shell trên sock container:


  • Bây giờ chúng ta đã có một container đã được mount với docker socket, cùng xem làm sao có thể khai thác chúng.

  • Chúng ta cần cài đặt docker client bên trong container và tạo thêm một container bằng cách sử dụng container vừa tạo.


  • Container có thể tương tác với container lớp dưới thông qua Unix socket và -v/:/test:ro mount đường dẫn của root tới container, cuối cùng bật shell của container vừa tạo:



  • Đi tới /test là mount point của địa chỉ root thuộc máy chủ, có nghĩa là bạn đã có quyền tương tác bên trong máy chủ.

  • Output của lệnh ls tại ./test


7. Khai thác đặc quyền từ Container:

Khi một container được chạy với cờ đặc quyền, nó hoàn toàn có khả năng xâm nhập xuống máy chủ. Một trong số đó có thể kể đến CAP_SYS_MODULE, kẻ tấn công truy cập vào container và có được đặc quyền, hắn ta hoàn toàn có thể cài đặt một kernel module trực tiếp vào kernel của máy chủ.


 


Bây giờ chúng ta đã bật cap_sys_module trong container của mình, chúng ta có thể thoát khỏi container bằng cách cài đặt trực tiếp kernel module vào kernel của máy chủ.


8. Thông tin về các lỗ hổng bảo mật





  • Ngày nay, docker đang được sử dụng rộng rãi và hầu hết các developer làm việc với docker đều nghĩ rằng nó an toàn.

  • 10 image Docker hàng đầu với hơn 10 triệu lượt tải xuống, mỗi image chứa ít nhất 30 lỗ hổng.

  • Trong số 10 docker image miễn phí phổ biến, 50% có lỗ hổng bảo mật.

  • 80% developer không kiểm tra docker image của họ trong quá trình phát triển.

  • 50% developer hoàn toàn không quét Docker image để tìm các lỗ hổng.

  • 20% Docker image có lỗ hổng bảo mật có thể được giải quyết bằng cách xây dựng lại.


9. Một số bước để  bảo mật tốt hơn

  • Nên sử dụng các phần mềm để quét qua Docker image.

  • Một container chỉ nên chứa một phần mềm hoặc chương trình.

  • Trước khi pull image từ docker Hub, chúng ta nên đảm bảo độ tin cậy từ nhà xuất bản và kiểm tra tính xác thực của image.

  • Không sử dụng root để chạy image docker, hãy tạo user để chạy image docker.

  • Nên xây dựng lại dockerfile của bạn.

  • Giám sát các Docker container của bạn trong quá trình phát triển bằng cách tự động quét các package và image của bạn.

Phần kết luận

Trong bài viết này, chúng ta đã tìm hiểu về các lỗ hổng của Docker và cách bảo vệ Docker container. Tóm lại, khi sử dụng Docker chúng ta nên quét image và container thường xuyên để giảm nguy cơ phát sinh các vấn đề về bảo mật.


Tác giả: Aaryan

Dịch bởi Devera Academy