제목 : RCE 취약성 분석 및 Windows RDP의 재현성 (CVE-2019-0708)

0x00 漏洞描述​

2019 년 5 월 15 일에 고위험 취약점이 노출되었습니다. 취약점에는 Windows 2003, Windows 2008, Windows 2008 R2 및 Windows XP 시스템과 같은 광범위한 영향이 있습니다. 이 서버의 취약성 방법은 원격 데스크탑 포트 3389 및 RDP 프로토콜을 통해 공격됩니다. 이 취약점은 올해 이전의 랜섬웨어 인 Eternal Blue 바이러스와 유사하게 가장 유해한 취약점입니다. CVE-2019-0708 취약점은 사용자의 ID 인증을 확인함으로써 상호 작용없이 인증을 우회하고 RDP 프로토콜을 직접 연결하여 악성 코드 실행 명령을 서버에 보내는 것입니다. 공격자가 악용하면 Wannacry Eternal Blue 취약성과 같은 서버 침입, 바이러스 및 대규모 감염이 발생합니다. 2019 년 9 월 7 일 오전 1 시경, Metaspolit은 악용을 업데이트했습니다.
2019 년 5 월, Microsoft는 원격 코드 실행 취약성 CVE-2019-0708을위한 패치 업데이트를 발표했습니다. CVE-2019-0708은 원격 데스크탑 서비스 (RDS)에 존재하는 "BlueKeep"이라고도합니다. 이 취약점은 사전 승인이며 사용자 상호 작용이 필요하지 않으므로 잠재적 인 무기 화 된 웜 성적 착취의 위험이 있습니다. 이 취약점이 성공적으로 이용되면 시스템 권한을 사용하여 임의 코드를 실행할 수 있습니다. Microsoft Security Response Center의 권장 사항에 따르면이 취약점은 Wannacry 및 Eseemaudit과 같은 공격과 유사하게 벌레 공격이 될 수 있습니다. Microsoft는 이러한 취약점의 심각성과 사용자에게 잠재적 인 영향으로 인해 더 이상 Windows 사용자를 보호하기 위해 지원되지 않는 Windows XP 운영 체제에 패치를 발행하기 위해 드문 조기 경고 단계를 수행했습니다.

0x01 漏洞影响​

이 취약점은 Windows 7, Windows Server 2008 R2, Windows Server 2008, Windows 2003 및 Windows XP를 포함한 이전 버전의 Windows 시스템에 영향을 미칩니다. Windows 8 및 Windows 10 이상은이 취약점의 영향을받지 않습니다.

0x02 cve_2019_0708_bluekeep_rce.rb 介绍​

이 PR은 RDP를 통해 해제 된 후 취약점을 이용하는 CVE-2019-0708 (일명 BlueKeep) 용 Exploit 모듈을 추가합니다. RDP termdd.sys 드라이버는 내부적으로 만 채널 MS_T120에 대한 바인딩을 올바르게 처리하지 않으므로 릴리스 후 사용될 수있는 끊임없는 분리 공급자 표시 메시지가 가능합니다. 제어 가능한 데이터 및 원격 비 페이지 풀 힙 제트를 사용하여 유휴 채널 용 간접 통화 위젯을 사용하여 임의의 코드 실행을 구현합니다.
이 모듈은 원래 @zerosum0x0과 @ryhanson에 의해 개발되었으며 @oj, @zerosteiner, @rickoates, @wvu-r7, @bwatters-r7, @wchen-r7, @tsellers-r7, @todb-r7 등이 추가로 개발했습니다. Metasploit의 RDP 및 기타 라이브러리 향상을 활용하려면 모듈이 파이썬 외부 모듈에서 기본 루비 모듈로 포팅됩니다. 현재 구현과 확인하고 비교하려면 원래 Python 모듈이 커밋 기록에 있습니다.
이 모듈은 현재 64 비트 버전의 Windows 7 및 Windows Server 2008 R2를 대상으로합니다. Windows Server 2008 R2의 경우 RDPSND 채널을 통해 힙 제트를 활성화하기 위해 레지스트리 키를 수정해야하지만 모든 Windows 운영 체제에서 기본적으로 사용할 수있는 다른 대체 채널이 있습니다.
이 모듈은 사용자가 추가 대상 정보를 제공하거나 대상 호스트에 충돌 할 위험이 있기 때문에 현재 수동 모듈로 나열됩니다. 이 모듈은 취약한 호스트 만 확인하고 특정 대상 운영 체제에 대한 초기 정보를 표시하는 기본 포인트 전용 대상 옵션을 구현하지만 사용자는 보조 정찰을 기반으로 더 정확한 대상을 지정해야하거나 추가 개선이 런타임에 대상 커널 메모리 레이아웃을보다 정확하게 결정할 수 있습니다.
표적 환경에 기본 주소를 추가로 전송하는 다른 변수가있을 수 있지만, 배치되지 않은, 베어 메탈, VirtualBox, VMware 및 Hyper-V에 대한 특정 대상이 있습니다.

