BEAST Attack
이 TLS 1.0에서 TLS 1.1로 업그레이드되는 과정 중 중요한 변화로 초기화 벡터(IV)가 CBC 모드에서 계산되는 방식을 꼽을 수 있다. 초기화 벡터(IV)는 무엇일까.
TLS는 공개 채널을 통한 암호화 키의 안전한 교환을 위한 사양으로 키 교환이 끝나면(대칭 암호화를 대신하여) 전송된 데이터의 보안을 유지한다. 대칭 암호화 알고리즘은 이제 한물간 방식이라고 평가되지만, 초기화 백터(IV)의 중요성을 이해하는 데 좋은 사례이다. 대칭 암호화 알고리즘의 대표적인 DES 알고리즘을 간단히 알아보면 블록 암호화 알고리즘으로 고정된 크기의 데이터 블록에서 동작한다는 특징이 있다. 암호화 키(8 바이트)와 함께 8 바이트의 평문을 입력 받아 8 바이트의 암호문을 출력한다. 이 암호문을 공개적으로 전송하여도 암호화 키를 모른다면 원본 문자열로 복구할 수 없으므로 안심할 수 있다. 이와 같이 모든 블록 암호는 정확하게 블록 크기에서 동작한다. 만약 데이터가 부족한 경우 쓰레기 데이터를 채워 넣어서 블록의 크기를 맞춰준다.
블록 암호의 한 가지 문제점은 결정적이라는 것이다. 예를 들어 8 바이트 문자열 sendhelp
와 8 바이트 키 password
가 주어지면 모든 DES 구현체들은 8 바이트 암호문 df a1 16 88 92 5c ad 78
를 생성한다. 이는 모든 블록 암호화 알고리즘의 자연스러운 특징으로 복호화를 위해서 이러한 예측이 가능해야하며 다른 키를 사용한다면 전혀 다른 암호문을 생성한다는 사실을 확인할 수 있다.
동일한 키를 사용하여 동일한 8 바이트 데이터를 암호화하면 출력된 암호문이 동일하다는 점을 공격자는 어떻게 악용할 수 있을까. 생각보다 컴퓨터 통신은 상당히 반복적인 경향이 있다. HTML 문서를 떠올려보자. 얼마나 많은 반복적인 8 바이트 시퀀스들이 있는지 (Ex. <div><div>
)
하나의 가설을 세워보자. 댄은 밥이 자신의 아내 킴벌리와 바람을 피우고 있다고 의심한다. 모튼 통신 내용은 암호화하여 전달되지만, 댄은 밥이 편지를 항상 Dearest
로 시작한다는 것을 알고 있다. 그래서 댄은 밥이 Dearest Kimberly
로 시작하는 편지를 보내는 것이 아닌 지 알고 싶어한다. 우연히 킴벌리의 이름은 정확히 8 바이트이지만, 댄은 암호화 키(password
)를 예측할 수 없다.
밥이 편지를 작성하여 보낼 때, 첫 번째 블록인 Dearest
는 f9 1b d5 c2 f6 42 2e 42
로 암호화된다. 두 번째 블록인 Kimberly
는 94 04 8d d0 ca 9f f9 9c
로 암호화한다.
댄은 암호를 추측하는 것 대신 밥이 보낸 두 번째 블록을 보고 밥을 속여 Kimberly
를 전송하고 출력을 관찰한다. 이전에 관찰된 두 번째 암호화 블록과 일치하면 Kimberly
에게 보냈다는 것을 알 수 있게 된다.
블록 암호화 알고리즘에서 이러한 문제는 오랜 시간 고민되어졌고 이제는 CBC(Cipher Block Chaining)이라는 보편적인 방어법이 존재한다. 바로 이전 블록과 XOR 연산을 하는 것이다. (XOR은 복호화 시간에 영향을 최소화하는 좋은 방법이다.) 이때 첫 번째 블록은 XOR 연산을 수행할 대상이 없으므로 초기화 벡터(IV) 값을 추가하게 된다. 초기화 벡터(IV)에 관련된 TLS 1.0과 TLS 1.1의 주요 차이점은 TLS 1.0에서 초기화 벡터(IV) 값은 실제로 비밀로 간주되어 암호화 키와 동일하게 처리된다는 점이다. 그래서 키 협상과 초기화 벡터(IV) 협상을 같이 진행했다. 이 방식은 2002년 Phil Rogaway가 결함을 문서화하기 전 까지 모두가 안전하다고 생각하였다.
데이터 전송을 위해서 CBC 모드와 TLS 데이터를 전송 가능한 덩어리로 분할하게 된다. 1000 바이트 메시지는 송신을 위해 10 개의 100 바이트 패킷으로 분할 될 수 있으며 각각의 개별 SSL 패킷이다. 논리적으로 그들은 하나의 긴 메시지인 것 처럼 처리된다. 여기서 n - 1 패킷의 마지막 8 바이트는 패킷 n의 처음 8 바이트의 CBC 잔여 값이다. 즉, 공격자가 자신의 패킷을 SSL 스트림에 삽입할 수 있으면 CBC가 메시지의 시작 부분을 암호화하는 데 사용된다는 것을 알 수 있다.
공격자는 이점을 악용하여 공격할 수 있다. TLS에는 보안 MAC이 포함되어 있으므로 공격자 패킷은 거부되고 보안 채널을 닫기 때문에 통신을 손상시킬 패킷은 하나뿐이다.
다시 댄, 밥, 킴벌리 이야기로 돌아가서 밥이 CBC를 사용하기 시작했다고 가정하자. 무작위로 01 23 45 67 89 ab cd ef
의 IV를 생성한다. 이제 Dearest
는 IV와 함께 XOR된다.
Plaintext block 1: Dearest Initialization Vector
+----+----+----+----+----+----+----+----+ +----+----+----+----+----+----+----+----+
| 44 | 65 | 61 | 72 | 65 | 73 | 74 | 20 | | 44 | 65 | 61 | 72 | 65 | 73 | 74 | 20 |
+----+----+----+---------+----+----+----+ +----+----+----+---------+----+----+----+
| |
| +-----+ |
+---------------------^+ XOR +^---------------------+
+--+--+
|
^
+----+----+----+---------+----+----+----+
| 44 | 46 | 24 | 15 | EC | D8 | B9 | CF |
+----+----+----+---------+----+----+----+
|
^
+-------+-------+
| DES(password) |
+-------+-------+
|
Plaintext block 2: Kimberly | CBC Residue
+----+----+----+----+----+----+----+----+ | +----+----+----+----+----+----+----+----+ Output
| 44 | 65 | 61 | 72 | 65 | 73 | 74 | 20 | +----^+ 44 | 65 | 61 | 72 | 65 | 73 | 74 | 20 +---------->
+----+----+----+---------+----+----+----+ +----+----+----+---------+----+----+----+
| |
| +-----+ |
+---------------------^+ XOR +^---------------------+
+--+--+
|
^
+----+----+----+----++---+----+----+----+
| A6 | BE | C8 | 6B | 02 | AB | E5 | 5F |
+----+----+----+---------+----+----+----+
|
^
+-------+-------+
| DES(password) |
+-------+-------+
|
|
| +----+----+----+----+----+----+----+----+ Output
+-----^+ F3 | 3C | 02 | A7 | B8 | FD | 22 | 7D +---------->
+----+----+----+----+----+----+----+----+
댄이 밥의 트래픽을 스니핑하여 보는 것은 ed d7 a5 09 67 d9 89 26 f3 3c 02 a7 b8 fd 22 7d
이다. 이제 댄은 밥이 Kimberly
를 암호화하도록 속여서 두 번째 블록 f3 3c 02 a7 b8 fd 22 7d
과 비교하도록 패킷 인젝션 공격을 시도한다. (밥의 TLS 구현은 이전 블록과 XOR하는 방식이다.) CBC 모드에서 위협이 가능한 지 추가로 가정을 해보자. 댄은 CBC 구성을 위한 이전 블록의 값이 fe dc ba 98 76 54 32 10
인 상태에서 밥의 통신에 Kimberly
를 삽입하였다.
Injected block: Kimberly CBC Residue(can't change this)
+----+----+----+----+----+----+----+----+ +----+----+----+----+----+----+----+----+ Output
| 44 | 65 | 61 | 72 | 65 | 73 | 74 | 20 | | FE | DC | BA | 98 | 76 | 54 | 32 | 10 +---------->
+----+----+----+---------+----+----+----+ +----+----+----+---------+----+----+----+
| |
| +-----+ |
+---------------------^+ XOR +^---------------------+
+--+--+
|
^
+----+----+----+---------+----+----+----+
| B5 | B5 | D7 | FA | 13 | 26 | 5E | 69 |
+----+----+----+---------+----+----+----+
|
^
+-------+-------+
| DES(password) |
+-------+-------+
|
|
| +----+----+----+----+----+----+----+----+ Output
+-----^+ 1D | FD | E2 | 97 | 8F | EE | E1 | 91 +---------->
+----+----+----+----+----+----+----+----+
이것은 원래의 암호문의 두 번째 블록과 동등하게 비교되지 않아 아직 쓸모가 없다. 하지만 댄이 XOR에 대해 알고 있다면 이야기가 달라진다. 동일한 값을 두번 XOR하면 첫 번째 값의 영향을 제거한다. 그래서 CBC 이전 블록과 XOR할 것이라는 것을 예측하고 Kimberly
를 먼저 XOR한다.
Injected block: Kimberly CBC Residue(can't change this)
+----+----+----+----+----+----+----+----+ +----+----+----+----+----+----+----+----+
| 44 | 65 | 61 | 72 | 65 | 73 | 74 | 20 | | FE | DC | BA | 98 | 76 | 54 | 32 | 10 |
+----+----+----+---------+----+----+----+ +----+----+----+---------+----+----+----+
| |
| +-----+ |
+---------------------^+ XOR +^---------------------+
+-----+
그런 후 첫 번째 블록의 출력 값인 두 번 째 블록(비교 대상 블록)과 다시 XOR한다.
Plaintext block 1: Dearest Initialization Vector
+----+----+----+----+----+----+----+----+ +----+----+----+----+----+----+----+----+
| 44 | 65 | 61 | 72 | 65 | 73 | 74 | 20 | | 44 | 65 | 61 | 72 | 65 | 73 | 74 | 20 |
+----+----+----+---------+----+----+----+ +----+----+----+---------+----+----+----+
| |
| +-----+ |
+---------------------^+ XOR +^---------------------+
+--+--+
|
^
+----+----+----+---------+----+----+----+
| 44 | 46 | 24 | 15 | EC | D8 | B9 | CF |
+----+----+----+---------+----+----+----+
|
^
+-------+-------+
| DES(password) |
+-------+-------+
|
XXX | CBC Residue
XXXXX | +----+----+----+----+----+----+----+----+ Output
XXXXX +----^+ 44 | 65 | 61 | 72 | 65 | 73 | 74 | 20 +---------->
Injected block XXXXX +----+----+----+---------+----+----+----+
+----+----+----+----+----+----+----+----+ XXXX |
| B5 | B5 | D7 | FA | 13 | 26 | 5E | 69 | XXXXXX |
+----+----+----+---------+----+----+----+ XXXX |
| XXXX |
| +-----+ XXXXX +
+---------------------^+ XOR +------------------+XXXXX
+--+--+ XXXX
| XXXX
Adjusted injected block ^ XXXX
+----+----+----+---------+----+----+----+ XXXXX
| 58 | 62 | 72 | F3 | 74 | FF | D7 | 4F | XXXX
+----+----+----+----+----+----+----+----+
그 후 밥을 속여 동일한 CBC 블록을 사용하여 암호화할 수 있다면
Injected block CBC Residue
+----+----+----+----+----+----+----+----+ +----+----+----+----+----+----+----+----+
| 44 | 65 | 61 | 72 | 65 | 73 | 74 | 20 | | FE | DC | BA | 98 | 76 | 54 | 32 | 10 |
+----+----+----+---------+----+----+----+ +----+----+----+---------+----+----+----+
| |
| +-----+ |
+---------------------^+ XOR +^---------------------+
+--+--+
|
^
+----+----+----+---------+----+----+----+
| A6 | BE | C8 | 6B | 02 | AB | E5 | 5F |
+----+----+----+---------+----+----+----+
|
^
+-------+-------+
| DES(password) |
+-------+-------+
|
| CBC Residue
| +----+----+----+----+----+----+----+----+ Output
+-----^+ F3 | 3C | 02 | A7 | B8 | FD | 22 | 7D +---------->
+----+----+----+----+----+----+----+----+
출력된 값은 원래의 두 번 째 블록과 동일하다. 이것은 XOR의 교환성 때문에 일어나는 것이다. (a xor b = b xor a
) TLS 그룹은 이러한 이론적 결함을 심각하게 생각했지만, SSL 개발자는 그렇지 않았다. 그 결과 BEAST 공격으로 실체화되고 실제로도 악용이 가능하다는 것이 증명되었다.
보안 측면에서 HTTP의 문제점 중 하나는 알기 쉬운 일반 텍스트를 포함한다는 것이다. 일반적인 HTTP Requeset를 살펴보자.
GET /index.html HTTP/1.1
Host: mysite.com
Cookie: Session=12345678
Accept-Encoding: text/html
Accept-Charset: utf-8
분명한 부분은 굵게, 약간의 추측 과정을 거치면 알 수 있는 것을 기울여 구분해보자.
GET /index.html HTTP/1.1
Host: mysite.com
Cookie: Session= 12345678
Accept-Encoding: text/html
Accept-Charset: utf-8
여기서 유일한 변수는 요청되는 페이지와 세션 쿠키의 값이다. 이제 CBC 모드에서 요청 값의 첫 번째 78 바이트가 다음과 같다고 가정해보자.
GET /index.html HTTP/1.1\r\nHost: www.somesite.com\r\nCookie: Session=12345678
password
키와 0x0123456789abcdef
IV 값으로 DES CBC 모드 암호화한 결과는 다음과 같다.
GET / ind | ex.html | HTTP/1.1 | \r\nHost | : mysite | .com\r\n | Cookie: | Session= | 12345678 |
---|---|---|---|---|---|---|---|---|
a7d25abbd67b2dbf | e2ade7246ea5ed5 | e99063ebe430b75b | 746ae5eca36e2bc3 | f6f62f99a076056f | 6b14704973a779ae | 7fa9300d4e490cba | b6040b9542a59ad5 | f9bb888ac3763722b |
공격자는 마지막 블록인 f9bb888ac3763722b
에 관심을 가질 것이다. (HTTP 특성으로 인해 민감한 정보가 존재하는 블록을 정확하게 결정할 수 있다.) 패킷을 주입할 수 있다고 가정하고 일치하는 값을 얻을 때까지 00000000
부터 시작해서 삽입할 수 있다. 그러나 세션 쿠키가 간단한 8 바이트 숫자 값이라도 을 수행해야한다. 하지만 패킷을 주입할 수 있다면 요청을 수정하는 것도 가능하다.
GET / ind | ex.html | HTTP/1.1 | \r\nHost | : mysite | .com\r\n | Cookie: | Session= | 12345678 |
---|---|---|---|---|---|---|---|---|
GET / ind | ex.jsp H | TTP/1.1\ | r\nHost: | mysite. | com\r\nC | ookie:S | ession=1 | 2345678 |
요청 값을 index.jsp
수정하여 제거된 한 문자로 인해 세션 쿠키의 첫 번째 숫자를 찾기 위해서 단지 10개의 추측만 필요하다.
ession=0
ession=1
...
다시 요청 값을 수정한 후 다음 세션 쿠키 값을 추측해보자.
GET / ind | ex.html | HTTP/1.1 | \r\nHost | : mysite | .com\r\n | Cookie: | Session= | 12345678 |
---|---|---|---|---|---|---|---|---|
GET / ind | ex.js HT | TP/1.1\r | \nHost: | mysite.c | om\r\nCo | okie:Se | ssion=12 | 345678 |
ssion=10
ssion=11
ssion=12
...
실제 세션 ID 값은 이보다 길고 다양하며 공격을 성립하기 위해서 필요한 조건들이 있다. 해당 공격은 TLS 1.1에서 수정되었으나, 많은 서버들이 오래된 버전을 사용하고 있어 SSL 다운그레이드 고역에 취약하여 클라이언트가 안전한 버전을 지원하다라도 취약한 버전을 사용하도록 속일 수 있다.
참고
데일리 시큐 - SSL 사이트 90%, BEAST SSL 공격에 취약해!
An Illustrated Guide to the BEAST Attack
BEAST