tradução - https://alicegg.tech/2019/06/23/aes-cbc.html (muito bom artigo)
Os perigos do AES-CBC
Como muitas cifras de bloco, o AES (Advanced Encryption Standard, também conhecido como Rijndael) vem com muitos modos diferentes, todos rotulados com nomes confusos de 3 letras, como ECB, CBC, CTR ou CFB. Muitos desenvolvedores são informados de que não devem usar o ECB (Electronic Code Book) porque ele não fornece uma forte confidencialidade de dados. No entanto, muitas pessoas vão supor que o modo CBC (Cipher Block Chaining) muito popular é perfeitamente adequado para todos os casos de uso. Infelizmente, isso não é verdade, porque, embora forneça uma confidencialidade de dados muito boa, o CBC não garante a integridade dos dados.

O que é essa coisa de CBC?
A primeira coisa que você precisa saber antes de entender o que é CBC é o que é uma cifra de bloco. Uma cifra de bloco é uma função que pegará um bloco de texto simples (a entrada legível por humanos) de comprimento n e uma chave, e usará isso para produzir um bloco de texto cifrado (o sem sentido criptografado) de comprimento n . AES é a cifra de bloco mais popular atualmente, pois é recomendada tanto pelo NIST quanto pela NSA, opera em blocos de 128 bits com chaves de 128, 192 ou 256 bits.
O problema aqui é que uma função destinada a receber entradas de 128 bits não vai criptografar uma grande quantidade de dados em uma única chamada. Quando confrontado com esse problema, a solução intuitiva é simplesmente dividir seus dados em vários blocos de 128 bits e simplesmente chamar o AES com a mesma chave em cada um deles.

Esse método é chamado de Livro de Código Eletrônico e, como mencionei anteriormente, não é seguro porque os padrões de dados podem permanecer e servir como base para análise. O CBC visa resolver isso adicionando aleatoriedade a cada chamada à cifra de bloco aplicando a operação ou exclusiva (XOR) a cada bloco de texto simples com o bloco de texto cifrado gerado anteriormente (ou um vetor de inicialização aleatório (IV), para o primeiro bloco) . A descriptografia funciona fazendo o processo inverso e fazendo XOR de cada texto simples gerado com o texto cifrado anterior.


Apresentando os ataques de inversão de bits
É o processo de XORing de blocos de texto simples com o bloco de texto cifrado anterior durante a descriptografia que introduzirá uma vulnerabilidade de integridade de dados. Se dermos uma olhada na tabela de verdade XOR , podemos ver que mudar um bit de um dos textos cifrados mudará a saída de 0 para 1, ou 1 para 0:
Texto cifrado | Texto simples | Resultado |
---|---|---|
0 | 0 | 0 |
1 | 0 | 1 |
0 | 1 | 1 |
1 | 1 | 0 |
O que esta tabela está nos dizendo é que se trocarmos um bit do bloco anterior de texto cifrado, ele também será trocado no próximo bloco decifrado.
Claro, isso pode fazer com que o bloco anterior de texto simples seja substituído por dados imprevisíveis de lixo. Algumas pessoas podem supor que, se o texto cifrado for modificado, o texto simples não será legível e o aplicativo simplesmente retornará um erro. Essa é uma suposição muito perigosa porque há muitos casos em que algumas partes dos dados podem ser embaralhadas, mas não acionar nenhum erro que possa avisar o usuário sobre um problema e a mensagem modificada afetará o sistema da maneira que o invasor deseja.
Lembre-se de que também é possível alterar o primeiro bloco de dados simplesmente alterando o IV, o que não causará alterações imprevisíveis de texto simples (já que o IV é descartado após a descriptografia). Isso é especialmente perigoso, pois às vezes seu texto cifrado é apenas um único bloco.

Um cenário de exploração
Digamos que Alice queira enviar 100$ para Bob por meio de um serviço bancário criptografado. Ela primeiro criptografará a string codificada em ASCII “Enviar 100$ para Bob” com AES-256 e enviará esse pedido para seu banqueiro. Isso pode ser feito usando uma função simples como esta (em Go):
func encrypt(plaintext, key []byte) { // generate unique IV iv := make([]byte, aes.BlockSize) io.ReadFull(rand.Reader, iv) // instantiate block cipher block, _ := aes.NewCipher(key) mode := cipher.NewCBCEncrypter(block, iv) // encrypt ciphertext := make([]byte, len(plaintext)) mode.CryptBlocks(ciphertext, plaintext) fmt.Printf("iv: %x\n", iv) fmt.Printf("ciphertext: %x\n", ciphertext) }
Alice enviará por um canal inseguro o seguinte IV e texto cifrado:
iv: 9bc423909ac569b5016525cb4b2660b5
ciphertext: c6d55918176051c5a603d62cdf23fa8a
Infelizmente, esta mensagem será interceptada por Eva. Como Eve usa o mesmo sistema bancário que Alice e sabe que Alice é uma boa amiga de Bob, ela pode adivinhar que a mensagem será moldada Send xxx$ to Bob
. Eve simplesmente calculará o XOR de Send xxx$ to Bob
e Send xxx$ to Eve
saberá como alterar o texto cifrado (ela não precisa saber a quantidade real de dinheiro que está sendo enviada). Isso pode ser feito usando esta função simples:
func xor(plaintext, malicious []byte) { output := make([]byte, len(plaintext)) for i := 0; i < len(plaintext); i++ { output[i] = plaintext[i] ^ malicious[i] } fmt.Printf("%x\n", output) }
Que irá produzir:
00000000000000000000000000071907
Como XOR é uma operação associativa, ela pode apenas fazer XOR na saída anterior com o IV para inverter os bits corretos. Dessa forma, Eve enviará de volta ao banqueiro o IV alterado e o texto cifrado:
iv: 9bc423909ac569b5016525cb4b2179b2
ciphertext: c6d55918176051c5a603d62cdf23fa8a
Quando o banqueiro os decodificar através da função de descriptografia abaixo:
func decrypt(iv, ciphertext, key []byte) { // instantiate block cipher block, _ := aes.NewCipher(key) mode := cipher.NewCBCDecrypter(block, iv) // decrypt plaintext := make([]byte, len(ciphertext)) mode.CryptBlocks(plaintext, ciphertext) fmt.Printf("plaintext: %s\n", plaintext) }
Ele irá produzir:
plaintext: Send 100$ to Eve
O que usar no lugar do CBC?
A maneira mais segura de evitar essa armadilha é usar criptografia autenticada, que garante a integridade dos dados e a confidencialidade. O modo Galois/Counter (GCM) é uma alternativa popular ao CBC que fornece criptografia autenticada com cifras de bloco como AES. Se você realmente não tiver escolha e precisar usar o CBC, ainda poderá protegê-lo calculando um código de autenticação de mensagem (MAC) do texto cifrado e do IV, isso pode ser feito usando o algoritmo HMAC popular. Embora, como em muitos tópicos relacionados a criptografia, a autenticação de mensagens seja um assunto complicado e facilmente exigiria outra postagem de blog inteira para cobri-lo adequadamente.
Fontes e muito mais
Código-fonte para o aplicativo vulnerável
Ataque de inversão de bits no modo CBC - Cryptography Stack Exchange