دوره SEC542 – بخش بیست و هشتم

دوره آموزشی SEC542

در این بخش از دوره آموزشی SEC542 از موسسه SANS با مبحث Null در SQL Injection همراه شما بوده و همچنین به دستورات لازم برای این نوع حمله SQL Injection می پردازیم.

قدرت NULL

عنصر موثر دیگر در برقرار ساختن پیش‌نیازهای UNION ، NULL است. دومین پیش‌نیاز این بود که انواع داده ستون‌ها با هم سازگار باشند (نیازی نیست حتما یکی باشند). اکثر افراد فکر می‌کنند که رشته‌ها و اعداد با هم ناسازگارند در حالی که RDBMS به راحتی می‌تواند این دو نوع را به هم تبدیل کند.

با دانستن این مطلب، کار ما راحت خواهد بود. با استفاده از NULL ، این کار راحت‌تر نیز می‌شود. NULL هیچ نوع داده خاصی ندارد بنابراین با هر نوع داده‌ای می‌تواند همراه شود.

همچنین می‌توانیم از NULL در دستورات SELECT خود استفاده کنیم.

در ادامه مبحث Null در SQL Injection به تعریف نحوه استفاده از آن می پردازیم.

UNION و NULL

با ترکیب NULL با SELECT بدون FROM ، می‌توانیم تعداد ستون‌ها و نوع داده آن‌ها را بدست آوریم. ابتدا سعی می‌کنیم تعداد ستون را مشخص کنیم.

SELECT * FROM Users WHERE lname=’Dent’ UNION SELECT NULL;– ‘;
SELECT * FROM Users WHERE lname=’Dent’ UNION SELECT NULL,NULL;– ‘;
SELECT * FROM Users WHERE lname=’Dent’ UNION SELECT NULL,NULL, NULL;– ‘;

هرکدام از دستورات بالا، موجب تولید خطای زیر می‌گردند:

حمله SQL Injection

SELECT * FROM Users WHERE lname=’Dent’ UNION SELECT NULL,NULL, NULL,NULL;– ‘;

آسیب پذیری SQL Injection

نکته: این روش، در دستورات INSERT هم مورد استفاده قرار می‌گیرد.

متدی دیگر برای مشخص کردن تعداد ستون‌ها، تزریق عبارت ORDER BY می‌باشد. آنقدر تعداد ستون‌ها را افزایش دهید تا خطایی مبنی بر “استفاده از ORDER BY برای تعداد ستون ناموجود”، دریافت کنید.

انوع داده‌ها

در بخش قبل توانستیم با استفاده از NULL ، موقتا از نوع داده‌ها چشم‌پوشی کرده و تعداد ستون‌ها را بدست آوریم. بدین ترتیب با استفاده از پیلود زیر و استفاده از 4 NULL، فهمیدیم که تعداد ستون‌های مثال ما 4 می‌باشد.

Dent’ UNION SELECT NULL,NULL,NULL,NULL;–

در این مرحله، می‌خواهیم با استفاده از UNION دیتا برگردانیم. بنابراین نیاز داریم نوع داده را بدست آوریم. معمولا به حداقل یک ستون نیاز داریم که بتواند نوع داده رشته (string) را برگرداند.

آشنایی با حمله Stacked Queries SQLi

برای این کار، در کوئری قبلی خود، با جایگزین کردن هر NULL با یک رشته (مثلا ‘42’)، تک به تک ستون‌ها را بررسی کرده تا نقطه ورودی را بیابیم که خطا تولید نکند.

Dent’ UNION SELECT ‘42’,NULL,NULL,NULL;–

دستیابی به دیتا با UNION

همانطور که گفتیم، آخرین پیش‌نیاز برای یک UNION injection موفق، دانستن جداول و ستون‌های مورد هدف بود. بحث‌های قبلی در خصوص fingerprint کردن، روش‌های ممکن برای پیدا کردن نام دیتابیس، جداول و ستون‌ها را به ما نشان داد.

