نگاره‌هایی پیرامون امنیت، شبکه و رمزنگاری

21 مارس 2020

نزدیک به یک ماه قبل یه آسیب پذیری توی سرور های apache tomcat توسط یه فرد چینی پیدا شد. اگه بخوام خیلی خلاصه بگم، اگه روی سرور هدف، پورت ۸۰۰۹ باز باشه، مهاجم میتونه هر فایل دلخواه رو که روی سرور قرار داره بخونه (LFI) و اگر سرور به درستی تنظیم نشده باشه، میتونه روی سرور فایل آپلود کنه و خب چون میتونه اون فایل رو هم بخونه، آسیب پذیری Remote Code Execution اتفاق میوفته!

خب بریم سراغ جزییات این آسیب پذیری. همونطور که میدونین سرورهای tomcat جدا از این که از پروتکل HTTP برای ارتباط استفاده میکنن، از یه پروتکل دیگه ای به اسم AJP یا Apache Jserv Protocol هم برای ارتباطات استفاده میکنن. این نکته خیلی مهمه که بدونین این پروتکل packet-oriented هست. نکته بعدی که از اولی مهمتره اینه که بخاطر سرعت بیشتر، اطلاعاتی که رد و بدل میشن بجای این که plaintext باشن به صورت binary هستن. حالا چیزی که این پروتکل رو جذاب تر میکنه اینه که وب سرور با servlet container روی TCP ارتباطات خودشون رو برقرار میکنن و برای از بین بردن هزینه زیاد فرآیند ساخت سوکت، وب سرور کانکشنی که زده میشه رو نمیبنده و اون رو برای چرخه request و response های آینده نگه میداره. به این صورت که زمانی که کانکشنی که مربوط به یه request هست زده میشه، ازش برای ارتباطات دیگه استفاده نمیشه تا وقتی که چرخه هندل کردن مربوط به اون request مشخص به پایان برسه. به این صورت که requestهای چندگانه به یه connection وجود نداره ! حالا زمانی که یه کانکشن به سرور زده میشه، اون کانکشن میتونه تو یکی از این ۲ وضعیت زیر باشه :
Idle: به این معنی که هیچ درخواستی روی این کانکشن وجود نداره!
Assigned: یعنی کانکشن با یه request درگیر هست.

چون آسیب پذیری روی این پروتکل هستش، باید با جزییات فنی این پروتکل بیشتر آشنا بشیم، من یه سری از توضیحات رو سعی میکنم روی وایرشارک بگم که واضح تر باشه. چون میدونم جزییات این تئوری ها خیلی وقتا تو ذهن خوب نمیشینه. این رو‌ فقط اضافه کنم که این پروتکل خیلی شباهت داره به HTTP ! متودها که همون متودها هستن. ولی خب headerها فرق میکنن.

متودها توی این پروتکل هم به صورت زیر هستن:

خب بریم سراغ وایرشارک! این تصویری که پایین میبینین اولین درخواستی هست که به سمت سرور ارسال میشه.

همونطور که میبینین درخواست ما با متود GET ارسال شده و توی پاسخ، ۳ تا Response از سرور داریم دریافت میکنیم روی پروتکل AJP13 که با هم همشون رو قدم به قدم بررسی میکنیم. فقط هدف ما از این آسیب پذیری اینه که فایلی که حاوی این اطلاعات هست رو بخونیم :

قدم اول : ارسال درخواست GET

تصویر بالا نشون دهنده یه Request از پروتکل AJP13 هست. همونطور که مشخصه، توی قسمت Magic یه کد ۴ رقمی مشاهده میشه. این کد نشان دهنده اینه که درخواست جدیدی به سمت server داره ارسال میشه. اصولا این کد نشان دهنده اینه که کلاینت به سرور داره request میفرسته. تو قسمت بعدی طول درخواست رو مشاهده میکنین. کلا توی پروتکل AJP طول پیام ها خیلی مهمه. مثلا اگه شما طول پیامتون ۲۰۰ تا کاراکتر باشه، به اندازه ۲۰۰ تا کاراکتر توی سرور براش جا باز میشه و همینطور فقط اندازه ۲۰۰ تا کاراکتر از درخواست خونده میشه! (حتی اگه درخواست GET باشه ! که همونطور که میدونین توی پروتکل HTTP فقط توی درخواست های از نوع POST هدری داریم که طول درخواست رو مشخص میکنه! اما توی این پروتکل حتی طول هدر ها هم اول از همه و قبل از هرچیز دیگه ای به سمت سرور ارسال میشه) خط سوم نشون میده که درخواست از نوع FORWARD REQUEST هستش با کد شماره ۲! به صورت کلی این پیام ها میتونن تو یکی از حالت های زیر باشن.

