حملات SQLi (بررسی مقدمات و UNION-Base SQLi)

برای شما

سلام من علی هستم

امروز تصمیم گرفتم مطالبی که از مطالعه چند کتاب و خوندن مقالات مختلف راجع به حملات تزریق SQL یاد گرفتم رو توی چند سری نوشته ویرگول بنویسم .

حملات تزریق SQL چیه ؟

ببینیم ویکی پدیا چی گفته :

طبق تعریف ویکی پدیا حمله تزریق SQL در واقع یه مدل حمله تزریق کد هستش که هکر کد های مخرب به زبان SQL رو به یک ورودی آسیب پذیر تزریق میکنه و اون برنامه (Web Application) کد مخرب SQL مد نظر هکر رو اجرا میکنه و هکر میتونه برای اهداف مختلفی ازش استفاده کنه که توی عکس زیر توضیح داده ?

چی باعث بوجود اومدن باگ SQLi میشه ؟

اول باید بگیم که دلیل بوجود اومدن این باگ مشکل داشتن وب سرور یا پایگاه داده نیست بلکه مشکل از برنامه نویسی و توسعه Web Application هستش و مشکل درست فیلتر نکردن ورودی هاست ، دلیلش هم آگاهی پایین برنامه نویس از نحوه کار این حمله و یا بی دقتی برنامه نویس و حتی باید بگیم بعضی برنامه نویس ها اصلا هیچی در مورد این باگ نمیدونن ،‌صرفا کد میزنن که کار کنه اصلا به مباحث امنیتی کار دقت نمیکنن (کد نویسی امن چیست ؟)


بررسی حملات SQLi ( SQL injection ):

اول از همه باید بگیم که برای درک نحوه کار این باگ و جلوگیری ازش و پچ کردنش نیاز داره که شما حداقل با دیتابیس های رابطه ای و زبان SQL که برای کار با اون دیتابیس ها استفاده میشه آشنایی کافی داشته باشد.

به صورت کلی SQLi به سه دسته تقصیم میشه (اسکرین شات از این کتابه ) :

عکس ۱
عکس ۱

خب ما از اولین نوع یعنی یونیون-بیس شروع میکنیم و اول یه توضیحی روش میدیم و سپس یه مثال ازش حل میکنیم:

ما فعلا MySQL ورژن ۵ به بالا رو بررسی میکنیم

نوع اول : Union-Based SQL Injection

طبق عکس ۱ این نوع اولا شایع ترین نوع این حمله SQLi هستش و دوما میاد از دستور UNION توی زبان SQL استفاده میکنه خب بهتره که اول بدونیم دستور UNION چیکار میکنه

دستور UNION چیکار میکنه ؟ اول میریم از گوگل میپرسیم و گوگل w3schools رو پیشنهاد میده خب ببینیم چی میگه این سایت :

https://www.w3schools.com/sql/sql_union.asp

SQL UNION Operator
SQL UNION Operator
W3Schools offers free online tutorials, references and exercises in all the major languages of the web. Covering popular subjects like HTML, CSS, JavaScript, Python, SQL, Java, and many, many more.

داره بهمون میگه که دستور UNION استفاده میشه برای ترکیب کردن نتایج ۲ یا چند دستور SELECT که یکسری شروط هم باید وجود داشته باشه برای این که بتونیم ازش استفاده کنیم :

– باید در نتایج همه دستور های SELECT ،‌ تعداد ستون ها برابر باشند
– باید در نتایج همه دستور های SELECT ، ستون ها همه نوع داده یکسان داشته باشن
– ترتیب ستون های هر دستور SELECT هم یکی باشه

فرض کنید یک دیتابیس رابطه ای داریم که ۲ جدول داره به نام های Customers و Suppliers که توی تصاویر زیر میبینیم :

جدول Customers
جدول Customers
Suppliersجدول
Suppliersجدول

همون طوری که مشاهده میکنید هر جدول تعدادی ستون داره مثل SupplierID و SupplierName و … که به این ها میگن –> columns

و همچنین یکسری سطر میبینیم که اطلاعات جدول ما هستن که بهشون میگن –> rows

