JavaRush /Java блогы /Random-KK /Java-дағы қауіпсіздік: ең жақсы тәжірибелер
Roman Beekeeper
Деңгей

Java-дағы қауіпсіздік: ең жақсы тәжірибелер

Топта жарияланған
Серверлік қосымшаларда маңызды көрсеткіштердің бірі қауіпсіздік болып табылады. Бұл Функционалды емес талаптардың бір түрі . Java-дағы қауіпсіздік: ең жақсы тәжірибелер - 1Қауіпсіздік көптеген компоненттерден тұрады. Әрине, барлық белгілі қорғаныс принциптері мен әрекеттерін толығымен қамту үшін сізге бірнеше мақала жазу керек, сондықтан ең маңыздыларына тоқталайық. Осы тақырыпты жақсы меңгерген, барлық процестерді реттей алатын және олардың жаңа қауіпсіздік саңылауларын жасамайтындығына көз жеткізе алатын адам кез келген командаға қажет болады. Әрине, егер сіз осы тәжірибелерді орындасаңыз, қолданба толығымен қауіпсіз болады деп ойламауыңыз керек. Жоқ! Бірақ олармен қауіпсізрек болады. Бар.

1. Java тілі деңгейінде қауіпсіздікті қамтамасыз етіңіз

Ең алдымен, Java-дағы қауіпсіздік тіл мүмкіндіктері деңгейінде басталады. Кіру модификаторлары болмаса, біз осылай істейтін едік?... Анархия, кем емес. Бағдарламалау тілі бізге қауіпсіз code жазуға көмектеседі, сонымен қатар көптеген жасырын қауіпсіздік мүмкіндіктерін пайдаланады:
  1. Күшті теру. Java – жұмыс уақытында қателерді анықтау мүмкіндігін беретін статикалық түрде терілген тіл.
  2. Қол жеткізу модификаторлары. Олардың арқасында біз сыныптарға, әдістерге және сынып өрістеріне қол жеткізуді қажет етіп конфигурациялай аламыз.
  3. Жадты автоматты басқару. Осы мақсатта бізде (Javaists ;)) сізді қолмен конфигурациялаудан босататын қоқыс жинағыш бар. Иә, кейде қиындықтар туындайды.
  4. Байтcodeты тексеру: Java оны іске қоспас бұрын орындалу уақыты бойынша тексерілетін byte codeқа құрастырады .
Басқа нәрселермен қатар, қауіпсіздік бойынша Oracle ұсыныстары бар . Әрине, бұл «жоғары стильде» жазылмаған және сіз оны оқығанда бірнеше рет ұйықтап қалуыңыз мүмкін, бірақ бұл тұрарлық. Қауіпсіз codeты жазу жолы бойынша кеңестер беретін Java SE үшін қауіпсіз codeтау нұсқаулары ерекше маңызды құжат болып табылады . Бұл құжатта көптеген пайдалы ақпарат бар. Мүмкін болса, міндетті түрде оқуға тұрарлық. Бұл материалға қызығушылықты арттыру үшін мына бірнеше қызықты кеңестер берілген:
  1. Қауіпсіз-сезімтал сыныптарды сериялаудан аулақ болыңыз. Бұл жағдайда, серияланатын деректерді айтпағанда, сынып интерфейсін серияланған файлдан алуға болады.
  2. Өзгермелі деректер кластарынан аулақ болуға тырысыңыз. Бұл өзгермейтін сыныптардың барлық артықшылықтарын береді (мысалы, жіп қауіпсіздігі). Егер өзгермелі нысан болса, бұл күтпеген әрекетке әкелуі мүмкін.
  3. Қайтарылған өзгермелі нысандардың көшірмелерін жасаңыз. Егер әдіс ішкі өзгермелі нысанға сілтемені қайтарса, клиент codeы нысанның ішкі күйін өзгерте алады.
  4. Тағыда басқа…
Жалпы, Java SE үшін қауіпсіз codeтау нұсқаулары Java тілінде codeты дұрыс және қауіпсіз жазуға қатысты кеңестер мен әдістер жинағын қамтиды.

2. SQL инъекциясының осалдығын жою

