آشنایی با مفهوم Defensive Programming در صنعت توسعهٔ نرم‌افزار

آشنایی با مفهوم Defensive Programming در صنعت توسعهٔ نرم‌افزار

اگر بخواهیم به طور ساده توضیح دهیم، Defensive Programming (برنامه‌نویسی تدافعی) یک سبک برنامه‌نویسی با هدف پیش‌بینی حفره‌های امنیتی و نقاط ضعف احتمالی است. در واقع، هدف نهایی این رویکرد برنامه‌نویسی، جلوگیری از بروز مشکلات احتمالی قبل از رویداد آنها است! 

برای مشخص شدن دلایل اهمیت نوشتن یک اپلیکیشن ایمن، موارد زیر را مد نظر قرار دهید:
- وجود باگی در نرم‌افزار یک سیستم رادیولوژی، باعث مرگ ۵ بیمار شد (سال ۱۹۸۰).
- باگی در نرم‌افزار سیستم دفاع هوایی موشکی MIM-104 Patriot باعث می‌شد که در هر یکصد ساعت، یک‌سوم ثانیه ساعت این سیستم جلو می‌افتاد که در نهایت به خاطر اشتباه در هدف‌گیری، منجر به کشته شدن ۲۸ آمریکایی شد (سال ۱۹۹۱).
- سفینهٔ فضایی Ariane 5 به ارزش یک میلیون دلار متعلق به آژانس فضایی اروپا، به خاطر وجود یک باگ در نرم‌افزارش صرفاً ۴۰ ثانیه پس از بلند شدن منفجر شد (سال ۱۹۹۶).

به نظر می‌رسد که مثال‌های فوق‌الذکر فجایعی که بی‌دقتی در کدنویسی می‌تواند به بار بیاورد را به خوبی روشن کرده باشند. به طور کلی، ایدهٔ Defensive Programming این است که «غیرممکن، ممکن است گاهی ممکن گردد». به طور کلی، زمانی که پای ایمنی، امنیت و حساسیت یک پروژه به میان می‌آید، برنامه‌نویسی Defensive (تدافعی) خوش خواهد درخشید. به منظور پیاده‌سازی این رویکرد در پروژه‌های نرم‌افزاری، می‌بایست همواره موارد زیر را مد نظر داشته باشیم:

هیچ‌گاه به داده‌های کاربران اعتماد نکنید
به عنوان یک قانون همیشگی، هیچ‌وقت به Input (داده‌هایی که توسط کاربران وارد سیستم می‌شوند) اعتماد نکنید و همه چیز را قبل از ثبت در دیتابیس چک کنید. به طور مثال، اگر کاربر قرار است در فرمی عکسی را آپلود کند، هیچ‌گاه پسوند تصاویر که کاربر نمی‌تواند استفاده کند (Blacklist) را چک نکنید بلکه برعکس، یک اصطلاحاً Whitelist از پسوند‌هایی که مورد تأییدتان هستند تهیه کرده، کلیهٔ ورودی‌ها را با آن بسنجید.

در پاسخ به این سؤال که چرا به جای Blacklist باید از Whitelist استفاده کنیم، بایستی گفت که چنانچه از لیست سیاه پسوندها استفاده کنیم، همواره این احتمال وجود دارد که پسوندی از قلم بیافتد اما اگر از لیست سفید پسوندها استفاده نماییم (مثلاً صرفاً پسوندهای jpg و png)، خیالمان راحت خواهد بود که سیستم راه نفوذی ندارد.

کوئری‌های درست برای دیتابیس ارسال نمایید
SQL Injection همواره یکی از آسیب‌پذیری‌های رایج در سراسر دنیا است (برای آشنایی با این مفهوم، به مقالهٔ‌ آشنایی با مفهوم SQL Injection در زبان PHP مراجعه نمایید). با استفاده از ابزارها و لایبرری‌های ایمن برای ارتباط با دیتابیس، تا حد قابل‌توجهی می‌توان این تضمین را ایجاد کرد که کوئری‌های مخرب وارد دیتابیس نخواهد شد. به طور مثال، در زبان PHP می‌توان از لایبرری PDO استفاده کرد (برای آشنایی بیشتر با این لایبرری، به مقالهٔ ارتباط با دیتابیس در PHP از طریق لایبرری PDO مراجعه نمایید).

هیچ‌گاه به فریمورک‌ها اعتماد نکنید
درست است که بسیاری فریمورک‌ها و لایبرری‌های اپن‌سورسی هستند که در سراسر دنیا دولوپرهای بسیاری از آنها استفاده می‌کنند، تست شده هستند و هیچ راه نفوذی ندارند، اما هیچ‌گاه مبنا را این قرار ندهید که فریمورک یا لایبرری مورد استفادهٔ‌تان ۱۰۰٪ ایمن و تست شده است.

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