برای این که یه درک ذهنی (نه لزوما درست ) توی ذهنمون ایجاد بشه میتونیم بگیم یک جدول (table) توی پایگاه داده رابطه ای شبیه یک فایل اکسل هستش.

خب حالا میخوایم از UNION روی این دو جدول استفاده کنیم تا کامل جا بیوفته

1234SELECT City FROM Customers
UNION
SELECT City FROM Suppliers
ORDER BY City;

این قطعه کد SQL چی میگه ؟

داره میگه از جدول Customers و از ستون City تمام سطر هارو استخراج کن و از جدول Suppliers هم اینکارو بکن و این دو رو UNION کن یعنی چی؟

یعنی خروجی ما چی میشه ؟

خروجی ما یونیون (پیوند) شده ستون City از اون دو جدوله که حاوی تمام سطر های ستون City اون دو جدوله یعنی این شکلی ?

خب این یه درک اولیه از مفهوم UNION بود

دو مورد دیگه هم از این دستور SQL بررسی میکنیم و میریم سراغ مثال عملی

یونیون آل (UNION ALL)

این دستور در واقع اگه چند سطر از دو جدول چند بار تکرار شده بودن همرو در نظر میگیره و سطر های تکراری رو حذف نمیکنه

و بالاخره بخش اصلی که باید بدونیم ?

یونیون به همراه WHERE

اگه به این قطعه کد دقت کنیم ما میتونیم یک SELECT و WHERE بعد UNION اعمال کنیم که ما از این بحث برای تزریق SQL استفاده میکنیم برگردیم به کتابی که قبلا اشاره کردم بهش و بعدش عملی روی یک Lab آزمایش کنیم


چجوری این باگ رو تشخیص بدیم روی یک سایت یا برنامه تحت وب؟

اولا باید تمام ورودی ها رو بررسی کنیم ببینیم فیلتر شدن یا نه ؟

دوما ربطی به GET یا POST بودن درخواست HTTP هم نداره هر دو میتونن آسیب پذیر باشن

سوما میتونه این حمله از طریق کوکی ها یا HTTP Header ها هم اتفاق بیوفته