خط های بعدی هم که مشخص هستن و فکر نمیکنم نیازی به توضیح داشته باشن. اما چیزی که برای مهمه ۲ خط آخر این درخواست هست که قسمت اصلی آسیب پذیری همین جاست!! تو این پروتکل شما جدا از این که میتونین هدرهای معمول رو ارسال کنین، میتونین یه سری attibute هم توی requestتون اضافه کنین و ارسال کنین به سمت سرور. لیست این attributeها رو میتونین توی اینجا ببینین. فرقی نمیکنه که از کدوم نسخه tomcat استفاده میشه، این ۲ تا attribute که اینجا استفاده شده تو نسخه های Servlet 3 و Servlet 4 معتبر هستن. که همونطور که مشخص هستش توی attribute دوم ما میخوایم آدرس اون فایلی که روی سرور قرار داره و ما ازش اطلاع داریم و میخوایم بخونیمش رو اینجا قرار میدیم. که مثلا من یه فایلی به اسم test.txt روی سرور ساختم و میخوام اون رو بخونم.

قدم دوم : دریافت اطلاعات از سرور و خواندن اطلاعات

همونطور که قبلا هم اشاره شد، ۳ تا response از سرور ما دریافت کردیم. response اول تو تصویر زیر قابل مشاهده ست.

اولین نکته اینه که توی همه responseها کد magic به 4142 تغییر پیدا میکنه. اون نکته ای که توی قدم اول گفتم تو اینجا همه صدق میکنه (طول هدرها. که اینجا ۱۲۱ کاراکتر هست). نکته خاص دیگه ای وجود نداره توی اولین response. فقط چیزی که اینجا مهمه اینه که فیلد Content-Length مقدار ۸۲ رو گرفته ! که میخواد بگه شما پاسخی با طول ۸۲ رو دارین دریافت میکنین و قاعدتا باید منتظر response بعدی از سمت سرور باشیم.

خب همونطور که میبینین ما تونستیم محتوای فایل test.txt رو بخونیم و چیزی که از بیرون قابل دیدن نیست رو با استفاده از ۲ تا attribute توی درخواست GET مشاهده کنیم و به هدفمون رسیدیم.

همونطور که اول داکیومنت توضیح دادم، سرور باید بعد از این که response رو دریافت که تو یکی از stateهای گفته شده بره. که با این response اخر نشون داده میشه که سرور کانکشن رو به حالت Idle میبره و منتظر requestهای بعدی از سمت کلاینت هستش!!

نتیجه گیری

همونطور که دیدین attributeهای زیادی برای Servlet وجود داره که میتونین شما هر کدوم که دوست داشته باشین تست کنین یا درباره هر کدوم مطالعه کنین. اما ترکیب ۲ attribute که باعث میشه شما از آسیب پذیری LFI بهره برداری کنین، اون هایی بود که من توی قدم اول گفتم. این قسمت مربوط به LFI بود. شما میتونین با استفاده از خلاقیت خودتون و مقداری خوش شانسی که ادمین سرور برای آپلود فایل محدودیت نذاشته باشه، میتونین هر فایل که دوست داشته باشین رو آپلود کنین و اون فایل رو فراخوانی کنین و کدتون رو اجرا کنین و …
اگر کمکی از دستم بر بیاد برام میل بفرستین یا همینجا کامنت بذارین.

محمدرضا تیموری
2 پست نوشته شده
من یه گیک ام (^__^) که اینجا درباره آسیب‌پذیری های جدیدی که پیدا کردم یا برام جالب بودن می‌نویسم.
زندگیم توی لینوکسم خلاصه میشه و بهترین دوستم کیبوردمه
ایمیل من : reza[dot]moreti[at]gmail[dot]com
  • به اشتراک بگذارید:
  1. Avatar امیر گفت:

    دوست عزیز خوو اصل درحواست با attribute LFI که چطوری آدرس test.txt رو روش ست کردی رو نذاشتی.

    بهتره محتوای درست و تکمیل ارائه بدی یا رفرنس قابل اتکا وگرنه ترجمه رو همه بلدن.

    • دوست من به نظرم شما یک بار دیگه باید پست رو بخونی، اولا که همونطوری که توی قدم اول مشاهده میکنین، اولین تصویری که گذاشته شده دقیقا همون درخواستی هست که به سمت سرور میره و attributeهای LFI توی همون درخواست میره به سمت سرور (مثلا فرض کنین که اون attributeها یه نوع هدر هستن توی HTTP) دوما هیچ داکیومنت انگلیسی، چینی یا روسی ای به این واضخی توضیح نداده که من بخوام ترجمه کنم از اون ها ! اگر این پست کوچکترین شباهتی به پست دیگه ای داشته باشه خوشحال میشم همینجا لینک رو ریپلای کنین. سوما اگر تو پیاده سازی مشکل داشتین بهم میل بدین تا بیشتر و بهتر راهنمایی تون کنم.

  2. Avatar محسن گفت:

    خیلی ممنون از آموزش مفیدتون ، ممنون میشوم درمورد اینکه چگونه نام فایل های روی سرور که درخواست میکنیم را حدس بزنیم توضیح دهید .

    • خواهش میکنم، خب معمولا فازینگ برای همچین هدفی مورد استفاده قرار میگیره ولی اگر ادمین سرور، محل فایل های حساس رو عوض نکرده باشه، شما میتونین اون فایل ها رو به راحتی بخونین (تو بیشتر موارد عوض نشده) یکی از فایلهایی که میتونه مهم باشه فایل server.xml هست که توی دایرکتوری WEB-INF میتونه وجود داشته باشه