Microsoft는 2020년 7월 15일 Check Point Security Research에 의해 발견된 취약점인 CVE-2020-1350 취약점을 패치하였습니다. 해당 취약점은 통칭 SIGRed라 불리며 Windows Server 2003부터 가장 최신 버전인 2019까지 영향을 미치는 매우 심각한 취약점으로 CVSS 10점을 부여받았습니다. 공격자가 Victim의 DNS Server에 접근할 수만 있다면 SYSTEM 권한으로 RCE까지 수행할 수 있습니다.

이 글에서는 해당 취약점에 대한 익스플로잇 개발 과정과 방법들을 소개합니다.

주요 내용은 다음과 같습니다.

  • 취약점 개요
  • 취약점 원인
  • Exploit 제작
  • 취약점 위험성 평가

취약점 개요

해당 취약점은 Windows Server 계열의 DNS Server에서 발생하는 Integer Overflow로 인한 Heap Overflow 취약점입니다. 취약점을 공격하여 RCE까지 연계할 수 있으며 공격자 DNS Server의 Malformed response에 의해 트리거 됩니다. DNS 서비스가 SYSTEM Integrity로 실행되므로 공격이 성공하면 Domain Administrator 권한을 탈취할 수 있습니다.


취약점 원인

Windows DNS Server는 다른 DNS 서버의 Response를 RR Record(Resource Record)란 구조체에 저장하여 로컬에 캐시합니다. DNS Response의 Type(A, SOA, SIG 등)에 따라 응답을 Cache 하기 위해 각 Type 별 Handler 함수가 호출됩니다.

rr_dispatch_func.png

RRWireReadTable에는 DNS Response Type에 대한 각각의 핸들러 함수들이 선언되어 있습니다.

rr_wire_read_tb.png


그 중 취약점이 발생하는 함수는 SIG Type의 Record를 읽기 위해 사용되는 SigWireRead 함수입니다.

SigWireRead 함수를 살펴보면 RR_AllocateEx 함수를 호출하여 RR 구조체를 할당한 뒤 memcpy를 통해 들어온 데이터를 복사합니다. RR_AllocateEx에 인자로 넘어가는 Size의 경우 Wire를 통해 전달된 Sig Data의 본문 길이 + PacketName을 계산한 값 + 0x14(Fixed Header Size)만큼을 더해서 계산됩니다.

rr_allocate_ex.png


하지만 계산된 Size의 하위 2byte(cx)만 인자로 들어가는 것을 볼 수 있는데 만약 0x10005가 계산된 Size라면 cx만 인자로 들어가므로 0x5가 됩니다. 이를 통해 예상된 할당 크기보다 훨씬 작은 Heap Object(RR Object)가 할당되므로 마지막의 memcpy 함수 호출에서 Heap Overflow가 발생하게 됩니다.

rr_allocate_asm.png


SigWireRead는 DNS Server가 다른 DNS Server의 Response를 Cache하기 위해 호출되는 것이므로 공격자 DNS Server에서 Response 한 값을 Victim DNS Server가 Cache 하여야 합니다.

간단히 그림으로 표현하면 다음과 같습니다.

sigred_overview.png


DNS 서버의 기본적인 Request & Response는 UDP 프로토콜을 통해 이루어집니다. 하지만 취약점을 Trigger 하기 위해서는 계산된 Size의 크기가 0xFFFF 이상은 되어야 하는데 UDP를 통한 DNS의 경우에는 메시지 본문의 크기가 512 Byte로 제한이 되어 있습니다. 이러한 경우에는 UDP Response에 TC(Truncation) Flag를 설정함으로써 Victim DNS Server가 TCP 프로토콜를 통해 다시 Query를 요청하도록 만들 수 있습니다. TCP의 경우 65,535 Byte의 Packet을 보낼 수 있으므로 취약점 Trigger가 가능해집니다.

여기서 공격자 DNS Client에서 취약점을 트리거하기 위해 사용할 도메인 명(4.exdiffense.io)도 매우 중요한데 취약점을 트리거하기 위해서는 계산된 Domain name size를 더 크게 하여야만 Overflow가 가능하기 때문입니다.

DNS Pointer Compression

한번 DNS Response를 살펴봅시다.

wireshark_capture1.png

Name을 클릭했는데 WireShark에서 0xC00C 부분을 하이라이트 해주는 것을 볼 수 있습니다.

