در این بخش از دوره آموزشی SEC542 از موسسه SANS با ادامه مبحث حمله SQL Injection و همچنین یافتن SQL Injection با شما هستیم و جزئیات بیشتری از این حمله را مطرح می نماییم.
یافتن SQL Injection
تا به حال با دستورات، انواع داده و کاراکترهای خاص SQL آشنا شدید. حال به بررسی انواع مختلف SQL injection میپردازیم.
اگر برای یافتن SQL Injection تنها در انتظار دریافت خطا از اپلیکیشن باشید، همه چیز آسان به نظر میرسد. اما برای موفق بودن در کشف این باگ، باید انواع مختلف آن را بشناسیم. در ادامه به بررسی کلاسهای مختلف از این آسیبپذیری پرداخته و با مقدمات پیدا کردن آنها آشنا میشویم.
مکانهای ورودی
صرف نظر از نوع SQLi، باید به دنبال ورودی مناسبی باشیم که ما را در یافتن SQL Injection یاری کند. اما ورودی مناسب چیست؟
بسته به نحوه پیادهسازی و کدنویسی اپلیکیشن، هر ورودی ممکن است ما را به مقصد مورد نظر برساند.
قطعا یکی از عوامل موثر در یافت نقاط ورودی جالب، ارتباط یافتن و کار کردن با بخشهای مختلف اپلیکیشن است. این نقاط، جاهایی هستند که در آنها اپلیکیشن برای پردازش اطلاعات به دیتابیس اتصال مییابد. مثلا در قسمت لاگین و احراز هویت کاربران.
علاوه بر این، در بخشهایی از درخواستهای HTTP معمولا احتمال یافت SQLi بیشتر است. این بخشها در زیر دیده میشوند:
- پارامتر کوئریهای GET URL
- پیلود POST
- کوکی HTTP – اینجا SQLi معمولا از نوع blind یافت میشود.
- HTTP User-Agent – اینجا SQLi معمولا از نوع blind یافت میشود.
کلاسهای SQLi
در بخش قبل به مکانهایی اشاره کردیم که در صورت داشتن SQLi معمولا از نوع blind میباشد. ممکن است این مطلب کمی شما را گیج کرده باشد. Blind SQLi یک دسته یا کلاس از باگهای SQLi تلقی میشود.
در حقیقت، SQL Injection یک نوع آسیبپذیری است که به اشکال مختلف بروز پیدا میکند. هر یک از این اشکال، به دلیل ارائه ورودی غیرمجاز توسط کاربر و قرار گرفتن ورودی در دستورات دیتابیس به منظور سوءاستفاده و دستکاری اطلاعات، ایجاد میشود.
گرچه یک آسیبپذیری ممکن است به صورتهای مختلف خود را نمایان کند، با این حال، به دلیل تفاوت محرز کلاسها، هر یک را جداگانه بررسی و شناسایی کرده تا درک بهتری از کشف، اکسپلویت و برطرفسازی آنها داشته باشیم.
In-Band/Inline SQLi
اولین کلاس آسیبپذیری SQLi ، کلاس in-band یا inline میباشد. واژه in-band یا inline بیان کننده این مطلب است که کاربر میتواند مستقیما و بدون هیچ محدودیتی، نتایج SQLi را ببیند. نکته متمایز کننده آن، همین قابل رویت بودن آن است. بدین ترتیب کشف و اکسپلویت این کلاس بسیار آسان خواهد بود.
Blind SQL Injection
با در نظر گرفتن توضیح inline SQLi و با توجه به نام blind SQLi، حتما میتوانید حدس بزنید با چه دستهای رو به رو هستیم. blindness یا کوری در این دسته از SQLi به معنای عدم دریافت نتیجه از injection اجرا شده است. درواقع آسیبپذیری مانند قبل است اما ما آن را طور دیگری تجربه میکنیم.
سادهترین دستهبندی آسیبپذیریهای SQLi، دو دستهبندی in-band/inline (visible) و blind میباشد.
درجات مختلف کوری
تقسیم کردن SQLi به دو دسته ساده inline و blind، جهت تشخیص ابتدایی نوع SQLi مفید به نظر میرسد. با این حال، همیشه همه چیز انقدر ساده نیست. مفهوم و درجات blind میتواند در مکانهای مختلف، متفاوت باشد. به زبان سادهتر، این میزان کوری یک مقدار آنالوگ است نه دیجیتال و میزان دید ما از نتایج SQLi ثابت نیست. در ادامه درجات مختلف را با هم بررسی میکنیم.
پیامهای خطای دیتابیس
اگر بازه inline تا blind را بجای گسسته بودن، یک بازه پیوسته در نظر بگیریم، آنگاه آشکارترین کران در این بازه، شامل پیامهای خطای دیتابیس است. در مورد اینکه یک آسیبپذیری چقدر باید blind باشد تا در کلاس blind SQLi قرار گیرد، اختلاف نظرهایی وجود دارد. با این حال مطمئن هستیم که اگر پیامهای خطای دیتابیس قابل مشاهده باشند، قطعا SQLi از نوع blind محسوب نمیشود.
اما این پیامها چه هستند که دستهبندی آسیبپذیری را عوض میکنند؟
پیامهای خطای دیتابیس، بیان کننده مشکلی در دیتابیس هستند که بر اساس ورودیهای ما ایجاد شده است. درواقع، رایجترین راه برای کشف باگ SQLi ، ارسال کاراکترهایی است که معمولا خطاهای دیتابیس تولید میکنند.
پیامهای خطای دیتابیس نه تنها وجود آسیبپذیری را به ما اثبات میکند، بلکه در پیدا کردن پیلود مناسب اکسپلویت نیز کمک کننده هستند.
مثالی از پیام خطای دیتابیس
برای اینکه منظور خود را از خطای دیتابیس مشخص کنیم، یک مثال را با هم میبینیم. در اپلیکیشن آسیبپذیر، رشته Dent’ را وارد می کنیم.
نتیجه به شکل زیر میباشد:
از خطاهای خود درس بگیرید
دریافت خطا از دیتابیس، اتفاق قابل توجهی است اما در نهایت نیاز داریم کاری کنیم که خطایی تولید نشود. خطاها خودشان ما را در این جهت هدایت میکنند. در اولین injection، ما مقدار Dent’ را وارد اپلیکیشن نمودیم. حالا کوتیشن دوم را به انتهای رشته اضافه کرده و مقدار Dent’’ را ارسال میکنیم.
نتیجه جالب است:
دیگر هیچ پیام خطا و اطلاعاتی از خطا دریافت نمیکنیم. از یک لحاظ، این یک آسیبپذیری SQLi آشکار نیست چون ما دیتای ورودی خود را در صفحه نمیبینیم. این امکان وجود داشت که پیام واضحتر و مفیدتری به ما برگردانده شود.
مثلا: “Employee Dent’ not found…” . کوتیشن دوم به DB پیشنهاد میدهد که شاید واقعا این کاراکتر یک حرف کوتیشن است. مانند اسم O’Connor .
اگر یک کوتیشن (‘) یا دو کوتیشن (‘’) خطا تولید میکند، آنگاه حرکت بعدی این است که یک کوتیشن دیگر به رشته اضافه کنیم.
Custom Error Messages
پیامهای خطای دیتابیس بسیار مفید بوده و کشف باگهای SQL injection را بسیار آسانتر میکنند. معمولا، نشانه وجود یک blind SQL injection ، عدم نمایش دادن خطاهای دیتابیس است.
شرایطی را در نظر بگیرید که در آن منطق کوئری مثال قبل هیچ تغییری نکرده باشد. یعنی به راحتی میتوان حدس زد که دیتابیس خطا تولید میکند، اما اپلیکیشن خطاها را handle کرده و بجای پیام دیتابیس، یک پیام دوستانهتر به کاربر نشان میدهد.
توجه داشته باشید که آسیبپذیری همچنان پابرجاست و هیچ تغییری نکرده است. تنها نحوه برخورد ما با شرایط فرق میکند. در این شرایط باید به دنبال چیزی بیشتر از پیامهای واضح خطا باشیم.
مثالی از Custom Error Message
به عنوان اولین تجربه از Blind SQLi، یک مثال با پیامهای خطای customize شده را با هم میبینیم.
این بار صفحهای به نشانی http://www.sec542.org/bsqli.php را باز میکنیم(در مثالهای قبل صفحه sqli.php را تست کردیم). نحوه عملکرد و هدف این اپلیکیشن مانند مثالهای قبل میباشد با این تفاوت که در این صفحه آسیبپذیری blind SQLi وجود دارد.
مانند قبل رشته Dent’ را وارد میکنیم:
این بار نتیجه متفاوتی دریافت میکنیم:
در این مثال همان کوئری سابق به دیتابیس ارسال میشود اما همانطور که میبینیم پیام خطای ثابتی نشان داده میشود که برای همه نامها یکسان است. بنابراین نمیتوانیم به سرعت وجود آسیبپذیری را تشخیص دهیم.
مطالب این بخش توسط سرکار خانم فهیمه رضایی تهیه شده است.