تاملی دراشتباهات رایج برنامه‌نویسی

 

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

اما در این میان اشتباهاتی ممکن است بر اثر کم‌دقتی به وجود آیند. اشتباهاتی که باعث به سرقت رفتن داده‌ها یا پدید آمدن رخنه‌هایی می‌شوند که راه را برای نفوذ هکرها هموار می‌سازند. در این مقاله، 10 مورد از رایج‌ترین اشتباهات برنامه‌نویسی که ممکن است در زمان کدنویسی با آن‌ها روبه‌رو شوید را مورد بررسی قرار داده‌ایم.

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

در نتیجه پیشنهاد می‌کنیم برای آنکه از اشتباهات رایج برنامه‌نویسی به دور باشید و برنامه شما به‌شکل درستی کار کند، به فهرستی که در این مقاله آماده کرده‌ایم نگاهی داشته باشید.

1.  سرریز بافر

مشکل سرریز بافر (Buffer Overflow) هنگامی به وجود می‌آید که داده‌ها در محدوده‌ای خارج از بافر تعیین شده در حافظه نوشته می‌شوند. این مشکل به‌واسطه محاسبه اشتباه مکان نوشتن داده‌ها به وجود می‌آید. همچنین، اگر سعی کنید بدون توجه به‌اندازه بافر مقادیر داده‌ای را به‌طور پیوسته در آن بنویسید مشکل یاد شده به وجود می‌آید. خطای سرریز بافر یکی از رایج‌ترین مشکلاتی است که در اغلب موارد هکرها به‌خوبی می‌توانند از آن بهره‌برداری کنند. کرم اینترنتی موریس که در سال 1988 شناسایی شد، کرم W32/Nima که در سال 2001 شناسایی و خطای ارسال ایمیل که در سال 2003 شناسایی شد، بر مبنای این مشکل برنامه‌نویسی به وجود آمده بودند. برای روشن شدن مطلب به فهرست 1 توجه کنید. 

char array[6] = “hello”;
strcat(array, “, joe”); /* <- This line causes a buffer overflow. */

فهرست 1

در خط دوم زمانی که برنامه‌نویس سعی می‌کند کلمه Joe را به آرایه array اضافه کند، مشکل سرریز بافر به وجود می‌آید. به‌واسطه آنکه اندازه بافر برای شش کاراکتر تعیین شده اما برنامه‌نویس در نظر دارد، هشت کاراکتر را به بافر وارد کند. 

2.  تزریق کد SQL

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

// The following is a parameter value with SQL injection
String username = “joe’; delete from user where username like ‘%”;
Connection con = ...; // create connection to database

// When this statement is executed, all users are deleted from the database.
con.createStatement().execute(“update user set logged_in = 1 where username = ‘” + username + “’”);

فهرست 2

3.  تزریق فرمان‌های سیستم‌ عامل 

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

4.  سرریز شدن مقادیر صحیح 

خطای سرریز مقادیر صحیح یا Wraparound هنگامی رخ می‌دهد که تلاش می‌کنید فراتر از مقداری که یک متغیر صحیح می‌تواند ذخیره‌سازی کند را در آن ذخیره‌ ‌کنید. زمانی که این اتفاق رخ می‌دهد، مقدار بزرگ‌تر به‌شکل ناقص درون متغیر قرار گرفته که همین موضوع باعث می‌شود تا نتیجه یک عملیات محاسباتی غیرقابل پیش‌بینی شود. به ‌طور مثال، یک متغیر دو بایتی unsigned short می‌تواند حداکثر مقدار 65535 را در خود ذخیره‌سازی کند.
حال تصور کنید دو عدد دیگر از همین نوع مثل 65530 و 10 را با یکدیگر جمع و در این متغیر ذخیره‌سازی کنید. نتیجه این محاسبه برابر با 65545 است که فراتر از محدوده مجاز این نوع است. این مشکل باعث می‌شود تا مقادیر پیش‌بینی نشده‌ای در حافظه ثبت شوند. حال اگر تلاش کنید از این متغیر در بخش دیگری از عملیات خود استفاده کنید، به ‌طور مثال از این متغیر به‌عنوان اندیس یک آرایه استفاده کنید، نتایج غیرمنتظره‌ای را دریافت خواهید کرد. فهرست 3 قطعه‌ کدی به زبان سی بوده که این مشکل را نشان می‌دهد.

short a = 65530, b = 10;
short c = a + b;
// on my computer, c has the unexpected value: 4

فهرست 3

5.  تخصیص مقدار نامناسب به‌عنوان اندیس به آرایه 

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

6.  تخصیص منابع بدون اعمال محدودیت یا نظارت

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

اگر از الگوریتمی در برنامه خود استفاده کردید و سپس متوجه شدید رخنه‌ای در آن کشف شده است، به‌سرعت باید کدهای خود را به‌روزرسانی کنید

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

7.  ارجاع به اشاره‌گر فاقد اعتبار (Expired Pointer Dereference)

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

8.  ارجاع به اشاره‌گر تهی (Null Pointer Dereference)

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