Бірегей осалдық. Оның бірегейлігі - бұл ең танымал және ең көп таралған осалдықтардың бірі. Қауіпсіздік мәселесі сізді қызықтырмаса, онда сіз бұл туралы білмейсіз. SQL инъекциясы дегеніміз не? Бұл күтпеген жерде қосымша SQL codeын енгізу арқылы дерекқорға шабуыл. Бізде дерекқорды сұрау үшін кейбір параметрді қабылдайтын әдіс бар делік. Мысалы, пайдаланушы аты. Осалдығы бар code келесідей болады:
// Метод достает из базы данных всех пользователей с определенным именем
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) {
   //переводит в коллекцию юзеров
}
Бұл мысалда sql сұрауы алдын ала бөлек жолда дайындалған. Мәселе неде болып көрінеді, солай ма? Мүмкін мәселе оны пайдалану жақсы болар еді String.format? Жоқ? Сонда ше? Өзімізді сынаушының орнына қойып, құндылықта нені жеткізуге болатынын ойланайық firstName. Мысалы:
  1. Сіз күтілетін нәрсені жібере аласыз - пайдаланушы атын. Содан кейін дерекқор осы атаумен барлық пайдаланушыларды қайтарады.
  2. Сіз бос жолды жібере аласыз: содан кейін барлық пайдаланушылар қайтарылады.
  3. Немесе келесіні өтуге болады: “''; КЕСТЕН ​​ПАЙДАЛАНУШЫЛАРЫН ТАСТАУ;». Ал мұнда бұдан да үлкен мәселелер болады. Бұл сұрау кестені дерекқордан жояды. Барлық деректермен. БАРЛЫҚ.
Бұл қандай проблемалар тудыруы мүмкін екенін елестете аласыз ба? Содан кейін қалағаныңызды жаза аласыз. Сіз барлық пайдаланушылардың атын өзгерте аласыз, олардың мекенжайларын жоя аласыз. Диversionның ауқымы кең. Бұған жол бермеу үшін дайын сұрауды енгізуді тоқтатып, оның орнына параметрлерді пайдаланып құрастыру керек. Бұл дерекқорды сұраудың жалғыз жолы болуы керек. Осылайша сіз бұл осалдықты жоя аласыз. Мысалы:
// Метод достает из базы данных всех пользователей с определенным именем
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) {
   //переводим в коллекцию юзеров
}
Осылайша, бұл осалдықтың алдын алады. Осы мақалаға тереңірек енгісі келетіндер үшін мына керемет мысал бар . Сіз бұл бөлікті түсінгеніңізді қалай түсінесіз? Төмендегі әзіл түсінікті болса, бұл осалдықтың мәні түсінікті екендігінің сенімді белгісі :D Java-дағы қауіпсіздік: ең жақсы тәжірибелер - 2

3. Тәуелділіктерді сканерлеңіз және жаңартып отырыңыз

Бұл нені білдіреді? Тәуелділіктің не екенін білмейтіндер үшін түсіндіремін: бұл басқа біреудің шешімін қайта пайдалану үшін автоматты құрастыру жүйелерін (Maven, Gradle, Ant) пайдаланып жобаға қосылған codeы бар банка мұрағаты. Мысалы, орындалу уақытында біз үшін алушыларды, орнатушыларды және т.б. генерациялайтын Project Lombok . Ал егер үлкен қосымшалар туралы айтатын болсақ, олар көптеген әртүрлі тәуелділіктерді пайдаланады. Кейбіреулері транзитивті (яғни әрбір тәуелділіктің өз тәуелділіктері болуы мүмкін және т.б.). Сондықтан, шабуылдаушылар ашық бастапқы тәуелділіктерге көбірек көңіл бөлуде, өйткені олар үнемі пайдаланылады және көптеген клиенттер үшін қиындықтар тудыруы мүмкін. Бүкіл тәуелділік ағашында белгілі осалдықтардың жоқтығына көз жеткізу маңызды (бұл дәл осылай көрінеді). Және мұны істеудің бірнеше жолы бар.

Бақылау үшін Snyk пайдаланыңыз

