스택 버퍼 오버플로
Stack buffer overflow소프트웨어에서 스택 버퍼 오버플로 또는 스택 버퍼 오버런은 프로그램이 의도된 데이터 구조(일반적으로 고정 길이 버퍼)[1][2] 외부에 있는 프로그램의 콜 스택 상의 메모리 주소에 쓸 때 발생합니다.스택 버퍼 오버플로 버그는 프로그램이 스택에 있는 버퍼에 실제로 할당된 것보다 더 많은 데이터를 쓸 때 발생합니다.이로 인해 거의 항상 스택상의 인접 데이터가 파손됩니다.또한 실수로 오버플로가 트리거된 경우에는 프로그램이 크래시되거나 올바르게 동작하지 않는 경우가 많습니다.스택 버퍼 오버플로는 버퍼 오버플로(또는 버퍼 오버런)[1]로 알려진 보다 일반적인 프로그래밍 오동작의 일종입니다.스택에 모든 액티브함수 호출의 반환 주소가 포함되어 있기 때문에 스택상의 버퍼가 과잉으로 채워지는 것보다 스택상의 버퍼가 과잉으로 채워지면 프로그램 실행이 지연될 가능성이 높아집니다.
스택 버퍼 오버플로는 스택스매싱이라고 불리는 공격의 일부로 의도적으로 발생할 수 있습니다.영향을 받는 프로그램이 특수 권한으로 실행 중이거나 신뢰할 수 없는 네트워크 호스트(웹 서버 등)로부터 데이터를 수신하는 경우 이 버그는 잠재적인 보안 취약성입니다.스택 버퍼가 신뢰할 수 없는 사용자로부터 공급된 데이터로 채워지면 실행 가능한 코드를 실행 중인 프로그램에 주입하고 프로세스를 제어하도록 스택을 손상시킬 수 있습니다.이것은 공격자가 컴퓨터에 [3][4][5]대한 무단 액세스 권한을 얻을 수 있는 가장 오래되고 신뢰할 수 있는 방법 중 하나입니다.
스택 버퍼 오버플로우를 부정 이용하는 중
스택 기반 버퍼 오버플로를 부정 이용하는 표준 방법은 함수 반환 주소를 공격자가 제어하는 데이터(통상은 스택 자체)[3][6]에 대한 포인터로 덮어쓰는 것입니다.이것은 로 설명되고 있다.strcpy()
다음 예시는 입니다.
#실패하다 <문자열>h> 무효 후우(차 *막대기) { 차 c[12]; 스트럭시(c, 막대기); // 경계 확인 없음 } 인트 주된(인트 argc, 차 **argv) { 후우(argv[1]); 돌아가다 0; }
이 코드는 명령줄에서 인수를 가져와 로컬스택 변수에 복사합니다.c
12자 미만의 명령줄 인수(아래 그림 B 참조)에서는 정상적으로 동작합니다.인수의 길이가 11자를 넘으면 스택이 파손됩니다.(C 프로그래밍 언어에서는 문자열이 늘바이트 문자로 끝남으로써 안전한 최대 문자 수는 버퍼 크기보다 1자 작습니다.따라서 12글자 입력은 저장하기 위해 13바이트가 필요하며, 이어서 센티넬 0바이트가 입력됩니다.그 후, 0 바이트는 버퍼의 끝을 1 바이트 초과한 메모리 위치를 덮어쓰게 됩니다).
프로그램 스택:foo()
다양한 입력:
위의 그림 C에서 11바이트보다 큰 인수가 명령줄에 입력된 경우foo()
는 로컬 스택 데이터, 저장된 프레임포인터 및 가장 중요한 반환 주소를 덮어씁니다.언제foo()
는 스택에서 반환 주소를 팝업하여 해당 주소로 점프합니다(즉, 해당 주소에서 명령 실행을 시작합니다).따라서 공격자는 반환 주소를 스택버퍼에 대한 포인터로 덮어썼습니다.char c[12]
공격자가 제공한 데이터가 포함되어 있습니다.실제 스택 버퍼 오버플로우에서 "A" 문자열은 플랫폼과 원하는 기능에 적합한 셸 코드입니다.이 프로그램에 특별한 특권(예를 들어 SUID 비트)이 설정되어 있는 경우 공격자는 이 취약성을 사용하여 영향을 받는 [3]머신에서 슈퍼 사용자 특권을 얻을 수 있습니다.
공격자는 내부 변수 값을 수정하여 일부 버그를 이용할 수도 있습니다.이 예에서는 다음과 같습니다.
#실패하다 <문자열>h> #실패하다 <stdio.h> 무효 후우(차 *막대기) { 흘러가다 마이플로트 = 10.5; // Addr = 0x0023FF4C 차 c[28]; // Addr = 0x0023FF30 // 10.500000 인쇄 인쇄물("내 부동값 = %f\n", 마이플로트); /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 메모리 맵: @ : c 할당 메모리 # : My_Float 할당 메모리 *c *My_Float 0x0023FF30 0x0023FF4C @@@@@@@@@@@@@@@@@@@@@@@@@@@@##### foo(내 문자열은 너무 깁니다!!!! XXXXX"; memcpy는 My_Float 값에 0x1010C042(리틀엔디안)를 추가합니다. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ 메모리(c, 막대기, 스트렌(막대기)); // 경계 검사 없음... // 96.031372 인쇄 인쇄물("내 부동값 = %f\n", 마이플로트); } 인트 주된(인트 argc, 차 **argv) { 후우("내 끈은 너무 길다!!!!!\x10\x10\xc0\x42"); 돌아가다 0; }
많은 플랫폼에서는 콜스택 구현에 미묘한 차이가 있어 스택버퍼 오버플로우 부정 이용의 동작 방법에 영향을 줄 수 있습니다.일부 머신 아키텍처는 콜스택의 최상위 리턴 주소를 레지스터에 저장합니다.즉, 덮어쓴 리턴 주소는 나중에 콜스택이 풀릴 때까지 사용되지 않습니다.이용 기술의 선택에 영향을 줄 수 있는 머신 고유의 세부 사항의 또 다른 예로는 대부분의 RISC 스타일의 머신 아키텍처가 메모리에 [7]대한 비정렬 액세스를 허용하지 않는다는 사실을 들 수 있습니다.머신 opcode의 고정 길이와 조합하면, 이 머신의 제한에 의해, 스택에의 점프 기술이 거의 실장할 수 없게 됩니다(단, 프로그램에 스택 [8][9]레지스터에 명시적으로 점프할 가능성이 낮은 코드가 포함되어 있는 경우는 예외입니다).
확장되는 스택
스택 버퍼 오버플로우라는 토픽에서 자주 논의되지만 드물게 보이는 아키텍처는 스택이 반대 방향으로 확장되는 아키텍처입니다.같은 스택 프레임 내에서 발생하는 스택버퍼의 오버플로우는 리턴 포인터를 덮어쓸 수 없기 때문에 이 아키텍처의 변경은 스택버퍼 오버플로우 문제의 해결책으로 자주 제안됩니다.단, 이전 스택프레임에서 버퍼로 발생한 오버플로는 리턴 포인터를 덮어쓰고 [10]버그를 악의적인 악용할 수 있습니다.예를 들어, 위의 예에서는 다음 반환 포인터가foo
스택 프레임 내에서 실제로 오버플로가 발생하기 때문에 덮어쓰지는 않습니다.memcpy
단, 콜 중에 오버플로우하는 버퍼는memcpy
이전 스택 프레임에 있는 반환 포인터memcpy
는 버퍼보다 높은 메모리주소를 가지고 있습니다.즉, 에 대한 리턴 포인터 대신foo
덮어쓰기, 반환 포인터memcpy
덮어쓰게 됩니다.즉, 스택을 반대 방향으로 확장하면 스택버퍼 오버플로우가 어떻게 부정 이용하는지에 대한 자세한 내용은 변경되지만 부정 이용하는 [citation needed]버그의 수는 크게 감소하지 않습니다.
보호 스킴
수년간 악의적인 스택버퍼 오버플로우 부정 이용을 방지하기 위해 다수의 제어 흐름 무결성 방식이 개발되어 왔습니다.이들은 보통 다음 세 가지 범주로 분류할 수 있습니다.
- 스택 버퍼 오버플로가 발생했음을 감지하여 명령 포인터를 악성 코드로 리디렉션하지 않도록 합니다.
- 스택 버퍼 오버플로를 직접 검출하지 않고 스택에서 악성 코드가 실행되지 않도록 합니다.
- 실행 가능한 코드를 찾을 수 없도록 메모리 공간을 랜덤화합니다.
스택 카나리아
스택 카나리아는 탄광의 카나리아와 유사하기 때문에 이름이 붙여진 것으로 악의적인 코드가 실행되기 전에 스택버퍼 오버플로를 검출하기 위해서 사용됩니다.이 방법은 프로그램 시작 시 값이 랜덤으로 선택되는 작은 정수를 스택 리턴 포인터 바로 앞에 메모리에 배치함으로써 작동합니다.대부분의 버퍼 오버플로는 낮은 메모리주소에서 높은 메모리주소로 메모리를 덮어쓰기 때문에 리턴 포인터를 덮어쓰려면(그리고 프로세스를 제어하기 위해) 카나리 값도 덮어써야 합니다.이 값은 루틴이 [2]스택의 리턴 포인터를 사용하기 전에 변경되지 않았는지 확인하기 위해 체크됩니다.이 기술은 공격자가 [2]스택의 다른 중요 변수를 손상시키는 등 기존과 다른 방법으로 명령 포인터를 제어하도록 하기 때문에 스택 버퍼 오버플로를 부정 이용하는 데 어려움을 크게 증가시킬 수 있습니다.
검출할 수 없는 스택
스택 버퍼 오버플로우 부정 이용을 방지하는 또 다른 방법은 스택메모리 영역에 메모리정책을 적용하여 스택으로부터의 실행을 금지하는 것입니다(W^X, "Write XOR Execute").즉, 공격자는 스택에서 셸 코드를 실행하기 위해 메모리로부터의 실행 보호를 디세블로 하는 방법을 찾거나 보호되지 않는 메모리 영역에 셸 코드 페이로드 배치 방법을 찾아야 합니다.이 방법은 대부분의 데스크톱 프로세서에서 실행 중지 플래그를 하드웨어에서 지원할 수 있게 되면서 더욱 보급되고 있습니다.
이 방법은 표준 스택스매싱 부정 이용을 방지하지만 스택오버플로는 다른 방법으로 악용될 수 있습니다.첫째, 셸 코드를 힙과 같은 보호되지 않은 메모리 영역에 저장하는 방법을 찾는 것이 일반적이기 때문에 [11]이용 방법을 변경할 필요가 거의 없습니다.
또 다른 공격은 셸 코드 작성을 위한 이른바 libc 메서드로의 복귀입니다.이 공격에서는 악의적인 페이로드가 셸 코드가 아닌 적절한 콜스택을 사용하여 스택을 로드하여 실행이 표준 라이브러리 콜의 체인으로 전환되도록 합니다.보통 메모리 실행 보호를 디세블로 하여 셸 [12]코드를 정상적으로 실행할 수 있도록 합니다.이는 실행이 실제로 스택 자체에 벡터가 되는 일이 없기 때문에 동작합니다.
Return-to-libc의 변형은 ROP(Return-Oriented Programming)로, 일련의 리턴 주소를 셋업하고, 각각은 기존 프로그램 코드 또는 시스템 라이브러리 내에서 작은 시퀀스의 체리픽 머신 명령을 실행하며, 이 시퀀스는 리턴으로 끝납니다.이러한 가젯이라고 불리는 가젯은 각각 반환되기 전에 간단한 레지스터 조작이나 유사한 실행을 수행하며, 이들을 함께 문자열로 묶어 공격자의 목적을 달성합니다.반환 [13]명령과 거의 비슷하게 동작하는 명령어 또는 명령어 그룹을 이용함으로써 "반환 없는" 반환 지향 프로그래밍을 사용할 수도 있습니다.
랜덤화
데이터로부터 코드를 분리하는 대신에, 다른 경감 기술은 실행 프로그램의 메모리 공간에 랜덤화를 도입하는 것이다.공격자는 사용할 수 있는 실행 가능한 코드가 어디에 있는지 확인해야 하므로 실행 가능한 페이로드가 제공되거나(실행 가능한 스택과 함께) ret2libc 또는 ROP(return-oriented programming)와 같은 코드 재사용을 사용하여 구축됩니다.메모리 레이아웃을 랜덤화하면 공격자가 코드가 어디에 있는지 알 수 없게 됩니다.다만, 일반적으로 실장에서는 모든 것을 랜덤화하는 것은 아닙니다.통상, 실행 파일 자체는 고정 주소로 로드되기 때문에, ASLR(주소 공간 레이아웃 랜덤화)이 검출 불가능한 스택과 조합되어 있는 경우에서도, 공격자는 이 고정 영역의 메모리를 사용할 수 있습니다.따라서 모든 프로그램은 이 메모리 영역마저 랜덤화되도록 PIE(위치 독립 실행 파일)로 컴파일해야 합니다.랜덤화의 엔트로피는 구현마다 다르며, 충분히 낮은 엔트로피 자체는 랜덤화된 메모리 공간을 강제하는 데 문제가 될 수 있습니다.
주목할 만한 예
- 1988년의 Morris 웜은 부분적으로 Unix finger 서버의 스택버퍼 오버플로를 이용하여 확산되었습니다.[1]
- 2003년의 Slammer 웜은 Microsoft SQL Server의 스택버퍼 오버플로를 이용하여 확산되었습니다.[2]
- 2003년의 Blaster 웜은 Microsoft DCOM 서비스의 스택버퍼 오버플로를 부정 이용하는 것으로 확산되었습니다.
- 2004년 위트 웜은 Internet Security Systems Black의 스택버퍼 오버플로를 부정 이용하는 것으로 확산되었습니다.ICE 데스크탑 에이전트[3]
- Wii가 수정되지 않은 시스템에서 임의 코드를 실행할 수 있도록 하는 몇 가지 예가 있습니다.젤다의 전설에서 주인공의 말에 긴 이름을 붙이는 "트와일라잇 해킹: 트와일라잇 [14]프린세스와 슈퍼 스매시 브라더스의 '스매시 스택'입니다. SD 카드를 사용하여 특별히 준비된 파일을 게임 레벨 에디터에 로드하는 싸움입니다.둘 다 임의의 코드를 실행하는 데 사용할 수 있지만, 후자는 변경을 [15]적용하여 단순히 Brawl 자체를 새로고침하는 데 자주 사용됩니다.
「 」를 참조해 주세요.
레퍼런스
- ^ a b Fithen, William L.; Seacord, Robert (2007-03-27). "VT-MB. Violation of Memory Bounds". US CERT.
- ^ a b c Dowd, Mark; McDonald, John; Schuh, Justin (November 2006). The Art Of Software Security Assessment. Addison Wesley. pp. 169–196. ISBN 0-321-44442-6.
- ^ a b c Levy, Elias (1996-11-08). "Smashing The Stack for Fun and Profit". Phrack. 7 (49): 14.
- ^ Pincus, J.; Baker, B. (July–August 2004). "Beyond Stack Smashing: Recent Advances in Exploiting Buffer Overruns" (PDF). IEEE Security and Privacy Magazine. 2 (4): 20–27. doi:10.1109/MSP.2004.36. S2CID 6647392.
- ^ Burebista. "Stack Overflows" (PDF). Archived from the original (PDF) on September 28, 2007.[데드링크]
- ^ Bertrand, Louis (2002). "OpenBSD: Fix the Bugs, Secure the System". MUSESS '02: McMaster University Software Engineering Symposium. Archived from the original on 2007-09-30.
- ^ pr1. "Exploiting SPARC Buffer Overflow vulnerabilities".
{{cite journal}}
:Cite 저널 요구 사항journal=
(도움말) - ^ Curious (2005-01-08). "Reverse engineering - PowerPC Cracking on Mac OS X with GDB". Phrack. 11 (63): 16.
- ^ Sovarel, Ana Nora; Evans, David; Paul, Nathanael. "Where's the FEEB? The Effectiveness of Instruction Set Randomization".
{{cite journal}}
:Cite 저널 요구 사항journal=
(도움말) - ^ Zhodiac (2001-12-28). "HP-UX (PA-RISC 1.1) Overflows". Phrack. 11 (58): 11.
- ^ Foster, James C.; Osipov, Vitaly; Bhalla, Nish; Heinen, Niels (2005). Buffer Overflow Attacks: Detect, Exploit, Prevent (PDF). United States of America: Syngress Publishing, Inc. ISBN 1-932266-67-4.
- ^ Nergal (2001-12-28). "The advanced return-into-lib(c) exploits: PaX case study". Phrack. 11 (58): 4.
- ^ Checkoway, S.; Davi, L.; Dmitrienko, A.; Sadeghi, A. R.; Shacham, H.; Winandy, M. (October 2010). "Return-Oriented Programming without Returns". Proceedings of the 17th ACM conference on Computer and communications security - CCS '10. pp. 559–572. doi:10.1145/1866307.1866370. ISBN 978-1-4503-0245-6. S2CID 207182734.
- ^ "Twilight Hack - WiiBrew". wiibrew.org. Retrieved 2018-01-18.
- ^ "Smash Stack - WiiBrew". wiibrew.org. Retrieved 2018-01-18.