9.  فراموش کردن مقداردهی اولیه به متغیرهای محلی 

متغیرهای محلی متغیرهایی (Missing Initialization) هستند که درون یک تابع یا بلوک از دستورات تعریف و تنها در دامنه‌ای که تعریف شده‌اند شناخته می‌شوند. به‌عنوان یک برنامه‌نویس این وظیفه شما است که به‌محض تعریف این متغیرها فرآیند مقداردهی اولیه به آن‌ها را انجام دهید. اگر از این متغیرها پیش از آنکه مقداردهی اولیه روی آن‌ها را انجام دهید استفاده کنید، با پیغام خطای مقداردهی اشتباه روبه‌رو خواهید شد. رویکردی که در اغلب موارد باعث می‌شود برنامه شما به‌شکل ناگهانی خاتمه پیدا کند. فهرست 4 مثالی در ارتباط با همین مشکل که به زبان سی نوشته شده است را نشان می‌دهد.

int pos;
char buffer[] = “hello world”;

// this line may print garbage and/or may crash the program since pos is not initialized.
printf(“Value of character at pos %d is: %cn”, pos, buffer[pos]);

فهرست 4

10.  الگوریتم رمزنگاری مشکل ‌آفرین یا شکسته شده

دنیای رمزنگاری به‌ طور پیوسته در حال تکامل و پیشرفت است. در نتیجه الگوریتمی که امروزه مورد تأیید و استفاده قرار می‌گیرد ممکن است فردا بی‌مصرف شود. افزایش توان و قدرت محاسباتی کامپیوترها باعث شده است تا آن‌ها به‌راحتی بتوانند از سد الگوریتم‌های رمزنگار عبور کنند. در نتیجه اگر در گذشته کامپیوتری برای شکستن یک فرآیند به سال‌ها زمان نیاز داشت، امروزه این کار را ظرف چند دقیقه انجام می‌دهد. کامپیوترهای کوانتومی از جمله این موارد هستند. حتی این احتمال وجود دارد که یک نفر موفق شود راهکار جدیدی را برای شکستن الگوریتم خاصی کشف و در نتیجه یک الگوریتم را بدون مصرف کند. باید درخصوص این مسائل کاملاً آگاه باشید و اخبار را به‌دقت دنبال کنید. به‌عبارت دقیق‌تر، اگر از الگوریتمی در برنامه خود استفاده کردید و سپس متوجه شدید رخنه‌ای در آن کشف شده است، به‌سرعت باید کدهای خود را به‌روزرسانی کنید. به‌ طور مثال، SHA-1 که یک الگوریتم درهم‌کننده است، مدت‌ها است در ارتباط با محاسبات مورد استفاده قرار نمی‌گیرد. در سال 2005 میلادی حملاتی در ارتباط با این الگوریتم شناسایی و باعث شد کارشناسان الگوریتم‌های جایگزین SHA-2 و SHA-3 را برای این منظور پیشنهاد کنند. در نتیجه اگر از این الگوریتم در برنامه خود استفاده کرده‌اید، بهتر است هرچه سریع‌تر نسبت به جایگزین کردن آن اقدام کنید. در غیر این صورت خود و سازمانی که از نرم‌افزار شما استفاده می‌کند را در معرض خطر قرار خواهید داد. 

درنهایت

در این مقاله سعی کردیم رایج‌ترین اشتباهات و خطاهای برنامه‌نویسی را به شما نشان دهیم. بدون شک با توجه به نکاتی که در این مقاله آموختید، این شانس را دارید تا برنامه‌هایی به‌مراتب کاراتر و ایمن‌تر طراحی کنید.

منبع:ماهنامه شبکه 201

    نظرات

    "تخریب خلاقانه"در سیلیکون ولی
    شرکت ها و برندها
    "تخریب خلاقانه"در سیلیکون ولی
    اگرچه سیلیکون ولی، دستاوردهای تحول آفرینی زیادی را به دنیای دیجیتال عرضه کرده، اما به طور خطرناکی به یک کارخانه تک محصولی مردان سفیدپوست و نخبه کامپیوتر تبدیل شده است.
      2018-10-05 16:25:00
    کناره گیری ایلان ماسک
    شخصیت ها
    کناره گیری ایلان ماسک
    اگر توافق به‌دست آمده طبق برنامه پیش برود، ماسک باید ظرف 45 روز از مقام ریاست هیئت مدیره کناره‌گیری کند و حداقل تا سه سال بعد از آن نمی‌تواند برای این پست انتخاب شود.
      2018-10-02 07:40:09
    استارتاپ ناب ،جذاب‌ترین بازیگر دنیای کارآفرینی
    تازه های کسب و کار
    استارتاپ ناب ،جذاب‌ترین بازیگر دنیای کارآفرینی
    این متدولوژی به شما می‌گوید، فرآیند آزمایش را به جای برنامه‌ریزی سنگین، بازخورد مشتری را به جای شهود و طراحی تکرار شدنی را به جای راه‌کار سنتی توسعه "طرحی کامل و عالی در ابتدا" مورد استفاده قرار دهید.
      2018-10-02 06:58:00