Image Image Image Image Image Image Image Image Image Image

NURILAB | February 22, 2019

Scroll to top

Top

아래아한글(HWP) 취약점 분석 방법

아래아한글(HWP) 취약점 분석 방법
최 원혁

Review Overview

분석 난이도
3.5
프로그래밍 요구
8
5.8

Rating

툴을 이용한 분석이라 난이도는 높지 않으나, 특정 부분을 분석하는데 파이썬 언어에 대한 이해가 필요하다.

개요

최근 APT 공격이 급증하고 있다. 그중에서도 아래아한글(HWP)를 이용한 공격이 두드러지고 있는 추세이다. 사실 아래야한글(HWP) 파일은 OLE 구조를 이용하고 있으며, 내부 스트림은 암호/압축되어 있는 상태이다. 그러기 위해서는 별도의 도구가 필요한 상태이다. 따라서 아래아한글(HWP)를 분석하기 위해서 HwpScan2를 사용하였다.

 

분석 방법

아래아한글(HWP) 파일 포맷 5.x 버전은 OLE 구조를 가지고 있다. 한컴사의 자체 포맷을 3.x 버전이라고 말한다. 이 글에서는 파일 포맷 5.x 버전에 대한 분석 방법이다. (향후 HwpScan2는 파일 포맷 3.x 버전에 대해서도 지원할 예정이다.)

OLE 파일 포맷은 MS사에서 개발한 파일 포맷으로 작은 파일시스템의 구조와 유사하다. 그런 이유로 OLE 파일 내부에는 폴더와 파일이 존재한다(정확히 표현한다면 Storage와 Stream 이다).

 

OLE 파일 구조

OLE 파일 구조

 

준비한 아래아한글(HWP) 악성코드는 다음과 같다.

HwpScan2를 이용하여 간단하게 취약점의 존재 유무를 확인해보자. 우선 HwpScan2은 아래 링크에서 다운로드 받을 수 있으며, 이를 실행하면 다음과 같은 옵션을 볼 수 있다.

HwpScan2 옵션 화면

HwpScan2 옵션 화면

 

옵션을 통해 -f 옵션을 사용하여 검사하고자 하는 대상 파일을 지정하면 된다.

C:\> hwpscan2.exe -f test.hwp

version

 

위의 실행 결과를 통해 test.hwp 문서는 버전이 5.0.2.2라는 사실을 알 수 있으며, 암호는 없지만, 압축되어 있는 상태임을 알 수 있다. 다음은 OLE 구조를 출력해보자. -p 옵션을 주면 OLE 구조를 확인할 수 있다.

C:\> hwpscan2.exe -f test.hwp -p

hwpole

 

아래아한글(HWP) 내부 구조가 상당히 복잡하다는 것을 알 수 있다.  구체적인 내부구조는 한컴사에서 공개하고 있는 HWP 파일 포맷 문서를 통해 확인할 수 있다[1]. 아래의 내용은 아래야한글(HWP)의 Storage와 Stream을 표로 표현하고 있다.

hwp_struct

 

위에서 test.hwp의 많은 부분은 BodyText 내부의 Section들로 구성되어 있음을 확인할 수 있다.  이제 취약점을 검사하기 위해서 -s 옵션을 추가해보자.

 C:\> hwpscan2.exe -f test.hwp -s

hwp_vul

 

test.hwp 파일은 Exploit.HWP.Generic.5A 취약점이 존재한다. 이는 23번 Property인 Section11에서 발견되었다.  좀 더 구체적으로 이를 확인해보기 위해서는 23번 Property를 덤프해보아야 한다. 그러기 위해서는 -d 옵션을 사용할 수 있다.

C:\> hwpscan2.exe -f test.hwp -d 23

hwp_dump

 

사실 23번 Property인 Section11은 HWP Information 정보에서 확인해보면 압축되어 있다고 표시되어 있다. 따라서 23.dmp는 압축이 해제되지 않은 상태이며, 압축을 해제한 것은 23_decom.dmp이다.

 

여기에서 압축이 해제된 23_decom.dmp는 레코드 구조로 이루어져 있다. 레코드 구조라 함은 4Byte(32 Bit)를 읽으면 다음과 같은 형태로 이루어져있다.

hwp_rec

 

  • Tag ID :  10 Bit
  • Level : 10 Bit
  • Size : 12 Bit (헤더 뒤에 오는 데이터의 크기)

 

압축이 해제된 23_decom.dmp의 경우 위의 구조가 덤프 파일 끝까지 계속적으로 반복된다. 이를 추적하기 위해서 간단하게 파이썬 코드로 다음과 같이 작성하였다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# -*- coding: utf-8 -*-
# Copyright (C) 2013 Nurilab.
# Author: Kei Choi(hanul93@gmail.com)

import struct

def Info(val) :
    b = 0b1111111111
    c = 0b111111111111
    Size = (val >> 20) & c
    print 'TagID : ' + hex(val &b)
    print 'Level : ' + hex((val >> 10) & b)
    print 'Size  : ' + hex(Size)
    print '-------------------------------'
    return Size

def GetDword(s, offset) :
    return struct.unpack("<L", s[offset:offset+4])[0]

fp = open('23_decom.dmp', 'rb')
fval = fp.read()
fp.close()

pos = 0
flen = len(fval)

while pos < flen :
    print 'Pos   : ' + hex(pos)
    val  = GetDword(fval, pos)
    size = Info(val)
    if size == 0xfff :
        pos = pos + 4
        size = GetDword(fval, pos)
    pos = pos + size + 4

if pos == flen :
    print 'EOF'

 

하지만, 위의 소스코드를 사용하여 23_decom.dmp 파일을 레코드 구조로 추적을 해보면 아래와 같이 특정 위치(0x294)에 도달했을 때 Tag ID가 0x5A 시점에서 Size가 엄청 큰 값이 오면서 덤프 파일 EOF(End of File)에 도달하지 못하는 것을 확인할 수 있다.

secinfo

 

즉, Tag ID가 0x5A인 시점에 문제가 존재함을 알 수 있다. 그렇다면 Tag ID 0x5A가 의미하는 바를 알아야 하는데, 이는 아래아한글(HWP) 파일 포맷 문서에서 확인해야 한다.

tagid

 

아래아한글(HWP) 파일 포맷 문서에는 위처럼 Tag ID에 대한 설명이 나오는데 0x5A를 찾기 전에 모든 Tag ID는 HWPTAG_BEGIN(0x10) 값이 기본적으로 더해져 있다. 따라서 Tag ID 0x5A를 찾으려면 0x10을 뺀 0x4A(10진수는 74)에 대해서 검색해야 한다.

 

tag5a

 

검색 결과 위의 그림에서 확인할 수 있듯이 “글맵시”에서 문제가 발생한 것을 확인할 수 있다. 즉, test.hwp 파일은 글맵시 취약점이다. 아래 그림에서 볼 수 있듯이 23_decom.dmp 파일을 열어 Tag ID 0x5A가 위치하는 0x294 위치에서 보면 이상한 값들이 존재하는 것을 확인할 수 있다.

 

hex294

 

참고문헌

[1] 한컴, “한글 문서 파일(HWP) 포맷 공개”, http://goo.gl/0d2wql

Previous Story

There are no older stories.