A warm welcome to DNS, powerdns.org 의 내용에 따르면

가능한 512byte 안에 많은 정보를 담기 위해서 DNS name은 압축될 수 있다. 이 경우에 Answer의 DNS Name은 0xC00C로 encode 된다. 0xC0(11000000)는 최상위 비트에 두 개의 비트가 set 되어 있다. 이때 두 개의 set bit를 제외한 뒤의 6+8 bit가 DNS Response의 앞에서 Domain Name을 가리키는 Offset이 된다. 이 케이스에서는 packet에서 12=(0x0C) offset 나타낸다.

즉, DNS Name은 압축될 수 있으며, Heap Allocation Size를 계산하는 부분에서 호출되는 함수인 Name_PacketNameToCountNameEx 는 이를 계산하기 위한 함수라는 것을 알 수 있습니다.

wireshark_capture2.png

DNS에서 Domain Name은 .을 기준으로 나뉘며 각 Label의 글자수 + Label로 이루어집니다.

Sig Name으로 0xC00C를 주게 되면 DNS Header 뒤의 이러한 압축 알고리즘 문자열을 가리키게 되는데 0xC00D를 하게 되면 기존의 Label Length(0x01) 대신 “4” = 0x34 를 가리키게 되어 Query한 DNS Name보다 더 큰 DNS Name으로 인식되게 됩니다. 그래서 Allocation Size를 제어하기 위해서는 이렇게 계산된 DNS Name이 내가 원하는 크기만큼까지 확장되도록 Sig Body를 구성해줘야 합니다.

원하는 Allocation Size에 맞게 다음과 같이 본문을 적절하게 구성하면 취약점을 트리거할 수 있습니다.

sigtcp.png


취약점 재현 환경 구성

Victim 서버는 운영체제는 Windows Server 2019(17763.737) 입니다.

victim_winver.png


Victim 서버에 DNS를 설치한 뒤 다음과 같이 조건부 전달자를 설정하여 줍니다. 이 때 IP주소는 공격자 DNS 서버 주소가 됩니다.

victim_setting.png

실제 공격환경에서는 공격자 도메인에 대한 NS 서버의 주소를 Attacker DNS IP로 설정해놓고 공격을 수행하게 됩니다.


취약점 Exploit

RR Record

DNS Server에 대한 응답은 Resource Record란 Object로 구성되며 구조체는 아래와 같습니다.

구조체는 Windows Version마다 조금씩 다르지만 크게 바뀌지 않습니다.

RR Object Structure

typedef struct PacketName
{
    UCHAR   Length;
    UCHAR   LabelCount;
    CHAR    Name[ DNS_NAME_MAX_LEN+1 ];
}
PACKET_NAME, *PPACKET_NAME;
typedef PACKET_NAME  DB_NAME, *RECORD_NAME;

# Windows Server 2019
typedef struct RR_RECORD
{
    struct RR_RECORD*    pRRNext;

    UCHAR           RecordRank;
    RECRESVFLAG     Reserved;
    WORD            wRRFlags;

    WORD            wType;              // in host order
    WORD            wDataLength;
    DWORD           dwTTLSeconds;       // in network order for regular fixed TTL 
                                        // in host order, if cached timeout
    DWORD           dwTimeStamp;        // create time stamp (hours)

    DWORD           Unkown1;
    DWORD           Unkown2; //0x01;
    DWORD           Unkonw3;
    DWORD           Unkonw4;
    DWORD           Unkonw5;
    DWORD           Unkonw6;
    DWORD           Unkonw7;
    WORD            Unknown8;

    union
    {
        struct
        {
            WORD            wType;
            BYTE            chAlgorithm;
            BYTE            chLabelCnt;
            DWORD           dwOrigTTL;
            DWORD           dwSigExp;
            DWORD           dwSigInc;
            WORD            wKeyTag;
            PACKET_NAME     nameSigner;
        }
        SIG;
    } Data;
}
RR_RECORD, *PRR_RECORD;


TTL

Time To Live, TTL이 만료될 경우 해당 RR Object는 Free됩니다. 또한 TTL이 0인 RR Object의 DNS Name에 대한 새로운 데이터를 DNS Server로부터 받았을 때 기존 RR Object는 Free되고 새로운 RR Object가 할당됩니다. 이를 통해 Heap 할당을 조절할 수 있습니다.


