فریم ورک ها و معماری های جدید

October 11th, 2008 یک نظر »

فریم ورک کدایگنایتر (CodeIgniter) از بسیاری جهات برای ساخت سیستم های مبتنی بر وب عملکرد خوبی از خود نشان می ده. این فریم ورک یکی از رقبای خوب کیک پی.اچ.پی (CakePHP) محسوب می شه. در حالی که CakePHP به صورت پیش فرض از ماژول ها پشتیبانی نمی کنه, CodeIgniter با قابلیت پشتیبانی از سیستم ماژولار و اپلیکیشن های مختلف, مورد توجه بسیاری از برنامه نویسان سیستم های مبتنی بر وب قرار گرفته.

CodeIgniter از مدل MVC مبتنی بر معماری مدل, ویو و کنترلر (Model, View, Controller) پشتیبانی می کنه و تمامی کارهاشو با استفاده از این مدل انجام می ده به این ترتیب که وجود هر کنترلر برای در دست گیری اپلیکیشن و ویو برای نمایش واسط های کاربری ضروری و استفاده از مدل ها برای ارتباط با پایگاه داده اختیاری است.

پس CodeIgniter از یک معماری دو لایه ی اصلی تشکیل شده که در لایه ی اول از کنترلر تشکیل می شه, در لایه ی بعدی, مشترکا مدل و ویو در دو بخش مجزا به نمایش اطلاعات و جمع آوری آن دست می زنند. در این وضعیت هسته ی سبک CodeIgniter در پایین ترین سطح, بدون نیاز به هک شدن و یا تغییر خاص برای هر گونه اپلیکیشن به کار مشغول می شود. (عدم نیاز به هک شدن از ادعاهای نویسندگان این فریم ورک هست ولی عملا برای سیستم های پیچیده نیاز به تغییر هسته محتمل به نظر می رسه با این حال با توجه به سادگی فوق العاده ی کدهای هسته, این کار راحت به نظر می رسه)

مزیت بعدی CodeIgniter عدم پشتیبانی اولیه از ارسال فرم ها با متد get هست. با این که امکان فعال سازی این متد وجود داره ولی به دلیل این که استفاده نکردن از این متد, هم شکل URL و هم امنیت بالاتر رو حفظ می کنه, فرم غیر فعال اون و استفاده از متد post و یا ارسال سگمنت (segment) ها توصیه شده. به این ترتیب در یک url ساده, می توانید application و کنترل مورد نظر و حتی پارامترهای ارسالی رو هم بدون نیاز به یک خظ کد اضافه داشته باشید!

مثال:

Normal URL:

http://yourdomain.com/index.php?app=content&task=show_content&content_id=23

CodeIgniter URL:

http://yourdomain.com/contents/show_content/23/

از مشکلات این فریم ورک عدم پشتیبانی مستقیم از Ajax (ای.جکس یا همان آژاکس ایرانی ها!) هست که با کلک های خاصی به راحتی قابل پیاده سازی است. همچنین عدم امکان ساخت ماژول های 100% مستقل به دلیل مشکلات namespace import از دیگر ضعف های این فریم ورک است.

پایگاه های داده و مشکلات نخ بندی

September 16th, 2008 یک نظر »

مبحث نخ بندی برنامه های سیستم عامل یا همون threadingاز جمله مسایلی هست که روی پایگاه های داده نقش بسزایی داره که هر مدیر database, طراح یا برنامه نویس وب باید به این قضیه نگاه عمیقی داشته باشه.

یکی از مشکلات بزرگ در هنگامی رخ می ده که چند مشتری در یک زمان اتصال (connection) باز با دیتابیس دارند و نحوه ی کدنویسی هم به صورتی هست که عملکرد هر کدوم بر دیگری تاثیر می ذاره. بذارید این سناریو رو بررسی کنیم که مثلا شما قضد دارید به کاربر با آی.دی 222 جایزه ی ویژه ای بدید. تا الان 221 بازدیدکننده به سایت شما سر زده و ثبت نام کرده اند. توجه کنید که در پروسه ی ثبت نام هیچ فیلد منحصر به فرد (unique field) دیگه ای جز آی.دی وجود نداره و همین آی.دی کلید اصلی جدول (primary key) هست. در این اثنا بازدید کننده ی شماره ی 222 وارد شده و شروع به وارد کردن اسم خودش می کنه. پس از این کار شما اسم رو ذخیره می کنید و کاربر رو به مرحله ی بعد پاس می دید. اسم با شماره ی 222 ذخیره می شه و تا این جای کار همه چیز درسته. در مرحله ی بعد شما چک می کنید که آیا جدول به شماره ی 222 رسیده که به بازدید کننده جایزه بدید و اون رو به فرم دریافت آدرس و شماره تلفن پاس بدید یا نه؟ برای این کار چه راهی پیشنهاد می شه؟

از اون جایی که عموما تمامی پروسه ی بالا در یک آن و یک مرحله ی اتصال انجام می شه, تنها چیزی که واقعا از کاربر در دست شماست اسم اونه و می خواید ببینید که نفر 222 ام هست یا نه؟ برای این کار راحت ترین راه حل مشاهده ی آخرین ردیف (row) وارد شده (inserted) در پایگاه داده هست. مسلما شما به راحتی قادر هستید با دستور (MAX id) و یا دستورات مشابه دریافت آخرین ردیف بر اساس نوع پایگاه داده ی خودتون, آخرین ردیف که احتمالا همون آقای 222 ام هست رو بگیرید. ولی چی می شه اگه بین دو تا خط دستورتون عمل threading اجرا بشه و برای چند لحظه این کد به حالت halt بره و آقای دیگه ای در اون سر جهان عمل ورود اسمش رو انجام بده! در این حالت سناریو به شکل زیر می شه:

