스택 카나리

Reading time: 5 minutes

tip

AWS 해킹 배우기 및 연습하기:HackTricks Training AWS Red Team Expert (ARTE)
GCP 해킹 배우기 및 연습하기: HackTricks Training GCP Red Team Expert (GRTE)

HackTricks 지원하기

스택가드와 스택쉴드

스택가드EIP (확장 명령 포인터) 앞에 카나리로 알려진 특별한 값을 삽입합니다. 이 값은 0x000aff0d로, null, newline, EOF, carriage return을 나타내어 버퍼 오버플로우로부터 보호합니다. 그러나 recv(), memcpy(), read(), bcopy()와 같은 함수는 여전히 취약하며, **EBP (기본 포인터)**를 보호하지 않습니다.

스택쉴드글로벌 리턴 스택을 유지하여 모든 리턴 주소(EIPs)를 저장함으로써 스택가드보다 더 정교한 접근 방식을 취합니다. 이 설정은 오버플로우가 발생하더라도 해를 끼치지 않도록 하며, 저장된 리턴 주소와 실제 리턴 주소를 비교하여 오버플로우 발생을 감지할 수 있게 합니다. 또한, 스택쉴드는 리턴 주소가 예상 데이터 공간 외부를 가리키는지 감지하기 위해 경계 값과 비교할 수 있습니다. 그러나 이 보호는 Return-to-libc, ROP (리턴 지향 프로그래밍) 또는 ret2ret와 같은 기술을 통해 우회될 수 있으며, 이는 스택쉴드가 지역 변수를 보호하지 않음을 나타냅니다.

스택 스매시 프로텍터 (ProPolice) -fstack-protector:

이 메커니즘은 EBP 앞에 카나리를 배치하고, 지역 변수를 재조직하여 버퍼를 더 높은 메모리 주소에 위치시켜 다른 변수를 덮어쓰지 않도록 합니다. 또한, 지역 변수 위의 스택에서 전달된 인수를 안전하게 복사하고 이 복사본을 인수로 사용합니다. 그러나 8개 미만의 요소를 가진 배열이나 사용자의 구조 내의 버퍼는 보호하지 않습니다.

카나리/dev/urandom에서 파생된 임의의 숫자이거나 기본값 0xff0a0000입니다. 이는 **TLS (스레드 로컬 저장소)**에 저장되어 스레드 간에 공유 메모리 공간이 스레드별 글로벌 또는 정적 변수를 가질 수 있도록 합니다. 이러한 변수는 처음에 부모 프로세스에서 복사되며, 자식 프로세스는 부모나 형제에게 영향을 주지 않고 데이터를 변경할 수 있습니다. 그럼에도 불구하고 fork()를 사용하여 새로운 카나리를 생성하지 않으면 모든 프로세스(부모 및 자식)가 동일한 카나리를 공유하게 되어 취약해집니다. i386 아키텍처에서는 카나리가 gs:0x14에 저장되고, x86_64에서는 fs:0x28에 저장됩니다.

이 지역 보호는 공격에 취약한 버퍼가 있는 함수를 식별하고 이러한 함수의 시작 부분에 카나리를 배치하기 위해 코드를 주입하며, 끝 부분에서 그 무결성을 확인합니다.

웹 서버가 fork()를 사용할 때, 카나리 바이트를 하나씩 추측하는 무차별 대입 공격을 가능하게 합니다. 그러나 fork() 후에 execve()를 사용하면 메모리 공간이 덮어쓰여져 공격이 무효화됩니다. vfork()는 자식 프로세스가 쓰기를 시도할 때까지 중복 없이 실행할 수 있게 하여, 그 시점에 중복이 생성되어 프로세스 생성 및 메모리 처리에 대한 다른 접근 방식을 제공합니다.

길이

x64 바이너리에서 카나리 쿠키는 0x8 바이트 쿼드워드입니다. 첫 7바이트는 임의의 값이고 마지막 바이트는 null 바이트입니다.

x86 바이너리에서 카나리 쿠키는 0x4 바이트 더블워드입니다. 첫 3바이트는 임의의 값이고 마지막 바이트는 null 바이트입니다.

caution

두 카나리의 가장 낮은 유효 바이트는 null 바이트입니다. 이는 스택에서 낮은 주소에서 오는 첫 번째 바이트이기 때문에 문자열을 읽는 함수는 이를 읽기 전에 멈출 것입니다.

우회 방법

카나리를 유출한 후 자신의 값으로 덮어쓰기 (예: 버퍼 오버플로우).

  • 자식 프로세스에서 카나리가 포크되면 한 바이트씩 무차별 대입이 가능할 수 있습니다:

BF Forked & Threaded Stack Canaries

  • 바이너리에 흥미로운 유출 또는 임의 읽기 취약점이 있다면 이를 유출할 수 있습니다:

Print Stack Canary

  • 스택에 저장된 포인터 덮어쓰기

스택 오버플로우에 취약한 스택은 덮어쓸 수 있는 문자열 또는 함수의 주소를 포함할 수 있습니다. 이를 통해 스택 카나리에 도달할 필요 없이 취약점을 악용할 수 있습니다. 확인하세요:

Pointer Redirecting

  • 마스터 및 스레드 카나리 모두 수정하기

카나리로 보호된 스레드 함수에서의 버퍼 오버플로우스레드의 마스터 카나리를 수정하는 데 사용될 수 있습니다. 결과적으로, 두 개의 동일한 카나리(수정된 것)가 사용되기 때문에 완화 조치는 무용지물이 됩니다.

게다가, 카나리로 보호된 스레드 함수에서의 버퍼 오버플로우TLS에 저장된 마스터 카나리를 수정하는 데 사용될 수 있습니다. 이는 스레드의 스택에서 bof를 통해 TLS가 저장된 메모리 위치에 도달할 수 있기 때문입니다.
결과적으로, 두 개의 동일한 카나리(수정된 것)가 사용되기 때문에 완화 조치는 무용지물이 됩니다.
이 공격은 다음의 글에서 수행됩니다: http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads

또한 https://www.slideshare.net/codeblue_jp/master-canary-forging-by-yuki-koike-code-blue-2015에서의 발표를 확인하세요. 이 발표에서는 일반적으로 TLS가 **mmap**에 의해 저장되며, 스레드의 스택이 생성될 때도 mmap에 의해 생성된다고 언급합니다. 이는 이전 글에서 보여준 것처럼 오버플로우를 허용할 수 있습니다.

  • __stack_chk_fail의 GOT 항목 수정하기

바이너리에 Partial RELRO가 있는 경우, __stack_chk_fail의 GOT 항목을 더미 함수로 수정하여 카나리가 수정되더라도 프로그램이 차단되지 않도록 할 수 있습니다.

이 공격은 다음의 글에서 수행됩니다: https://7rocky.github.io/en/ctf/other/securinets-ctf/scrambler/

참고 문헌

tip

AWS 해킹 배우기 및 연습하기:HackTricks Training AWS Red Team Expert (ARTE)
GCP 해킹 배우기 및 연습하기: HackTricks Training GCP Red Team Expert (GRTE)

HackTricks 지원하기