0x03 漏洞分析​

1. PDU​

MS-RDPBCGR (원격 데스크톱 프로토콜 : 연결 및 원격 처리) 문서에 따르면, 비트 맵 캐시 PDU의 전체 이름은 TS_BITMAPCACHE_PERSISTENT_LIST_PDU이며 주요 목록 PDU 데이터는 영구 키 목록에 내장되어 있습니다. 영구 키 목록 PDU는 클라이언트에서 서버로 전송되는 RDP 연결 시퀀스 PDU입니다.
RDP 접합 시퀀스의 연결 완료 단계는 그림 1에 나와 있습니다.
xqyflvosll316412.png

그림 1. 원격 데스크탑 프로토콜 (RDP) 연결 시퀀스
영구 키 목록 PDU 헤더는 일반적인 RDP PDU 헤더이며, 그림 2 : TPKTHEADER (4 바이트) + X224DATA (3 바이트) + MCSSDRQ (변수) + SecurityHeader (변수)와 같이 다음과 같이 구성됩니다.
lwkd0dkqt1s16413.png

그림 2. 클라이언트 지속적인 키 목록 PDU
MS-RDPBCGR 문서에 따르면 TS_BITMAPCACHE_PERSISTENT_LIST_PDU는 이전 세션에서 전송 된 캐시 비트 맵에서 저장된 캐시 비트 맵 키 목록을 포함하는 구조입니다. 그림 3에서 볼 수 있듯이.
p0bpxxzkiuv16414.png

그림 3. 영구 키 목록 PDU 데이터 (BitMapCache 영구 목록 PDU)
디자인별로 Bitmap Cache PDU는 RDP 클라이언트가 Key와 관련된 비트 맵의 로컬 사본을 가지고 있음을 서버에 알리기 위해 사용하여 서버가 클라이언트에 비트 맵을 재판매 할 필요가 없음을 나타냅니다. MS-RDPBCGR 문서를 기반으로 BitMap PDU는 네 가지 특성을 가지고 있습니다.
RDP 서버는 캐시 된 비트 맵 키를 저장하기 위해 커널 풀을 할당합니다.
RDP 서버에 의해 할당 된 커널 풀 크기는 구조의 NumentriesCache X 필드에 의해 제어 될 수 있으며 BitMapCache의 TotalErtriesCache X는 RDP 클라이언트의 목록 구조입니다.
비트 맵 캐시 PDU는 여러 번 법적으로 전송 될 수 있습니다. 비트 맵 키는 여러 영구 키 목록 PDU로 전송 될 수 있기 때문에 각 PDU에는 BBITMASK 필드에 태그가 표시됩니다.
비트 맵 키의 수는 169로 제한됩니다.
BitMapCache 영구 목록 PDU의 이러한 네 가지 기능을 기반으로, 169로 제한된 비트 맵 키의 수를 우회 할 수 있다면 모든 데이터를 커널에 기록 할 수 있습니다.

2.如何使用PDU将数据写入内核​