حالا برای گرفتن دیتا، بر روی ستون ها و جدول‌های جالب‌تر و مهم‌تر تمرکز می‌کنیم.

با بکارگیری تکنیک UNION، می‌توانیم به تمام دیتابیس‌هایی که کاربر جاری دیتابیس، حق دسترسی به آن‌ها را دارد، دست یابیم. استفاده از یک ابزار مناسب در اکسپلویت این آسیب‌پذیری، به دقت و سرعت ما کمک زیادی می‌کند.

دستیابی به دیتا بصورت Blind

اکسپلویت کردن blind SQL injection بصورت دستی و بدون ابزار، کاری دشوار و زمان‌بر است. زیرا باید دیتا را کاراکتر به کاراکتر، از طریق تکنیک‌های شرطی/استنتاجی استخراج کنیم.

روش پیشنهادی ما، استفاده از ابزارهای اتوماتیک مانند sqlmap است. این ابزار در اکسپلویت آسیب‌پذیری‌های SQLi بخصوص از نوع time based بسیار مفید است.

دستیابی به دیتا از طریق استنتاج Blind Boolean

ما قبلا راجع به این نوع از injection که شامل substring می‌شود، صحبت کردیم. به خاطر بیاورید که روش‌های ریاضیاتی متفاوتی در تکنیک‌های استنتاجی وجود دارد.

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

Round 1: (First: A ; Last: Z ; Key: M), Round 2: (First: A ; Last: M ; Key: G), …

Query: SELECT * FROM Users WHERE lname=’our input’;
Binary Condition: TRUE = Dent Info and FALSE = Employee not found
SQLi Prefix: Dent’ AND
SQLi Suffix: ;#

Binary Inject 1: substr((select table_name from information_schema.tables limit 1) ,1,1) > “m”
Binary Inject 2: substr((select table_name from information_schema.tables limit 1) ,1,1) > “g”
Results: “No employee found” = FALSE

حمله SQL Injection


Binary Inject 4: substr((select table_name from information_schema.tables limit 1) ,1,1) > “b”
Binary Inject 5: substr((select table_name from information_schema.tables limit 1) ,1,1) > “c”
Result 1: “Name:Arthur Dent” = TRUE

آسیب پذیری SQL Injection

در گام بعد، با تزریق substr((… limit 1) ,2,1) > “m” ، کاراکتر دوم را بدست می آوریم.

فراتر از دستیابی به دیتا

بدون شک رایج‌ترین و پرکاربردترین اکسپلویت در باگ‌های SQL injection ، استخراج دیتا است. نشت اطلاعات سازمان‌ها می‌تواند خسارات مالی و معنوی زیادی برای آن‌ها به بار بیاورد.

با این حال، آسیب‌پذیری‌های SQLi می‌توانند عواقب و تاثیرات دیگری نیز داشته باشند. لازم است درک اولیه‌ای از این تاثیرات داشته باشیم. این موضوع زمانی اهمیت می‌یابد که یک سازمان اعلام می‌کند محرمانگی اطلاعات بدست آمده برایش مهم نیست.

موارد بسیاری وجود دارد که دیتای بدست آمده از طریق SQLi یک دیتای عمومی بوده و یا ارزش زیادی برای سازمان ندارد. آیا در این موارد SQLi می‌تواند خطرناک باشد؟ البته که جواب مثبت است.

ما به جزئیات اجرای حملات مختلف با SQLi نمی‌پردازیم. همانطور که مهاجم از کارکرد مورد انتظار در یک RDBMS فاصله گرفته و حمله خود را گسترش می‌دهد، همه چیز پیچیده‌تر شده و بستگی زیادی به نوع ساختار backend اپلیکیشن پیدا می‌کند.

خوشبختانه، مهم‌ترین دیدگاه این است که از احتمالات موجود و گزینه‌های در دسترس خود برای پیشبرد حملات SQLi آگاه باشیم.

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

درباره نویسنده: احسان نیک آور

ممکن است دوست داشته باشید