메모리 해킹 이야기

@codemaru · September 04, 2007 · 13 min read

내용이 길어지다 보니 자칫 제가 뭔가 독창적인 아이디어를 내놓고 거기에 대해서 옹호하는 듯한 입장이 된 건 아닌가 하는 생각이 듭니다. 다른 분들을 위해서 거듭 강조하지만 이는 제 개인의 독창적인 생각이 아닙니다. 원 글에도 밝혔듯이 이 또한 해묵은 방법입니다.

원 글의 의도는 메모리 해킹이 새로운 방식이 아니고 보안 관계자들 또한 그 방식에 대해서 인지를 오래전부터 하고 있었다는 것을 알리는데 있었습니다. 또한 제가 제시한 한 가지 방법이 완벽한 대안은 절대 아닙니다. 알려져 있는 한 가지 방법을 제시한 것에 불과합니다.

우선 먼저 부족한 글임에도 고견 남겨주신 Jerry님, 고맙습니다. *^^*
지적하신 부분에 대한 답글을 작성하다 글이 길어질 것 갈아서 새 글로 작성합니다.
읽어 보시고 틀린 내용이나 제가 잘못 이해한 부분이 있다면 지적해 주셨으면 합니다.
논의 과정 중에서 더 좋은 시스템에 대한 아이디어가 나온다면 그 또한 좋은 일이라 생각됩니다.

현재의 인터넷 뱅킹에서의 취약점들은 사용자임과 동시에 공격자인 경우의 문제점을 적극적으로 방어하기가 곤란한 한계점이 분명 존재함니다.

사실 이 문제는 게임에서 가장 큰 이슈가 되고 있는 항목 입니다. 정상적인 게이머들 조차도 게임을 해킹해서 뭔가 더 좋은 아이템이나 레벨업에 걸리는 플레이 시간을 단축하려고 하기 때문이죠. 하지만 인터넷 뱅킹에 이 내용이 적용되는 것은 조금 이상하다고 생각됩니다. 메모리 해킹의 주된 대상이 되고 있는 은행 업무 프로세스는 이체입니다. 이체는 자신의 계좌에서 다른 사람의 계좌로 돈을 송금하는 절차입니다. 이 과정에서 사용자가 공격자인 경우에 얻을 수 있는 것이 무엇인지 궁금합니다.

위에서 언급한 바와 같이 어떤 방식이던지 암호화 구간은 클라이언트에서 사용자에게 해독되는 구간이 반드시 존재합니다. 따라서 언급해 주신 해결 방식은 공격자의 시도를 좀 더 어렵게 만드는 측면은 있겠습니다만, 사용자 입력 구간에 대한 보호와 위변조 여부를 Server 사이드에서 검증하기 어렵다는 문제는 여전히 남으며,

논의에 앞서 제가 지난 번에 소개한 이미지를 전송하는 방법에 관한 내용을 좀 더 세부적으로 적어 보는게 도움이 될 것 같습니다.

서버에서는 그림 열장과 그에 대응하는 키 열 개를 보낸다고 했습니다. 편의상 이미지를 i라 부르고, 키를 k라 부르겠습니다. 서버는 다음과 같은 종류의 데이터를 생성할 겁니다.

원본 숫자 배열: 3, 2, 1, 9, 0, 5, 7, 8, 4, 6
이미지: i0, i1, i2, i3, i4, i5, i6, i7, i8, i9
키: k0, k1, k2, k3, k4, k5, k6, k7, k8, k9

이 데이터 중에서 이미지와 키만 클라이언트로 전송됩니다. 클라이언트 측에서 i0를 누르면 k0가 입력되는 식이죠. i0에는 당연히 3이란 숫자가 기록되어 있을 겁니다. 이렇게 클라이언트에서 입력된 데이터는 서버로 전달됩니다. 서버에서는 원본 숫자 배열을 참조해서 클라이언트에서 보내온 값을 원복 시킬 겁니다. 만약 클라이언트에서 조작된 값이 왔다면 그 조작된 값대로 원복될 겁니다. 서버는 그 값을 재차 클라이언트로 보냅니다. 그러면 클라이언트측에서는 화면에 그 데이터를 표시하고 사용자에게 확인을 받습니다.

이 과정에서 우리가 생각해야 할 부분은 클라이언트에는 해독 과정이 없다는 것 입니다. 클라이언트는 단지 서버로부터 해독된 값을 받고 있을 뿐이죠. 이 과정을 해킹하기 위해서는 사람이 i0를 보고 3이라고 인식한 것처럼 프로그램이 그 숫자를 인지해야 합니다. 하지만 지난 글에도 소개 했듯이 아직도 그 작업은 매우 힘든 일로 여겨지고 있습니다.

해커가 악의 적인 목적으로 특정 계좌가 아닌 단지 입력값을 조작한 경우를 생각해 보겠습니다. 서버에서는 바뀐 데이터를 원복해서 클라이언트로 보냅니다. 만약 해커가 이 데이터를 조작하지 않는다면 사용자는 엉뚱한 계좌가 입력된 걸 보고 취소를 할겁니다. 해커 입장에서는 반드시 이 데이터를 조작해야 하죠. 그런데 중요한 것은 해커는 입력값을 단지 조작만 했을 뿐 그 결과 값이 무엇인지 모른다는데 있습니다. 따라서 결과 값을 메모리에서 수정할 수 없는 상황이 되는 것이죠. 이 상황에서도 해커는 다시 이미지 인식이라는 문제로 돌아가게 됩니다.

