Zip Slip یک آسیبپذیری شایع و مهم در بازنویسی فایل است که معمولا به اجرای دستورات به صورت Remote میانجامد. این آسیبپذیری که پیش از اعلان عمومی در تاریخ ژوئن 2018 بود، توسط تیم Snyk Security شناسایی و آشکار گشت، روی هزاران پروژه از جمله پروژههای HP، Amazon، Apache، Pivotal و بسیاری از موارد دیگر تاثیر میگذارد. البته این نوع از آسیبپذیری در گذشته نیز وجود داشته اما اخیرا به طرز قابل توجهی در پروژهها و Libraryها مشاهده شده است.
این آسیبپذیری با اینکه در JavaScript، Ruby، NET. و Go و مانند آنها رویت شده اما بیش از همه در Java شایع میباشد چراکه هیچ Library مرکزی برای پردازش قوی بر روی فایلهای آرشیو (مانند zip) وجود ندارد. عدم وجود چنین Library منجر به آن شده که نمونههای کد آسیبپذیری به صورت دستساز ایجاد و در بین اجتماعهای توسعهدهنده مانند StackOverflow به اشتراک گذاشته شوند.
این آسیبپذیری با استفاده از آرشیوی که برای این کار طراحی شده و مسیر پیمایش فایل در دایرکتوری (مثلا ../../evil.sh) را نگهداری میکند، ایجاد میگردد. آسیبپذیری Zip Slip میتواند روی چندین فرمت آرشیو از جمله، tar، jar، war، cpio، apk، rar و 7z تاثیر بگذارد.
Zip Slip نوعی پیمایش در دایرکتوری محسوب میشود که میتوان با خروجی گرفتن از فایلهای آرشیو، آن را آلوده نماید. فرضیه آسیبپذیریِ پیمایش در دایرکتوری این است که یک مهاجم میتواند به بخشهایی از فایل سیستم، خارج از پوشهی مقصدی که باید در آن قرار داشته باشند، دسترسی پیدا کند. مهاجم میتواند فایلهای قابل اجرا را بازنویسی کرده، سپس به صورت Remote آنها را اجرا کند و یا منتظر بماند تا سیستم یا کاربر آنها را فرا بخواند؛ و در نتیجه، اجرای دستور به صورت Remote روی دستگاه قربانی انجام میگردد. این آسیبپذیری همچنین میتواند با بازنویسی فایلهای پیکربندی یا دیگر منابع حساس، صدماتی را ایجاد کند و میتواند باعث آلودگی ماشینها و سرورهای کاربر شود.
دو بخش موردنیاز برای ایجاد کردن این آسیبپذیری، یک آرشیو مخرب و کد خروجی است که مراحل اعتبارسنجی را انجام نمیدهند. این موارد را بهترتیب بررسی میکنیم: قبل از هر چیز، محتویات فایل فشرده باید دارای یک یا چند فایل باشد که در هنگام Extract شدن، از دایرکتوری مقصد خارج میگردند. در مثال زیر میتوان محتویات یک فایل فشرده را مشاهده کرد. این فایل فشرده دارای دو بخش است، یک فایل good.sh که داخل دایرکتوری مقصد Extract میشود و یک فایل evil.sh که سعی دارد در درخت دایرکتوری پیمایش کند تا به Root برسد و سپس فایلی را به دایرکتوری tmp اضافه کند. وقتی میخواهید در دایرکتوری Root دستور cd .. را اجرا کنید، همچنان در دایرکتوری Root باقی میمانید، در نتیجه مسیر مخرب میتواند حاوی سطوح بسیاری از /.. باشد تا پیش از اقدام برای پیمایش به سمت فایلهای حساس، شانس بیشتری برای دستیابی به دایرکتوری Root وجود داشته باشد.
Tue Jun 5 11:04:29 BST 2018 good.sh
Tue Jun 5 11:04:42 BST 2018 ../../../../../../../../tmp/evil.sh
محتویات این فایل فشرده، باید به صورت دستساز طراحی گردند. ابزارهای ساخت فایلهای فشرده معمولا به کاربران اجازهی اضافه نمودن فایل به این مسیرها را نمیدهند با این حال خصیصهی فایل ZIP اجازه میدهد. با این حال، با وجود نرمافزارهای مناسب، ایجاد فایل در این مسیرها کار سادهای است.
مورد دومی که برای آلوده شدن با این آسیبپذیری لازم است، Extract کردن آرشیو با استفاده از کد متعلق به خود فرد و یا یک Library است. این آسیبپذیری زمانی وجود دارد که کد خروجی، اعتبارسنجی در مسیرهای فایلِ آرشیو را حذف کند. مثالی از بریدهای از کد آسیبپذیر (مثال در جاوا نشان داده شده است) در ادامه قابل مشاهده است.
Enumeration<ZipEntry> entries = zip.getEntries();
while (entries.hasMoreElements()) {
ZipEntry e = entries.nextElement();
File f = new File(destinationDir, e.getName());
InputStream input = zip.getInputStream(e);
IOUtils.copy(input, write(f));
}
در خط 4، e.getName با دایرکتوری مقصد، dir دارای پیوستگی است، بدون اینکه تایید اعتبار شده باشد. در این زمان، وقتی که آرشیو زیپ به evil.sh برسد، مسیر کامل (شامل تمام /.. ها) ورودی زیپ را به دایرکتوری مقصد اضافه مینماید و در نتیجه evil.sh خارج از دایرکتوری مقصد نوشته میشود.
مشخصات کاربر آسیبپذیر
کاربر در صورتی آسیبپذیر است که از یک Library حاوی آسیبپذیری Zip Slip استفاده کند یا اینکه پروژهاش به طور مستقیم حاوی کد آسیبپذیری باشد که بدون طی کردن مراحل تایید اعتبار لازم در دایرکتوری، فایلهایی را از یک آرشیو خروجی میگیرد. تیم Snyk تمام پروژههای آسیبپذیر نسبت به Zip Slip را شناسایی و در سایت GitHub معرفی کردهاند و زمان و نسخهی اصلاح شدهی آنها را نیز فهرست نمودهاند. مجموعهی گستردهای از افراد میتوانند در این فهرست مشارکت کنند تا اطمینان حاصل شود که فهرست دارای بهروزترین وضعیت است.
اقدامات لازم برای شناسایی آسیبپذیری
مراحلی که کاربر میتواند طی آن بررسی کند که زیرمجموعههای کد پروژهاش حاوی آسیبپذیری Zip Slip است یا خیر، به شرح زیر میباشد:
1. جستجو در بین پروژه مربوطه برای یافتن کدهای آسیبپذیر
در هر بخش از اکوسیستم، مثالهایی از بریدههای کدی که آسیبپذیری خاصی را نشان میدهند قابل مشاهده است. کد تایید اعتبار همراه را میتوان به بریدهی کد آسیبپذیر اضافه کرد تا این مراحل در دایرکتوری تست گردد. کاربر باید در کد خود به دنبال الگوهای خروجی مشابه بگردد و اطمینان حاصل کند که در نسخههای اصلاحشدهی Libraryها قرار دارد، که آسیبپذیری آنها کشف شده است.
2. اضافه کردن Zip Slip Security Testing به Pipeline نسخهی (Build) برنامهی کاربردی
اگر کاربر تمایل به جستجو به صورت مستقیم و انتقال یافته ی آسیبپذیریهای (که ممکن است صدها مورد وجود داشته باشد.) خود نداشته باشد، میتواند از یک ابزار بررسی برای وابستگیِ آسیبپذیری، مانند Snyk استفاده کند. اضافه کردن تستهای امنیتی به مراحل روند تکامل، مثلا در زمان توسعه، CI، پیادهسازی و تولید، اقدام مناسبی است. کاربر میتواند پروژههای خود را (تمام اکوسیستمهایی که در بالا به آنها اشاره شده پشتیبانی میشوند) تست کند تا مشخص گردد که آیا نسبت به Zip Slip آسیبپذیر هستند یا خیر.
دیگر پروژههای آسیبپذیر
پروژههای آسیبپذیر شامل پروژههایی در اکوسیستمهای متفاوت است که یا از Libraryهایی استفاده میکنند که در بالا به آنها اشاره شد و یا به طور مستفیم حاوی کد آسیبپذیر میباشند. از بین هزاران پروژهای که حاوی نمونههای کد آسیبپذیر مشابه بودهاند یا به Libraryهای آسیبپذیر دسترسی داشتهاند، حائز اهمیتترین آنها عبارتاند از: Oracle، Amazon، Spring/Pivotal، Linkedin، Twitter، Alibaba، Jenkinsci، Eclipse، OWASP، SonarCube، OpenTable، Arduino، ElasticSearch، Selenium، JetBrains و Google.