چگونه یک تست امنیتی بنویسیم

htxt.africaقبل شروع موضوعات باید بگم این نوشته طولانی است و اگر حال خواندن این مطلب را نداشتید به طور خلاصه باید بگم اگر می خواهید نرم افزار مورد نظرتان حد اقل های امنیتی را داشته باشد باید در هر مرحله از توسعه نرم افزارتان تست های امنیتی را جدا از تست های دیگر اجرا کنید و به قول آقای یاشار شاهین زاده Continuous Scanning داشته باشید.اگر بخواهیم برنامه ای بنویسیم که حد اقل های امنیتی را دارا باشد باید امنیت را در چرخه حیات توسعه نرم افزار در نظر بگیریم.چون تست امنیت بعد از تولید نرم افزار هزینه بر تر خواهد بود.چرخه حیات توسعه نرم افزار یا SDLCبرای تعریف Software Development Life Cycle می شود گفت یک طرح دقیق شامل نحوه توسعه(development)،نگهداری(maintain)،جایگزینی یا تغیر نرم افزاری خاص است.به بیان دیگر یک روش برای بهبود کیفیت و فرآیند توسعه نرم افزار است که شامل مراحل زیر می شود.tutorialspointمدل های معرفی شده برای SDLC را شاید خیلی شنیده باشید مانندمدل Waterfallمدل Iterativeمدل Spiralمدل Vمدل Agile...در چرخه حیات توسعه نرم افزار بحثی با نام چرخه حیات توسعه نرم افزار امن یا S-SDLC مطرح است که به افراد نقشه راه یا roadmap می دهد برای اطلاعات بیشتر در این زمینه به ویکی OWASP مراجعه کنید.در چرخه حیات هر بخش کار امنیت خاص خود را دارد برای مثال طبق تصویر زیرguru99در مرحله پیش نیاز ها یا Requirements باید پش نیاز های لازم برای تست و الزامات و موارد سوء استفاده تجزیه و تحلیل شود.در مرحله طراحی یا Design باید خطرات احتمالی در طراحی بررسی و در تست ها در نظر گرفته شود.در مرحله کد نویسی و تست واحد یا Coding & Unit Testing باید به صورت ثابت یا پویا با در نظر گرفتن کد ها و به صورت White Box تست انجام شود.در مرحله تست یکپارچه یا Integration Testing باید بدون در نظر گفتن کد و به صورت Black Box تست انجام شود.در مرحله تست سیستم یا System Testing باید علاوه بر تست Black Box باید آسیب پذیری های احتمالی بررسی شود.در مرحله پیاده سازی یا Implementation باید تست نفوذ همراه با شناسایی آسیب پذیری ها صورت گیرد.در مرحله آخر چرخه حیات توسعه نرم افزار باید بحث پشتیبانی یا Support در نظر گرفته شود به این معنی که اثرات یا Impact ها تجزیه و تحلیل شود.در تصویر زیر علاوه بر موارد بالا مواردی مثل آموزش توسعه دهندگان هم در نظر گرفته شده استموارد کاربرد های تستتست های امنیتی باید موارد زیر را بررسی کنند تا بتوانند طیف وسیعی از آسیب پذیری های احتمالی پوشش دهند.سطح دسترسی و احراز هویت بررسی ورود ها و رمز گذاری(Encoding)رمزگذاری(Encryption)نشست های کاربرمدیریت و کنترل خطاهاگزارش گیری یا Loggingسناریو های تستخواندن و بررسی سناریو ها یک راه خوب برای نوشتن یک تست خوب است.برای مثال داخل این مخزن و یا این یکی موارد بسیار خوبی قرار گرفته است که با خواندن و بررسی می توان تست بهتری نوشت.ابتدا چند سناریو را بررسی کنیمفرم ورودی داریم که نام کاربری و کلمه عبور میگیرد پس تست ما پس باید موارد زیر را بررسی کند.نام کاربری نباید شامل مواردی مانند "Admin" یا "Administrator" باشد.کلمه عبور نباید کمتر از ۸ رقم باشد.پیام ثبت نام نباید شامل پیام های آشکار مانند "ایمیل قبلا موجود است" یا "نام کاربری قبلا ثبت شده است" باشد.هر یک از ورودی ها باید بررسی شود تا از ورود کاراکتر های مخرب جلوگیری شود.درخواست ورود نباید بیشتر از ۳ بار باشد.پیام های خطای سیستمی مانند "syntax error" به هیچ عنوان نباید نشان داده شود.اطلاعات حساس فرم به هیچ عنوان نباید در url استفاده شود.فضاهای خالی در ورودی ها از لحاظ کاراکتر های مخرب و یا رمز شده بررسی شود .قسمت جست و جو محصولاتی داریم که یک ورودی از کاربر میگیرد.ورودی مربوط باید سمت سرور بررسی شود نه در سمت کاربرورودی باید شامل کاراکتر های مجاز باشد و مثلا کاراکتر ها و یا کلماتی که سمت سرور و دیتابیس رزرو شده است نباید اجازه اجرا داده شود.بررسی درخواست جست و جو باید دو بار انجام شودیکبار موقع ارسال درخواست و یکبار موقع ارسال نتایج که مطمئن شویم این همان مورد جست و جو شده کاربر است.دکمه ارسال درخواست نباید سمت کاربر تایید شودخیلی مواقع پیش میاید دکمه ارسال سمت کاربر و با جاوااسکریپت بررسی و سپس فرم ارسال می شوداین مورد بستر بسیار مناسبی را برای xss به وجود می آورد.تا حد ممکن درخواست رمز و سپس ارسال شود. نوشتن یک تستبا توجه به زبان و تکنولوژی که با آن کار می کنید فریمورک های تست هم متفاوت است برای مثالJUnit(java)PHPUnitPyUnit(python)NUnit(.net)اگر بخواهیم لایه به لایه به تست نگاه کنیم پس ابتدا باید Unit Test انجام شود.مثلا در JUnit برای تست معتبر بودن ورودی می توان از کد زیر استفاده کرد(دقت کنید قرار است پیش نیاز های هر حمله مورد بررسی قرار بگید).public void testIllegalCharactersInPhoneNumber() { String number = "+(23)';[]232 - 321"; acc.setPhone(number); validator.validate(acc, errors); assertTrue(number+" did not cause a validation error.", errors.hasFieldErrors("phone")); } public void testAlphabeticInPhoneNumber() { String number = "12a12121"; acc.setPhone(number); validator.validate(acc, errors); assertTrue(number+" did not cause a validation error.", errors.hasFieldErrors("phone")); }از مزیت های تست در لایه Unit Test می توان به مشکلات سریعا شناسایی می شوندتست ها به سرعت انجام می شوندپوشش بالا تستاز معایب تست در لایه Unit Test هم می توان به بسیار از آسیب پذیری ها در این لایه قابل شناسایی نیستندلایه بعدی Integration Test است.برای مثال برای بررسی سطح دسترسی می توان از کد زیر استفاده کرد.public class TestAccessControl extends ServletTestCase { public void beginUnprivilegedUserAccessControl(WebRequest theRequest) { theRequest.setAuthentication(new BasicAuthentication("user", "password")); } public void testUnprivilegedUserAccessControl() throws IOException, javax.servlet.ServletException { AdminServlet admin = new AdminServlet(); admin.doGet(request, response); } public void endUnprivilegedUserAccessControl(WebResponse theResponse) throws IOException { assertTrue("Normal users must not be able to access /admin", theResponse.getStatusCode() == 401) } }از مزایا تست در لایه Integration می توان بهتست نرم افزار ها تحت سرورشناسایی آسیب پذیری های بیشتر نسبت به لایه قبل مانند انواع injection از معایب هم می توان بهبار اضافی برای سیستمعدم شناسایی آسان آسیب پذیری هایی مانند xss لایه بعدی Acceptance Test است.که بسیار از ابزار های شناسایی آسیب پذیری به صورت Black box در این لایه کار می کنندو برای تست API خارجی کاربردی است.ابزار های این لایه به دو دسته۱- HTTP client یا HTML parser ۲-Driver Browser Instance روش اول مانند ابزار هایی مانند HTTPUnit مانند یک کاربر پروتکل http عمل می کنند.روش دوم هم مانند WATIR یا Selenium مانند یک مرورگر عمل می کنند.برای مثال برای تست SQL Injection با WATIR می توان از کد زیر استفاده کرد.class SQL_Injection_Test < Test::Unit::TestCase include Watir def test_SQL_Blind_Injection_in_Login() $ie.goto('http://localhost:8080/ispatula') $ie.link(:url, /signonForm.do/).click $ie.text_field(:name, 'username').set('corsaire1\' OR 1=1--') $ie.form(:action, "/ispatula/shop/signon.do").submit assert($ie.contains_text('Signon failed')); end endخودکار سازی فرآیند تستدر توسعه نرم افزار چابک و سیستم هایی که CI/CD دارند بحث خودکار سازی فرآیند تست می تواند کار ساز باشد.برای مثال در تصویر زیر بعد از کامیت شدن کد در Jenkins موقع هر build تست ها اجرا و تست دیگری بر اساس زمان بندی تعریف شده اجرا و نتایج در سرور تست ها ذخیره و آسیب پذیری های کشف شده در Vulnerability Management ذخیره می شود.secodisدر این سیستم برای بخش Pipline به صورت زمان بندی شده از اسکنری مانند Arachni استفاده می کنند تا آخرین آسیب پذیری های کشف شده بر روی کد شناسایی و گزارش شود(به جای ThreadFix از sonarqube هم می توانید استفاده کنید).واقعیت با توجه به پیشرفت تکنولوژی و هوش مصنوعی، خودکار سازی فرآیند های تست آسان تر شده است.ولی این به معنی نیست که باید این تست ها اطمینان شود و گاهی خود این فرآیند خودکار سازی بستر جدید حمله برای هکر خواهد شد.برای اطلاعات بیشتر فایل ارائه آقای وحید بهزادان مراجعه کنید.معذرت بابت کم و کاستی های فراوان این مطلب خیلی خوشحال میشوم نظرات خود را اینجا بگذاریدبا تشکر از شمامنابعguru99.comtutorialspoint.comSecurity Testing through Automated Software Tests - OWASPSecure Development Lifecycle - OWASPhttps://blog.secodis.comhttps://bawetech.com