𝗖𝗕𝗖 𝗕𝗶𝘁 𝗙𝗹𝗶𝗽𝗽𝗶𝗻𝗴 𝗘𝘅𝗽𝗹𝗮𝗶𝗻𝗲𝗱

암호화가 곧 데이터가 변조로부터 안전하다는 것을 의미하지는 않습니다.

많은 개발자가 이 실수를 범합니다. 공격자가 데이터를 읽을 수 없다면 데이터를 변경할 수도 없을 것이라고 생각하는 것이죠. 하지만 이는 틀린 생각입니다. 암호학에서는 기밀성(secrecy)과 무결성(integrity)을 서로 다른 두 가지 작업으로 다룹니다.

CBC 비트 플리핑 공격이 이를 증명합니다. 공격자는 비밀 키를 모르더라도 데이터를 변경할 수 있습니다.

작동 방식은 다음과 같습니다:

AES는 데이터를 하나의 커다란 덩어리로 암호화하지 않습니다. 데이터를 16바이트 블록으로 나눕니다. CBC 모드에서는 이 블록들이 서로 체인처럼 연결됩니다. 첫 번째 블록의 암호화된 출력값이 두 번째 블록의 평문(plaintext)과 혼합됩니다.

이 체인 구조는 복호화 과정에서 취약점을 만듭니다. 블록 2의 원래 텍스트를 얻기 위해 서버는 이를 복호화한 뒤 블록 1의 암호문(ciphertext)과 결합합니다.

공격자는 이를 다음과 같이 악용할 수 있습니다:

공격자는 메시지를 읽을 필요가 없습니다. 그저 비트를 뒤집어(flip) 최종 결과값을 바꿀 뿐입니다.

세션 관리를 위해 암호화된 쿠키를 사용하는 오래된 웹 앱을 예로 들어보겠습니다. 쿠키에는 다음과 같은 내용이 들어있을 수 있습니다: userid=994;role=user;

공격자가 이 쿠키를 가로채 암호문의 비트를 뒤집습니다. 그리고 서버가 하나를 받아들일 때까지 수많은 요청을 보냅니다. 서버는 데이터가 복호화되는지만 확인하기 때문에 변조된 텍스트를 그대로 처리합니다. 갑자기 복호화된 문자열이 다음과 같이 바뀝니다: userid=994;role=admi;

이제 공격자는 관리자(admin) 권한을 갖게 됩니다. 공격자는 키를 읽지도, 원래의 쿠키 내용을 알지도 못했습니다.

실수는 암호화가 무결성을 보장한다고 가정하는 것입니다.

이를 해결하려면 AES-GCM과 같은 인증된 암호화(Authenticated Encryption)를 사용하십시오. 이는 암호화 태그(cryptographic tag)를 생성합니다. 이 태그는 인장(seal)과 같은 역할을 합니다. 공격자가 단 1비트라도 변경하면 인장이 깨지게 됩니다. 그러면 서버는 즉시 해당 데이터를 거부합니다.

만약 반드시 CBC를 사용해야 한다면, Encrypt-then-MAC 구조를 사용하십시오. 암호문에 대한 인증 코드(authentication code)를 생성하고, 복호화를 시작하기 전에 이를 검증해야 합니다.

비밀 데이터라고 해서 항상 신뢰할 수 있는 데이터인 것은 아닙니다. 데이터를 의사 결정에 사용하기 전에, 데이터가 변경되지 않았음을 항상 증명하십시오.

CBC 비트 플리핑(Bit-Flipping) 설명: 왜 암호화만으로는 무결성을 보장할 수 없는가

암호화는 흔히 데이터를 비밀로 유지하는 방법으로 생각됩니다. 이는 사실이지만, 암호화만으로는 데이터의 **무결성(Integrity)**을 보장할 수 없다는 점을 이해하는 것이 매우 중요합니다.

이 글에서는 CBC(Cipher Block Chaining) 모드에서 발생하는 비트 플리핑 공격이 무엇인지, 그리고 왜 암호화만으로는 충분하지 않은지 자세히 살펴보겠습니다.

기밀성 vs 무결성

보안의 핵심 개념 중 두 가지는 기밀성과 무결성입니다.

암호화는 데이터를 읽기 어렵게 만들지만, 공격자가 데이터를 수정하는 것을 항상 막아주는 것은 아닙니다. 데이터가 수정되었는지 여부를 알 수 없다면, 기밀성은 유지될지언정 무결성은 깨진 것입니다.