Alloc & Free

Alloc은 DNS Response를 통해 RR Object를 Cache 시킴으로써 가능합니다.

Free는 Response되는 Object의 TTL 값을 설정하거나 (특정 시간이 지난 후에 RR Free가 호출됨) TTL값을 0으로 설정한 뒤 동일한 Request에 대해 다른 Response를 돌려줌으로써 가능합니다.


DNS Server Custom Memory Allocator

DNS Server는 별도의 Memory Allocator가 있습니다.

dns.exe에서 메모리 할당을 수행하는 Mem_Alloc 함수를 리버싱 해보면 쉽게 알 수 있는데 할당할 Memory Size가 0xA0보다 작은 경우 (Windows Server 2019의 경우에는 0xA0, 2008의 경우에는 0x90) Custom Memory Allocator를 통해 Memory를 할당합니다. Custom Memory Allocator를 통해 메모리가 한번 할당된 경우, Mem_Free 함수가 호출되어도 HeapFree 함수를 호출하지 않고 DNS Server 자체에서 해당 메모리를 관리합니다. 즉, Windows 상에서는 HeapAlloc 함수를 통해 할당된 메모리가 해제되지 않고 DNS Server 내부에서 Free, Alloc이 관리됩니다.

정리하면 할당하려는 Memory Size가 특정 크기보다 작은 경우 Custom Memory Allocator를 통해 Alloc과 Free가 수행됩니다. Allocator는 Memory 관리를 위해 16 byte의 Custom Memory Header를 추가로 할당합니다.

custom_alloc1.png


Memory Allocator는 크게 4가지의 Bucket을 가지고 있습니다. Bucket Size와 Count는 Windows 버전마다 다르지만 2019를 기준으로는 아래와 같습니다. 아래의 Range에 해당하는 Memory 할당 요청은 모두 정해진 Size로 할당되게 됩니다. 예를 들어 0x39 Memory 할당을 요청했을 때 실제로는 0x50 크기의 Memory Block이 할당됩니다.

Index 0 : 0x50 (Size) * 0x33 (Count) = 0xFF0 (Range 0x00 ~ 0x50)
Index 1 : 0x68 (Size) * 0x27 (Count) = 0xFD8 (Range 0x51 ~ 0x68)
Index 2 : 0x88 (Size) * 0x1e (Count) = 0xFF0 (Range 0x69 ~ 0x88)
Index 3 : 0xA0 (Size) * 0x19 (Count) = 0xFA0 (Range 0x89 ~ 0xA0)

custom_alloc2.png

Memory Allocator의 할당 방식은 LIFO(Last Input First Out)이며 가장 마지막에 Free된 Object가 할당시 재사용 됩니다. 만약 할당할 메모리 Block이 없다면 해당하는 Bucket의 Size * Count 만큼의 영역을 Heap Alloc으로 할당하고 할당된 힙에서 영역들을 분할하여 할당하여 줍니다.

Mem Header Structure

typedef struct DNS_MEM_HEADER
{
    DWORD                       HeaderTag;
    UCHAR                       Active;
    BYTE                        Tag;
    WORD                        Size;
    struct DNS_FREE_BLOCK *     NextFreeBlock;
}
MEMHEAD, *PMEMHEAD;

typedef struct DNS_FREE_BLOCK
{
    MEMHEAD                 MemHead;
    PVOID                   FreeTag;
}
FREE_BLOCK, *PFREE_BLOCK;

SIG Record에 대해서 할당되는 Memory Object를 살펴보면 아래와 같습니다.

rr_graphic.png


Memory Leak 원리

취약점을 트리거하여 Memory Leak을 발생시키기 위해서는 아래와 같은 메모리 구조가 형성되어야 합니다.

Free Hole 뒤에 RR Objec가 연속되게 만들고 취약점을 트리거했을 때 만들어지는 RR Object가 해당 Free Hole에 위치하게 만들면 됩니다.

heap_graphic1.png

취약점을 Trigger 하게 되면 아래와 같이 Free Hole 뒤의 다른 RR Object를 덮어씌울 수 있습니다. 만약 Heap구조가 아래와 같이 구성되지 않으면 Crash가 발생하게 됩니다.

heap_graphic2.png

