
چکلیست برنامهنویسی امن
برنامهنویسی امن یکی از موضوعات جدید و با اهمیت در دنیای برنامهنویسی است. متاسفانه vulnerability یا آسیبپذیریهای نرمافزار همواره وجود دارند. روشهای برنامهنویسی ناامن منجر به آسیبپذیریهای پرهزینه در نرمافزارها و در نهایت سرقت دادههای حساس میشوند. به همین دلیل کسب اطمینان از امنیت برنامه و رعایت اصول برنامهنویسی امن، بسیار مهم است.
برای این که برنامههای کاربردی با الزامات امنیتی مناسب، طراحی و پیادهسازی شوند؛ شیوههای برنامهنویسی امن، رمزگذاری و تمرکز بر خطرات امنیتی باید در تمامی عملیات و فرآیندهای توسعه، یکپارچهسازی شوند.
در ادامهی این مقاله، سعی داریم به اصول برنامهنویسی امن بپردازیم و بهترین روشها را برای کدنویسی امن ارائه دهیم.
برنامهنویسی امن چیست؟
برنامهنویسی امن یا کدنویسی امن روشی برای نوشتن کدهای یک نرمافزار است؛ به گونهای که برنامه در برابر انواع آسیبپذیری، حمله یا هر چیزی که میتواند باعث آسیبرساندن به نرمافزار یا سیستم شود، محافظت میشود.
چکلیست برنامهنویسی امن برای توسعهدهندگان نرمافزار
به این نکته توجه داشته باشید که امنیت باید به عنوان بخشی از سیستم، در ابتدای شروع توسعهی نرمافزار در نظر گرفته شود و نباید در انتها به عنوان یک لایه به آن افزوده شود.
در ادامه به بررسی اصول برنامهنویسی امن در مراحل مختلف چرخهی توسعهی نرمافزار میپردازیم.
امنیت کلی نرمافزار
- دستورالعملهای مربوط به زبان برنامهنویسی و نوع نرمافزار مورد استفادهی خود را مطالعه کنید.
- از کدهای قابل اعتماد مانند کتابخانهها و ماژولها مجددا استفاده کنید.
- کدهایی با کیفیت، قابل خواندن و قابل نگهداری بنویسید.
معماری برنامه
- ماژولار بودن برنامهی خود را به چند بخش مستقل تقسیم کنید (رابطهای کوچک و کاملا مشخص برای هر ماژول یا تابع).
- جداسازی هر بخش از برنامه باید بتواند صرف نظر از عملکرد سایر بخشهای برنامه، به درستی کار کند.
- دفاع در عمق به جای اعتماد به یک مکانیسم محافظت، چندین لایهی دفاعی بسازید. به عنوان مثال: داده های ورودی کاربر را در نقطه ورود، اعتبارسنجی کنید و تمام مقادیری که به بخشهای حساس برنامه (مانند مدیریت فایل و...) منتقل میشوند را دوباره بررسی کنید.
- ساده سازی استفاده از راهکارهای پیچیده، به احتمال زیاد کد شما را ناامن میکند.
طراحی برنامه
- بخشهای حساس و امنیتی کد را به بخشهای کوچکتر تقسیم کنید.
- اصل حداقل بودن اختیارات(به انگلیسی: Principle of least privilege) را رعایت کنید. این اصل بیان میکند که هر موجودیتی(اعم از کاربر، فرآیند یا بخشی از برنامه) تنها به اطلاعات و منابعی دسترسی داشته باشد که برای رسیدن به اهداف مشروع خود به آنها نیاز دارد. به عبارت دیگر، به هر کس تنها به اندازهای اطلاعات داده میشود که به آن نیاز دارد. مثال: کد خود را با کمترین اختیار مورد نیاز کاربر اجرا کنید و آن را به عنوان root یا با پرچم SUID اجرا نکنید
- از نرمافزار، با حساب کاربری ادمین اصلی، به پایگاه داده متصل نشوید.
- پیش فرضهای امن را انتخاب کنید؛ برای مثال: هنگام ثبت نام کاربران از یک گذرواژهی تصادفی به جای یک رمز عبور پیش فرض استفاده کنید.
- کاربران را هنگام ورود، اعتبارسنجی کنید.
- مصرف منابع را برای پیشگیری از حملات "Denial of Service" محدود کنید.
- در اپلیکیشنهای تحت وب و توزیع شده به کلاینت اعتماد نکنید. انتظار نداشته باشید که کاربر الزاما دادههای صحیح را وارد کند.به همین دلیل، شما باید تمام دادههای ورودی کاربران را (مجددا) در سمت سرور اعتبارسنجی کنید. به یاد داشته باشید که فیلدهای سرآیند پاسخ HTTP (کوکیها، user-agent, referrer و...) ممکن است جعل یا دستکاری شوند.
- از الگوریتمهای رمزنگاری عمومی استفاده کنید. به جای آنکه خودتان الگوریتمها یا پروتکلهای رمزنگاری شده بنویسید؛ از الگوریتمها، پروتکلها و محصولات قابل اعتماد عمومی، برای رمزنگاری استفاده کنید.
کدنویسی برنامه
- به دادههای ورودی اعتماد نکنید و تمام آنها را اعتبارسنجی کنید. همهی ورودیها در سطوح مختلف را تا زمان اعتبارسنجی، خطرناک تلقی کرده و به صورت پیش فرض رد کنید چرا که دادههای وارد شده توسط کاربران، دلیل اصلی بروز حوادث مربوط به امنیت (Buffer overflow ،SQL Injection، تزریق اسکریپت از طریق درگاه (XSS)، کد درون دادهها و...) است.
- هیچ گونه پیش فرضی در مورد محیط نداشته باشید. اطمینان حاصل کنید که کد شما با PATH تغییر یافته، CLASSPATH و سایر متغیرهای محیطی، دایرکتوری فعلی، متغیر INC Perl@، سیگنالها، umask و... به مشکل برخورد نمیکند.
- مراقب شرایط رقابت باشید و برای هر اتفاقی آمادگی داشته باشید. آیا کد شما میتواند به صورت موازی اجرا شود؟ اگر کسی دو نمونه از برنامهی شما را همزمان اجرا کند یا محیط را در میانهی اجرای خود تغییر دهد، چه اتفاقی رخ میدهد؟
- استثنائات و خطاها را مدیریت کنید. گمان نکنید که همه چیز به درستی کار خواهد کرد (به خصوص عملیات فایل و فراخوانیهای سیستم و شبکه)، استثنائات را تست کرده و نتایج کد را بررسی کنید. پیامهای خطای داخلی، خطای کوئریهای SQL، ردیابی پشته و... را به کاربران نمایش ندهید.
- جزئیات وقایع را ثبت کنید. اگر خطای غیر منتظرانهای وجود دارد که نمیتوانید آن را بازیابی کنید؛ جزئیات وقایع را ثبت کنید. سپس به مدیر سیستم هشدار دهید؛ سیستم را تمیز کرده(حذف فایلهای موقت و پاک کردن حافظه) و کاربر را مطلع کنید.
- از گذر واژهها و اطلاعات مخفی محافظت کنید. تا حد امکان از رمزهای عبور با کد سخت افزاری استفاده نکنید چرا که تغییر دادن آنها دشوار و افشای آنها آسان است. به جای آن از فایلهای اکسترنال رمزگذاری شده استفاده کنید یا اعتبارنامههای موجود (مانند گواهینامهها) را وارد کنید و یا به سادگی از کاربر بخواهید تا رمز عبور را وارد کند.
- هنگام استفاده از فایلها محتاط باشید. در صورت ایجاد فایلهای تکراری گزارش خطا ارسال کنید. پس از ایجاد فایل، مجوزهای آن را تنظیم کنید.اگر فایلی را برای خواندن دادهها باز میکنید، درخواست مجوز نوشتن در آن فایل نداشته باشید. قبل و بعد از باز کردن فایل، بررسی کنید که فایل باز شده، با تابع ()lstat پیوندی نداشته باشد(تابع ()lstat اطلاعاتی را دربارهی یک فایل یا یک لینک سمبلیک بازمیگرداند). همچنین هنگامی که نام یک فایل (یا بخشی از آن) توسط کاربر تعیین میشود، بسیار مراقب باشید و سیاستهای خاصی را برای آن در نظر بگیرید.
- در فراخوانیهای Shell، توابع eval و... دقت کنید. چنین توابعی، آرگومان رشته را به عنوان کد، ارزیابی و تفسیر کرده یا آن را بر روی Shell اجرا میکنند. بنابراین اگر یک مهاجم، موفق به وارد کردن ورودی مخرب به آن آرگومان شود، شما کد او را اجرا میکنید.
- از ایجاد و استفاده از فایلهای موقت اجتناب کنید. لولهها (Pipeline) روشی مطمئنتر و کارآمدتر در برقراری ارتباط بین فرآیندها هستند. فایلهای موقت، شما را در برابر حملات سیملینک یا "Symbolic Link" آسیب پذیر میکنند(در این حمله کاربر مخرب نام فایل موقت شما را حدس میزند و آن را به فایل دیگری، مثلاً bin / bash شما پیوند میدهد و یک Shortcut از برنامه ایجاد میکند). هنگامی که مجبور به استفاده از فایل های موقت هستید؛ در نامگذاری این فایلها، از اسامی غیر قابل حدس و منحصر به فرد استفاده کنید.
شما میتوانید با استفاده از روشهای زیر از بروز حملات سیملینک پیشگیری کنید:
- کم کردن سطح دسترسی فایلها و پوشهها(تغییر مجوز دسترسی یا مجوز فایل /bin/ln به ۴۰۰). در سیستم عامل لینوکس با استفاده از دستور chmod میتوانید این کار را انجام دهید:
Chmod 400 /bin/ln
- اگر از هاست اشتراکی استفاده میکنید، مجوز فایلهای تنظیمات یا پیکربندی خودتان را به ۴۰۰ تغییر دهید.
- فایل php.ini را بیابید و توابع symlink و proc_open را در سرور خود، غیر فعال کنید.
- از اجرای اسکریپتهای cgi ،Python ،Perl و… در صورتی که به آنها نیاز ندارید، خودداری کنید.
- حالت "safe mode" سرور خود را فعال کنید.
- از جدیدترین نسخهی وب سرور استفاده کنید.
امنیت کد بعد از پیادهسازی
- کد خود را مرور کنید و از همکارانتان بخواهید تا در این کار به شما کمک کنند.
- از ابزارهای اختصاصی زبان برنامهنویسی خود استفاده کنید. مانند: Bounds checkers, memory testers, bug finders و...
- هشدارهای کامپایلر با مفسر را روشن کنید و آنها را بررسی کنید(perl-w، gcc -Wall).
- اطلاعات عیبیابی یا debugging را غیر فعال کنید(strip command ،javac -g:none و...).
تست امنیت کد چیست؟
تست امنیت، نوعی از تستهای نرمافزاری است که آسیبپذیریها، خطرات و تهدیدات موجود در یک نرمافزار را کشف کرده و به شما کمک میکند تا با شناسایی و رفع آنها از حملات مخرب جلوگیری کنید. هدف از تستهای امنیتی شناسایی تمام نقاط ضعف و ضعفهای ممکن سیستم نرمافزاری است که تشخیص آن به توسعه دهندگان در رفع مشکلات و خطرات احتمالی از طریق کدنویسی کمک میکند.
انواع تست امنیتی
تستهای امنیتی را میتوان به ۷ نوع کلی تقسیم کرد:
- Vulnerability Scanning این تست از طریق نرمافزار به صورت خودکار انجام میشود تا سیستم در برابر اثرات آسیبپذیریهای شناخته شده اسکن شود.
- Security Scanning اسکن امنیتی، شامل شناسایی نقاط ضعف شبکه و سیستم است و راهکارهایی برای کاهش این خطرات ارائه میدهد. این اسکن در هر دو حالت دستی و خودکار قابل انجام است.
- Penetration testing در این نوع تست نفوذ، حملهی هکرهای مخرب شبیهسازی میشود. به طور کلی این تست شامل تجزیه و تحلیل یک سیستم خاص برای بررسی آسیبپذیریهای خارجی احتمالی است.
- Risk Assessment تست ارزیابی ریسک، شامل تجزیه و تحلیل خطرات امنیتی است که در سازمان مشاهده میشود. ریسکها به گروههای کم، متوسط و زیاد طبقهبندی میشوند. این تست، کنترلها و اقدامات لازم را برای کاهش ریسک توصیه میکند.
- Security Auditing این تست یک بازرسی داخلی از جریان امنیتی برنامهها و سیستم عاملها انجام میدهد. همچنین میتواند بازرسی خط به خط کد را انجام دهد.
- Ethical hacking در تست هک اخلاقی، متخصصان امنیت تلاش میکنند تا با هک کردن اخلاق مدارانهی سیستمهای نرمافزاری سازمان، آسیبپذیریهای آن را کشف کنند. بر خلاف هکرهای مخرب، هدف این هکرها پیدا کردن نقصهای امنیتی سیستم است.
- Posture Assessment این تست ترکیبی از اسکن امنیتی، هک اخلاقی و ارزیابی ریسک را به نمایش میگذارد تا وضعیت امنیتی کلی یک سازمان را نشان دهد.
چه زمانی تست امنیت نرمافزار را انجام دهیم؟
بررسیها نشان میدهد که به تعویق انداختن تست نرمافزار به بعد از مرحلهی اجرای نرمافزار، هزینه بیشتری را برای سازمانها در پی خواهد داشت. بنابراین بهتر است تستهای امنیتی را از ابتدا تا انتهای چرخهی عمر توسعهی نرمافزار به عنوان بخشی از فرآیند توسعهی نرمافزار در نظر بگیریم.
ابزارهای تست امنیت نرمافزار
ابزارهای تست امنیت نرمافزار به شما کمک میکنند تا این فرآیند را با دقت بالاتر و سرعت بیشتری انجام دهید. در ادامه برخی از این ابزارها را به شما معرفی میکنیم.
- OWASP
OWASP یک سازمان غیر انتفاعی جهانی است که تمرکز آن بر بهبود امنیت نرمافزار میباشد. این پروژه چندین ابزار تست نفوذ و پروتکلها و محیطهای مختلف نرمافزاری را در خود جای داده است. از جمله:
Zed Attack Proxy یا ZAP: تست نفوذ یکپارچه
OWASP Dependency Check: بررسی وابستگیهای پروژه برای کشف آسیبپذیریها
OWASP Web Testing Environment Project: مجموعهای از ابزارها و مستندات امنیتی
- WireShark
Wireshark ابزاری برای تجزیه و تحلیل ترافیک و پروتکلهای شبکه است که قبلاً با نام Ethereal شناخته شده بود. این ابزار، بستهها را به صورت بلادرنگ ضبط میکند و آنها را در قالبی قابل خواندن توسط انسان، نمایش میدهد. وایرشارک اطلاعات دقیقی در مورد پروتکلهای شبکه، رمزنگاری، اطلاعات بستهها و... ارائه میدهد. این ابزار متن باز بوده و میتواند در لینوکس، ویندوز، OS X، Solaris، NetBSD ، FreeBSD و بسیاری سیستمهای دیگر مورد استفاده قرار گیرد.
- W3af
W3af یک اسکنر محبوب و رایگان است که سه نوع پلاگین کشف، ارزیابی و حمله را در خود جای داده است. این سه پلاگین با یکدیگر برای کشف هرگونه آسیبپذیری در سایت ارتباط برقرار میکنند، به عنوان مثال یک پلاگین کشف در w3af به دنبال آدرسهای مختلف برای تست آسیبپذیریها و ارسال آن به پلاگین ارزیابی است و سپس از این آدرسها برای جستجوی آسیبپذیریها استفاده میکند.
جمع بندی
امروزه بیش از هر زمان دیگری نیاز به امنیت در دنیای تکنولوژی احساس میشود. وجود رخنهها و آسیبپذیریهای نرمافزاری، ضررهای زیادی به سازمانها وارد میکند. سازمانها همواره به دنبال روشهای بهبود امنیت نرمافزارها و حفظ دادههای مهم خود و کاربران هستند. برنامهنویسان میتوانند به کمک نکات سادهای که در چکلیست برنامهنویسی امن به آنها پرداخته شد، با کدنویسی امن به سازمانها در این زمینه کمک کنند. همچنین میتوانند با استفاده از ابزارهای تست امنیت نرمافزار مانند: WOASP، Wireshark، W3af و... آسیبپذیریها را کشف کرده و آنها را رفع کنند.