CBC 모드란 무엇인가?

CBC(Cipher Block Chaining) 모드는 블록 암호화의 한 방식입니다. 각 평문 블록을 암호화하기 전에 이전 암호문 블록과 XOR 연산을 수행합니다. 첫 번째 블록의 경우, 이전 암호문 블록 대신 **초기화 벡터(IV)**를 사용합니다.

CBC 암호화 과정의 수식은 다음과 같습니다: $C_i = E_k(P_i \oplus C_{i-1})$

여기서:

복호화 과정은 그 반대입니다: $P_i = D_k(C_i) \oplus C_{i-1}$

여기서 $D_k$는 키 $k$를 사용한 복호화 함수입니다.

비트 플리핑 공격의 원리

비트 플리핑 공격의 핵심은 복호화 수식 $P_i = D_k(C_i) \oplus C_{i-1}$에 있습니다.

공격자가 $i$번째 평문 블록($P_i$)을 조작하고 싶다면, $i-1$번째 암호문 블록($C_{i-1}$)을 수정하면 됩니다. 공격자는 암호문을 해독할 수는 없지만, 암호문의 특정 비트를 마음대로 바꿀 수 있습니다.

만약 공격자가 $C_{i-1}$의 특정 비트를 $\Delta$만큼 변경하여 $C'{i-1} = C{i-1} \oplus \Delta$로 만든다면, 복호화된 평문 $P'_i$는 다음과 같이 변합니다:

$P'i = D_k(C_i) \oplus C'{i-1}$ $P'i = D_k(C_i) \oplus (C{i-1} \oplus \Delta)$ $P'i = (D_k(C_i) \oplus C{i-1}) \oplus \Delta$ $P'_i = P_i \oplus \Delta$

결과적으로, $C_{i-1}$에서 비트를 반전시키면 $P_i$의 대응하는 비트도 정확히 동일하게 반전됩니다.

주의: $C_{i-1}$을 수정하면 $P_{i-1}$ 블록은 완전히 깨져서(garbage data) 읽을 수 없게 되지만, $P_i$ 블록은 공격자가 의도한 대로 정밀하게 조작할 수 있습니다.

실질적인 예시

다음과 같은 쿠키 데이터가 있다고 가정해 봅시다: user_id=123;role=user

이 데이터가 CBC 모드로 암호화되어 전송되고 있습니다. 공격자는 이 쿠키를 가로채서 자신의 권한을 user에서 admin으로 바꾸고 싶어 합니다.

  1. 공격자는 암호문에서 role=user에 해당하는 평문 블록($P_i$)이 위치한 곳을 찾습니다.
  2. 공격자는 $P_i$의 user 부분을 admin으로 바꾸기 위한 $\Delta$ 값을 계산합니다. $\Delta = \text{"user"} \oplus \text{"admin"}$
  3. 공격자는 이 $\Delta$ 값을 이전 암호문 블록($C_{i-1}$)에 XOR 연산하여 수정합니다.
  4. 서버가 수정된 암호문을 받으면, 복호화 과정에서 $P_i$는 admin으로 변하게 됩니다.

이제 공격자는 관리자 권한을 얻게 됩니다!

비트 플리핑 공격 방지 방법

암호화만으로는 무결성을 보장할 수 없으므로, 데이터를 수정했는지 확인할 수 있는 추가적인 메커니즘이 필요합니다.

1. MAC (Message Authentication Code) 사용

암호화된 데이터에 대해 HMAC(Hash-based Message Authentication Code)과 같은 MAC을 함께 사용합니다.

2. AEAD (Authenticated Encryption with Associated Data) 모드 사용

가장 현대적이고 안전한 방법은 암호화와 인증을 동시에 수행하는 AEAD 모드를 사용하는 것입니다.

결론

암호화는 데이터의 기밀성을 지켜주지만, 데이터의 무결성을 자동으로 보장하지는 않습니다. CBC 모드와 같은 방식에서는 비트 플리핑 공격을 통해 공격자가 평문을 예측 가능한 방식으로 조작할 수 있습니다.

따라서 보안이 중요한 애플리케이션을 설계할 때는 반드시 AES-GCM과 같은 AEAD 모드를 사용하거나, Encrypt-then-MAC 패턴을 적용하여 데이터의 무결성을 함께 검증해야 합니다.