국가암호공모전 (II-A 분야) 문제 02 (2016)
추천글 : 【암호론】 암호론 목차
1. 문제 [본문]
2. 풀이 [본문]
1. 문제 [목차]
X 기업에서는 직원들이 온라인으로 중요 메시지를 전송할 때 반드시 암호화 하여 전송하는 보안 정책을 실행하고 있다. 사내에서는 암호화/복호화 기능을 모두 할 수 있는 프로그램을 사용하고, 사외에서는 암호화 기능만 할 수 있는 프로그램을 사용하고 있다. 외근, 출장 등 회사 외부에서 메신저, e-mail 등을 이용할 때 중요 메시지를 암호화하여 전송하고, 본사에서는 이를 복호화하여 확인한다.
문제 A. 경쟁사 Y 기업에서는 X 기업의 직원을 매수하여 암호문 생성 프로그램(EncryptString.exe)을 입수하였고, 해커를 고용하여 해당 실행 프로그램을 분석하였다. 해당 실행 프로그램에서 암호화에 사용되는 암호키를 추출하시오. 암호키를 추출하는 방식을 최소 2가지 이상 사용하고, 그 과정을 기술하시오. (정적 분석 방식과 동적 분석 방식 각각 한 가지 이상)
문제 B. X 기업에서는 암호문 생성 프로그램이 유출된 것을 확인하였다. 이에 보안팀과 개발팀이 긴급회의를 열어 암호화 생성 프로그램이 유출되었을 때 발생하는 문제 A번과 같은 취약성을 없애기 위한 방안을 검토하고 있다. 해당 실행 프로그램에서 암호키를 추출할 수 있는 취약성에 대한 대응(Secure Coding)과 보다 근본적으로 안전한 암호화 환경을 위한 대응 방안(Secure Design)을 제시하시오. (Secure Coding / Secure Design 각각 한 가지 이상)
※ 참고: 문제 A의 암호키를 가장 먼저 제출하는 것을 최초 정답자로 인정한다. 문제 B의 경우, 제시하는 방안의 독창성과 안정성을 고려하여 점수를 부여한다.
2. 풀이 [목차]
악성 프로그램 혹은 중요 소프트웨어를 (선한 목적이든 악한 목적이든) 분석하는 방법은 총 3가지(정적 분석 방식, 동적 분석 방식, 초기 분석 방식(상세 분석 방식))가 있다. 여기서 정적 분석 방식은 실행파일을 가지고 초기 소스를 역추론하는 방식이다. 그리고 동적 분석 방식은 소프트웨어를 실행시킨 뒤 계속해서 메모리나 프로세스와 같은 시스템의 변화를 살펴보는 방법이다. exe 파일을 실행시키는지의 여부에 따라 정적, 동적으로 구분한 것 같다. (ref)
1. 정적 분석 방식을 통한 암호키 추출
암호문 생성 프로그램은 대략 이런 식으로 작동할 것이다. 일단, 입력된 문장을 적절한 규칙으로 바꾼다. 그리고 프로그램에 내장된 암호키도 적절한 규칙으로 바꾼다. 변형된 문장과 변형된 키를 적당히 연산하여 암호문을 생성한다. 암호문을 적절한 규칙으로 바꾼다. 이때 '적절한 규칙'으로서 padding이나 해쉬함수가 쓰일 수 있다. 그리고 출력된 문장으로 보건데 마지막의 '적절한 규칙'에 문장을 PEM 형식으로 바꾸는 함수가 포함돼 있을 것이다. 전문가들은 dependency scan을 해 보면서 쓰이는 함수와 그 관계를 파악하거나 어셈블리어 분석을 통해 내부 내용을 대략적이나마 들여다 볼 수 있을 것이다. 하지만 암호키는 온전한 형태로 라이브러리 및 실행 파일에 저장돼 있을 것이기 때문에, 전문가들이 하는 굉장히 어려운 과정을 거칠 필요가 없을 것이다. 그리고 라이브러리는 함수의 정의 같은 것을 포함하기 때문에 key를 저장하고 있는 것은 exe 파일일 것이다.
그렇다면 exe 파일을 어떻게 들여다 보면 좋을까? 이를 위해 아주 좋은 프로그램인 PE Explorer를 사용하고자 한다. 설치는 여기에서 SETUP 파일을 다운 받으면 된다. 이제 PE Explorer의 사용법을 익힐 겸 실험을 하나 해 보자.
1) 다음 C 소스를 빌드해서 exe 파일을 생성시킨다.
#include <stdio.h>
char* key = "abc ABC123_!?_";
int main(){
printf("the string is: %d", key[0]);
return 0;
}
2) 그 뒤 PE Explorer를 실행시킨 뒤 File - Open File을 통해 해당 exe 파일을 선택하자.
3) Tools - Disassembler - Start Now를 선택한다. (View에서는 도움될 만한 정보가 없다.)
4) 하단의 탭에서 Unprocessed data, Strings, View1 ~ View4 중에서 Strings를 선택하자.
5) 그러면 다음 정보를 확인할 수 있다.
00403000: SSZ00403000_libgcj_13_dll
db 'libgcj-13.dll',0
0040300E: SSZ0040300E__Jv_RegisterClasses
db '_Jv_RegisterClasses',0
00403024: SSZ00403024_abc_ABC_123____',0
db 'abc ABC123_!?_'0
00403033: SSZ00403033_the_string_is___d
db 'the string is: %d',0
0040304C: SSZ0040304C_Mingw_runtime_failure_
db 'Mingw runtime failure:',0Ah,0
00403064: SSZ00403064__VirtualQuery_failed_for__d_byt
db 'VirtualQuery failed for %d bytes at address %p',0
00403098: SSZ00403098__Unknown_pseudo_relocation_prot
db ' Unknown pseudo relocation protocol version %d.',0Ah,0
004030CC: SSZ004030CC__Unknown_pseudo_relocation_bit_
db ' Unknown pseudo relocation bit size %d.',0Ah,0
0040xxx 뒤의 문장에서 식별할 수 없는 문자는 언더바(_)로 표현하는 것 같다. 하여튼 아주 성공적으로 key와 printf에 대한 정보가 담겨져 있음을 알 수 있다. 그렇다면 동일한 방법으로 EncryptString.exe를 분석하면 어떤 결과가 나올까? 그 결과는 다음과 같았다.
0040375C: SSZ0040375C_error
db 'error',0
00403764: SSZ00403764__s___s_
db '%s [%s]',0
00403770: SSZ00403770_An_error_occurred_in_running_the
db 'An error occurred in running the program. ',0Ah,0
0040393C: SSZ0040393C_Error_during_converting__
db 'Error during converting ',0Ah,0
00403958: SSZ00403958_Error_during_CryptEncrypt___
db 'Error during CryptEncrypt. ',0Ah,0
00403978: SSZ00403978_memory_allocation_fail
db 'memory allocation fail',0
00403990: SSZ00403990_Error_during_CryptDeriveKey__
db 'Error during CryptDeriveKey!',0Ah,0
004039B0: SSZ004039B0_Error_during_CryptHashData
db 'Error during CryptHashData',0
004039CC: SSZ004039CC_Cryptoforum2016_1
db 'Cryptoforum2016!1',0
004039E0: SSZ004039E0_Error_during_CryptCreateHash__
db 'Error during CryptCreateHash!',0Ah,0
00403A00: SSZ00403A00_Error_during_CryptAcquireContext
db 'Error during CryptAcquireContext!',0
00403AA8: SSZ00403AA8_Delete
db 'Delete',0
00403AB0: SSZ00403AB0_NoRemove
db 'NoRemove',0
00403ABC: SSZ00403ABC_ForceRemove
db 'ForceRemove',0
사실 이들 후보를 추리는 과정이 필요하지만, 이제는 정답이 너무 분명해 보인다. 암호공모전의 주최기관이 한국암호포럼(Korean Cryptoforum)이고 공모전은 올해(2016년) 문제이므로 'Cryptoforum2016!1'이 굉장히 수상해 보인다. 실제로 다른 문장들은 제각기 암호키가 되기에 부적절한 문장들이다. 우선 위의 예제에서도 보여지듯이 당연히 runtime error와 관련된 문장이 반드시 있어야 한다. 여기에서는 관련된 문장이 딱 하나 있다. 바로 'An error occurred in running the program. '이다. 또 Crypt 시리즈들은 제각기 실제로 EncryptString.exe에서 쓰일 법한 함수들과 관계된다. (ref1, ref2). Delete, NoRemove, ForceRemove도 서로서로 관련 있는 문장이므로 이들이 암호키가 되기에 적절치 않다. 마지막으로 'error'는 너무 짧고, '%s [%s]'는 문장을 출력하기 위해 필요하므로 이들도 부적절하다. 따라서 'Cryptoforum2016!1'이 정답이다.
2. 동적 분석 방식을 통한 암호키 추출
동적 분석은 프로세스를 실행시킨 후 점검하는 방법으로 대체로 정적 분석 방식이 선행된 뒤에 행해진다. 하지만 악성 프로그램으로 컴퓨터가 망가질 수 있으므로 아주 조심스러워야 한다. 동적 분석을 할 때 여러 가지 프로그램을 이용할 수 있지만 MS에서 무료로 배포한 Process Explorer는 무조건 실행해야 하는 아주 중요한 프로그램이다. (ref) 다운은 여기서 받을 수 있다. 그 뒤 EncrypteString.exe가 쓰는 메모리의 내용을 확인하기 위해 다음 과정을 따른다.
1) 좌측 Process 바에서 EncryptString.exe를 찾고 오른쪽 마우스 클릭, "Properties.."를 누른다.
2) Image, Performance, Performance Graph, GPU Graph, Threads, TCP/IP, Security, Environment, Job, Strings 탭 중 Strings를 선택한다.
3) 암호키로 추정되는 string을 찾는다.
4) 텍스트 파일로 저장하길 원한다면 하단에 Save, Find 버튼 중 Save를 선택해서 저장한다.
5) (추가) 문제 03의 PBKDF2.exe도 동일한 과정을 거친다.
우선 정적 분석 방식에 비해 string이 훨씬 많으므로 단번에 분석하기는 어렵고, 문제 03의 PBKDF2.exe도 동일하게 분석해 보면서 Strings에서 보여주는 정보의 구조를 파악해 보려고 한다. (컴파일러마다 상이한 string을 보여주는 듯 하기 때문에 주최측에서 제공한, 동일한 컴파일러로 제작했을 exe 파일과 비교해 보려는 것이다.) 만약 문제 03의 Q1이라는 폴더에 PassWord.txt가 없으면 다음 메시지를 출력한다.
분명히 "PassWord"이라는 문장이 PBKDF2.exe에 저장돼 있을 것이다. (뒤의 한글은 깨져 보일 가능성이 크다.) 이제 두 Strings를 비교해 보자.
PBKDF2.exe는 사용자가 패스워드를 입력하면, 그걸 바탕으로 128 비트의 블록암호 키를 생성하는 프로그램으로 에러 메시지를 제외해서는 어떤 특별한 string을 저장하고 있지 않다. (ref) 따라서 "PassWord.txt"와 "Masterkey.txt"라는 string이 있는 부분에 EncryptString.exe가 대응되는 부분에 바로 암호키가 저장돼 있을 것이라고 추론할 수 있다. 그 부분에는 정적 분석 방식에서 다룬 바로 그 string들이 있으므로 동일한 추론 과정에 따라 암호키가 'Cryptoforum2016!1'이라는 사실을 알 수 있다.
한편, "val", "RSDS", "Zwf"가 좀 걸리는데 암호키가 되기엔 짧은 느낌이 없지 않다. 물론 정적 분석 결과를 알고 있으면, 이들은 정적 분석 시 검출이 안 됐으므로 암호키가 될 수 없다는 것을 알 수 있을 것이다.
PBKDF2.exe Properties 창에서 마지막 부분에 0123456789ABCDEF가 있음을 알 수 있다. 하지만 PBKDF2.exe가 하는 역할을 볼 때 이것은 암호키라고 볼 수 없다. DEC를 HEX로 바꾸기 위한 목적이든 우연히 그런 값이 나왔든 암호키가 아니다.
3. 암호키 방어 대책
3.1. Secure Coding
의미를 쉽게 유추하거나 너무 난수열인 것처럼 티가 나지 않도록 암호키를 설정하는 것도 하나의 방법일 수 있다. 하지만 이는 패스워드를 생성하는 입장에서 자유도가 많이 낮다. 이를 위해 다음 몇 가지 방법을 제시하려고 한다.
일단 패스워드로써 한글을 사용하는 것이다. 사실 한국어를 사용하는 사람으로서 영어 암호보다 한글 암호가 더 암기하기 쉽다. 물론 모든 암호를 한글로 하기 어렵다면 맨 앞의 몇 개의 원소에만 한글로 저장해서 패스워드를 이렇게 바꿔라, 라고 지정하는 indicator로 사용할 수도 있다. 한글을 쓰는 게 좋은 이유는 정적 분석 방식이든 동적 분석 방식이든 한글 정보를 제대로 출력하지 못하기 때문이다. 물론 이는 한글을 저장하는 과정에서 문자값이 음수가 되기 때문으로 이런 것까지 커버하는 새로운 툴이 나오면 무력화될 수 있다. 하지만 NULL 문자를 출력하지 않으려는 시도로 보이기 때문에 NULL 문자와 조합해서 쓰면 툴을 만들기 쉽지 않을 것이다. 또 한글로 쓰였다는 것을 인지하는 것도 쉽지는 않을 것이다.
#include <stdio.h>
#include <stdlib.h>
char* a = "가ABCDEF12345678!@#$%^&*()_+=~";
int main()
{
printf("%c%c%c %d", a[0],a[1], a[2], a[0]);
system("pause");
return 0;
}
두 번째 방법은 양동작전을 쓰는 것이다. 만약 암호키를 안 뒤 1시간만에 해독을 할 수 있더라도 암호키의 후보가 1,000,000개가 넘는다면 114년 정도가 걸리므로 현실적으로 해독이 불가능하다. 그렇다면 어떻게 암호키의 후보를 1,000,000개를 넘게 만들 수 있을까? 20자리가 넘는 동일한 자릿수의 암호키 두 개를 준비한다. 그 다음 입력값이 주어지면 (2로 나눈 나머지를 기준으로 하는 등) 비트단위로 두 암호키 중 하나의 비트를 취한다. 이런 식으로 1,000,000개 이상의 조합의 암호키가 생성된다. 그리고 암호화 과정에서 어떤 비트를 취했는지 그 정보를 뒤에 붙여서 복호화 때 참고하는 것이다. 아무리 어셈블리어 전문가가 뛰어나도 뒤에 붙여진 정보를 가지고 각 비트에서 어떤 암호키를 선택했는지 알아낼 수 있을 것같지 않다. 또한 복호화 과정에서 복호화 키가 1,000,000개가 필요하냐고 걱정할 수도 있는데, 비트단위로 두 암호키 중 하나의 비트를 취하는 과정만 잘 손 보면 선택된 암호키의 조합을 단 몇 개뿐으로 만들 수 있을 것이다. (단, 해커의 입장에서 막연할 뿐이다.) 그리고 애초에 양동작전으로 2개의 암호키만을 준비할 필요도 없다. 5개든 10개든 적절히 마련해 주면 될 것이다. ㅁㄴ
3.2. Secure Design
단순히 회사가 input에 개입하지 않고 output만 검사한다면, 당연히 input에서 해커가 공격할 여지가 있다. 따라서 output을 검사하는 것뿐만 아니라 input에서 회사가 관여할 수 있어야 정보를 안전하게 지킬 수 있을 것이다. 예를 들어서 RSA 암호를 사용하고 있던 회사가 있다고 하자. 이때 input에서 어떤 해쉬함수로 일차적으로 주어진 문서의 정보를 바꾼 뒤 RSA 암호를 적용하는 것이다. 그렇게 되면 만약 암호 생성 프로그램이 유출되었단 사실을 인지했을 때, input에서 일차적으로 바꾸는 그 방식을 바꾸면 그 시점부터 생성되는 정보는 안전하게 지킬 수 있다. 좀 더 구체적으로 해쉬함수는 초기값이 필요한데, 강력하게 보안이 된 웹사이트에 그 초기값을 올려서 회사원들이 사이트에 접속해서 상수값을 취한 뒤 스스로 해쉬함수를 쓸 수 있도록 하면 되겠다.
좀 더 나아가 여러 초기값과 if문 같은 걸로 조합해서 좀 매끄러운 문장이 나올 때 그게 원문이라고 인식할 수 있도록 코딩을 하면 "누가" 정보를 누출하는지 알 수 있다. 한편 SSL 같은 경우 비대칭키 알고리즘과 대칭키 알고리즘을 동시에 사용하는데, 이때 디칭키인 session key로서 제공하는 것이다. 이러면 회사 비관계자가 그 웹사이트에 접근하는 것을 막을 수 있을 것이다.
그런 식으로 웹사이트를 운영하면 상당히 보안이 강력할 것이다.
입력: 2016.08.13 17:53
'▶ 자연과학 > ▷ 암호·보안' 카테고리의 다른 글
【국가암호공모전】 (II-A 분야) 문제 06 - 1부 (2016) (3) | 2016.08.15 |
---|---|
【국가암호공모전】 (II-A 분야) 문제 05 (2016) (5) | 2016.08.14 |
【국가암호공모전】 (II-A 분야) 문제 04 (2016) (10) | 2016.08.14 |
【국가암호공모전】 (II-A 분야) 문제 03 (2016) (0) | 2016.08.13 |
【국가암호공모전】 (II-A 분야) 문제 01 (2016) (0) | 2016.08.13 |
최근댓글