Przejdź do treści

~/cyberbezpieczenstwo cat co-to-jest-scram.md

Co to jest SCRAM? Uwierzytelnianie SCRAM-SHA-256 wyjaśnione prosto

Co to jest SCRAM i jak działa SCRAM-SHA-256? Wyjaśniamy mechanizm logowania bez wysyłania hasła, jego zalety nad MD5 i konfigurację w PostgreSQL oraz Kafce.

CZCzarek Zawolski--aktualizacja=--czas=7 min--dział=Cyberbezpieczeństwo
Ilustracja bezpiecznego logowania z kłódką i wymianą kluczy między klientem a serwerem
tldr.txt — W skrócie

~ xad tldr co-to-jest-scram

  • SCRAM (Salted Challenge Response Authentication Mechanism) to mechanizm uwierzytelniania hasłem, w którym hasło ani jego skrót nie są przesyłane przez sieć.
  • Serwer przechowuje tylko sól, liczbę iteracji i dwa klucze pochodne (StoredKey, ServerKey), a nie samo hasło.
  • Uwierzytelnianie jest wzajemne: klient sprawdza też, czy serwer naprawdę zna dane użytkownika.
  • SCRAM-SHA-256 jest domyślny w PostgreSQL od wersji 14 i obsługują go m.in. MongoDB, Apache Kafka, serwery XMPP i poczty.
  • SCRAM nie zastępuje TLS — szyfrowania połączenia nadal potrzebujesz, a wariant -PLUS wiąże logowanie z sesją TLS.
$ tree --spis-tresci

SCRAM (Salted Challenge Response Authentication Mechanism) to mechanizm uwierzytelniania hasłem, w którym ani hasło, ani jego skrót nie trafiają do sieci. Klient udowadnia serwerowi, że zna hasło, odpowiadając na jednorazowe wyzwanie, a serwer w tym samym czasie udowadnia klientowi, że zna jego dane. Dzięki temu przechwycenie logowania nic atakującemu nie daje.

Mechanizm opisano w RFC 5802 (SCRAM-SHA-1) i RFC 7677 (SCRAM-SHA-256). Działa jako tzw. mechanizm SASL, więc spotkasz go w bazach danych (PostgreSQL, MongoDB), brokerach komunikatów (Apache Kafka), serwerach poczty i komunikatorach XMPP. Jeśli trafiłeś tu, szukając metodyki pracy zespołowej, na końcu artykułu znajdziesz krótkie wyjaśnienie różnicy między SCRAM a Scrum.

Co to jest SCRAM i jaki problem rozwiązuje

Klasyczne logowanie hasłem ma dwa słabe punkty. Pierwszy to transmisja: jeśli hasło (albo jego prosty skrót) leci przez sieć, ktoś może je przechwycić i użyć ponownie. Drugi to przechowywanie: jeśli serwer trzyma hasło w postaci, którą da się bezpośrednio wykorzystać do logowania, wyciek bazy oznacza przejęcie kont.

Starsze mechanizmy rozwiązywały tylko jeden z tych problemów. PLAIN wysyła hasło otwartym tekstem (bezpieczne wyłącznie w tunelu TLS). CRAM-MD5 i DIGEST-MD5 nie wysyłały hasła, ale wymagały, żeby serwer znał je w postaci jawnej lub równoważnej. Uwierzytelnianie md5 w PostgreSQL przechowywało skrót, który sam w sobie wystarczał do zalogowania się.

SCRAM łączy oba wymagania:

  • hasło nie jest wysyłane, a każda wymiana jest inna dzięki losowym wartościom (nonce),
  • serwer przechowuje tylko dane pochodne, z których nie da się bezpośrednio zalogować,
  • skrót hasła jest „solony” i wielokrotnie przeliczany (PBKDF2), co spowalnia łamanie słownikowe,
  • uwierzytelnianie jest wzajemne — fałszywy serwer bez danych użytkownika nie przejdzie weryfikacji po stronie klienta.

Jeśli chcesz odświeżyć podstawy, zajrzyj do tekstów o funkcjach skrótu kryptograficznego i hashowaniu z solą — SCRAM korzysta z obu tych idei.

Co serwer przechowuje zamiast hasła

Przy ustawianiu hasła serwer (lub klient, np. polecenie \password w psql) wylicza z niego kilka wartości:

  1. SaltedPassword = PBKDF2(HMAC-SHA-256, hasło, sól, liczba_iteracji)
  2. ClientKey = HMAC(SaltedPassword, "Client Key")
  3. StoredKey = SHA-256(ClientKey)
  4. ServerKey = HMAC(SaltedPassword, "Server Key")

W bazie zostają tylko: sól, liczba iteracji, StoredKey i ServerKey. Samego hasła ani ClientKey serwer nie zna. W PostgreSQL wygląda to tak (kolumna rolpassword w pg_authid):

SCRAM-SHA-256$4096:<sól w base64>$<StoredKey w base64>:<ServerKey w base64>

StoredKey to skrót z ClientKey, więc znając go, nie da się po prostu „podać” go serwerowi jako dowodu — trzeba mieć ClientKey, a ten powstaje wyłącznie z hasła.

Jak działa logowanie SCRAM krok po kroku

Cała wymiana to cztery komunikaty. Przykład dla SCRAM-SHA-256:

  1. client-first-message — klient wysyła nazwę użytkownika i losowy nonce, np. n,,n=user,r=rOprNGfwEbeRWgbNEkqO.
  2. server-first-message — serwer dokleja swój nonce i odsyła sól oraz liczbę iteracji: r=rOprNGfwEbeRWgbNEkqO%hvYDpWUa2RaTCAfuxFIlj)hNlF$k0,s=W22ZaJ0SNY7soEsUEjb6gQ==,i=4096.
  3. client-final-message — klient sam wylicza SaltedPassword, ClientKey i StoredKey, a następnie podpis: ClientSignature = HMAC(StoredKey, AuthMessage). Wysyła dowód ClientProof = ClientKey XOR ClientSignature (pole p=).
  4. server-final-message — serwer liczy ten sam podpis ze swojego StoredKey, „odejmuje” go od dowodu (XOR), dostaje ClientKey, haszuje go i porównuje ze StoredKey. Jeśli się zgadza, odsyła własny podpis ServerSignature = HMAC(ServerKey, AuthMessage) (pole v=), który klient weryfikuje.

AuthMessage to sklejone treści wszystkich wcześniejszych komunikatów, łącznie z oboma nonce. Dlatego każdy dowód jest ważny tylko dla tej jednej sesji — powtórzenie przechwyconej wymiany (replay attack) nie zadziała.

W komunikacie 3 widać też pole c=biws — to zakodowany w base64 nagłówek n,,, czyli informacja, że klient nie używa wiązania z kanałem TLS. W wariancie z channel binding w tym miejscu trafiają dane z sesji TLS.

Warianty: SCRAM-SHA-1, SCRAM-SHA-256, SCRAM-SHA-512 i -PLUS

WariantGdzie opisanyUwagi
SCRAM-SHA-1RFC 5802Najstarszy, wciąż obecny m.in. w XMPP i MongoDB; w nowych wdrożeniach wybieraj SHA-256
SCRAM-SHA-256RFC 7677Standard de facto: PostgreSQL, MongoDB 4.0+, Kafka, Dovecot
SCRAM-SHA-512szkic IETFObsługiwany m.in. przez Apache Kafka i część serwerów XMPP
SCRAM-…-PLUSRFC 5802, RFC 9266Wariant z channel binding — logowanie powiązane z konkretną sesją TLS

Wariant -PLUS warto znać szczególnie. Bez niego atakujący, który przechwyci połączenie TLS (np. podstawionym certyfikatem), może pośredniczyć w logowaniu. Channel binding dokłada do AuthMessage informację o sesji TLS (tls-server-end-point lub dla TLS 1.3 tls-exporter), więc dowód wygenerowany w jednym połączeniu nie zadziała w innym.

SCRAM w PostgreSQL: jak przejść z MD5 na scram-sha-256

PostgreSQL obsługuje SCRAM-SHA-256 od wersji 10, a od wersji 14 jest to domyślna wartość password_encryption. W PostgreSQL 18 uwierzytelnianie MD5 zostało oficjalnie oznaczone jako przestarzałe, więc jeśli w starszej instalacji nadal masz hasła MD5, to dobry moment na migrację.

  1. Sprawdź, którzy użytkownicy mają jeszcze hasła w starym formacie:
SELECT rolname,
       CASE WHEN rolpassword LIKE 'SCRAM-SHA-256$%' THEN 'scram'
            WHEN rolpassword LIKE 'md5%' THEN 'md5'
            ELSE 'brak/inne' END AS format
FROM pg_authid
WHERE rolcanlogin;
  1. Upewnij się, że nowe hasła będą zapisywane jako SCRAM (w postgresql.conf lub dla sesji):
SET password_encryption = 'scram-sha-256';
  1. Ustaw ponownie hasła użytkownikom z formatem md5. Najbezpieczniej w psql poleceniem \password nazwa_uzytkownika — hasło jest wtedy haszowane po stronie klienta i nie trafia do logów serwera.
  2. W pliku pg_hba.conf zmień metodę z md5 na scram-sha-256, np.:
hostssl  all  all  10.0.0.0/24  scram-sha-256
  1. Przeładuj konfigurację: SELECT pg_reload_conf(); lub systemctl reload postgresql.

Wskazówka: Metoda md5 w pg_hba.conf akceptuje także hasła zapisane jako SCRAM. Możesz więc najpierw zmienić hasła wszystkim użytkownikom, a dopiero na końcu przełączyć pg_hba.conf na scram-sha-256 — bez przestoju dla aplikacji.

Od PostgreSQL 16 liczbę iteracji PBKDF2 zmienisz parametrem scram_iterations (domyślnie 4096). Wyższa wartość utrudnia łamanie wykradzionych hashy, ale spowalnia każde logowanie, co ma znaczenie przy aplikacjach otwierających wiele połączeń bez puli.

Typowe błędy po włączeniu SCRAM

  • SCRAM authentication requires libpq version 10 or above — klient lub sterownik jest za stary. Zaktualizuj libpq, sterownik JDBC, psycopg, Npgsql itd. do wersji wspierającej SCRAM.
  • password authentication failed po zmianie pg_hba.conf — użytkownik ma nadal hasło w formacie MD5. Ustaw je ponownie przy password_encryption = 'scram-sha-256'.
  • Pooler (np. PgBouncer) odrzuca logowanie — starsze wersje i konfiguracje auth_type musiały zostać dostosowane do SCRAM; sprawdź dokumentację swojej wersji poolera.

Aby wymusić po stronie klienta wiązanie z TLS, w łańcuchu połączenia libpq (PostgreSQL 13+) dodaj channel_binding=require — klient odmówi wtedy logowania do serwera, który nie potrafi przeprowadzić SCRAM-SHA-256-PLUS.

SCRAM w Apache Kafka, MongoDB i innych usługach

Apache Kafka

Kafka obsługuje SASL/SCRAM-SHA-256 i SASL/SCRAM-SHA-512. Dane logowania tworzysz narzędziem kafka-configs.sh:

kafka-configs.sh --bootstrap-server localhost:9092 --alter \
  --add-config 'SCRAM-SHA-512=[iterations=8192,password=TwojeHaslo]' \
  --entity-type users --entity-name aplikacja1

W konfiguracji klienta ustawiasz sasl.mechanism=SCRAM-SHA-512 i security.protocol=SASL_SSL. Dokumentacja Kafki wprost zaleca łączenie SCRAM z TLS.

MongoDB

MongoDB używa SCRAM jako domyślnego mechanizmu uwierzytelniania: SCRAM-SHA-1 od wersji 3.0, SCRAM-SHA-256 od wersji 4.0. Mechanizm wybierasz parametrem authMechanism w adresie połączenia, np. authMechanism=SCRAM-SHA-256.

Poczta i komunikatory

W serwerach IMAP/SMTP (np. Dovecot) SCRAM działa jako jeden z mechanizmów SASL obok PLAIN i LOGIN. W XMPP SCRAM-SHA-1 jest mechanizmem obowiązkowym według RFC 6120, a nowoczesne serwery oferują też SCRAM-SHA-256 i warianty -PLUS.

Ograniczenia SCRAM — przed czym nie chroni

