이 영역을 누르면 첫 페이지로 이동
천천히 꾸준히 조용히 블로그의 첫 페이지로 이동

천천히 꾸준히 조용히

페이지 맨 위로 올라가기

천천히 꾸준히 조용히

천천히 꾸준히 조용히.. i3months 블로그

[SSS] Software Defense

  • 2025.11.10 18:20
  • Computer Science/Computer Security
반응형

 

 

 

Buffer Overflow, Format String Attack 등 Control Flow Hijack을 수행하는 방법을 공부했으니.. 이제 그 공격을 방어하는 방법을 살펴보자. 

 

프로그램 분석, 퍼징 등을 사용해 프로그램에 심어져 있는 잠재적인 버그를 찾는게 가장 좋지만.. 이게 힘들다.

버그가 있더라도 공격이 어렵게 만드는 차선택을 선택하자. Stack Canary / Data Execution Prevention / Address Space Layout Randomiztion 등 여러 기법을 사용한다.

 

 

Data Execution Prevention

코드 주입 공격을 방어한다.

메모리 영역의 권한을 엄격하게 분리해서, Writable한 공간은 Non-Executable하게 만든다.

 

프로그램 스택은 Writable한 공간이다. DEP 기법은 이 스택 영역에 Non-Executable 속성을 부여한다.

요즘은 CPU 하드웨어 수준에서 이 기능을 직접 제공한다. (제어 비트 및 플래그 사용)

 

 

 

 

DEP 가 강력한 방어 기법이긴 하지만.. 우회할 수 있다.

 

악성 코드를 스택에 주입하지 않고, 이미 메모리에 존재하면서 실행 가능 권한을 가진 코드를 재활용한다.

 

BOF로 Malicious Return 값을 조작하는데, 이 점프 주소는 이미 메모리에 로드된 라이브러리 영역에 있는 특정 함수의 주소로 설정되어있다.

 

즉..

Return Oriented Programming 공격에는 취약함.

 

 

 

 

Stack Canary

 

 

 

 

스택 카나리의 보호가 없으면 BOF 공격에 매우 취약하다.

사용자가 입력 버퍼를 초과하는 입력값을 넣으면 그 뒤에 있는 모든 공간이 망가진다.

 

스택 카나리가 적용되면 카나리는 컴파일러에 의해 특별한 값이 로컬 변수 버퍼와 중요한 제어 데이터 사이에 삽입된다.

똑같이 오버플로우가 발생하더라도 카나리가 먼저 손상된다.

 

함수가 종료될 때, 프로그램은 스택에 있는 카나리 값을 함수 시작 시 저장해둔 원본 카나리 값과 비교한다.

비교를 통해 공격이 발생했는지 확인할 수 있다. 카나리 값이 손상됐다면 프로그램을 강제 종료시킨다.

 

 

 

 

 

실제 기계어 수준에서는 왼쪽 그림처럼 저장된다.

 

원본 카나리 값인 gs:0x14 에서 gs 레지스터는 Thread Control Block을 가리키고,

0x14는 uintptr_t stack_guard 필드에 해당한다.

 

즉.. 프로그램이 시작될 때 런타임 다이나믹 링크에 의해 설정되는 값이다. 

 

스택 카나리도 강력한 Alert 시스템이지만, Format String Attack과 Byte-by-Byte Bruteforcing Attack은 방어할 수 없다.

포맷스트링 취약점을 사용하면 스택에 저장된 내용을 읽을 수 있는데.. 이러면 카나리 값이 공격자에게 노출된다. 

Byte 단위로 브루트포스 때려버리면 카나리의 모든 바이트를 알아낼 수 있다.

 

 

Address Space Layout Randomization (ASLR)

 

 

 

 

ASLR이 없을 때는 셸코드를 스택에 주입했을 때 공격이 바로 성공한다.

ASLR을 적용하면 스택, 힙, 라이브러리 등의 주소가 매번 실행할 때 마다 바뀐다. 

 

예전 주소에 반환 주소를 덮어쓰면 당연히 거기에 셸코드가 없다. 

프로그램은 이상한 주소를 실행하다가 크래시가 발생하고 강제 종료된다. 

 

핵심은 매번 실행할 때 마다 메모리 매핑이 달라진다는 것..

 

스택 주소가 매번 바뀌니까 공격자가 스택에 주입한 셸코드의 주소를 예측할 수 없다.

libc같은 라이브러리의 주소도 항상 바뀌니 system() 같은 라이브러리 함수를 호출하기가 매우 어려워진다. 

 

우분투에서는 기본적으로 ASLR이 활성화 되어 있고, 설정값으로 ASLR의 수준을 설정할 수 있다. (기본 2)

 

그런데 역시나 ASLR을 뚫는 방법도 있다.

 

- Brute Force Attack