MS-RDPBCGR 문서에 따르면, 정상적으로 해독 된 비트 맵 카시 영구 목록 PDU는 다음과 같습니다.
F200-TS_SHARECONTROLHEADER33333:TOTALLENGTH=0X00F2=242BYTES1700-TS_SHARECONTROLHEADER33333:PDUTYPE=0x00170x0017=0x0010 |0x0007=ts_protocol_version | pdutype_datapduef03-ts_sharecontrolheader:pdusource=0x03ef=1007e A030100-TS_SHAREDATAHEADER33333:SHAREID=0X000103EA00-TS_SHAREDATAHEADER3:PAD101-TSS_SHAREDATAHEADER3336 0:StreamID=stream_Low (1) 0000-TS_SHAREDATAHEADER3:UNCOMPRESSEDLENGTH=02B-TS_SHAREDATAHEADER:3360PD UTYPE2=PDUTYPE2_BITMAPCACHE_PERSISTENT_LIST (43) 00-TS_SHAREDATAHEADER33333:GeneralCoppressedType=00000-TS_SHARE Dataheader333333:GeneralCoppressedLength=00000-ts_bitmapcache_persistent_list333:numentRies [0]=00000-ts_b ITMAPCACHE_PERSISTENT_LIST3333333:NumentRies [1]=01900-TS_BITMAPCACHE_PERSISTENT_LIST:NumentRIES [2]=0x19=250000-TS_BITMAPCACHE_PERSISTENT_LIST3333333333333:numumentRies ]=00000-ts_bitmapcache_persistent_list333333:numentRies [3]=00000-ts_bitMapCache_Persistent_List3333333:numentRies [3]=00000-ts_BitmapCache_Persistent_List333333:numument Ries [4]=00000-ts_bitmapcache_persistent_list:totalentries [0]=00000-ts_bitmapcache_persistent_list:333 60totalentries [1]=01900-ts_bitmapcache_persistent_list333333:totalentries [2]=0x19=250000-ts_bitmapcache_persist ENT_LIST33333:TOTALERTRIES [3]=00000-TS_BITMAPCACHE_PERSISTENT_LIST333:TOTALENTRIES [4]=003-TS_BITMAPCACHE _persistent_list3333333:bbitmask=0x030x03=0x01 |0x02=persist_first_pdu | persist_last_pdu00-ts_bitmapcache_persiste nt_list33333333:pad20000-ts_bitmapcache_persistent_list3333333:pad3ts_bitmapcache_persistent_list3333:Ent IES:A31E5116-CACHE2, KEY0, LOW32 비트 (TS_BITMAPCACHE_PERSISTENT_LIST_ENTRY:Key1) 48292278-CACHE2, KEY0, HI GH32 비트 (TS_BITMAPCACHE_PERSISTENT_LIST_ENTRY:Key2) 61F7899C-CACHE2, KEY1, LOW32 비트 (TS_BITMAPCACHE_PERSIS tent_list_entry:key1) cda966a8-cache2, key1, high32 bits (ts_bitmapcache_persistent_list_entry3333:key2)
커널 모듈 RDPWD.SYS에서 기능 루틴 ShareClass : SBC_HANDLEPERSISTENTCACHELIST는 BitMapCache 영구 목록 PDU를 구문 분석 할 책임이 있습니다. 구조의 bbitmask 필드가 비트 값0x01로 설정된 경우, 현재 PDU가 지속적인 첫 번째 PDU임을 나타냅니다. 그런 다음 SBC_HANDLEPERSISTENTCACHELIST는 WDLIBRT_MEMALLOC를 호출하여 그림 4와 같이 영구 비트 맵 캐시 키를 저장하기 위해 커널 풀 (커널 메모리를 할당)을 할당합니다.0x00 값은 현재 PDU가 지속 중간 PDU임을 나타냅니다. 값0x02는 현재 PDU가 지속 된 마지막 PDU임을 나타냅니다. 지속적인 중간 PDU 및 지속적인 PDU를 구문 분석 할 때 SBC_HANDLEPERSISTENTCACHELIST는 그림 5에 표시된 것처럼 비트 맵 캐시 키를 이전에 할당 된 메모리에 복사합니다.
o3umk2sbpko16416.png

그림 4
zd5rqjxdyqx16417.png

그림 5. sbc_handlepersistentCachelist 사본 비트 맵 캐시 키
Wind
1w3k1fxarra16419.png

그림 6. sbc_handlepersistentCachelist 스택 추적
aj3unnodyta16420.png

그림 7. SBC_HANDLEPERSISTENTCACHELIST의 두 번째 매개 변수로서 TS_BITMAPCACHE_PERSISTENT_LIST 구조
도 4에 도시 된 바와 같이, BitMapCachElistPoollen=0xc * (총 길이 + 4) 및 총 길이=TotalErtriesCache0 + TotalErtriesCache1 + TotalErtriesCache2 + TotalErtriesCache3 + TotalErtriesCache4.
이 공식에 따라 BitMapCachelistPoollen을 최대 값으로 만들기 위해 "Word value"TotalErtriesCache x=0xffff를 설정할 수 있습니다. 그러나 그림 8에 표시된 각각의 TotalErtriesCache X에 대해 TOTALERTRIESCACHELIMIT 검사가 있습니다.
TotalErtriesCachelimit X는 ts_bitmapcache_capabilityset_rev2 구조에서 나 왔으며, dcs_init가 rdpwd를 통해 호출 될 때 capapi_load_ts_bitmapcache_capabilityset_rev2 기능에서 시작되었습니다. 그림 8에 표시된대로 이것은 capapi_capcache _capcache th the the the the th the th the th the th th the th the th the th the th the th th the parset th the th the th the th the parset _capcache에서 결합됩니다. 도 9에 도시 된 바와 같이 PDU의 확인.
ztv2axyczq316422.png

