Stack Canaries
Last updated
Last updated
AWS 해킹 배우기 및 연습하기:HackTricks Training AWS Red Team Expert (ARTE) GCP 해킹 배우기 및 연습하기: HackTricks Training GCP Red Team Expert (GRTE)
스택가드는 EIP (확장 명령 포인터) 앞에 카나리로 알려진 특별한 값을 삽입합니다. 이 값은 0x000aff0d
로, 널, 줄 바꿈, EOF, 캐리지 리턴을 나타내어 버퍼 오버플로우로부터 보호합니다. 그러나 recv()
, memcpy()
, read()
, bcopy()
와 같은 함수는 여전히 취약하며, **EBP (기본 포인터)**를 보호하지 않습니다.
스택쉴드는 글로벌 리턴 스택을 유지하여 모든 리턴 주소(EIP)를 저장함으로써 스택가드보다 더 정교한 접근 방식을 취합니다. 이 설정은 오버플로우가 발생하더라도 해를 끼치지 않도록 하며, 저장된 리턴 주소와 실제 리턴 주소를 비교하여 오버플로우 발생을 감지할 수 있습니다. 또한, 스택쉴드는 리턴 주소가 예상 데이터 공간 외부를 가리키는지 확인하기 위해 경계 값과 비교할 수 있습니다. 그러나 이 보호는 리턴-투-리브시, ROP (리턴 지향 프로그래밍) 또는 ret2ret와 같은 기술을 통해 우회될 수 있어, 스택쉴드도 지역 변수를 보호하지 않습니다.
-fstack-protector
:이 메커니즘은 EBP 앞에 카나리를 배치하고, 지역 변수를 재조직하여 버퍼를 더 높은 메모리 주소에 위치시켜 다른 변수를 덮어쓰지 않도록 합니다. 또한, 지역 변수 위에 스택에서 전달된 인수를 안전하게 복사하고 이 복사본을 인수로 사용합니다. 그러나 8개 미만의 요소를 가진 배열이나 사용자의 구조 내의 버퍼는 보호하지 않습니다.
카나리는 /dev/urandom
에서 파생된 랜덤 숫자이거나 기본값 0xff0a0000
입니다. 이는 **TLS (스레드 로컬 저장소)**에 저장되어, 스레드 간에 공유 메모리 공간이 스레드별 글로벌 또는 정적 변수를 가질 수 있도록 합니다. 이러한 변수는 처음에 부모 프로세스에서 복사되며, 자식 프로세스는 부모나 형제에게 영향을 주지 않고 데이터를 변경할 수 있습니다. 그럼에도 불구하고 fork()
를 사용하여 새로운 카나리를 생성하지 않으면 모든 프로세스(부모 및 자식)가 동일한 카나리를 공유하게 되어 취약해집니다. i386 아키텍처에서는 카나리가 gs:0x14
에 저장되고, x86_64에서는 fs:0x28
에 저장됩니다.
이 지역 보호는 공격에 취약한 버퍼가 있는 함수를 식별하고, 이러한 함수의 시작 부분에 카나리를 배치하기 위해 코드를 주입하며, 끝 부분에서 그 무결성을 확인합니다.
웹 서버가 fork()
를 사용할 때, 카나리 바이트를 바이트 단위로 추측하는 무차별 대입 공격을 가능하게 합니다. 그러나 fork()
후에 execve()
를 사용하면 메모리 공간이 덮어쓰여져 공격이 무효화됩니다. vfork()
는 자식 프로세스가 쓰기를 시도할 때까지 복제를 하지 않고 실행할 수 있게 하여, 그 시점에 복제가 생성되어 프로세스 생성 및 메모리 처리에 대한 다른 접근 방식을 제공합니다.
x64
바이너리에서 카나리 쿠키는 0x8
바이트 쿼드워드입니다. 첫 7바이트는 랜덤이고 마지막 바이트는 널 바이트입니다.
x86
바이너리에서 카나리 쿠키는 0x4
바이트 더블워드입니다. 첫 3바이트는 랜덤이고 마지막 바이트는 널 바이트입니다.
두 카나리의 가장 낮은 유효 바이트는 널 바이트입니다. 이는 스택에서 낮은 주소에서 오는 첫 번째 바이트이기 때문에 문자열을 읽는 함수는 이를 읽기 전에 멈춥니다.
카나리를 유출한 다음 자신의 값으로 덮어쓰기(예: 버퍼 오버플로우).
자식 프로세스에서 카나리가 포크되면 한 번에 한 바이트씩 무차별 대입이 가능할 수 있습니다:
바이너리에 흥미로운 유출 또는 임의 읽기 취약점이 있다면 이를 유출할 수 있습니다:
스택에 저장된 포인터 덮어쓰기
스택 오버플로우에 취약한 스택은 문자열이나 함수의 주소를 포함할 수 있으며, 이를 덮어써서 카나리에 도달하지 않고도 취약점을 악용할 수 있습니다. 확인하세요:
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 항목 수정하기
바이너리에 부분 RELRO가 있는 경우, 임의 쓰기를 사용하여 __stack_chk_fail
의 GOT 항목을 프로그램이 카나리가 수정되더라도 차단하지 않는 더미 함수로 수정할 수 있습니다.
이 공격은 다음의 글에서 수행됩니다: https://7rocky.github.io/en/ctf/other/securinets-ctf/scrambler/
AWS 해킹 배우기 및 연습하기:HackTricks Training AWS Red Team Expert (ARTE) GCP 해킹 배우기 및 연습하기: HackTricks Training GCP Red Team Expert (GRTE)