fork 기반 시스템에서는 브루트포스를 사용할 수 있다. 

요청이 들어올 때 마다 부모 프로세스를 fork 따서 자식 프로세스를 만드는데.. 이 때 자식 프로세스는 부모와 동일한 메모리 주소 배치를 가지게 된다. 

부모의 주소는 매번 바뀌지만 자식은 모두 같은 주소를 사용한다.

언젠가는 잘 찍어서 맞추게 되니까.. 

 

- Non-Randomized Memory

ASLR은 주소를 무작위로 섞긴 하지만 모든 요소가 다~ 섞이지는 않는다.

주소가 고정된 메모리 영역이 있고.. 이걸 악용할 수 있다.

 

프로그램의 메인 코드는 섞지 않는다. (섞을 수는 있는데 성능이 느려지는 경우가 많아서 안 쓰는 경우 있음)

BOF로 반환 주소를 조작하고, 메인 코드 영역의 특정 함수 주소로 점프하도록 설정한다. 

 

- Stack Juggling

메인 코드 영역이 난수화되지 않았고, 스택을 가리키는 포인터 변수의 값을 덮어쓸 수 있고, 포인터 변수가 취약 버퍼보다 더 높은 주소에 위치할 때 사용할 수 있다.

 

셸코드의 주소로 직접 점프하는게 아니라, 셸코드를 가리키고 있는 기존 포인터의 주소로 점프한다.

 

 

 

 

argv[1] 에 셸코드가 들어있다고 하자. 

function이 호출되면 스택의 높은 주소에 셸코드가 포함된 argv[1]가 위치한다.

strcpy로 BOF가 발생하면 function의 반환 주소를 덮어쓸 수 있다.

 

이 반환주소를 셸코드 주소 대신 메인 코드 안에 있는 또다른 ret명령어의 주소로 덮어쓴다.

 

 

- GOT Hijacking

 

 

 

GOT : Global Offset Table

PLT : Procedure Link Table

 

처음 puts 함수를 호출할 때는 PLT에 있는 puts의 대리인을 호출함.

puts@plt는 GOT에 있는 puts의 주소로 점프하는데.. 아직 puts의 실제 주소를 모르기에 PLT의 다음 명령어 주소(a)를 가리킴.

 

프로그램은 a로 돌아와 동적 링커를 호출함 

동적 링커가 라이브러리에서 puts의 실제 주소를 찾고 GOT를 업데이트한다.

 

두 번째 호출 부터는 동적 링커가 GOT 항목을 puts의 실제 주소로 덮어썼으니 실제 함수로 바로 점프한다.

 

GOT 영역은 Writable하다.

그러니 공격자는 프로그램이 자주 호출하는 함수의 GOT 항목 주소를 알아내고 셸코드 주소로 덮어쓴다면..

그냥 바로 공격 되는거임..

 

 

- Relocation Read-Only

GOT Hijacking을 막기 위해 RELRO를 사용한다.

 

GOT 영역 자체를 Read-Only로 만드는 기법이 RELRO

 

Partial RELRO는 GOT의 일부 영역을 읽기 전용으로 만들지만 ret2got 공격 대상인 .got.plt 영역은 여전히 Writable하다.

그러니 Full RELRO를 사용한다.

 

 

 

-z, now 옵션이 추가됐는데.. 지금 재배치하라는 뜻으로 생각하면 됨.

프로그램이 시작될 때 동적 링커가 모든 라이브러리의 함수 주소를 미리 찾아서 GOT에 바인딩한다.

이러면 GOT가 프로그램 실행 중에 변경될 필요가 없으니.. GOT 영역 전체를 Read-Only로 다룰 수 있다. 

 

 

 

Kernel Address Space Layout Randomization (KASLR)

지금까지는 User Space에서의 방어를 다뤘다. 이제 Kernel Space의 방어기법을 살펴보자.

KASLR은 말그대로 커널에 ASLR을 적용한거임.. 부팅 할 때 마다 커널의 주소 배치를 무작위로 변경한다.

 

 

 

 

 

2014년부터 리눅스에 제대로 적용되기 시작했고.. 윈도우는 2007년, 맥은 2012~2014 사이에 도입했다.

 

Kernel Exploit의 주된 목표는 일반 사용자 권한에서 루트 권한으로 권한을 높이는 것.

commit_creds(prepare_kernel_cred(0));

 

루트 권한을 얻기 위해 이런 코드 조각을 커널에서 실행하려고 하는데.. 

KASLR은 이런 커널 함수의 주소를 쉽게 찾지 못하게 하기 위해 사용한다.

 

일반 사용자는 커널 함수의 주소를 볼 수 없는데, 루트 권한을 가진 사용자는 주소를 볼 수 있다.