실제로 취약점을 Exploit 하기 위해 Payload를 구성해보면 취약점이 트리거 되는 RR Object 바로 뒤에 위치한 두 개의 RR Object는 오염되어 사용하기 어렵고 sp_03 부분에 해당하는 RR Object부터 Fake RR Object를 구성하여 줄 수 있습니다.

heap_graphic3.png

RR Object의 구조체에는 DataLength 필드가 존재하므로 저 Fake RR Object의 Data Length 값을 원본 RR Object보다 크게 만들면 다른 RR Object에 존재하는 Heap Memory Address를 Leak 할 수 있습니다. 하지만 Sig Type의 특성상 무한정 크게 할 수는 없고 0xFF까지만 가능하여 다음 Object의 일부분만 Leak이 가능합니다. Fake RR Object의 헤더 값들은 고정된 값들이 사용되므로 별다른 Leak 없이 구성하여 줄 수 있습니다.

이렇게 Leak 된 주소는 추후 RCE Exploit을 만드는 데 사용됩니다.

rr_length_field.png

fake_rr.png

Leak이 성공했을 때 Leak을 위해 만들어진 Fake RR Domain에 대해 데이터를 요청하면 아래와 같이 Heap Address가 Leak 되는 것을 확인할 수 있습니다.

leak_address.png


RCE 원리

Using timeout object

RR Object가 Free될 때에는 RR_Free 함수가 호출됩니다.

pRRNext가 0xFF0B0BEFFE0B0BEF가 아니고(이미 Free된 상태가 아니라면) wType이 2와 6이 아니라면 Mem_Free 함수가 호출됩니다.

rr_free.png

하지만 wType이 2거나 6이라면 Timeout_FreeWithFunctionEx 함수가 호출됩니다.

여기를 참고하면 0x2와 0x6이 각각 DNS_TYPE_NS, DNS_TYPE_SOA 임을 알 수 있습니다. 즉, Free되는 RR Object의 type이 NSSOA라면 Timeout_FreeWithFunctionEx가 호출됩니다.

timeout_freewith.png

그렇다면 Timeout_FreeWithFunctionEx를 좀 더 살펴봅시다.

해당 함수를 살펴보면 0x28 크기의 Memory Block을 할당 요청하고(실제로는 0x28 + 0x10 = 0x38 크기의 Memory Block이 할당) 할당된 Timeout Object에 인자들을 설정합니다.

Timeout Object Structure

typedef struct DnsTimeoutObject
{
    struct DnsTimeoutObject*    pNext;
    PVOID                       pItem;
    PVOID                       pFreeFunction;
    LPSTR                       pszFile;
    DWORD                       Tag;
    DWORD                       LineNo;
}
TIMEOUT_OBJ, *PTIMEOUT_OBJ;

timeout_obj.png

주목할 점은 pFreeFunction과, pItem입니다. 만들어진 Timeout Object는 Timeout_CleanupDelayedFreeList 함수 내부에서 호출됩니다.

call_timeout_obj.png

그렇다면 0x38이 할당되는 Memory Block을 우리가 제어 가능한 영역(Overflow 영역)에 만들 수 있다면 Timeout Object를 덮어씌워 RCE가 가능합니다. 앞에서도 말했다시피 0x380x00 ~ 0x50 Range에 포함되므로 0x50 크기의 메모리 Block이 사용됩니다.

heap_graphic4.png

heap_graphic5.png

heap_graphic6.png

0xA0 크기의 RR Object를 0x50의 RR Object로 인식시켜 Free 시킵니다.

fake_rr_50_1.png

저렇게 구성된 Fake RR Object는 실제로는 0xA0 Block 이지만 Free되었을 때 0x50 Block으로 인식됩니다.

fake_rr_50_2.png

만약 성공적으로 Fake Timeout Object를 구성한다면 EIP를 제어할 수 있습니다.

fake_timeoutobj.png

저렇게 할당된 Timeout Object는 일정 시간이 지난 뒤 Timeout_CleanupDelayedFreeList에서 호출되고 결과적으로는 Fake Timeout Object안에 있는 Function Ptr이 호출됩니다.

취약점이 트리거되었을 때 Crash가 된 함수를 보면 CFG에서 Call Target 검사를 위해 호출되는 ntdll!LdrpDispatchUserCallTarget인 것을 알 수 있고 이 함수의 인자로 deadbeefdeadbeef가 정상적으로 들어간 것을 확인할 수 있습니다.

rce_deadbeef.png


Exploit 만들기

