Server ilovalarida eng muhim ko'rsatkichlardan biri xavfsizlikdir. Bu Funktsional bo'lmagan talablarning turlaridan biridir . Xavfsizlik ko'plab komponentlarga ega. Albatta, ma'lum bo'lgan barcha himoya tamoyillari va harakatlarini to'liq qamrab olish uchun siz bir nechta maqola yozishingiz kerak, shuning uchun eng muhimlariga e'tibor qarataylik. Ushbu mavzuni yaxshi biladigan, barcha jarayonlarni o'rnata oladigan va ular yangi xavfsizlik teshiklarini yaratmasligini ta'minlaydigan odam har qanday jamoaga kerak bo'ladi. Albatta, agar siz ushbu amaliyotlarga rioya qilsangiz, dastur butunlay xavfsiz bo'ladi deb o'ylamasligingiz kerak. Yo'q! Lekin, albatta, ular bilan xavfsizroq bo'ladi. Bor.
1. Java tili darajasida xavfsizlikni ta'minlang
Birinchidan, Java-da xavfsizlik to'g'ridan-to'g'ri til xususiyatlari darajasida boshlanadi. Kirish modifikatorlari bo'lmaganida, biz nima qilar edik?... Anarxiya, kam emas. Dasturlash tili bizga xavfsiz kod yozishga yordam beradi va ko'plab yashirin xavfsizlik xususiyatlaridan foydalanishga yordam beradi:- Kuchli yozish. Java statik tarzda yozilgan til bo'lib, ish vaqtida xatoliklarni aniqlash imkonini beradi.
- Kirish modifikatorlari. Ularning yordami bilan biz sinflar, usullar va sinf maydonlariga kirishni kerakli tarzda sozlashimiz mumkin.
- Avtomatik xotirani boshqarish. Shu maqsadda bizda (Javachilar ;)) sizni qo'lda sozlashdan ozod qiladigan Garbage Collector mavjud. Ha, ba'zida muammolar paydo bo'ladi.
- Bayt kodini tekshirish: Java uni ishga tushirishdan oldin ish vaqti bo'yicha tekshiriladigan bayt kodiga kompilyatsiya qiladi .
- Xavfsiz sezgir sinflarni ketma-ketlashtirishdan saqlaning. Bunday holda siz seriyali fayldan sinf interfeysini olishingiz mumkin, ketma-ketlashtirilayotgan ma'lumotlarni hisobga olmaganda.
- O'zgaruvchan ma'lumotlar sinflaridan qochishga harakat qiling. Bu o'zgarmas sinflarning barcha afzalliklarini beradi (masalan, ip xavfsizligi). Agar o'zgaruvchan ob'ekt bo'lsa, bu kutilmagan xatti-harakatlarga olib kelishi mumkin.
- Qaytarilgan o'zgaruvchan ob'ektlarning nusxalarini yarating. Agar usul ichki o'zgaruvchan ob'ektga havolani qaytarsa, mijoz kodi ob'ektning ichki holatini o'zgartirishi mumkin.
- Va hokazo…
2. SQL injection zaifligini yo'q qilish
Noyob zaiflik. Uning o'ziga xosligi shundaki, u eng mashhur va eng keng tarqalgan zaifliklardan biri hisoblanadi. Agar siz xavfsizlik masalasiga qiziqmasangiz, unda siz bu haqda bilmaysiz. SQL in'ektsiyasi nima? Bu kutilmagan joyda qo'shimcha SQL kodini kiritish orqali ma'lumotlar bazasiga hujum. Aytaylik, bizda ma'lumotlar bazasini so'rash uchun ba'zi parametrlarni oladigan usul mavjud. Masalan, foydalanuvchi nomi. Zaiflikka ega kod quyidagicha ko'rinadi:// Метод достает из базы данных всех пользователей с определенным именем
public List<User> findByFirstName(String firstName) throws SQLException {
// Создается связь с базой данных
Connection connection = DriverManager.getConnection(DB_URL, USER, PASS);
// Пишем sql request в базу данных с нашим firstName
String query = "SELECT * FROM USERS WHERE firstName = " + firstName;
// выполняем request
Statement statement = connection.createStatement();
ResultSet result = statement.executeQuery(query);
// при помощи mapToUsers переводит ResultSet в коллекцию юзеров.
return mapToUsers(result);
}
private List<User> mapToUsers(ResultSet resultSet) {
//переводит в коллекцию юзеров
}
Bu misolda sql so'rovi alohida satrda oldindan tayyorlangan. Muammo nimada ekan, shunday emasmi? Ehtimol, muammo shundaki, undan foydalanish yaxshiroqmi String.format
? Yo'qmi? Keyin nima? Keling, o'zimizni sinovchining o'rniga qo'yaylik va qiymatda nimani etkazish mumkinligi haqida o'ylaymiz firstName
. Masalan:
- Siz kutilgan narsani o'tkazishingiz mumkin - foydalanuvchi nomi. Keyin ma'lumotlar bazasi shu nomdagi barcha foydalanuvchilarni qaytaradi.
- Siz bo'sh qatorni o'tkazishingiz mumkin: keyin barcha foydalanuvchilar qaytariladi.
- Yoki siz quyidagilarni topshirishingiz mumkin: “''; JADVAL FOYDALANUVCHILARINI TOSHLASH;”. Va bu erda yanada katta muammolar bo'ladi. Ushbu so'rov jadvalni ma'lumotlar bazasidan olib tashlaydi. Barcha ma'lumotlar bilan. HAMMA.
// Метод достает из базы данных всех пользователей с определенным именем
public List<User> findByFirstName(String firstName) throws SQLException {
// Создается связь с базой данных
Connection connection = DriverManager.getConnection(DB_URL, USER, PASS);
// Создаем параметризированный request.
String query = "SELECT * FROM USERS WHERE firstName = ?";
// Создаем подготовленный стейтмент с параметризованным requestом
PreparedStatement statement = connection.prepareStatement(query);
// Передаем meaning параметра
statement.setString(1, firstName);
// выполняем request
ResultSet result = statement.executeQuery(query);
// при помощи mapToUsers переводим ResultSet в коллекцию юзеров.
return mapToUsers(result);
}
private List<User> mapToUsers(ResultSet resultSet) {
//переводим в коллекцию юзеров
}
Shunday qilib, bu zaiflikning oldini oladi. Ushbu maqoladan ko'ra muammoga chuqurroq kirishni istaganlar uchun bu erda ajoyib misol . Bu qismni tushunganingizni qanday bilasiz? Agar quyidagi hazil aniq bo'lsa, bu zaiflikning mohiyati aniq ekanligining aniq belgisidir: D
3. Bog'liqlarni skanerlang va yangilab turing
Bu nima degani? Bog'liqlik nima ekanligini bilmaganlar uchun tushuntiraman: bu boshqa birovning yechimini qayta ishlatish uchun avtomatik qurish tizimlari (Maven, Gradle, Ant) yordamida loyihaga ulangan kodli jar arxivi. Masalan, biz uchun ish vaqtida oluvchilar, o'rnatuvchilar va hokazolarni ishlab chiqaradigan Project Lombok . Va agar biz katta ilovalar haqida gapiradigan bo'lsak, ular juda ko'p turli xil bog'liqliklardan foydalanadilar. Ba'zilari tranzitivdir (ya'ni har bir bog'liqlikning o'ziga xos bog'liqliklari bo'lishi mumkin va hokazo). Shu sababli, tajovuzkorlar ochiq manbali bog'liqliklarga tobora ko'proq e'tibor berishmoqda, chunki ular muntazam ravishda qo'llaniladi va ko'plab mijozlar uchun muammolarga olib kelishi mumkin. To'liq qaramlik daraxtida ma'lum zaifliklar yo'qligiga ishonch hosil qilish muhim (bu xuddi shunday ko'rinadi). Va buni amalga oshirishning bir necha yo'li mavjud.Monitoring uchun Snyk-dan foydalaning
Snyk vositasi loyihaning barcha bog'liqliklarini tekshiradi va ma'lum zaifliklarni belgilaydi. U erda, masalan, GitHub orqali loyihalaringizni ro'yxatdan o'tkazishingiz va import qilishingiz mumkin. Bundan tashqari, yuqoridagi rasmdan ko'rinib turibdiki, agar yangiroq versiyada ushbu zaiflikka yechim bo'lsa, Snyk buni qilishni va Pull-Request yaratishni taklif qiladi. U ochiq kodli loyihalar uchun bepul ishlatilishi mumkin. Loyihalar ma'lum bir chastotada skanerdan o'tkaziladi: haftada bir marta, oyda bir marta. Men ro'yxatdan o'tdim va barcha ommaviy omborlarimni Snyk skaneriga qo'shdim (bu erda hech qanday xavfli narsa yo'q: ular allaqachon hamma uchun ochiq). Keyinchalik, Snyk skanerlash natijasini ko'rsatdi: Va bir muncha vaqt o'tgach, Snyk-bot bog'liqliklar yangilanishi kerak bo'lgan loyihalarda bir nechta Pull-Requestlarni tayyorladi: Va yana bir narsa: Demak, bu zaifliklarni qidirish va yangilanishni kuzatish uchun ajoyib vosita. yangi versiyalar.GitHub xavfsizlik laboratoriyasidan foydalaning
GitHub-da ishlaydiganlar o'zlarining o'rnatilgan vositalaridan ham foydalanishlari mumkin. Ushbu yondashuv haqida ko'proq ma'lumotni GitHub Xavfsizlik Laboratoriyasining e'lonlari blogidagi tarjimamda o'qishingiz mumkin . Ushbu vosita, albatta, Snyk-ga qaraganda sodda, ammo siz buni e'tiborsiz qoldirmasligingiz kerak. Bundan tashqari, ma'lum zaifliklar soni faqat o'sib boradi, shuning uchun ham Snyk, ham GitHub Security Lab kengayadi va yaxshilanadi.Sonatype DepShield-ni faollashtiring
Agar siz omborlaringizni saqlash uchun GitHub-dan foydalansangiz, MarketPlace - Sonatype DepShield-dan loyihalaringizga ilovalardan birini qo'shishingiz mumkin. Uning yordami bilan siz loyihalarni bog'liqliklar uchun ham skanerlashingiz mumkin. Bundan tashqari, agar biror narsa topilsa, quyida ko'rsatilganidek, tegishli tavsif bilan GitHub muammosi yaratiladi:4. Nozik ma'lumotlarga ehtiyotkorlik bilan munosabatda bo'ling
Ingliz tilida nutqda "sezgir ma'lumotlar" iborasi ko'proq uchraydi. Mijozning shaxsiy ma'lumotlari, kredit karta raqamlari va boshqa shaxsiy ma'lumotlarini oshkor qilish tuzatib bo'lmaydigan zarar etkazishi mumkin. Avvalo, siz dastur dizaynini diqqat bilan ko'rib chiqishingiz va biron bir ma'lumot haqiqatan ham zarurligini aniqlashingiz kerak. Ehtimol, ularning ba'zilariga ehtiyoj yo'q, lekin ular kelmagan va kelishi dargumon kelajak uchun qo'shilgan. Bundan tashqari, loyiha jurnali paytida bunday ma'lumotlar oqishi mumkin.toString()
Maxfiy ma'lumotlarning jurnallaringizga kirishini oldini olishning oddiy usuli bu domen ob'ektlari usullarini (masalan, Foydalanuvchi, Talaba, O'qituvchi va boshqalar) tozalashdir . Bu nozik maydonlarni tasodifan chop etishning oldini oladi. Agar usul yaratish uchun Lombok'dan foydalansangiz , maydonni usuli orqali chiqishda foydalanishni oldini olish uchun toString()
izohdan foydalanishingiz mumkin . Bundan tashqari, tashqi dunyo bilan ma'lumotlarni almashishda juda ehtiyot bo'ling. Misol uchun, barcha foydalanuvchilarning ismlarini ko'rsatadigan http so'nggi nuqtasi mavjud. Foydalanuvchining ichki noyob identifikatorini ko'rsatishning hojati yo'q. Nega? Chunki undan foydalanib, tajovuzkor har bir foydalanuvchi haqida boshqa, ko'proq maxfiy ma'lumotlarni olishi mumkin. Misol uchun, agar siz POJO-larni JSON- ga seriyalashtirish va seriyadan chiqarish uchun Jeksondan foydalansangiz, muayyan maydonlarni ketma-ketlashtirish va seriyadan chiqarishni oldini olish uchun va izohlardan foydalanishingiz mumkin . Umuman olganda, turli joylar uchun turli POJO sinflaridan foydalanishingiz kerak. Bu nima degani? @ToString.Exclude
toString()
@JsonIgnore
@JsonIgnoreProperties
- Ma'lumotlar bazasi bilan ishlash uchun faqat POJO - Entity dan foydalaning.
- Biznes mantig'i bilan ishlash uchun ob'ektni Modelga o'tkazing.
- Tashqi dunyo bilan ishlash va http so'rovlarini yuborish uchun uchinchi shaxslar - DTO dan foydalaning.
Kuchli shifrlash va xeshlash algoritmlaridan foydalaning
Mijozlarning maxfiy ma'lumotlari xavfsiz tarzda saqlanishi kerak. Buning uchun siz shifrlashdan foydalanishingiz kerak. Vazifaga qarab, qanday shifrlash turidan foydalanishni hal qilishingiz kerak. Bundan tashqari, kuchliroq shifrlash ko'proq vaqt talab etadi, shuning uchun unga bo'lgan ehtiyoj unga sarflangan vaqtni qanchalik oqlashini yana bir bor o'ylab ko'rishingiz kerak. Albatta, algoritmni o'zingiz yozishingiz mumkin. Lekin bu keraksiz. Siz ushbu sohada mavjud echimlardan foydalanishingiz mumkin. Masalan, Google Tink :<!-- https://mvnrepository.com/artifact/com.google.crypto.tink/tink -->
<dependency>
<groupId>com.google.crypto.tink</groupId>
<artifactId>tink</artifactId>
<version>1.3.0</version>
</dependency>
Keling, uni qanday ishlatishni ko'rib chiqaylik, masalan, qanday qilib shifrlashning bir usuli va boshqasi:
private static void encryptDecryptExample() {
AeadConfig.register();
KeysetHandle handle = KeysetHandle.generateNew(AeadKeyTemplates.AES128_CTR_HMAC_SHA256);
String plaintext = "Цой жив!";
String aad = "Юрий Клинских";
Aead aead = handle.getPrimitive(Aead.class);
byte[] encrypted = aead.encrypt(plaintext.getBytes(), aad.getBytes());
String encryptedString = Base64.getEncoder().encodeToString(encrypted);
System.out.println(encryptedString);
byte[] decrypted = aead.decrypt(Base64.getDecoder().decode(encrypted), aad.getBytes());
System.out.println(new String(decrypted));
}
Parolni shifrlash
Ushbu vazifa uchun assimetrik shifrlashdan foydalanish eng xavfsiz hisoblanadi. Nega? Chunki ilova haqiqatan ham parollarni qayta shifrlashi shart emas. Bu umumiy yondashuv. Haqiqatda, foydalanuvchi parolni kiritganda, tizim uni shifrlaydi va uni parollar omboridagi narsalar bilan taqqoslaydi. Shifrlash xuddi shu vositalar yordamida amalga oshiriladi, shuning uchun siz ularning mos kelishini kutishingiz mumkin (agar siz to'g'ri parolni kiritsangiz; albatta). Buning uchun BCrypt va SCrypt mos keladi. Har ikkisi ham bir tomonlama funksiyalar (kriptografik xeshlar) bo‘lib, ular juda ko‘p vaqt talab qiladigan hisoblash jihatidan murakkab algoritmlarga ega. Bu sizga kerak bo'lgan narsa, chunki uni boshdan kechirish abadiy davom etadi. Masalan, Spring Security bir qator algoritmlarni qo'llab-quvvatlaydi.SCryptPasswordEncoder
Siz ham foydalanishingiz mumkin BCryptPasswordEncoder
. Endi kuchli shifrlash algoritmi keyingi yil zaif bo'lishi mumkin. Natijada, biz foydalanilgan algoritmlarni tekshirish va kutubxonalarni algoritmlar bilan yangilash kerak degan xulosaga keldik.
Chiqish o'rniga
Bugun biz xavfsizlik haqida gaplashdik va, albatta, ko'p narsalar sahnada qolib ketdi. Men senga endigina yangi dunyo eshigini ochdim: o‘z hayotini o‘tkazadigan dunyo. Xavfsizlik bilan siyosat bilan bir xil: agar siz siyosat bilan shug'ullanmasangiz, siyosat siz bilan shug'ullanadi. An'anaga ko'ra, men Github hisobimga obuna bo'lishni taklif qilaman . U erda men o'zim o'rganadigan va ishda qo'llaydigan turli texnologiyalar bo'yicha ishimni joylashtiraman.foydali havolalar
Ha, saytdagi deyarli barcha maqolalar ingliz tilida yozilgan. Biz xohlaymizmi yoki yo'qmi, ingliz tili dasturchilar uchun muloqot qilish tilidir. Dasturlash bo'yicha barcha eng yangi maqolalar, kitoblar va jurnallar ingliz tilida yozilgan. Shuning uchun tavsiyalarga havolalarim asosan ingliz tilida:- Habr: Yangi boshlanuvchilar uchun SQL Injection
- Oracle: Java Xavfsizlik Resurs Markazi
- Oracle: Java SE uchun xavfsiz kodlash bo'yicha ko'rsatmalar
- Baeldung: Java xavfsizligi asoslari
- O'rta: Java xavfsizligingizni kuchaytirish uchun 10 ta maslahat
- Snyk: Java xavfsizligi bo'yicha 10 ta eng yaxshi amaliyot
- JR: GitHub Security Lab e'loni: barcha kodlaringizni birgalikda himoya qilish
GO TO FULL VERSION