
مُدقق وظائف مكتبة libc زمن التنفيذ الذي يكتشف حالات السباق في الوصول إلى الملفات وثغرات الروابط الرمزية عن طريق ربط استدعاءات نظام الملفات عبر LD_PRELOAD، مع تسجيل مسارات تصعيد الامتيازات المحتملة.
PathAuditor هي أداة مصممة للعثور على ثغرات متعلقة بالوصول إلى الملفات عن طريق تدقيق وظائف libc.
الفكرة تقريبًا كالتالي:
نحن نستخدم LD_PRELOAD لربط جميع استدعاءات المكتبات المتعلقة بنظام الملفات وتسجيل أي مخالفات يتم مواجهتها في syslog.
هذا ليس منتجًا مدعومًا رسميًا من Google.
دعنا نلقي نظرة على مثال لنوع الثغرة التي يمكن لهذه الأداة اكتشافها. كانت CVE-2019-3461 خطأ في tmpreaper، وهي أداة تجتاز /tmp وتحذف الملفات القديمة. تُشغَّل عادةً كوظيفة cron بصلاحيات الجذر. نظرًا لأنها لا تريد حذف الملفات خارج 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 (مبسط):
"/tmp/foo" للوسيطة الأولى."/tmp/foo/x" للوسيطة الثانية.هناك حالة سباق هنا حيث سيتم حل "/tmp/foo" مرتين. إذا كان تحت سيطرة المستخدم، يمكن للمستخدم استبداله بملف مختلف في أي وقت.
على وجه الخصوص، نريد أن يكون "/tmp/foo" دليلاً في البداية لاجتياز فحص if(S_ISDIR) في كود tmpreaper. ثم نستبدله بملف قبل أن يدخل الكود إلى استدعاء النظام. عندما تحل النواة الوسيطة الأولى، سترى ملفًا بمحتوى يتحكم فيه المستخدم.
الآن نستبدله مرة أخرى، هذه المرة برابط رمزي إلى دليل عشوائي على نفس نظام الملفات. ستحل النواة المسار مرة ثانية، تتبع الرابط الرمزي وتنقل الملف المتحكم به إلى دليل مختار.
القيود المتعلقة بنفس نظام الملفات لأن rename لا يعمل بين أنظمة الملفات. لكن في بعض توزيعات Linux، /tmp هو مجرد مجلد على rootfs افتراضيًا، ويمكنك استخدام هذا الخطأ لنقل ملف إلى /etc/cron، والذي سيتم تنفيذه بصلاحيات الجذر.
لتجربته، تحتاج إلى بناء libpath_auditor.so باستخدام bazel وتحميله في برنامج ثنائي باستخدام 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 المرفقة مع هذا المشروع:
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