دستورات شرطی را به صورت کامل بنویسید
این مورد را با ذکر مثال توضیح خواهیم داد. فرض کنیم متغیری داریم تحت عنوان var$ که می‌تواند مقداری همچون ۱ یا ۲ داشته باشد و بسته به این مقدار، یکی از دستورات شرطی زیر اجرا خواهد شد:

$var = 1;
if ($var == 1) {
    echo 'It`s One';
} elseif ($var == 2) {
    echo 'It`s Two';
}

چنانچه مقدار متغیر var$ برابر با ۱ باشد، دستور داخل if اجرا خواهد شد و چنانچه این مقدار برابر با ۲ باشد، دستور داخل elseif. اما اگر این مقدار چیزی به غیر از مقادیر ۱ و ۲ باشد، هیچ حالت سومی برای هَندل کردن این موضوع در نظر گرفته نشده است. آنچه برنامه‌نویسی Defensive به ما حکم می‌کند این است که حتی اگر هم مقدار متغیر var$ توسط خود دولوپر پر می‌شود و ۱۰۰٪ یکی از مقادیر ۱ یا ۲ خواهد بود، باز هم احتمال دهید که ممکن است روزی بنا به شرایط خاصی این مقدار تغییر یابد و کدی بنویسید که این موضوع در آن دیده شده باشد؛ لذا خواهیم داشت:

$var = 'none';
if ($var == 1) {
    echo 'It`s One';
} elseif ($var == 2) {
    echo 'It`s Two';
} else {
    echo 'None of Them';
}

می‌بینیم که اگر مقدار این متغیر استرینگی همچون none شود، به سادگی وارد دستور else شده و برنامه به خوبی مدیریت خواهد شد و از اجرای سایر اسکریپت‌ها جلوگیری به عمل خواهد آمد.

گزینهٔ default برای دستورات switch را هرگز از یاد نبرید
سوئیچ هم نوعی دستور شرطی است. برای روشن‌تر شدن این مسئله، اسکریپت زیر را در نظر می‌گیریم: 

$var = 1;
switch ($var) {
    case 1: echo 'It`s One';
    break;
    case 2: echo 'It`s Two';
    break;
}

در تفسیر اسکریپت فوق بایستی بگوییم که اگر مقدار متغیر var$ برابر با ۱ باشد، case اول اجرا خواهد شد و اگر این مقدار برابر با ۲ باشد، وارد case دوم خواهیم شد اما اگر این مقدار برابر با ۳ باشد، هیچ شرطی برای این منظور در نظر گرفته نشده است. اینجا است که می‌بایست همواره به خاطر داشته باشیم که در حین استفاده از دستور switch می‌بایست مقدار پیش‌فرض default را در نظر بگیریم:

$var = 3;
switch ($var) {
    case 1: echo 'It`s One';
    break;
    case 2: echo 'It`s Two';
    break;
    default: echo 'It`s None of Them';
    break;
}

 به عبارت دیگر، اگر هیچ کدام از شروط فوق برآورده نشوند، دستورات داخل default اجرا خواهند شد. داخل این دستور، می‌توان به راحتی یک اکسپشن ایجاد کرد تا کسی که اپلیکیشن را مدیریت می‌کند متوجه موضوع گردد. به طور کل، default در شرایط غیرقابل پیش‌بینی از اجرای سایر اسکریپت‌ها جلوگیری به عمل خواهد آورد و این دقیقاً همان چیزی است که ما می‌خواهیم.

در یک کلام، Defensive programming حاکی از آن است که اپلیکیشن می‌بایست رفتاری ثابت و قابل‌ پیش‌بینی داشته باشد حتی در شرایطی کاملاً غیرقابل پیش‌بینی.

حال نوبت به نظرات شما می‌رسد. آیا رویکرد کدنویسی به اصطلاح Defensive را در حین انجام پروژه‌های نرم‌افزاری مد نظر دارید؟ آیا پیاده‌سازی این رویکرد بسته به زبان‌های برنامه‌نویسی مختلف می‌تواند متفاوت باشد؟ و در نهایت اینکه آیا این رویکرد ۱۰۰٪ تضمین می‌کند که در شرایط غیرقابل پیش‌بینی، اپلیکیشن عملکردی قابل پیش‌بینی از خود نشان خواهد داد؟ نظرات، دیدگاه‌ها و تجربیات خود را با ما و سایر کاربران سکان آکادمی به اشتراک بگذارید.