Snyk құралы жобаның барлық тәуелділіктерін тексереді және белгілі осалдықтарды белгілейді. Онда, мысалы, GitHub арқылы жобаларыңызды тіркеуге және импорттауға болады. Java-дағы қауіпсіздік: ең жақсы тәжірибелер - 3Сондай-ақ, жоғарыдағы суреттен көріп отырғаныңыздай, егер жаңа нұсқада осы осалдықтың шешімі болса, Snyk мұны істеуді және Pull-Request жасауды ұсынады. Оны ашық бастапқы жобалар үшін тегін пайдалануға болады. Жобалар белгілі бір жиілікте сканерленеді: аптасына бір рет, айына бір рет. Мен тіркелдім және барлық қоғамдық репозиторийлерімді Snyk сканеріне қостым (мұнда қауіпті ештеңе жоқ: олар барлығына ашық). Әрі қарай, Snyk сканерлеудің нәтижесін көрсетті: Java-дағы қауіпсіздік: ең жақсы тәжірибелер - 4Біраз уақыттан кейін Snyk-бот тәуелділіктерді жаңарту қажет жобаларда бірнеше Pull-Requests дайындады: Java-дағы қауіпсіздік: ең жақсы тәжірибелер - 5Міне, тағы біреуі: Java-дағы қауіпсіздік: ең жақсы тәжірибелер - 6Демек, бұл осалдықтарды іздеуге және жаңартуды бақылауға арналған тамаша құрал. жаңа нұсқалар.

GitHub қауіпсіздік зертханасын пайдаланыңыз

GitHub-те жұмыс істейтіндер өздерінің кірістірілген құралдарының артықшылығын да пайдалана алады. Бұл тәсіл туралы толығырақ олардың GitHub қауіпсіздік зертханасының хабарландыруы блогынан менің аудармамнан оқи аласыз . Бұл құрал, әрине, Snyk-ке қарағанда қарапайым, бірақ сіз оны елемеуге болмайды. Сонымен қатар, белгілі осалдықтардың саны тек өседі, сондықтан Snyk және GitHub қауіпсіздік зертханасы кеңейіп, жақсарады.

Sonatype DepShield іске қосыңыз

Егер сіз репозитарийлерді сақтау үшін GitHub қолданбасын пайдалансаңыз, жобаларыңызға MarketPlace - Sonatype DepShield қолданбаларының бірін қосуға болады. Оның көмегімен жобаларды тәуелділіктерге де сканерлеуге болады. Сонымен қатар, егер ол бірдеңе тапса, төменде көрсетілгендей сәйкес сипаттамасымен GitHub шығарылымы жасалады: Java-дағы қауіпсіздік: ең жақсы тәжірибелер - 7

4. Құпия деректерді абайлап өңдеңіз

Java-дағы қауіпсіздік: ең жақсы тәжірибелер - 8Ағылшын тілінде «сенситив деректер» тіркесі жиі кездеседі. Клиенттің жеке мәліметтерін, несие картасының нөмірлерін және басқа да жеке мәліметтерін жария ету орны толмас зиян келтіруі мүмкін. Ең алдымен, қосымшаның дизайнын мұқият қарап шығу керек және қандай да бір деректердің шынымен қажет екенін анықтау керек. Мүмкін олардың кейбіреулері қажет емес шығар, бірақ олар келмеген және келуі екіталай болашақ үшін қосылды. Сонымен қатар, жобаны тіркеу кезінде мұндай деректер ағып кетуі мүмкін. toString()Құпия деректердің журналдарыңызға енуіне жол бермеудің қарапайым жолы - домен нысандарының әдістерін (мысалы, пайдаланушы, студент, мұғалім және т.б.) тазалау . Бұл сезімтал өрістердің кездейсоқ басып шығарылуын болдырмайды. Егер сіз Lombok әдісін генерациялау үшін қолдансаңыз , әдіс арқылы өрістің шығыста пайдаланылуын болдырмау үшін toString()annotationны пайдалануға болады . Сондай-ақ, деректерді сыртқы әлеммен бөліскенде өте сақ болыңыз. Мысалы, барлық пайдаланушылардың атын көрсететін http соңғы нүктесі бар. Пайдаланушының ішкі бірегей идентификаторын көрсетудің қажеті жоқ. Неліктен? Себебі оны пайдалану арқылы шабуылдаушы әрбір пайдаланушы туралы басқа, анағұрлым құпия ақпаратты ала алады. Мысалы, POJO файлдарын JSON ішіне сериялау және сериядан шығару үшін Джексонды пайдалансаңыз , нақты өрістердің сериялануын және сериядан шығарылуын болдырмау үшін және annotationларын пайдалануға болады . Жалпы, әртүрлі орындар үшін әртүрлі POJO сыныптарын пайдалану керек. Бұл нені білдіреді? @ToString.ExcludetoString()@JsonIgnore@JsonIgnoreProperties
  1. Дерекқормен жұмыс істеу үшін тек POJO - Entity пайдаланыңыз.
  2. Бизнес логикасымен жұмыс істеу үшін нысанды үлгіге тасымалдаңыз.
  3. Сыртқы әлеммен жұмыс істеу және http сұрауларын жіберу үшін үшінші нысандарды пайдаланыңыз - DTO.