A.insert(“hassan”); //id 222 automatically generates, auto_increment property

A.halt();

B.insert(“ali”); //id 223 automatically generates, auto_increment property

B.halt();

A.get_last_row(); //produces B row with id 223

B.get_last_row(); //produces B row with id 223

خب! هیچ کس که برنده نشد! ممکنه فکر کنید می تونید بگید آخرین ردیف وارد شده ای که اسمش hassan هست می تونه به ما کمک کنه! ولی توجه داشته باشید که ممکنه از شانس خوب شما, همون طور که threading ها افتاد وسط کد, اسم آقای دوم هم hassan باشه که اتفاقا اسم نادری هم نیست!

خود MySQL و حتی MSSQL برای غلبه بر این مشکل راه حل هایی با توابع داخلی خاصی ازایه داده اند که اکثرا فقط در مورد یک کاربر صدق می کنه ولی راه حل های عمومی تر ولی مشکل تری برای غلبه بر این مسئله و یا مسایل شبیه این وجود داره. از جمله:

· استفاده ازtransaction (تراکنش؟!) باعث می شه که بین دستوراتتون وقفه ی تاثیر گذار نیفته.

· استفاده از قفل/باز کردن جداول (lock/unlock)

· و یا استفاده از کدهای hash منحصر به فرد مختص هر کاربر که نیاز به ایجاد تغییراتی در جدول داره.

به هر حال در کار با دیتابیس و خصوصا در حیطه ی وب, علاوه بر توجه شدید به مسایل امنیتی و تزریقی, باید توجه بالایی هم به این گونه مسایل بشه…

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

February 25th, 2008 بدون نظر »

حملات تزریقی پایگاه های داده ای مثل اس.کیو.ال “SQL Injection” بر مبنای انتخاب های محدودی استواره. مثلا برای یک دیتابیس از نوع اس.کیو.ال با چند تست مختلف می شه قابلیت نفوذ رو بررسی کرد که اگه این تست ها جواب نداد, به احتمال زیاد کلا امکان نفوذ از طریق تزریق با امکانات موجود وجود نداره.

نفوذ تزریقی بیشتر در سیستم های مبتنی بر وب و یا وب سایت هایی امکان پذیره که به نوعی با داده های وارد شده مستقیما از طریق کاربر سر و کار دارن. گاهی اوقات تصور می شه که این گونه مشکلات بیشتر در سیستم هایی که مستقیما ورودی کاربر رو در دیتابیس ذخیره می کنن به وجود می یاد. این در حالیه که عملا در این گونه حملات, بین پروسه ی تبدیل ورودی به دیتای ذخیره شده و یا پروسه ی تحلیل ورودی برای فیلترینگ دیتای از پیش ذخیره شده هیچ فرقی وجود نداره! به همین خاطر در مثال زیر, فرایندی رو مطرح می کنیم که به هیچ وجه از دستوراتی نظیر UPDATE و یا INSERT استفاده نمی کنه!

 

کد زیر رو در نظر بگیرید که پس از اجرای event مورد نظر عمل می کنه:

 

$sql = “SELECT * FROM users a WHERE a.user_name = ” . $_GET['name'];

 

با چند تست ساده می شه مشکل نفوذ پذیری رو با تزریق تشخیص داد:

 

1- http://urdomain.com/?user_name=

2- http://urdomain.com/?user_name=”+UNION+SELECT+*+FROM+users+WHERE 1

 

تا این جا یک نفوذگر به چند نکته باید توجه داشته باشه! یکی نحوه ی استفاده از دستور UNION هست که با چند تست ساده می تونه به فرمت کلی لازم برای نفوذ پی ببره. یکی دیگه هم نحوه ی استفاده از این حفره ی موجود خواهد بود. چون برای یک نفوذ گر اجرای دستوری که به دردش نمی خوره چه فایده ای می تونه داشته باشه!

در این جا باید بگم که شاید بهترین بخش قضیه, اجرای یک تابع مشخص و یا حتی دریافت یا اجرای یک فایل روی سرور می تونه باشه! اصلا فکر نکنید که یک پایگاه داده ی نصب روی سرور از این قابلیت ها پشتیبانی نمی کنه! شما به راحتی می تونید به وسیله ی همین دستورات اس.کیو.ال یک فایل موجود روی سرور رو بخونید و حتی تغییر بدید! البته این کار علاوه بر نیاز به عدم توجه به حفره های تزریقی, به عدم تنظیم اقدامات امنیتی سرور هم نیاز داره.

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

حمله  ی بر مبنای لغت هم عموما برای کش رفتن کلمه ی رمز سرور های ریموت استفاده می شه. این نوع حملات هم بر دو نوع وحشیانه و هوشمند استوار هستن. حملات مبتنی بر لغت هوشمند یکی از قشنگ ترین حملات هستند که واقعا نیاز شدیدی به فعالیت ذهنی دارن! این بخش برای خیلی از ما توصیه نشده باقی می مونه :-D

مدیریت شده توسط فواد امیری, تحلیل گر, برنامه نویس و مدیر پروژه ی سیستم های مبتنی بر وب