이 과정 전반에는 아직 사람과 동일한 능력으로 인식할 수 있는 이미지 스캐너가 존재하지 않는다는 가정이 포함되어 있습니다. 만약 그러한 알고리즘이 있다면 이러한 과정과 논의는 전부 쓸모없는 일이겠죠.

암호화와 난독화
암호화(encryption)과 난독화(obfuscation)의 차이에 대해서 잠시 소개하겠습니다. 암호화란 암호화 과정만 있는 경우를 말합니다. 즉 해독 과정이 프로그램 상에 전혀 없는 경우죠. 반면 난독화는 프로그램 상에 암호화와 함께 해독 과정이 같이 있는 경우를 말합니다. 이 경우는 단지 리버싱을 통해서 암호를 구할 수 있죠.

한가지 예를 살펴보도록 하겠습니다. 패스워드를 입력하는 곳 입니다. 사용자가 패스워드를 설정하면 그것을 저장했다가 비교하는 루틴이라고 해 봅시다.

암호화를 이곳에 적용하면 이렇게 됩니다. 최초 설정시 입력한 사용자의 입력 값을 암호화해서 저장합니다. 그리고 다음 번에 사용자가 로그인하기 위해 입력하면 그 데이터를 암호화해서 원본 값과 비교하죠. 이 과정에는 해독 과정이 없습니다. 따라서 해커가 프로그램을 리버싱한다고 하더라도 원본 암호를 알아낼수는 없습니다.

난독화를 이곳에 적용하면 이렇게 됩니다. 최초 설정시 입력한 사용자의 입력 값을 암호화해서 저장합니다. 그리고는 다음번에 사용자가 로그인하기 위해 값을 입력하면 원본 데이터의 암호를 해제한 다음 그 값을 비교합니다. 이 과정은 해독 과정이 포함되어 있기 때문에 프로그램을 리버싱하면 원본 암호를 알아낼 수 있습니다.

예가 조금 작위적인면이 없지만 대부분의 경우 후자와 같이 처리해 놓고는 암호화를 했다고 합니다. 대표적인 경우가 파일 암호화입니다. 저장할 때 암호화해서 저장하고, 로딩할 때 그것을 해독해서 로딩합니다. 그리곤 암호화를 했다고 하죠. 이 경우에는 난독화가 정확한 표현입니다.

암호화를 한 경우에 그 데이터의 보안성은 코드 복잡도와 함께 암호화 알고리즘의 복잡도에 비례한다고 볼 수 있습니다. 반면 난독화의 경우에는 단순히 코드 복잡도에 비례합니다.

두번째는 그 수많은 사용자를 위한 서비스를 이미지 방식으로 만들면, 서버사이드에서 이미지를 생성하거나, 클라이언트에서 사용자의 입력값을 이미지로 조합하는데, 상당한 시간이 걸릴 것은 분명하며, 이미지 변환을 위한 또다른 ActiveX와 같은 이미지 리더 및 이미지 메이커는 또 다른 비극의 시작일 수 있고, 이미지 방식의 인터넷 뱅킹은 현재의 인터넷 뱅킹 시스템을 엄청나게 확장해야 가능한 시나리오라는 점 입니다. 또한, 저속 인터넷 사용자들의 경우에는 이미지 다운로드 및 업로드를 통해 인터넷 뱅킹을 사용하는데, 상당한 애로를 격을 수도 있다는 점 입니다.

지금의 인터넷 인프라를 생각한다면 그렇게 힘든 일이 아닙니다. 홈페이지에 접속하는 순간 벌써 우리는 엄청난 데이터를 전송받습니다. 홈페이지에 포함된 이미지, 보안프로그램, 플래시 파일 같은 것들이죠. 수 메가에 달하는 이런 것들도 지금 잘 받아서 사용하고 있지 않습니까? 여기에 몇 십 킬로바이트에 불과한 이미지 열 개를 더 받는다고 느려진다고 주장하는 것은 바람직하지 않다고 생각합니다.

또한 이미지 프로그램을 ActiveX 형태로 만들어야 한다고 생각할 필요는 없습니다. Ajax를 사용해서 만들 수 있습니다. 단지 이미지를 읽어오고, 그것을 화면에 배치하고 클릭했을때 키를 입력해 두었다 서버로 전송하는 것은 Ajax를 일주일만 공부한 사람도 만들 수 있을만큼 간단한 내용입니다.

@codemaru
돌아보니 좋은 날도 있었고, 나쁜 날도 있었다. 그런 나의 모든 소소한 일상과 배움을 기록한다. 여기에 기록된 모든 내용은 한 개인의 관점이고 의견이다. 내가 속한 조직과는 1도 상관이 없다.
(C) 2001 YoungJin Shin, 0일째 운영 중