Осылайша сіз қай өрістер сырттан көрінетінін және қайсысы көрінбейтінін нақты анықтай аласыз.

Күшті шифрлау және хэштеу алгоритмдерін пайдаланыңыз

Тұтынушының құпия деректері қауіпсіз сақталуы керек. Мұны істеу үшін шифрлауды пайдалану керек. Тапсырмаға байланысты шифрлаудың қандай түрін қолдану керектігін шешу керек. Әрі қарай, күшті шифрлау көп уақытты қажет етеді, сондықтан оған қажеттілік оған жұмсалған уақытты қаншалықты ақтайтынын тағы да ескеру қажет. Әрине, алгоритмді өзіңіз жаза аласыз. Бірақ бұл қажет емес. Сіз осы саладағы бар шешімдерді пайдалана аласыз. Мысалы, 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>
Бір жолмен, екіншісін шифрлаудың мысалын пайдаланып, оны қалай пайдалану керектігін көрейік:
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));
}

Құпия сөзді шифрлау

Бұл тапсырма үшін асимметриялық шифрлауды пайдалану қауіпсіз. Неліктен? Өйткені қолданба шынымен құпия сөздерді қайта шифрлауды қажет етпейді. Бұл жалпы көзқарас. Шындығында, пайдаланушы құпия сөзді енгізген кезде, жүйе оны шифрлайды және оны құпия сөз қоймасындағымен салыстырады. Шифрлау бірдей құралдарды қолдану арқылы жүзеге асырылады, сондықтан олардың сәйкес келуін күтуге болады (егер сіз дұрыс парольді енгізсеңіз; әрине). Бұл мақсат үшін BCrypt және SCrypt қолайлы. Екеуі де көп уақытты қажет ететін күрделі есептеу алгоритмдері бар бір жақты функциялар (криптографиялық хэштер). Бұл сізге қажет нәрсе, өйткені оны бетпе-бет шешу мәңгілікке созылады. Мысалы, Spring Security бірқатар алгоритмдерді қолдайды. SCryptPasswordEncoderСіз де пайдалана аласыз BCryptPasswordEncoder. Қазір күшті шифрлау алгоритмі келесі жылы әлсіз болуы мүмкін. Нәтижесінде қолданылған алгоритмдерді тексеріп, кітапханаларды алгоритмдермен жаңарту қажет деген қорытындыға келдік.

Шығарудың орнына

Бүгін біз қауіпсіздік туралы айттық және, әрине, көп нәрсе сахнаның артында қалды. Мен саған жаңа дүниенің есігін аштым: өз өмірін сүретін әлем. Қауіпсіздік саясатпен бірдей: егер сен саясатпен айналыспасаң, саясат сенімен айналысады. Дәстүрлі түрде мен Github тіркелгісіне жазылуды ұсынамын . Онда мен оқып, жұмыста қолданатын түрлі технологиялар бойынша жұмысымды жариялаймын.

пайдалы сілтемелер

Иә, сайттағы мақалалардың барлығы дерлік ағылшын тілінде жазылған. Біз қаласақ та, қаламасақ та, ағылшын тілі бағдарламашылар үшін тіл табысатын тіл. Бағдарламалау бойынша барлық жаңа мақалалар, кітаптар мен журналдар ағылшын тілінде жазылған. Сондықтан менің ұсыныстарға сілтемелерім негізінен ағылшын тілінде:
  1. Habr: Жаңадан бастаушыларға арналған SQL инъекциясы
  2. Oracle: Java қауіпсіздік ресурстық орталығы
  3. Oracle: Java SE үшін қауіпсіз codeтау нұсқаулары
  4. Baeldung: Java қауіпсіздік негіздері
  5. Орташа: Java қауіпсіздігін күшейтуге арналған 10 кеңес
  6. Snyk: java қауіпсіздігінің 10 үздік тәжірибесі
  7. JR: GitHub қауіпсіздік зертханасының хабарландыруы: барлық codeты бірге қорғау
Пікірлер
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION