𝗖𝗕𝗖 𝗕𝗶𝘁 𝗙𝗹𝗶𝗽𝗽𝗶𝗻𝗴 𝗘𝘅𝗽𝗹𝗮𝗶𝗻𝗲𝗱
Encryption does not mean your data is safe from tampering.
Many developers make this mistake. They think if an attacker cannot read the data, they cannot change it. This is wrong. Cryptography treats secrecy and integrity as two different tasks.
The CBC Bit Flipping attack proves this. An attacker can change your data without knowing your secret key.
Here is how it works:
AES does not encrypt data in one large piece. It breaks data into 16-byte blocks. In CBC mode, these blocks chain together. The encrypted output of the first block mixes into the plaintext of the second block.
This chain creates a weakness during decryption. To get the original text of Block 2, the server decrypts it and combines it with the ciphertext from Block 1.
An attacker can exploit this:
- The attacker intercepts your encrypted traffic.
- They do not know the key, so the data looks like gibberish.
- They change specific bits in the ciphertext of Block 1.
- They send this altered data to your server.
- When the server decrypts it, the change in Block 1 shifts the math for Block 2.
The attacker does not need to read the message. They just flip bits to change the final result.
Consider an old web app using encrypted cookies for sessions. A cookie might hold: userid=994;role=user;
An attacker intercepts this cookie and flips bits in the ciphertext. They send many requests until the server accepts one. Because the server only checks if the data decrypts, it processes the modified text. Suddenly, the decrypted string reads: userid=994;role=admi;
The attacker now has admin access. They never read the key or the original cookie.
The mistake is assuming encryption guarantees integrity.
- Confidentiality stops people from reading data.
- Integrity stops people from changing data.
To fix this, use Authenticated Encryption like AES-GCM. It creates a cryptographic tag. This tag acts like a seal. If an attacker changes even one bit, the seal breaks. The server rejects the data immediately.
If you must use CBC, use an Encrypt-then-MAC architecture. Create an authentication code for the ciphertext and verify it before you start decryption.
Secret data is not always trustworthy data. Always prove your data is unchanged before you use it to make decisions.
Wyjaśnienie ataku CBC Bit-Flipping: Dlaczego samo szyfrowanie nie gwarantuje integralności
W świecie kryptografii często słyszymy o poufności (confidentiality). Szyfrowanie jest głównym narzędziem służącym do zapewnienia, że tylko uprawnione osoby mogą odczytać dane. Jednak samo szyfrowanie nie gwarantuje integralności (integrity).
Integralność to zapewnienie, że dane nie zostały zmienione w nieautoryzowany sposób podczas przesyłania lub przechowywania. To właśnie tutaj pojawia się problem z trybem CBC (Cipher Block Chaining).
Czym jest tryb CBC?
W trybie CBC każdy blok tekstu jawnego jest łączony (za pomocą operacji XOR) z poprzednim blokiem szyfrogramu przed zaszyfrowaniem. Pierwszy blok jest łączony z wektorem inicjującym (IV).
Proces szyfrowania wygląda następująco:
$C_i = E_k(P_i \oplus C_{i-1})$
Gdzie:
- $C_i$ to bieżący blok szyfrogramu.
- $P_i$ to bieżący blok tekstu jawnego.
- $E_k$ to funkcja szyfrująca z kluczem $k$.
- $C_{i-1}$ to poprzedni blok szyfrogramu (dla pierwszego bloku jest to IV).
Podatność na atak Bit-Flipping
Kluczowa słabość CBC polega na tym, jak odbywa się proces odszyfrowywania. Aby uzyskać tekst jawny, musimy wykonać operację odwrotną:
$P_i = D_k(C_i) \oplus C_{i-1}$
Zauważ, że aby uzyskać blok tekstu jawnego $P_i$, używamy poprzedniego bloku szyfrogramu $C_{i-1}$ w operacji XOR.
To oznacza, że jeśli atakujący zmieni konkretny bit w bloku szyfrogramu $C_{i-1}$, spowoduje to dokładnie taką samą zmianę w odpowiadającym mu bicie w odszyfrowanym bloku tekstu jawnego $P_i$.
Przykład praktyczny
Wyobraźmy sobie, że aplikacja przechowuje dane o uprawnieniach użytkownika w zaszyfrowanym ciasteczku (cookie).
Tekst jawny: user_id=123;role=user
Załóżmy, że ten tekst został zaszyfrowany w trybie CBC. Atakujący nie zna klucza szyfrującego, ale wie, w którym miejscu w szyfrogramie znajduje się słowo user.
Jeśli atakujący zmieni bity w bloku szyfrogramu $C_{i-1}$ tak, aby po operacji XOR wynik zmienił się z user na root, to po odszyfrowaniu przez serwer, tekst jawny będzie brzmiał:
user_id=123;role=root
Atakujący nie może kontrolować tego, jak zmieni się blok $P_{i-1}$ (zostanie on całkowicie zniekształcony/uszkodzony), ale jeśli dane w $P_{i-1}$ nie są krytyczne, atak może zakończyć się sukcesem.
Jak temu zapobiec?
Samo szyfrowanie to za mało. Aby zapewnić zarówno poufność, jak i integralność, należy stosować mechanizmy uwierzytelniania.
1. HMAC (Hash-based Message Authentication Code)
Można zastosować podejście "Encrypt-then-MAC". Najpierw szyfrujemy wiadomość, a następnie obliczamy kod HMAC dla otrzymanego szyfrogramu. Przy odbiorze najpierw sprawdzamy poprawność HMAC, a dopiero potem odszyfrowujemy dane. Jeśli jakikolwiek bit szyfrogramu został zmieniony, HMAC nie będzie się zgadzać i wiadomość zostanie odrzucona.
2. Tryby AEAD (Authenticated Encryption with Associated Data)
Najlepszą i najnowocześniejszą metodą jest użycie trybów szyfrowania, które natywnie wspierają uwierzytelnianie. Przykładem jest AES-GCM (Galois/Counter Mode). Tryby AEAD łączą szyfrowanie i uwierzytelnianie w jednym procesie, co jest bardziej wydajne i bezpieczniejsze od ręcznego łączenia szyfrowania z HMAC.
Podsumowanie
- Szyfrowanie zapewnia poufność (nikt nie może przeczytać danych).
- Integralność zapewnia, że dane nie zostały zmienione.
- CBC Bit-Flipping pokazuje, że można zmienić treść zaszyfrowanej wiadomości bez znajomości klucza, manipulując szyfrogramem.
- Rozwiązanie: Zawsze używaj uwierzytelnionego szyfrowania (AEAD), takiego jak AES-GCM, zamiast polegać na samym trybie CBC.