
रनटाइम libc फ़ंक्शन ऑडिटर जो LD_PRELOAD के माध्यम से फ़ाइलसिस्टम syscalls को हुक करके फ़ाइल एक्सेस रेस कंडीशन और सिमलिंक कमज़ोरियों का पता लगाता है, संभावित प्रिविलेज एस्केलेशन पथों को लॉग करता है।
PathAuditor एक उपकरण है जो libc फ़ंक्शनों का ऑडिट करके फ़ाइल एक्सेस से संबंधित कमजोरियों का पता लगाने के लिए है।
विचार मोटे तौर पर इस प्रकार है:
हम LD_PRELOAD का उपयोग कर रहे हैं ताकि सभी फ़ाइलसिस्टम से संबंधित लाइब्रेरी कॉल को हुक किया जा सके और किसी भी सामने आए उल्लंघन को syslog में लॉग किया जा सके।
यह आधिकारिक रूप से समर्थित Google उत्पाद नहीं है।
आइए इस प्रकार की कमजोरी का एक उदाहरण देखें जिसे यह उपकरण पहचान सकता है। CVE-2019-3461 tmpreaper में एक बग था, एक उपकरण जो /tmp को ट्रैवर्स करता है और पुरानी फ़ाइलों को हटाता है। यह आमतौर पर रूट के रूप में क्रॉन जॉब के रूप में चलाया जाता है। चूंकि यह tmp के बाहर फ़ाइलों को हटाना नहीं चाहता, यह जांचने के लिए निम्नलिखित कोड का उपयोग कर रहा था कि कोई निर्देशिका माउंट पॉइंट है या नहीं:
if (S_ISDIR (sb.st_mode)) {
char *dst;
if ((dst = malloc(strlen(ent->d_name) + 3)) == NULL)
message (LOG_FATAL, "malloc failed.\n");
strcpy(dst, ent->d_name);
strcat(dst, "/X");
rename(ent->d_name, dst);
if (errno == EXDEV) {
free(dst);
message (LOG_VERBOSE,
"File on different device skipped: `%s/%s'\n",
dirname, ent->d_name);
continue;
}
// [...]
संक्षेप में, यह कोड rename("/tmp/foo", "/tmp/foo/x") कॉल करता है जो EXDEV लौटाएगा यदि "/tmp/foo" एक माउंट पॉइंट है।
PathAuditor इस कॉल को एक संभावित कमजोरी के रूप में चिह्नित करेगा यदि "/tmp/foo" रूट के अलावा किसी अन्य उपयोगकर्ता के स्वामित्व में है।
यह समझने के लिए कि क्यों, हमें यह सोचना होगा कि जब rename syscall निष्पादित होता है तो कर्नेल में क्या होता है (सरलीकृत):
"/tmp/foo" को ट्रैवर्स करता है।"/tmp/foo/x" को ट्रैवर्स करता है।यहाँ एक रेस कंडीशन है क्योंकि "/tmp/foo" दो बार हल किया जाएगा। यदि यह उपयोगकर्ता-नियंत्रित है, तो उपयोगकर्ता किसी भी समय इसे एक अलग फ़ाइल से बदल सकता है।
विशेष रूप से, हम चाहते हैं कि "/tmp/foo" पहले एक निर्देशिका हो ताकि tmpreaper कोड में if(S_ISDIR) जांच पास हो सके। फिर हम कोड के syscall में प्रवेश करने से ठीक पहले इसे एक फ़ाइल से बदल देते हैं। जब कर्नेल पहले तर्क को हल करता है, तो वह उपयोगकर्ता-नियंत्रित सामग्री वाली एक फ़ाइल देखेगा।
अब हम इसे फिर से बदलते हैं, इस बार उसी फ़ाइलसिस्टम पर एक मनमानी निर्देशिका के लिए एक सिमलिंक के साथ। कर्नेल दूसरी बार पथ को हल करेगा, सिमलिंक का अनुसरण करेगा और नियंत्रित फ़ाइल को एक चुनी हुई निर्देशिका में ले जाएगा।
एक ही फ़ाइलसिस्टम की बाध्यता इसलिए है क्योंकि rename फ़ाइलसिस्टम के बीच काम नहीं करता है। लेकिन कुछ Linux वितरणों पर /tmp डिफ़ॉल्ट रूप से rootfs पर एक फ़ोल्डर है और आप इस बग का उपयोग किसी फ़ाइल को /etc/cron में ले जाने के लिए कर सकते हैं, जो रूट के रूप में निष्पादित होगी।
इसे आज़माने के लिए, आपको bazel के साथ libpath_auditor.so बनाना होगा और LD_PRELOAD का उपयोग करके इसे एक बाइनरी में लोड करना होगा। कोई भी उल्लंघन syslog में लॉग किया जाएगा, इसलिए सुनिश्चित करें कि आपके पास यह चल रहा है।
bazel build //pathauditor/libc:libpath_auditor.so
LD_PRELOAD=/path/to/bazel-bin/pathauditor/libc/libpath_auditor.so cat /tmp/foo/bar
tail /var/log/syslog
इसे /etc/ld.so.preload में जोड़कर सिस्टम पर सभी प्रक्रियाओं पर चलाना भी संभव है। हालांकि सावधान रहें कि यह केवल परीक्षण प्रणालियों पर अनुशंसित है क्योंकि यह अस्थिरता का कारण बन सकता है।
त्वरित शुरुआत के रूप में, आप इस प्रोजेक्ट के साथ आने वाले डॉकर कंटेनर को आज़मा सकते हैं:
docker build -t pathauditor-example .
docker run -it pathauditor-example
# LD_PRELOAD=/pathauditor/bazel-bin/pathauditor/libc/libpath_auditor.so cat /tmp/foo/bar
# cat /var/log/syslog