برای تست این آسیب پذیری ما اول باید ‘ و ” و ‍‍‍‍‍` رو توی ورودی مشکوکمون تست کنیم و ببینیم Web Application چه واکنشی نشون میده که اغلب وب اپلیکیشن آسیب پذیر به مورد اول واکنش نشون میده اگه اروری روی صفحه نمایش داده شد یعنی این آسیب پذیری صد درصد وجود داره

البته اگه ارور نشون نداد به معنی این نیست که برنامه تحت وب آسیب پذیر نیست (مربوط به بحث SQLi کور !)


تشخیص نوع تزریق (عدد صحیح یا رشته ای ؟)

در حالت اول نیازی به کوتیشن نیست و میتونیم مستقیم SQL تزریق کنیم و در حالت دوم نیازه که از کوتیشن استفاده کنیم و در نهایت با کامنت کردن ادامه کوعری خود Web Application از اجرای کوعری اصلی برنامه جلوگیری کنیم و فقط کوعری مد نظر خودمون اجرا بشه یدونه + هم میذاریم آخرش تا یدونه فاصله بیوفته آخر چیزی که تزریق کردیم و — به چیزی نچسبه و با موفقیت عبارت بعد خودشو کامنت کنه

فاز عملی UNION-Based SQLi

فرض کنید کد PHP زیر و این دیتابیس رو داریم

گفتیم فاز اول حمله ما باید بررسی ورودی ها باشه

خب تست میکنیم

ارور گرفتیم پس ورودی id به SQLi آسیب پذیره

خب گفتیم که برای استفاده از دستور UNION باید ستون های خروجی دستورات SELECT برابر باشند ولی اینجا ما نمیدونیم تعداد ستون ها چند تاست پس با آزمون و خطا تعدادشونو پیدا میکنیم یک ترفند سریع برای این کار وجود دارد و استفاده از ORDER BY هستش

از نوشته این سایت متوجه میشیم که :

The SQL ORDER BY clause is used to sort the data in ascending or descending order, based on one or more columns. Some databases sort the query results in an ascending order by default.

یعنی این دستور میاد بر اساس تعداد ستون که بهش میگیم به صورت صعودی یا نزولی نتایج رو به ما نشون میده و اگه مثلا فرض کنیم دستور های SELECT ما ۳ ستون رو میخوان واکشی کنن و ما ORDER BY بکنیم تعداد 4 رو ، چون خروجی کوعری SELECT این تعداد ستون نداره ارور دریافت میکنیم

پس چیکار میکنیم : یه تعداد بالا به ORDER BY میدیم و با آزمون و خطا هی کمش میکنیم وقتی به مقداری رسیدیم که ارور دریافت نکردیم یعنی تعداد ستون ها رو پیدا کردیم بریم تست کنیم :

این تعداد ستون واکشی نمیکنه دیگه چون غیر معموله

سورس رو چک میکنیم میبینیم توی کوعری * گذاشته یعنی از روی سورس نمیتونیم متوجه بشیم تعداد ستون هارو پس بازم تست میکینم

با تعداد ستون 4 ارور گرفتیم پس چهار تا ستون نداریم و با ۳ ستون ارور نمیگیریم پس در نتیجه جمعا ۳ ستون رو دستورات SELECT واکشی میکنن

البته با GROUP BY هم میشه تعداد ستون هارو شمرد که میتونید گوگلش کنید (در صورت وجود WAF)

حالا میدونیم که ۳ تا ستون داریم و String-Base هستش بریم و با کمک UNION به همراه SELECT و WHERE اطلاعات دیتابیس ها و جدول ها و سطر هاشون رو استخراج کنیم

توی این بحث به ستون هایی آسیب پذیر میگیم که نتایجشون روی صفحه چاپ بشه

و از UNION ALL استفاده میکنیم تا داده تکراری ای از قلم نیوفته

1http://localhost/sqli/less-1/index.php?id=-3' UNION ALL SELECT 1,2,3 --+ 

الان دو تا کار کردیم یکی قسمت سمت چپ رو با گذاشتن یدونه منفی قبل 3 خنثی کردیم تا قسمت سمت راست که وارد کردیم اجرا بشه و دیدیم که از کل مقادیری که SELECT از MySQL درخواست میکنه فقط دو مقدار رو روی صفحه نمایش میده (ستون های آسیب پذیر)

خب حالا از همین دو تا شروع میکنیم به استخراج هر چی میخوایم اینجوری هم میشد سمت چپ رو خنثی کرد با وارد کردن یک عبایرت ریاضی با ارزش False

1http://localhost/sqli/less-1/index.php?id=3' AND 11=12 UNION ALL SELECT 1,2,3 --+ 

بیرون کشیدن اطلاعاتی مثل کاربر دیتابیس،نام دیتابیس،ورژن دیتابیس

1http://localhost/sqli/less-1/index.php?id=-3' UNION ALL SELECT 1,USER(),DATABASE() --+ 

توی عکس بالا میبینیم که USER دیتابیس ما root هستش این یعنی این که ما قدرت root داریم و خیلی بعدا به دردمون میخوره


اینفورمیشن اسکیما چیه ؟ (Information_schema)

ببینیم کتاب چی گفته :

در واقع یک دیتابیس فقط خواندنی هستش که اطلاعات همه دیتابیس هارو نگه میداره از قبیل نام تیبل ها نام ستون ها و دسترسی هایی که هر کاربر دیتابیس داره و این که هر کاربر به چه تیبیل هایی دسترسی داره و باهاشون چیکار میتونه بکنه و چون ما الان روت هستیم به همه جدول ها دسترسی داریم

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

  • Information_schema.schemata

این جدول حاوی اطلاعات تمام دیتابیس های موجود در MySQL Server ‌رو میده

  • Information_schema.tables

این جدول حاوی اطلاعات تمام جدول های تمام دیتابیس هاست

  • Information_schema.columns

این جدول حاوی اطلاعات تمام ستون های تمام جدول های تمام پایگاه داده هاست


چگونه نام دیتابیس هارو استخراج کنیم ؟

گفتیم که کجا قرار دارن؟ توی جدول schemata از پایگاه داده اینفورمیشن اسکیما

پس با یدونه UNION SELECT استخراجشون میکنیم

ما فقط به ستون SCHEMA_NAME نیاز داریم دیگه پس :

1http://localhost/sqli/less-1/index.php?id=-3' UNION ALL SELECT 1,2,SCHEMA_NAME from information_schema.schemata --+ 

الان فقط یک مورد رو به ما نشون میده و ما باید تک تک پیمایش کنیم چجوری ؟

من این راه حل رو پیدا کردم

1http://localhost/sqli/less-1/index.php?id=-3' UNION ALL SELECT 1,2,SCHEMA_NAME from information_schema.schemata LIMIT 100 OFFSET 0 --+ 
1http://localhost/sqli/less-1/index.php?id=-3' UNION ALL SELECT 1,2,SCHEMA_NAME from information_schema.schemata LIMIT 100 OFFSET 4 --+ 

چگونه Table هارو بیرون بکشیم ؟

فهمیدیم نام دیتابیسی که برنامه داره ازش استفاده میکنه security هستش

بازم میریم سراغ دیتابیس اینفورمیشن اسکیما و با کمک UNION , SELECT و WHERE که اول نوشته اشاره کردیم اطلاعات جدول های هر دیتابیس که خواستیمو بیرون بکشیم

1http://localhost/sqli/less-1/index.php?id=-3' UNION ALL SELECT 1,2,table_name from information_schema.tables where table_schema="security" LIMIT 100 OFFSET 0 --+ 

باز هم چون در هر لحظه یک نتیجه به ما نشون میده پس ما میایم از لیمیت و آفست استفاده میکنیم (البته آزمایشگاهی من الان دارم روش تست میکنم اینجوریه توی بقیه تارگت ها شاید خودش همه نتایج رو نشون بده و نیاز به تک تک دیدن نباشه البته ما وقتی اصول کار رو یادگرفتیم دیگه دستی نمیرنیم میدیم برنامه هایی مثل sqlmap اینکارو بکنن برامون )

و همون طوری که میبینید تک تک بهمون نشون میده جدول های دیتابیس security رو

چگونه ستون های هر جدول رو استخراج کنیم؟

مثل قبل با یکمی تغییرات

1http://localhost/sqli/less-1/index.php?id=-3' UNION ALL SELECT 1,2,column_name from information_schema.columns where table_schema="security" LIMIT 100 OFFSET 5 --+ 

چون این LAB به گونه ای طراحی شده که هر لحظه یک نتیجه رو نشون میده من از افست و لیمیت استفاده کردم و گرنه توی بقیه تارگت ها اینجور ممکنه نباشه

استخراج مقادیر از هر ستون دلخواه

اول باید بدونیم group_concat چیکار میکنه

https://www.geeksforgeeks.org/mysql-group_concat-function/

MySQL | Group_CONCAT() Function - GeeksforGeeks
MySQL | Group_CONCAT() Function – GeeksforGeeks
A Computer Science portal for geeks. It contains well written, well thought and well explained computer science and programming articles, quizzes and practice/competitive programming/company interview Questions.

The GROUP_CONCAT() function in MySQL is used to concatenate data from multiple rows into one field.

در واقع میاد تمام اطلاعات سطر هایی که خودمون بهش میگیم رو به هم میچسبونه و به یک فیلد تبدیل میکنه و به میده

فرض کن میخوایم اطلاعات هر فیلد این جدول رو بیرون بکشیم

جدولمون چیه ؟ –> security.users

چیارو میخوایم ؟ –> یوزر نیم و پسورد –> group_concat(username , 0x3a , password)

پس پیلود ما به این شکل میشه

1http://localhost/sqli/less-1/index.php?id=-3' UNION ALL SELECT 1,2,group_concat(username,0x3a,password) from security.users --+ 

صفر ایکس تری ای (0x3a) –> :

این بخش به پایان رسید

بخش نظرات منتظرتون هستم

نویسنده مطلب: Ali Gholami

منبع مطلب

به فکر سرمایه‌گذاری هستی؟

با هر سطحی از دانش در سریع‌ترین زمان با آموزش گام به گام، سرمایه گذاری را تجربه کن. همین الان میتونی با لینک زیر ثبت نام کنی و ۱۰ درصد تخفیف در کارمزد معاملاتی داشته باشی

ثبت نام و دریافت جایزه
ممکن است شما بپسندید
نظر شما درباره این مطلب

آدرس ایمیل شما منتشر نخواهد شد.