
Linux ELF x32/x64 ASLR DEP/NX 우회 익스플로잇 with 스택 스프레이
스택 스프레이를 이용한 Linux ELF x32/x64 ASLR DEP/NX 우회 익스플로잇

속성:
의존성:
제한 사항:
Heap Spraying 공격에 대해 들어보셨나요? Stack Spraying도 유사하지만, 대부분의 경우, 특히 x86-64의 ASLR에서는 실용적이지 않은 것으로 간주되었습니다.
제 연구는 그 반대를 증명할 것입니다.
32비트의 경우 이론적으로 2^32 (4,294,967,296) 개의 주소가 있지만, 커널은 가상화된 메모리에서 실행을 위해 약 절반의 비트(2^(32/2) = 65,536)만 제어할 수 있도록 허용합니다. 즉, 스택에서 50,000개 이상의 문자를 제어한다면, 커널 리디렉션 및 재변환 덕분에 주소에 관계없이 거의 확실히 셸코드를 가리킬 수 있습니다. 제 테스트에 따르면, 호출된 함수에 다른 변수 생성이 없으면 100자 또는 10자만으로도 충분하며, 이는 ROP 스타일 공격을 가능하게 합니다.
이는 셸 변수를 사용하여 달성할 수 있습니다. 셸 변수는 특정 길이로 제한되지 않지만, 실제 제한은 약 10만 자 정도이며, 그 이상이면 TTY가 포화 상태가 됩니다.
따라서 임의의 셸코드로 성공적으로 익스플로잇하려면, 셸 변수에 셸코드와 함께 를 넣고 임의의 주소로 바이너리를 익스플로잇하기만 하면 됩니다. NOP sled는 필수는 아니며, 익스플로잇을 일반화하기 위한 것입니다.
64비트 시스템에서는 상황이 다르지만, 제가 발견한 바에 따르면 그리 다르지 않습니다.
물론 2^64 모든 가능성을 다룰 필요는 없습니다. 실제로 커널은 48비트만 허용하며, 그중 일부는 예측 가능하고 정적이므로 약 2^(4x8+5) (137,438,953,472) 가지 가능성이 남습니다.
셸 변수 크기 제한에 대해 언급했지만, 개수 제한도 있으며 약 10개로 보입니다. 따라서 1,000,000자 길이의 셸코드를 저장할 수 있으며, 빠르고 자동으로 테스트할 수 있는 몇 만 가지 가능성만 남게 됩니다. 하지만 이번에는 무차별 대입(bruteforce)을 사용하고 NOP 슬레드를 사용하여 속도를 높여야 합니다.
즉, 32비트와 64비트 모두의 ASLR은 몇 분 안에, 몇 줄의 셸 코드로 쉽게 우회할 수 있습니다.
한편, DEP/NX는 x32에서 return-to-libc 기술을 사용하여 다양한 OS의 통계 연구, 특히 ASLR 제한 및 구현과 결합함으로써 우회할 수 있으며, 이는 두 가지 이유로 성공적인 익스플로잇으로 이어질 수 있습니다. 첫째는 ASLR이 선택에 있어 그다지 무작위적이지 않고 일부 상수와 낮은 엔트로피를 가진다는 점입니다(libC 주소를 추측하기 쉽고 각 OS마다 고유한 상수가 있습니다). 둘째는 libC의 셸 인수를 환경에 스프레이한다는 점입니다(환경에서 쉽게 찾아서 libC에 전달할 수 있습니다).
결론적으로, 32비트의 DEP/NX는 ASLR 때문에 약화됩니다.
더 자세한 설명은 Hakin9-12-14 호에서 확인할 수 있습니다.
버퍼 오버플로우를 한 번이라도 익스플로잇해본 적이 있다면 건너뛰어도 됩니다. 하지만 혹시 모르니:
apt install gcc libc6-dev-i386 || kill -9 $$
chmod u+x ASLRay.sh
sudo gcc -z execstack test.c -o test
sudo gcc -m32 -z execstack test.c -o test32
sudo chmod +s test test32
source ASLRay.sh test32 1024
source ASLRay.sh test 1024
source ASLRay.sh test 1024 \x31\x80...your_shellcode_here
sudo gcc -m32 test.c -o test32x
sudo chmod +s test test32
source ASLRay.sh test32x 1024
Debian x32에서 NOP 슬레드가 필요하지 않음을 증명:
!!! 경고 !!! 이 작업은 /etc/passwd를 수정하고 /etc/shadow의 권한을 변경합니다. 가상 머신에서 실행하는 것을 권장합니다.
chmod u+x PoC.sh
source PoC.sh
grep ALI /etc/passwd
그래도 작동하지 않으면 처음에 NOP(\x90)를 몇 개 추가하십시오.
Debian x32에서 환경 변수조차 필요하지 않음을 증명:
chmod u+x PoC2.sh
source PoC2.sh
따라서 셸코드를 변수에 넣고 ASLR 상태에서 레지스터에 임의의 주소를 지정하여 셸을 얻을 수 있습니다. 이는 함수에 하나의 변수만 있고 그 변수가 덮어쓰여지기 때문에 특정 컨텍스트에서 발생하며, 따라서 스택이 우리의 셸코드로 EIP에 팝(pop)됩니다. 이는 ROP 공격에 더 가깝습니다.
Arch/Ubuntu의 경우 스택 스매싱 보호를 비활성화해야 하며, 무차별 대입에 더 오랜 시간이 걸릴 수 있습니다(실행 지연, 아마도 brk(NULL/0) syscall 또는 canary 때문):
sudo gcc -z execstack -fno-stack-protector test.c -o test
sudo gcc -m32 -z execstack -fno-stack-protector test.c -o test32
sudo gcc -m32 -fno-stack-protector test.c -o test32x
Debian 10에서는 특히 AppArmor로 인해 이 문제가 부분적으로 패치되었습니다.
항상 단일 보호가 아닌 여러 보호에 의존하십시오.
새로운 시스템 보안 메커니즘이 필요합니다.
"우리가 서 있는 곳에서 비는 무작위적으로 보인다. 만약 우리가 다른 곳에 서 있다면, 그 안의 질서를 볼 수 있을 것이다."
토니 힐러먼, 코요테는 기다린다