Exploit 개발의 주요 과정은 크게 3가지로 구성됩니다. CFG(Control Flow Guard) 때문에 힙영역에 Shell Code를 올려 공격을 수행하기는 어렵고 정상적인 함수를 호출하여 RCE를 수행하여야 합니다. 여기서는 msvcrt!system 함수를 사용하였습니다.

  1. Crash가 안나도록 Heap Grooming 하기
  2. 만들어진 Heap 구조를 이용해서 msvcrt!system, heap object adress leak하기
  3. 만들어진 Heap 구조를 이용해서 RCE(msvcrt!system) 수행하기

Heap Grooming

힙을 아래와 같은 형태로 만들어야 합니다. Target RR Object 뒤에 빠짐없이 Crash가 나지 않도록 0xFFFF 만큼의 공간이 확보되어야 하고 만약 중간에 빈 공간이 생길 경우 다른 Object가 할당되어 Crash가 발생할 수 있습니다.

/img/Sigred/heap_graphic7.png

전략

  1. 0x1000F Block(_Heap_Entry 0x10 + 0xFFFF)를 할당 후 중간에 한 Block을 Free
  2. 0xF05F Block을 할당하여 0xFB0의 Free Space가 남도록 유도
  3. 0xA0 Block을 요청해서 Allocator가 0xFB0 Block을 0xFB0 free space에 할당하도록 유도(0xFA0+0x10(_HEAP_ENTRY) = 0xFB0)
  4. Remain Free Size가 0xFB0이 되도록 유도

heap_graphic8.png

heap_graphic9.png

Windows 2019 (Window 10 Based) : SigWireWrite에서 Overflow된 RR Object의 Header로 인해 memcpy의 Size 인자가 음수로 되었지만 음수 체크로 인해 해당 부분에서 크래쉬가 발생하지 않음

Windows 2008 R2 (Windows 7 Based) : SigWireWrite에서 Overflow된 RR Object의 Header로 인해 memcpy의 Size 인자가 음수로 되었지만 음수 체크를 하지 않아 Crash가 발생

Windows 2008의 경우에는 취약점을 Trigger한 뒤 공격자에게 반환되는 RR Object를 복사할 때 SigWireWrite 함수에서 호출되는 memcpy의 Size가 음수가 됨으로써 Crash가 발생하여 정상적으로 Exploit이 불가능했습니다. 취약점을 트리거하기 위해서는 nameSize가 커져야만 하는데 nameSize가 커지면 SigWireWrite에서 Size가 음수가 되므로 크래쉬가 발생합니다.

2008_sigwirewrite.png

해당 부분의 경우, Windows 2019에서는 Size 체크로 인해 Crash가 발생하지 않습니다.

2019_sigwirewrite1.png

2019_sigwirewrite2.png


Module address & Heap address Leak

Timeout Object에 RR_FREE를 가리키는 Function Ptr 변수를 dns.exe의 Module addr를 Leak 하기 위해 사용했습니다.

RR_Free 함수의 주소 값을 얻어오면 dns.exe load addr과의 offset을 사용해서 dns.exe의 module addr을 계산할 수 있습니다.

leak_dns_address.png

Sigred%20%E1%84%87%E1%85%B3%E1%86%AF%E1%84%85%E1%85%A9%E1%84%80%E1%85%B3%209181a3bcd5094b5ca0dd885b52610095/Untitled%2037.png

위와 같이 구성한 상태에서 Leak Point1과 Leak Point2에 DNS 요청을 보내면 기존의 DataLen을 0xFF로 증가시켰으므로 Leak Point를 넘어서서 뒤의 Timeout Object까지 읽을 수 있습니다.

Result

[0] Heap Spray
	Free Target(sp_8.exdiffense.io)
.................
[1] Make Hole. (sp_34.exdiffense.io)
[2] Trigger Bug.
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 39661
;; flags: qr tc rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;4.exdiffense.io.               IN      SIG
[3] Fake timeout object free.
[4] Timeout object alloc
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 61416
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;sp_37.exdiffense.io.           IN      SIG
;; ANSWER SECTION:
sp_37.exdiffense.io.    0       IN      SIG     000000000000000070dbd8805e0be10000000573705f33370a657864696666656e736502696f0000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000ee2250003089aa3406020000ef0b0bfeef0b0bfe618010201800180000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000070dbd8805e0be100000016030573705f33380a657864696666656e736502696f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ff00000000bb22a3
[DNS.exe Addr]:0x0x7ff6952e1000

