NoSQL injection
زمان مطالعه :5 دقیقه
NoSQL operator injection & Exploiting syntax injection to...
NoSQL operator injection
NoSQL injection | Web Security Academy (portswigger.net)
پایگاههای داده NoSQL اغلب از عملگرهای Query استفاده میکنند، که روشهایی برای تعیین شرایطی که دادهها باید برآورده کنند تا در نتیجه Query گنجانده شوند، ارائه میدهند. مثالهایی از عملگرهای Query در MongoDB شامل موارد زیر است:
$where - مطابقت با اسنادی که یک عبارت JavaScript را برآورده میکنند.
$ne - مطابقت با تمام مقادیر که برابر با مقدار مشخصی نیستند.
$in - مطابقت با تمام مقادیر مشخص شده در یک آرایه.
$regex - انتخاب اسنادی که مقادیر آنها با یک عبارت منظم مشخص مطابقت دارد.
شما ممکن است بتوانید عملگرهای Query را برای دستکاری Queryهای NoSQL تزریق کنید. برای انجام این کار، به صورت سیستماتیک عملگرهای مختلف را در مجموعهای از ورودیهای کاربر ارسال کنید، سپس پاسخها را برای پیامهای خطا یا تغییرات دیگر بررسی کنید.
Submitting query operators
در پیامهای JSON، میتوانید عملگرهای Query را به عنوان اشیاء تو در تو درج کنید. به عنوان مثال، {"username":"wiener"} به {"username":{"$ne":"invalid"}} تبدیل میشود.
برای ورودیهای مبتنی بر URL، میتوانید عملگرهای Query را از طریق پارامترهای URL درج کنید. به عنوان مثال، username=wiener به username[$ne]=invalid تبدیل میشود. اگر این کار نکرد، میتوانید موارد زیر را امتحان کنید:
روش درخواست را از GET به POST تغییر دهید.
Header Content-Type را به application/json تغییر دهید.
JSON را به بدنه پیام اضافه کنید.
عملگرهای Query را در JSON تزریق کنید.
توجه: شما میتوانید از افزونه Content Type Converter برای تبدیل خودکار روش درخواست و تغییر یک درخواست POST URL-encoded به JSON استفاده کنید.
Detecting operator injection in MongoDB
یک برنامه آسیبپذیر را در نظر بگیرید که یک نام کاربری و رمز عبور را در بدنه یک درخواست POST میپذیرد:
{"username":"wiener","password":"peter"}
هر ورودی را با مجموعهای از عملگرها تست کنید. برای مثال، برای تست اینکه آیا ورودی username عملگر Query را پردازش میکند، میتوانید تزریق زیر را امتحان کنید:
{"username":{"$ne":"invalid"},"password":{"peter"}}
اگر عملگر $ne اعمال شود، این همه کاربران را Query میکند که نام کاربری آنها برابر با invalid نیست.
اگر هر دو ورودی username و password عملگر را پردازش کنند، ممکن است بتوانید با استفاده از Payload زیر Authentication را دور بزنید:
{"username":{"$ne":"invalid"},"password":{"$ne":"invalid"}}
این Query تمام اطلاعات ورود را برمیگرداند که هر دو نام کاربری و رمز عبور برابر با invalid نیستند. در نتیجه، شما به عنوان اولین کاربر در مجموعه به برنامه وارد میشوید.
برای هدف قرار دادن یک حساب کاربری، میتوانید Payloadی را که شامل یک نام کاربری شناخته شده است یا نام کاربری که حدس زدهاید، بسازید. برای مثال:
{"username":{"$in":["admin","administrator","superadmin"]},"password":{"$ne":""}}
Exploiting syntax injection to extract data
در بسیاری از پایگاههای داده NoSQL، برخی از عملگرها یا توابع Query میتوانند کد JavaScript محدودی را اجرا کنند، مانند عملگر $where و تابع mapReduce() در MongoDB. این به این معنی است که اگر یک برنامه آسیبپذیر از این عملگرها یا توابع استفاده کند، پایگاه داده ممکن است JavaScript را به عنوان بخشی از Query ارزیابی کند. بنابراین، ممکن است بتوانید از توابع JavaScript برای استخراج داده از پایگاه داده استفاده کنید.
Exfiltrating data in MongoDB
یک برنامه آسیبپذیر را در نظر بگیرید که به کاربران اجازه میدهد نامهای کاربری ثبت شده دیگر را جستجو کنند و نقش آنها را نمایش دهد. این یک درخواست به URL زیر ایجاد میکند:
https://insecure-website.com/user/lookup?username=admin
این منجر به Query NoSQL زیر در مجموعه کاربران میشود:
{"$where":"this.username == 'admin'"}
از آنجا که Query از عملگر $where استفاده میکند، میتوانید تلاش کنید توابع JavaScript را به این Query تزریق کنید تا دادههای حساس را برگرداند. برای مثال، میتوانید Payload زیر را ارسال کنید:
admin' && this.password[0] 'a' || 'a''b
این اولین کاراکتر رشته رمز عبور کاربر را برمیگرداند و به شما امکان میدهد رمز عبور را کاراکتر به کاراکتر استخراج کنید.
همچنین میتوانید از تابع JavaScript match() برای استخراج اطلاعات استفاده کنید. برای مثال، Payload زیر به شما امکان میدهد تشخیص دهید که آیا رمز عبور شامل ارقام است یا نه:
admin' && this.password.match(/\d/) || 'a'=='b
Identifying field names
چون MongoDB با دادههای نیمهساختاری که نیازی به یک شمای ثابت ندارد کار میکند، ممکن است لازم باشد که قبل از استخراج دادهها با استفاده از JAVASCRIPT INJECTION، فیلدهای معتبر در مجموعه را شناسایی کنید.
به عنوان مثال، برای شناسایی اینکه آیا پایگاه داده MongoDB دارای یک فیلد رمز عبور است، میتوانید Payload زیر را ارسال کنید:
https://insecure-website.com/user/lookup?username=admin'+%26%26+this.password!%3d'
Payload را برای یک فیلد موجود و یک فیلد که وجود ندارد دوباره ارسال کنید. در این مثال، شما میدانید که فیلد username وجود دارد، بنابراین میتوانید Payloadهای زیر را ارسال کنید:
admin' && this.username!='
admin' && this.foo!='
اگر فیلد password وجود داشته باشد، انتظار میرود پاسخ مشابه پاسخ برای فیلد موجود (username) باشد، اما متفاوت با پاسخ برای فیلد که وجود ندارد (foo).
اگر میخواهید نامهای فیلدهای مختلف را تست کنید، میتوانید یک حمله دیکشنری انجام دهید، با استفاده از یک wordlist برای بررسی نامهای فیلدهای احتمالی.
نکته: میتوانید به جای این کار، از NoSQL operator injection استفاده کنید تا نام فیلدها را کاراکتر به کاراکتر استخراج کنید. این روش به شما امکان میدهد تا نام فیلدها را بدون حدس زدن یا انجام حمله دیکشنری شناسایی کنید. در بخش بعدی نحوه انجام این کار را به شما آموزش خواهیم داد.
Exploiting NoSQL operator injection to extract data
برای استخراج دادهها حتی اگر query اصلی از هیچ اپراتوری که به شما امکان اجرای JAVASCRIPTدلخواه را بدهد استفاده نمیکند، ممکن است بتوانید یکی از این اپراتورها را خودتان اینجکت کنید. سپس میتوانید از شرایط منطقی استفاده کنید تا مشخص کنید آیا برنامه هر جاوااسکریپتی که شما از طریق این اپراتور اینجکت میکنید را اجرا میکند یا نه.
Injecting operators in MongoDB
یک برنامه آسیبپذیر را در نظر بگیرید که نام کاربری و رمز عبور را در بدنه یک درخواست POST میپذیرد:
{"username":"wiener","password":"peter"}
برای تست اینکه آیا میتوانید اپراتورها را اینجکت کنید، میتوانید سعی کنید اپراتور $where را به عنوان یک پارامتر اضافی اضافه کنید، سپس یک درخواست ارسال کنید که شرط آن false باشد و دیگری که true باشد. به عنوان مثال:
{"username":"wiener","password":"peter", "$where":"0"}
{"username":"wiener","password":"peter", "$where":"1"}
اگر تفاوتی بین پاسخها وجود داشته باشد، ممکن است نشان دهد که عبارت جاوااسکریپت در clause $where ارزیابی میشود.
Extracting field names
اگر اپراتوری را اینجکت کردهاید که به شما امکان اجرای جاوااسکریپت را میدهد، ممکن است بتوانید از متد keys() برای استخراج نام فیلدهای داده استفاده کنید. به عنوان مثال، میتوانید Payload زیر را ارسال کنید:
"$where":"Object.keys(this)[0].match('^.{0}a.*')"
این متد اولین فیلد داده در شیء کاربر را بررسی میکند و اولین کاراکتر نام فیلد را برمیگرداند. این به شما امکان میدهد نام فیلد را کاراکتر به کاراکتر استخراج کنید.
Exfiltrating data using operators
به طور جایگزین، ممکن است بتوانید با استفاده از اپراتورهایی که به شما امکان اجرای جاوااسکریپت را نمیدهند دادهها را استخراج کنید. به عنوان مثال، ممکن است بتوانید از اپراتور $regex برای استخراج دادهها کاراکتر به کاراکتر استفاده کنید.
یک برنامه آسیبپذیر را در نظر بگیرید که نام کاربری و رمز عبور را در بدنه یک درخواست POST میپذیرد. به عنوان مثال:
{"username":"myuser","password":"mypass"}
میتوانید با تست اینکه آیا اپراتور $regex پردازش میشود، به شکل زیر شروع کنید:
{"username":"admin","password":{"$regex":"^.*"}}
اگر پاسخ به این درخواست با پاسخی که هنگام ارسال یک رمز عبور نادرست دریافت میکنید متفاوت باشد، این نشان میدهد که برنامه ممکن است آسیبپذیر باشد. میتوانید از اپراتور $regex برای استخراج دادهها کاراکتر به کاراکتر استفاده کنید. به عنوان مثال، Payload زیر بررسی میکند که آیا رمز عبور با حرف a شروع میشود یا نه:
{"username":"admin","password":{"$regex":"^a*"}}
فادیا مرادنژاد
مشاهده مقاله های بیشتر
مقالات مرتبط
NoSQL injection, Types of NoSQL injection, NoSQL syntax injection
زمان مطالعه :5 دقیقه
Timing based injection, Preventing NoSQL injection & NoSQL databases, NoSQL database models
زمان مطالعه :5 دقیقه
Exploiting syntax injection to extract data, Exploiting NoSQL operator injection to extract data &...
زمان مطالعه :5 دقیقه