Najczęstsze wzorce błędnego użycia kryptografii
Proszę poznać najczęstsze błędy programistów: tryb ECB, inicjalizację słabym ziarnem PRNG i samodzielne tworzenie kryptografii.
Najczęstsze wzorce błędnego użycia kryptografii to bezpłatna lekcja Cryptology Academy na CoddyKit. To lekcja 4 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Cryptology Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Cryptology Academy zawiera 4 lekcji w sumie.
Tryb ECB ujawnia wzorce bloków
Tryb Electronic Codebook (ECB) szyfruje każdy blok niezależnie, używając tego samego klucza. Identyczne bloki tekstu jawnego dają identyczne bloki szyfrogramu. Klasyczną demonstracją jest „pingwin ECB”: zaszyfrowanie obrazu bitmapowego w trybie ECB zachowuje strukturę obrazu na poziomie bloków, dzięki czemu kontur pingwina pozostaje wyraźnie widoczny w szyfrogramie. Tryb ECB nie zapewnia bezpieczeństwa semantycznego i nigdy nie powinien być używany do żadnego praktycznego celu związanego z szyfrowaniem.
Pisanie własnej kryptografii
Implementowanie prymitywów kryptograficznych od podstaw jest jedną z najbardziej niebezpiecznych praktyk w tworzeniu oprogramowania. Kryptografia wymaga bezbłędnej poprawności w warunkach działania przeciwnika: subtelny wyciek czasowy, błąd o jeden w dopełnieniu lub niezrozumienie wymagań bezpieczeństwa mogą utworzyć możliwe do wykorzystania podatności, których podczas zwykłych testów nie da się odróżnić od poprawnego działania. Nawet doświadczeni kryptografowie popełniają błędy implementacyjne, dlatego twórcy aplikacji powinni korzystać wyłącznie z dobrze zbadanych bibliotek.
MD5 i SHA-1 w zastosowaniach bezpieczeństwa
Od 2004 roku znane są praktyczne ataki łamiące odporność kolizyjną MD5; utworzenie dwóch plików o tym samym skrócie MD5 jest obliczeniowo banalne. Ataki kolizyjne na SHA-1 zostały praktycznie zademonstrowane w 2017 roku przez atak SHAttered firmy Google, w ramach którego utworzono dwa pliki PDF o tym samym skrócie SHA-1. Żadnego z tych algorytmów nie należy używać do celów związanych z bezpieczeństwem: podpisów cyfrowych, integralności danych, przechowywania haseł ani HMAC. We współczesnych wdrożeniach należy używać SHA-256, SHA-3 lub BLAKE2.
Przewidywalne inicjowanie PRNG
Używanie time() lub innych przewidywalnych wartości do zainicjowania generatora pseudolosowego jest krytyczną podatnością, gdy wynik PRNG służy do celów związanych z bezpieczeństwem. Napastnik, który zna przybliżony czas wygenerowania klucza, może metodą siłową przeszukać przestrzeń ziaren (wszystkie możliwe znaczniki czasu w niewielkim przedziale) i odzyskać klucz. Klasycznym przykładem są wczesne wersje Netscape, które inicjowały generowanie kluczy SSL na podstawie czasu i identyfikatora procesu, a obie te wartości były możliwe do ustalenia przez napastnika na tej samej maszynie.
Wybór słabego PRNG
rand() w języku C, java.util.Random oraz moduł random języka Python używają deterministycznych generatorów liniowych kongruencyjnych lub algorytmu Mersenne Twister, zaprojektowanych z myślą o jakości statystycznej w symulacjach, a nie o bezpieczeństwie. Napastnik, który zaobserwuje wystarczająco wiele wyników tych generatorów, może odtworzyć ich stan wewnętrzny i przewidywać wszystkie przyszłe wyniki. Do celów związanych z bezpieczeństwem należy używać dostarczanych przez system operacyjny kryptograficznie bezpiecznych generatorów liczb pseudolosowych (CSPRNG): secrets.token_bytes() w Pythonie, crypto.randomBytes() w Node.js lub /dev/urandom w systemie Linux.
Szyfrowanie bez uwierzytelniania
Szyfrowanie bez uwierzytelniania zapewnia wyłącznie poufność, a nie integralność. Napastnik, który nie może odczytać tekstu jawnego, nadal może modyfikować szyfrogram, potencjalnie powodując przewidywalne zmiany tekstu jawnego, zwłaszcza w trybie CTR lub CBC. Ta podatność na modyfikacje umożliwia ataki: napastnik przechwytujący zaszyfrowaną transakcję bankową może odwrócić wybrane bity, aby zmienić kwotę przelewu lub numer rachunku odbiorcy, nie znając tekstu jawnego. Należy zawsze używać szyfrowania uwierzytelnionego (AEAD).
Zakodowane na stałe klucze i IV
Zakodowanie kluczy szyfrujących lub wektorów inicjalizujących w kodzie źródłowym na stałe jest krytyczną podatnością. Kod źródłowy często trafia do repozytoriów kontroli wersji, czasami publicznych. Nawet w prywatnych repozytoriach klucz zna każda osoba mająca dostęp do kodu. Zakodowane na stałe klucze oznaczają, że wszystkie instancje używają tego samego klucza, a jego rotacja wymaga ponownego wdrożenia. Klucze należy przechowywać w zmiennych środowiskowych, systemach zarządzania sekretami (HashiCorp Vault, AWS Secrets Manager) lub modułach bezpieczeństwa sprzętowego.
Ponowne używanie wektorów inicjalizujących
Używanie tego samego wektora inicjalizującego podczas wielu operacji szyfrowania z użyciem tego samego klucza tworzy poważne podatności. W trybie CTR ponowne użycie IV powoduje powstanie tego samego strumienia kluczowego, co umożliwia odzyskanie tekstu jawnego za pomocą operacji XOR. W trybie CBC ponowne użycie IV pozwala napastnikowi wykryć, kiedy dwie wiadomości rozpoczynają się od tych samych bloków tekstu jawnego. W trybie GCM ponowne użycie nonce ma katastrofalne skutki (zobacz lekcję o ponownym użyciu nonce). Dla każdej operacji szyfrowania należy generować nowy losowy IV i dołączać go na początku szyfrogramu, aby przechowywać go wraz z kontekstem odszyfrowywania.
Haszowanie haseł za pomocą szybkich funkcji skrótu
Przechowywanie haseł po zastosowaniu funkcji skrótu MD5, SHA-256 lub dowolnej innej szybkiej kryptograficznej funkcji skrótu jest niewystarczające. Współczesne procesory GPU mogą obliczać miliardy skrótów SHA-256 na sekundę, dzięki czemu ataki siłowe offline na skradzione bazy skrótów są trywialnie szybkie. Haszowanie haseł wymaga specjalnie do tego przeznaczonych, powolnych funkcji wymagających dużej ilości pamięci: bcrypt, scrypt lub Argon2id. Zostały one zaprojektowane tak, aby ataki siłowe były kosztowne nawet przy użyciu wyspecjalizowanego sprzętu, dzięki czemu ataki offline stają się obliczeniowo niewykonalne.
Ignorowanie weryfikacji certyfikatów
Wyłączenie weryfikacji certyfikatów SSL/TLS (ustawienie ssl.CERT_NONE w Pythonie, przekazanie -k do curl lub ustawienie trustAllCerts=true w Androidzie) eliminuje ochronę przed atakami typu man-in-the-middle. Napastnik może przedstawić dowolny certyfikat i przechwycić całą komunikację. Praktyka ta pojawia się w środowiskach programistycznych w celu pomijania błędów związanych z certyfikatami samopodpisanymi, ale często pozostaje także w środowisku produkcyjnym. Należy zawsze stosować prawidłową weryfikację certyfikatów i właściwie naprawiać leżące u podstaw problemy z certyfikatami.
Brak sprawdzania wartości zwracanych
Funkcje kryptograficzne sygnalizują błędy za pomocą wartości zwracanych lub wyjątków. Ignorowanie tych informacji pozwala kontynuować działanie z nieprawidłowym stanem: po odszyfrowaniu mogły powstać bezsensowne dane, weryfikacja mogła się nie powieść albo generowanie klucza mogło zakończyć się błędem. W interfejsach API opartych na C, takich jak OpenSSL, ignorowanie wartości zwracanych jest szczególnie niebezpieczne, ponieważ program może kontynuować działanie z niezainicjalizowaną pamięcią. Należy sprawdzać każdą wartość zwracaną przez funkcje kryptograficzne i bezpiecznie obsługiwać błędy.
Słabość trybu ECB
Dlaczego tryb ECB (Electronic Codebook) uznaje się za niebezpieczny podczas szyfrowania danych?
Podsumowanie niewłaściwego użycia kryptografii
Najważniejsze wzorce niewłaściwego użycia, których należy unikać: nigdy nie używać trybu ECB (wyciek wzorców bloków), nigdy samodzielnie nie implementować prymitywów kryptograficznych, odrzucać MD5 i SHA-1 do celów związanych z bezpieczeństwem, inicjować PRNG za pomocą CSPRNG, a nie time(), używać CSPRNG do całej losowości wrażliwej z punktu widzenia bezpieczeństwa, zawsze uwierzytelniać zaszyfrowane dane (AEAD), nigdy nie kodować kluczy ani IV na stałe, generować nowy IV dla każdej operacji szyfrowania, używać Argon2id do haseł zamiast szybkich funkcji skrótu, zawsze weryfikować certyfikaty TLS oraz sprawdzać każdą wartość zwracaną przez funkcje kryptograficzne.
Często zadawane pytania
Czy lekcja „Najczęstsze wzorce błędnego użycia kryptografii” jest bezpłatna?
Tak — pełny tekst „Najczęstsze wzorce błędnego użycia kryptografii” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Cryptology Academy, przejdź na CoddyKit PRO. Kurs Cryptology Academy zawiera 4 lekcji w sumie.
Co nauczysz się w „Najczęstsze wzorce błędnego użycia kryptografii”?
Proszę poznać najczęstsze błędy programistów: tryb ECB, inicjalizację słabym ziarnem PRNG i samodzielne tworzenie kryptografii. Ćwiczysz Cryptology Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.
Czy potrzebuję doświadczenia, aby zacząć Cryptology Academy?
Nie wymagamy żadnego doświadczenia. Cryptology Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 4 z 4.
Ile czasu zajmuje lekcja „Najczęstsze wzorce błędnego użycia kryptografii”?
Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.
Czy mogę pisać i uruchamiać kod w tej lekcji Cryptology Academy?
Tak. Każda lekcja Cryptology Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.
Wszystkie lekcje w tym kursie
- Ataki padding oracle w szczegółach
- Ataki typu replay i luki związane z ponownym użyciem nonce
- Ataki czasowe w kodzie na poziomie aplikacji
- Najczęstsze wzorce błędnego użycia kryptografii