در ۱۱ آپریل سال ۲۰۱۹، بلاگ ZDI مقالهای با عنوان A SERIES OF UNFORTUNATE IMAGES: DRUPAL 1-CLICK TO RCE EXPLOIT CHAIN DETAILED منتشر کرد. چیزی که در این مقاله بسیار هوشمندانه است استفاده از ۳ آسیبپذیری در کنار هم به صورت زنجیرهای و در نهایت کمی خلافیت است. حال نگاهی به این آسیبپذیریها میاندازیم.
نوشتن یک فایل بدون پسوند
در مکانیزم و ساختار دروپال قوانینی وجود دارد. یکی از آنها حفظ نام تصاویر بارگذاری (upload) شده توسط کاربر است. اگر تصاویری که بارگذاری میشوند همنام باشند به ترتیب در انتهای آنها _0
و _1
اضافه خواهد شد. همچنین دروپال به منظور حفظ هماهنگی با encodingهای مختلف اقدام به تعویض نویسههایی (charecters) مینماید که مقدار آنها کمتر از 0x20
باشد.
اگرچه، اگر در نام پرونده (file) یک نویسه در بازه x80\
و xff\
باشد، PHP یک PREG_BAD_UTF8_ERROR
ارسال مینماید. اگر یک خطا رخ بدهد، تابع preg_replace
مقدار NULL باز میگرداند. و در نهایت مقدار $basename
مقدار NULL خواهد بود.
هنگامی که basename
مقدار NULL داشته باشد، محتوای پرونده زیر در یک پرونده با نام _0
نوشته خواهد شد.
طبق توضیحات داده شده، تصویر در محل زیر بارگذاری میشود.
/sites/default/files/pictures/<YYYY-MM>/
لذا آدرس نهایی تصویر به صورت زیر خواهد بود.
/sites/default/files/pictures/<YYYY-MM>/_0
حال زمانی که اجازه بارگذاری تصویر از سمت کارگزار (server) فراهم میشود و یا کاربر دسترسی نویسنده داشته باشد، حمله کننده میتواند با بارگذاری یک تصویر gif
و همان تصویر با نویسههای آلوده حمله را شروع کند. چرا که محتوای تصویر آلوده با مقدار _0
در همان محل ذخیره میگردد.
ولی اگر دسترسی به این پرونده، مستقیم باشد، احتمال دارد که اجرا نشود. علت این امر به دلایل زیر است:
- مرورگر ابتدا بر اساس
content-type
ای که از طریق کارگزار اعلام شده است، اقدام به نمایش محتوا میکند. این درحالی است که مقدارapplication/octet-stream
برای پروندههایی بدون پسوند اعلام میشود. - مرورگرها در برخورد با پروندهها از روی محتوا تصمیم گیری میکنند. به طور مثال اگر پرونده با مقدار
<html>
شروع شده باشد، برخی مرورگرها آن را به صورت پروندهhtml
در نظر گرفته و نمایش میدهند. - بعضی مرورگرها به صورت پیشفرض مقداری را برای
content-type
در نظر میگیرند ولی اکثر مرورگرها آنها را نادیده میگیرند و عملیات parse را انجام نمیدهند.
در این لحظه، نیاز داریم تا از یک خلاقیت خاص استفاده نماییم. تگ a میتواند نوع محتوا پرونده مورد نظر برای باز شدن را مشخص سازد (تنها برای مرورگر کروم این چنین نیست)
زمانی که شما به یک صفحه دسترسی داشته باشید، این صفحه به صورت یک پرونده html
نمایش داده خواهد شد و کدهای داخل آن اجرا میشوند.
1 | <html> |
زمانی که قربانی به این صفحه دسترسی پیدا کند، میتوان یک حمله از نوع xss
انجام داد. که یک موقعیت خوب برای حمله را ایجاد میکند. که در این صورت یک محیط خارجی برای اجرای js خواهیم داشت.
اجرای کد از راه دور با استفاده از phar deserialization
در کنفرانس BlackHat سال 2018، سم توماس به یک جریان api یا Stream API در PHP اشاره کرده بود. Phar یک Wrapper برای PHP است که از این جریان دادهای استفاده میکند.
محقق امنیتی Seaii در Knownsec تیم ۴۰۴ اشاره کرده بود که تمامی پروندههای توابع از stream wrapperها پیشتیبانی میکنند. همچنین اشاره کرد، اگر بتوان یک پرونده تابعی قابل کنترل و دستکاری یافت که بتوان مقادیر ورودی آن را تحت کنترل در آورد، میتوان به وسیله پرونده phar، دستور دلخواه خود را با استفاده از deserializer اجرا کرد.
در دروپال، یک تابع سیستمی وجود دارد که درباره آدرسهای ورودی تصمیم گیری میکند. is_dir
باعث بروز مشکل امنیتی در این قسمت خواهد شد.
با استفاده از کدهای زیر کد مخرب را تولید میکنیم
1 |
|
پس از ایجاد تغییر در پسوند به png و ارسال این تصویر به کارگزار، اقدام به تنظیم آن به عنوان یک file system
مینماییم.
phar://./sites/default/files/2019-04/drupal.png
و میتوان آن را اجرا کرد.