SCRAM jest dużym krokiem naprzód względem MD5 i PLAIN, ale ma granice:

  • Słabe hasło nadal jest słabe. Wykradziony wpis z bazy (sól, iteracje, klucze) pozwala na atak słownikowy offline. PBKDF2 z 4096 iteracjami to umiarkowane spowolnienie — narzędzia takie jak Hashcat radzą sobie z prostymi hasłami szybko.
  • Wyciek bazy + podsłuch = przejęcie konta. Kto ma StoredKey i przechwyci jedną poprawną wymianę, może odtworzyć ClientKey i logować się jako użytkownik. Dlatego połączenie musi być szyfrowane TLS.
  • Kradzież ServerKey pozwala podszyć się pod serwer wobec klientów tego użytkownika.
  • Nie chroni przed phishingiem i keyloggerami. Jeśli hasło wycieknie u źródła, mechanizm logowania nic nie pomoże. O tym, jak najczęściej się to dzieje, przeczytasz w tekście o sposobach kradzieży haseł.

Ważne: SCRAM to mechanizm uwierzytelniania, nie szyfrowania. Zawsze uruchamiaj go wewnątrz TLS, a tam, gdzie klient to wspiera, wymuszaj wariant z channel binding.

Tam, gdzie to możliwe, warto dołożyć drugi składnik albo przejść na uwierzytelnianie bez haseł — certyfikaty klienta, Kerberos w środowiskach Active Directory lub klucze FIDO2 w aplikacjach webowych.

SCRAM czy Scrum? Częsta pomyłka w wyszukiwarce

Wiele osób wpisujących „scram” szuka w rzeczywistości Scruma — zwinnej metody organizacji pracy zespołu. To zupełnie inny temat:

  • Scrum to framework zarządzania projektami opisany w Scrum Guide. Praca dzieli się na sprinty (zwykle 1–4 tygodnie), a zespół tworzą Product Owner, Scrum Master i Developerzy. Artefakty to Product Backlog, Sprint Backlog i Increment, a wydarzenia to Sprint, Sprint Planning, Daily Scrum, Sprint Review i Sprint Retrospective.
  • SCRAM w informatyce to opisany wyżej mechanizm logowania.
  • SCRAM w energetyce jądrowej to nazwa awaryjnego wyłączenia reaktora (szybkie wprowadzenie prętów kontrolnych).

Role w zespole Scrum: Product Owner, Scrum Master i Developerzy

Jeśli więc w dokumentacji bazy danych, brokera komunikatów lub serwera poczty widzisz „SCRAM-SHA-256”, chodzi o bezpieczne uwierzytelnianie hasłem — i w nowych wdrożeniach to właśnie ten mechanizm powinien być Twoim domyślnym wyborem.

~ man faq

Najczęściej zadawane pytania

Co to jest SCRAM-SHA-256?

To wariant mechanizmu SCRAM opisany w RFC 7677, który używa funkcji skrótu SHA-256 i PBKDF2 z HMAC-SHA-256. Jest obecnie zalecanym sposobem logowania hasłem m.in. w PostgreSQL.

Czy SCRAM jest bezpieczniejszy niż MD5 w PostgreSQL?

Tak. Przy MD5 skrót zapisany w bazie wystarczy do zalogowania się, a sam algorytm jest szybki do łamania. SCRAM używa soli i wielu iteracji, a przechwycona wymiana nie pozwala zalogować się ponownie.

Czy SCRAM szyfruje połączenie?

Nie. SCRAM chroni tylko proces logowania. Dane przesyłane po zalogowaniu nadal trzeba szyfrować TLS, najlepiej z channel binding (SCRAM-SHA-256-PLUS).

Co oznacza błąd „SCRAM authentication requires libpq version 10 or above”?

Twój klient lub sterownik PostgreSQL jest zbyt stary i nie obsługuje SCRAM. Zaktualizuj bibliotekę libpq lub sterownik aplikacji do wersji zgodnej z PostgreSQL 10 lub nowszym.

Czy SCRAM to to samo co Scrum?

Nie. SCRAM to mechanizm uwierzytelniania w informatyce, a Scrum to zwinna metoda zarządzania pracą zespołu. Nazwy są często mylone ze względu na podobną pisownię.

Ten artykuł jest częścią tematów

CZ

$ whoami

Czarek Zawolski

Założyciel i redaktor XAD.pl. Pisze o sieciach, bezpieczeństwie IT, administracji systemami Windows i Linux oraz o sprzęcie, który sprawia ludziom problemy na co dzień.

~ ls ../podobne