Process finished with exit code 0


위와 같이 구성된 상태에서 SOA Type의 RR Object가 Free되도록 하여 제어 가능한 영역에 Timeout Object가(sp_40) 할당되도록 하고 sp_41.exdiffense.iosp_38.exdiffense.io를 순차적으로 Free하여 sp_38.exdiffense.io 영역에 sp_41.exdiffense.io의 heap addr이 오도록 합니다(free chunk가 다음 free chunk의 주소를 포함하는 것을 이용).

heap_graphic11.png

Leak이 성공적으로 수행되었을 때 아래와 같은 결과값을 얻을 수 있습니다.

leak_result.png


msvcrt!memcpy Address Leak

memcpy의 주소를 Leak 하기 위해서는 Read Primitive가 필요합니다.

NsecDnsRecordConvert 함수를 호출하여 우리가 제어가능한 힙 영역에 데이터를 복사할 수 있습니다. 인자로 Fake Heap Object의 주소를 넘겨줄 수 있는데 이를 적절히 구성하면 우리가 원하는 주소의 데이터를 string으로 인식하게 하여 다른 Heap Object로 데이터를 복사할 수 있습니다.

read_prim.png

아래는 NsecDnsRecordConvert의 Fake Argument Class입니다.

fake_read_arg.png

heap_graphic12.png

Module Address를 Leak하며 중간에 Free된 부분은 sp_201sp_202를 요청하여 Crash가 나지 않도록 채워줍니다.

정리

  1. 다시 취약점을 트리거하여 위에서 만든 sp_40.exdiffense.io(Timeout object)의 RR FREE주소를 NsecDnsRecordConvert 주소로 덮어씌운다. 취약점을 트리거하면서 sp_43.exdiffense.ioFake NsecDnsRecordConvert Argument로 사용하고 memcpy가 포함된 import address table을 sp_45.exdiffense.io 영역에 복사한다.
  2. sp_44.exdiffense.io를 다시 요청하여 memcpy addr를 얻어낸다.


RCE (calc.exe)

위의 과정을 통해 dns.exe Module Address, Heap Address, msvcrt!system address를 leak하였습니다.이제 다시 RCE를 수행하여 msvcrt!system 함수를 우리가 지정한 인자로 호출하면 계산기를 띄울 수 있습니다.

windbg_system.png

heap_graphic13.png

RCE 성공

rce_calc.png


Exploit (Reverse Shell)

System 함수로 넘어갈 인자를 다음과 같이 설정하면 공격자 서버로부터 HTA 파일을 받아와 실행할 수 있습니다.

rce_reverse_cmd.png

FakeDNS 서버의 경우 이 코드를 기초로 만들었고 영상에 사용된 HTA Reverse Shell은 이 코드를 사용했습니다.


실제 위험성 평가

  • Heap과 Fake Free List를 구성할 때 다른 사용자의 요청에 의해 공격자가 원하는 대로 Heap과 Free List가 구성되지 않을 수 있음
  • 처음 세 번의 Crash에서만 DNS Server가 재시작됨
  • DNS 서버에 공격자가 접근할 수 있어야 함

만약 DNS 서버에 공격자가 접근이 불가능하다면 공격이 불가능합니다. Victim의 Windows Version, Patch 버전 등에 따라 힙 구조가 다르므로 공격이 어려울 수 있지만, 공격자가 타겟 서버의 정보를 알고 있다면 충분히 활용할 수 있는 취약점이라고 생각합니다.


Conclusion

이번 글에서는 SIGRed 1 Day Exploit 개발에 관해 다뤄봤습니다. 만약 본 포스팅에서 다뤘던 Exploit 방법 외에도 좀 더 좋은 의견이 있으시다거나 궁금하신 점이 있다면 sheisback@diffense.co.kr로 연락 바랍니다.

감사합니다.


Reference

https://medium.com/@datafarm.cybersecurity/exploiting-sigred-cve-2020-1350-on-windows-server-2012-2016-2019-80dd88594228

https://research.checkpoint.com/2020/resolving-your-way-into-domain-admin:-exploiting-a-17-year-old-bug-in-windows-dns-servers/

https://www.citrix.com/blogs/2012/08/29/when-udp-is-not-enough-what-to-do-with-large-dns-responses/