그림 8. RDPWD! capapi_load_ts_bitmapcache_capabilityset_rev2
u3cvqpx5col16424.png

그림 9. RDPWD! capapi_combine_ts_bitmapcache_capabilityset_rev2
CAPAPI_COMBINE_TS_BITMAPCACHE_CAPABILYSET_REV2는 서버가 시작한 NumCellCaches (0x03)와 TotalErtriescachelimit [0-4] (0x258,0x258,0x100,0x0,0x0)를 Client Requests와 NumcellCaches (0x03) 및 Total Lestriescache [0-4]를 결합합니다. (0x80000258,0x80000fffc,0x0), 그림 9의 EDX 및 ESI 레지스터에 표시된 바와 같이.
클라이언트는 그림 10과 같이 NumcellCaches 및 TotalErtriesCache [0-4]를 제어 할 수 있지만, 그림 11과 같이 서버가 시작한 NumCellCaches (0x03) 및 TotalErtriesCachelimit [0-4]] (0x258,0x10000,0x0,0x0)으로 제어 할 수는 없습니다.
gxa1bp5gmid16425.png

그림 10. TS_BITMAPCACHE_CAPIBLESSET_REV2
ihmh2q3pdgr16426.png

그림 11. CAPAPI_COMBINE_TS_BITMAPCACHE_CAPABILITYSET_REV2 함수
이 정보를 사용하면 최대 비트 캡 카치 엘리 스포 롤렌=0xc * (0x10000 +0x258 +0x258 + 4)=0xc3870, 이론적으로0x8 * (0x10000 +0x258 +0x258 + 4)=0x825A0 Bytes of the kernel 12에서 제어 할 수 있습니다.
lvpwhwf2egc16427.png

그림 12. 영구 키 목록 PDU 메모리 덤프
그러나 BitMap 캐시 목록 풀에서 RDP 클라이언트가 예상 한대로 모든 데이터를 제어 할 수있는 것은 아닙니다. 제어되지 않은 데이터의 각 8 바이트 사이에는 4 바이트의 제어되지 않은 데이터 (인덱스 값)가 있으며, 이는 쉘 코드 스토리지에 그다지 친숙하지 않습니다. 또한0xc3870 크기의 커널 풀은 여러 번 할당 될 수 없습니다. 영구 키 목록 PDU는 합법적으로 한 번만 전송할 수 있기 때문입니다. 그러나 커널 풀이 동일한 메모리 주소로 할당 될 특정 통계 기능이 여전히 있습니다. 또한, 비트 맵 캐시 목록 풀 할당 이전에는 항상0x2B522C (x86) 또는0x2B5240 (x64) 커널 크기의 풀이 있으며, 이는 그림 13과 같이 힙 할당, 특히 X64에서 매우 유용합니다.
crnfq4ash4016428.png

그림 13. 지속적인 키 목록의 PDU 통계적 특성

3.刷新Rect PDU​

MS-RDPBCGR 문서에 따르면 PDU를 새로 고치면 RDP 클라이언트가 서버가 세션을 재 할당하도록 요청하게됩니다. 이 구조는 그림에 표시된 범용 PDU 헤더 및 CroseshRectPdudata (변수)를 포함합니다. 14.
d5ft3nkiywy16429.png

그림 14. Reshing the Rest PDU 데이터
Number-of-Pareas 필드는 Arethorefresh 필드에 포함 된 사각형 구조의 수를 정의하는 8 비트 부호없는 정수입니다. areatorefresh 필드는도 15에 도시 된 바와 같이 ts_rectangle16 구조의 배열이다.
pl0eei5fgpk16430.png

그림 15. 사각형 (ts_rectangle16)
새로 고침 rect PDU는 일련의 "포괄적 인 사각형"작업을 통해 서버를 알리기 위해 서버를 세션을 재 할당합니다. 기본 채널을 기반으로 채널 ID는0x03EA (서버 채널 ID)입니다. 연결 시퀀스가 완료되면 그림 1과 같이 RDP 서버는 새로 고침 매트릭스 PDU를 수신/구문 분석 할 수 있으며 가장 중요한 것은 법적으로 여러 번 전송 될 수 있습니다. ts_rectangle16 구조는 8 바이트로 제한되지만 RDP 클라이언트는 8 바이트 만 제어 할 수 있지만 여전히 커널에 임의의 데이터를 쓸 수 있습니다.

4.使用Refresh Rect PDU将数据写入内核​

정상적인 해독 된 새로워진 REPHYL PRDU는 그림 16에 나와 있습니다.
fzu5kbaz1kh16431.png
 
뒤로
상단