주소가 고정되어있다면.. 공격자가 한 번 이라도 어떻게든 루트 권한을 얻는다면 영구적인 공격 코드를 만들 수 있다는 것..

 

그래서 항상 바꿔 줘야 한다. KASLR 써서.

 

User Space에서 Kernel Space에 접근하려고 하면, Seg fault 뜬다.

인텔 CPU에서는.. 해당 Kernel Space 주소가 유효하다면 Seg fault를 발생시키기 전에 해당 주소 변환 정보를 TLB에 등록한다.

AMD CPU에서는 안 됨..!!!!!

 

즉, Page Fault가 발생하지만 TLB 항목이 생성된다는 것.

공격자는 시간을 정밀하게 측정해서, 느린 세그폴트 발생은 매핑되지 않았다고 판단하고 빠른 세그폴트가 발생하면 KASLR로 숨겨진 실제 커널의 유효한 주소라고 판단한다.

 

다른 공격 방법도 있다. 커널은 유저 공간에 접근할 수 있는데, 이걸 사용함.

공격자가 커널 메모리 내 함수 포인터나 데이터 포인터를 손상시키고, 포인터가 가리키는 주소를 커널 내 다른 주소가 아니라 공격자가 제어하는 사용자 공간의 악성 코드로 바꿔버린다.

 

 

 

 

 

 

 

반응형
저작자표시 (새창열림)

'Computer Science > Computer Security' 카테고리의 다른 글

[SSS] OPTEE - Open Portable Trusted Execution Environment  (0) 2025.11.20
[SSS] Trusted Execution Environment  (0) 2025.11.14
[SSS] OS kernel and Rootkit  (0) 2025.11.01
[SSS] Race Condition  (0) 2025.10.20
[SSS] Return Oriented Programming  (0) 2025.10.09

댓글

이 글 공유하기

  • 구독하기

    구독하기

  • 카카오톡

    카카오톡

  • 라인

    라인

  • 트위터

    트위터

  • Facebook

    Facebook

  • 카카오스토리

    카카오스토리

  • 밴드

    밴드

  • 네이버 블로그

    네이버 블로그

  • Pocket

    Pocket

  • Evernote

    Evernote

다른 글

  • [SSS] OPTEE - Open Portable Trusted Execution Environment

    [SSS] OPTEE - Open Portable Trusted Execution Environment

    2025.11.20
  • [SSS] Trusted Execution Environment

    [SSS] Trusted Execution Environment

    2025.11.14
  • [SSS] OS kernel and Rootkit

    [SSS] OS kernel and Rootkit

    2025.11.01
  • [SSS] Race Condition

    [SSS] Race Condition

    2025.10.20
다른 글 더 둘러보기

정보

천천히 꾸준히 조용히 블로그의 첫 페이지로 이동

천천히 꾸준히 조용히

  • 천천히 꾸준히 조용히의 첫 페이지로 이동

검색

방문자

  • 전체 방문자
  • 오늘
  • 어제

카테고리

  • 분류 전체보기 (679) N
    • Algorithm (205)
      • Data Structure (5)
      • Theory && Tip (33)
      • Baekjoon (166)
      • ALGOSPOT (1)
    • Spring (123)
      • Spring (28)
      • Spring Web MVC (20)
      • Spring Database (14)
      • Spring Boot (6)
      • Spring 3.1 (11)
      • Spring Batch (6)
      • Spring Security (16)
      • JPA (12)
      • Spring Data JPA (5)
      • QueryDSL (4)
      • eGovFramework (1)
    • Programming Language (74)
      • C (25)
      • C++ (12)
      • Java (19)
      • JavaScript (15)
      • Python (1)
      • PHP (2)
    • Computer Science (142)
      • Machine Learning (38)
      • Operating System (18)
      • Computer Network (28)
      • System Programming (22)
      • Universial Programming Lang.. (8)
      • Computer Architecture (4)
      • Compiler Design (11)
      • Computer Security (13)
    • Database (21)
      • Database (7)
      • MySQL (3)
      • Oracle (3)
      • Redis (5)
      • Elasticsearch (3)
    • DevOps (20)
      • Docker && Kubernetes (8)
      • Jenkins (4)
      • Amazon Web Service (8)
    • Mobile (28)
      • Android (21)
      • Flutter (7)
    • 💡 솔루션 (17)
    • 👥 모각코 (10)
    • 💬 기록 (8) N
    • 📚 공부 (6)
    • -------------- (25)

최근 글

나의 외부 링크

메뉴

  • 홈
반응형

정보

i3months의 천천히 꾸준히 조용히

천천히 꾸준히 조용히

i3months

블로그 구독하기

  • 구독하기
  • RSS 피드

티스토리

  • 티스토리 홈
  • 이 블로그 관리하기
  • 글쓰기
Powered by Tistory / Kakao. Copyright © i3months.

티스토리툴바