Catatan perev. : Catatan ini ditulis oleh seorang peneliti keamanan TI di Aqua Security, sebuah perusahaan DevSecOps. Dia adalah ilustrasi yang sangat baik tentang seluk-beluk dalam konfigurasi Kubernetes, yang penting untuk selalu diingat ketika melayani cluster dalam produksi. Tentu saja, jika Anda memikirkan keselamatan mereka ...
Kubernetes terdiri dari banyak komponen, dan kadang-kadang menggabungkannya dengan cara tertentu mengarah ke hasil yang tidak terduga. Pada artikel ini saya akan menunjukkan bagaimana pod diluncurkan dengan hak akses root dan direktori yang terpasang
/var/log
dari sebuah node dapat
memperluas konten seluruh sistem file host ke pengguna dengan akses ke log-nya. Kami juga akan membahas solusi untuk masalah ini.
Bagaimana Kubernetes melihat log
Pernahkah Anda bertanya-tanya bagaimana
kubectl logs <pod_name>
mengekstrak log dari pod? Siapa yang bertanggung jawab untuk mengumpulkan kayu dari wadah? Dan bagaimana mereka mendapatkannya di komputer Anda?
Diagram berikut menggambarkan proses:

Kubelet membuat struktur di dalam direktori
/var/log
pada host yang mewakili pod pada host. Ada file
0.log
(1) di direktori untuk
0.log
kami, tetapi sebenarnya itu adalah symlink ke log kontainer yang terletak di
/var/lib/docker/containers
. Ini semua dari sudut pandang tuan rumah.
Kubelet membuka titik akhir
/logs/
(2), yang hanya bekerja dengan server file HTTP di direktori (3), membuat log tersedia untuk permintaan yang datang dari server API.
Sekarang bayangkan kita memasang pod dengan
hostPath
terpasang di
/var/log
. Pod semacam itu akan memiliki akses ke semua file log di host. Meskipun ini sendiri merupakan masalah potensial, kita dapat mengambil langkah logis berikutnya. Bagaimana jika kita mengganti
0.log
dengan symlink ke ... katakanlah,
/etc/shadow
?
│ ├── var │ ├── logs │ │ ├── pods │ │ │ ├── default_mypod_e7869b14-abca-11e8-9888-42010a8e020e │ │ │ │ ├── mypod │ │ │ │ │ ├── 0.log -> /etc/shadow │ │ │ │ │ │
Sekarang, mencoba mengunduh log menggunakan
kubectl logs
pada mesin klien, kita mendapatkan:
$ kubectl logs mypod failed to get parse function: unsupported log format: "root:*:18033:0:99999:7:::\n"
Kubelet mengikuti tautan dan membaca isi file yang ditunjuknya (itu bisa berupa file apa pun pada node).
Karena JSON diharapkan, kubectl mogok setelah baris pertama, namun, kita dapat dengan mudah membaca baris spesifik dari file
shadow
dengan menjalankan perintah dengan
–-tail=-<line_number>
.
Ini luar biasa. Karena kubelet mengikuti symlink, Anda dapat menggunakan hak akses rootnya untuk membaca file apa pun pada node, cukup dengan membuat tautan simbolik di dalam pod.
Melarikan diri dari pod
Mari kita melangkah lebih jauh. Kita tahu bahwa ketika memulai sebuah pod di Kubernetes, token ServiceAccount diinstal di dalamnya. Dengan demikian, jika akun layanan memungkinkan akses ke log, kita dapat langsung mengakses hak akses kubelet dan root pada node.
Saya menulis bukti konsep (POC) yang menunjukkan vektor serangan ini:
- penyebaran pod dengan mount point
/var/log
; - membuat tautan simbolis ke direktori root host;
- membaca kunci pribadi ssh pengguna pada host.
Video berikut menunjukkan dua perintah khusus yang berjalan di dalam pod:
lsh == ls
(pada sistem file host);cath == cat
(pada sistem file host).
Catatan perev. : Sayangnya, mereka tidak memperbaiki penyisipan konten dari asciinema pada hub, meskipun kami sudah mengatasi masalah ini, oleh karena itu kami terpaksa "menyematkan" video dengan tautan sederhana di atas.Semua file yang terlibat dalam POC ini dapat ditemukan di
repositori GitHub yang sesuai . Ada skrip POC lain yang secara otomatis mengumpulkan kunci pribadi dan token ServiceAccount dari sistem file host.
Direktori pemasangan bisa berbahaya
Jadi apakah ini kerentanan atau hanya praktik buruk?
Menyebarkan pod dengan
hostPath
-open write-
hostPath
di
/var/log
jarang terjadi (di samping itu, ada cara lain untuk menyalahgunakan pemasangan direktori rahasia host di pod). Tetapi bahkan jika Anda tahu bahwa pemasangan
/var/log
adalah praktik yang meragukan, Anda mungkin tidak mengharapkannya untuk memungkinkan Anda mengambil alih simpul dengan mudah.
Sebelum dipublikasikan, kami menghubungi tim keamanan Kubernetes untuk mencari tahu apakah mereka menganggap ini kerentanan. Mereka menyimpulkan bahwa ini hanyalah konsekuensi menyedihkan dari pemasangan direktori host pribadi dengan izin menulis: risiko yang terlibat
didokumentasikan dengan baik. Namun, kerentanan ini cukup mudah untuk dieksploitasi. Di dunia ada
banyak proyek yang menggunakan mount ini. Jika Anda menggunakan salah satu proyek ini, ingatlah bahwa penyebaran Anda akan rentan terhadap cara pembajakan host ini.
Metode ini telah diuji pada Kubernetes 1.15 dan 1.13, tetapi kemungkinan besar memengaruhi versi lain.
Eliminasi
"Pelarian" seperti itu hanya dimungkinkan jika pod berjalan sebagai root. Ini umumnya
harus dihindari . Aqua CSP memungkinkan Anda untuk menetapkan kebijakan dengan upaya minimal yang mencegah kontainer berjalan sebagai root atau memberikan izin hanya ke grup gambar tertentu yang benar-benar membutuhkan root.
Cara lain adalah tidak menyebarkan pods dengan
hostPath
dengan hak akses tulis di
/var/log
. Pendekatan ini tidak ditetapkan secara default dan bukan praktik yang umum, oleh karena itu perlu untuk secara sadar menentukannya (namun, kemungkinan masih ada). Tapi bagaimana cara mengeceknya?
Kami menambahkan skrip baru (pemburu) ke
kube-hunter - alat Open Source kami yang ringan untuk menguji Kubernetes - yang memeriksa kluster untuk polong dengan titik pemasangan berbahaya tersebut.
( Catatan : Kube-hunter hadir dalam ulasan terbaru tentang utilitas keamanan K8, yang kami posting di blog kami.)Pengguna Aqua dapat melindungi diri mereka dari risiko ini dengan menggunakan kebijakan runtime untuk mencegah volume tertentu agar tidak dipasang:
Catatan perev. : Bagian dari masalah ini dapat diselesaikan dengan menggunakan Kebijakan Keamanan Pod , yaitu AllowedHostPaths
. Namun, ini juga bukan perlindungan terhadap symlink. Akhirnya, seperti komentar yang disarankan, kita bisa membatasi peluncuran sebagai root, sekali lagi dipandu oleh PSP .Ringkasan
Kubernetes adalah sistem yang kompleks dengan banyak kehalusan dalam pengaturan keamanan, yang tidak selalu jelas bagi pengguna rata-rata dan bahkan berpengalaman. Dalam artikel ini, saya telah menunjukkan bagaimana, dalam keadaan tertentu, penebangan tidak bersalah dapat menyebabkan potensi kerentanan. Dalam kebanyakan kasus ini tidak mungkin, tetapi Kubernetes menawarkan pengguna kebebasan bertindak yang lebih besar yang dapat memengaruhi keamanan. Penting untuk mengingat hal ini dan menerapkan kontrol yang sesuai untuk mencegah kesalahan tersebut.
PS dari penerjemah
Baca juga di blog kami: