
در این بخش از دوره آموزشی تست نفوذ سطح متوسط که برگرفته از دوره SEC642 می باشد به ادامه مبحث آشنایی با SQL Injection می پردازیم.
SQL Injection : Data Exfiltration
اکنون که ما یک روش برای تزریق Query با استفاده از تزریق SQL داریم، بر تکنیکهای استخراج دادهها تمرکز میکنیم. این تکنیکها از پرس و جوهای متناسب با روش تزریق ما استفاده میکنند و ما را قادر میسازند تا دادهها را از پایگاهداده پشتیبان سرور هدف بازیابی کنیم.
ما در درجه اول به تزریق SQL کور یا Blind با چند تکنیک غیرکور ارائهشده در مقابل نگاه میکنیم.
این تکنیکها بر اساس خروجی ارائه شده توسط برنامه کاربردی وب طبقه بندی میشوند. هرچه خروجی بیشتری از پایگاه داده بکاند در پاسخ برنامه وب به پرس و جوهای ما قابل مشاهده باشد، استخراج داده ها راحت تر خواهد بود و برای انجام این کار باید از کوئریهای کمتری استفاده شود.
با هر تکنیک، مقدار خروجی بازگشتی توسط برنامه هدف را محدود میکنیم و توضیح میدهیم که چگونه این تکنیک بر محدودیت غلبه میکند.
• در برخی موارد، یک برنامه یک خط از خروجی را از پایگاهداده بر میگرداند. این میتواند کل یک ردیف، چند فیلد، یا فقط یک فیلد باشد.
• گاهی اوقات، یک برنامه هیچ خروجی را بر نمیگرداند. با این حال، زمانی که یک خطای نحوی (Syntax Error) رخ میدهد، پیام خطای خام از پایگاهداده برگشت داده میشود.
• در موارد دیگر، که تزریق SQL کور نامیده میشود، تنها خروجی از برنامه کاربردی وب، شاخص موفقیت یا شکست است. این امر اغلب با تفاوت در یک صفحه HTML که در پاسخ بازگشت داده می شود، قابلشناسایی است.
• شکل دیگر تزریق SQL کور بدون هیچ خروجی از برنامه کاربردی وب و بدون هیچ شاخصی از موفقیت یا شکست طبقهبندی میشود. در عوض، پایگاهداده بک اند به یک Query اجازه میدهد تا با تاخیر اجرا شود (استفاده از توابعی مانند sleep یا waitfor delay) یا براساس یک شرایط (Boolean) منتظر بماند. سپس وجود یا عدم وجود تاخیر به عنوان شاخص موفقیت یا شکست استفاده میشود، که خروجی را برای ما فراهم میکند.
Example SQL
در نشان دادن این تکنیکها، ما از یک برنامه ساده شده وب استفاده میکنیم که در آن جستجو و ورودی کاربر که به پایگاهداده بکاند منتقل میشود، یکسان باقی میماند. تنها تفاوت در این مثالها مقدار خروجی است که توسط برنامه کاربردی وب به ما باز میگردد. SQL مورد استفاده برای این نمایش ساده شده به شرح زیر است:

در این مثال برنامه کاربردی وب، یک id با مقدار صفر، یک نتیجه نامعتبر را به همراه داشته و یک id با مقدار 1، یک ردیف را باز میگرداند. در این مثال SQL، هیچ پسوند یا پیشوند لازم نیست.
تمرکز این تکنیکها، استخراج دادهها است. برای نشان دادن دادههایی که میخواهیم بازیابی کنیم، از نمونه SELECT ‘data’ استفاده میکنیم. اگرچه این Query تنها یک ستون و یک ردیف را برمیگرداند، اصلاحات را میتوان برای هر پرس و جوی چند ردیفی و چند ستونی انجام داد تا یک ستون و سطر را در یک زمان برگرداند.
Single Line of Output
اصلیترین مثال تزریق SQL زمانی رخ میدهد که برنامه چندین ردیف خروجی را نشان دهد. در این مورد، شما میتوانید از تکنیک UNION استفاده کنید، تعداد ستونها را تطبیق دهید و دادهها را از خروجی صفحه دریافت نمایید.
با شروع از این آسیبپذیری آسان برای بهرهبرداری، اکنون میتوانید محدودیتهایی را اضافه کنید و در مورد تکنیکهای مورد استفاده برای دور زدن آنها بحث کنید. محدودیت اول تعداد خطوط خروجی نمایشدادهشده در صفحه است.
صفحه برنامه کاربردی وب اغلب برای نشان دادن تنها یک رکورد پایگاهداده در یک زمان در نظر گرفته میشود. بهرهبرداری از تزریقSQL در این مورد، مستلزم این است که شما خروجی پرس و جوی خود را به یک ردیف محدود کنید.
هر یک از تکنیکهای ارائهشده در بخشهای آتی شامل پرس وجوهای نمونه برای MySQL و SQL Server مایکروسافت است.

در مثال بالا، [r] نشاندهنده تعداد ردیفهایی است که میخواهیم پرس وجو برگردد و [0]نشاندهنده آفست است که از آن میخواهیم ردیفهای بازگشتی را شروع کنیم. به عبارت دیگر، هنگام تلاش برای بازگرداندن یک ردیف، [r] همیشه ۱ است و [0] از ۰ تا تعداد ردیفهای خروجی شمارش میشود.
MySQL یک عبارت LIMIT ساده برای استفاده ارائه میدهد که در پایان یک عبارت SQL استفاده میشود، که یک افست و تعدادی ردیف برای بازگشت نیاز دارد.
در MSSQL شرایط متفاوت است. برای انتخاب یک ردیف خروجی، ما در واقع باید دو Query ایجاد کنیم که در تصویر بالا قابل مشاهده میباشد.
Error Message Output
اجازه بدهید تا یک محدودیت اضافی در خروجی خود قرار دهیم. هیچ ردیف خروجی در صفحه نمایش داده نمیشود، اما برنامه کاربردی وب پیامهای خطای کامل را از پایگاهداده بک اند بر میگرداند.
با دانستن این موضوع، گاهی اوقات میتوان دادههای خروجی را در خود پیام خطای پایگاهداده تعبیه کرد. به طور معمول، ما محدود به نمایش یک ستون از یک ردیف خروجی هستیم.
درMySQL، این کار با بهرهبرداری از یک روش جالب بوسیله Group by انجام میشود. برای ایجاد خطا، ما یک SELECT COUNT() را روی FLOOR(RAND(0)2) x و سپس GROUP BY x انجام میدهیم. در این عبارت،x یک اسم مستعار است که به ستون حاوی عبارت RAND اشاره دارد. اثر آن این است که MySQL تلاش میکند تا یک ستون از دادهها شامل اعداد تصادفی را انتخاب کند و سپس از آن اعداد به عنوان یک کلید برای گروهبندی و شمارش تعداد ردیفها استفاده کند.
با توجه به برخی اشکال داخلی با چگونگی اعمال عملیات FLOOR و *2، این امر باعث ایجاد یک Duplicate Key در MySQL میشود و مقادیر ستون x، در یک جدول داخلی ایجاد میگردد. به همین دلیل خطایی نشان داده میشود که نمایانگر Duplicate Key است. برای استفاده از این مزیت و نمایش در خروجی، ما دادههای خود را بر روی کلید با الحاق این دو به یکدیگر به نمایش میگذاریم به طوری که وقتی کلید نمایش داده میشود، دادههای ما نیز نمایش داده میشوند.

MSSQL برای این تکنیک سادهتر است. ما باید سعی کنیم که فقط یک رشته، را به یک عدد صحیح INT، تبدیل کنیم. زمانی که MSSQL قادر به انجام این کار نیست، دادههای ما را به عنوان رشتهای که موفق به تبدیل آن نشده است، در خروجی نمایش میدهد.

تکنیکهای مشابهی برای PostgreSQL و Oracle به ترتیب با استفاده از تابع تبدیل و XMLType در دسترس هستند.
Error Message Example

در بالا میتوانید یک صفحه مبتنی بر MySQL و PHP را ببینید که برای نمایش یک رکورد کاربر استفاده میشود. ما یک Query را تزریق کردهایم که یک الحاق انجام میدهد. زمانی که MySQL دچار خطا میشود، دادههای انتخابشده ما و نتیجه RAND را به عنوان “data1” به ما نشان میدهد.
در زیر آن نیز میتوانید همان برنامه اجرا شده در MSSQL و ASP را ببینید. ما یک Query را تزریق کردهایم که تلاش میکند تا نتایج دادههای SELECT را به یک عدد صحیح، INT، تبدیل کند. پیام خطای حاصل به ما اطلاع میدهد که “data”، خروجی پرس و جوی ما، با موفقیت تبدیل نشده است.