隧道构建:端口转发的原理和实现
众所周知,黑客入侵到内网环境,必做的两件事就是:构架隧道和敏感信息翻查。通过翻查到的敏感信息再结合已构建的隧道就可以顺利攻下内网敏感系统。
近期正好在研究构架隧道的方法:端口转发,今天科普一下场景和具体实现逻辑,共同探讨下
端口转发概述
所谓端口转发,网上的定义多种多样,不过按照作者的理解,其实端口转发就是将内网服务的端口通过正向或反向连接的方式公布出去,让攻击着可以方便快捷的直接访问罢了。不过也许这个定义不好理解,下面咱们从使用场景和原理详细看下,相信就可以明白了。
端口转发使用场景和原理
1、反向连接:
纯反向连接:
黑客已拿下一台终端,需要以此终端为跳板对其他终端进行攻击,扩大战果,获取更多敏感数据。这种情况下,一般是利用被控终端木马,进行端口转发,以被控终端为跳板,将其他终端的服务端口转发出去,攻击者通过反向的方式,从被控终端B的随机端口访问其他终端的开放端口。
数据流向:
- 被控终端B(随机端口1)---> 攻击者(开放端口)
- 被控终端B(随机端口2)---> 其他终端(开放端口)
- 被控终端B(随机端口1)<--->被控终端B(随机端口2)
最终实现:
- 攻击者(开放端口)<--->(随机端口1)被控终端B(随机端口2)<--->其他终端(开放端口)
反向连接+正向连接:
黑客又拿下了一台开放端口的被控终端A,这样黑客就可以再次利用端口转发,通过正向连接,访问其他终端的开放端口。
数据流向:
- 被控终端B(随机端口1)---> 被控终端A(开放端口1)
- 被控终端B(随机端口2)---> 其他终端(开放端口)
- 被控终端B(随机端口1)<--->被控终端B(随机端口2)
- 被控终端A(开放端口1)<--->被控终端A(开放端口2)
- 攻击者(随机端口) --->被控终端A(开放端口2)
最终实现:
- 攻击者(随机端口)<--->(开放端口2)被控终端A(开放端口1)<--->(随机端口1)被控终端B(随机端口2)<--->其他终端(开放端口)
示意图如下:
2、正向连接:
纯正向连接:
代理类的业务暴漏在黑客面前(如代理),黑客可直接利用。这种情况下,攻击者利用已开放的代理类服务为跳板,访问其他终端。
数据流向:
- 攻击者(随机端口)---> 代理类服务(开放端口)
- 代理类服务(随机端口)---> 其他终端(开放端口)
- 代理类服务(开放端口)<--->代理类服务(随机端口)
最终实现:
- 攻击者(随机端口)<--->(开放端口)代理类服务(随机端口)<--->其他终端(开放端口)
也可实现:
- 攻击者(随机端口)<--->(开放端口)代理类服务(随机端口)<--->代理类服务本身127.0.0.1(开放端口)
正向连接+反向连接:
如代理类服务器在内网,可通过拿下一台被控终端B的方式,结合反向连接实现访问。
数据流向:
- 被控终端B(随机端口1)---> 攻击者(开放端口)
- 被控终端B(随机端口2)---> 代理类服务器(开放端口)
- 被控终端B(随机端口1)<--->被控终端B(随机端口2)
- 代理类服务(随机端口)---> 其他终端(开放端口)
- 代理类服务(开放端口)<--->代理类服务(随机端口)
最终实现:
- 攻击者(开放端口)<--->(随机端口1)被控终端B(随机端口2)<--->(开放端口)代理类服务(随机端口)<--->其他终端(开放端口)
示意图如下:
综上可见,无论是正向连接还是反向连接,实现端口转发核心原理是解决一台终端内多个端口间通信,也就是说将不同的socket通信流串到一起,如:
- 情况一:(随机端口1)被控终端B(随机端口2)
- 情况二:(开放端口2)被控终端A(开放端口1)
- 情况三:(开放端口)代理类服务(随机端口)
其中,情况三是代理类程序自身提供的功能,我们仅仅是利用了这种功能罢了,但原理其实就是将两个socket串到了一起。其实实现端口转发的工具实在是太多了,咱们就不一一分析了,网上资料很多,自行搜索。下面仅从代码实现角度简单分析下。
端口转发逻辑实现
以下是完整python代码(作者不擅长代码,谅解),为实现方便,作者利用自己的终端作为测试,稍微修改了逻辑,但原理相同,如下:
具体原理见代码注释(查照上图理解代码逻辑)
#解释:定义编码,导入需要库
# -*- coding: cp936 -*-
import socket
import thread
import time
#解释:定义其他终端的ip和开放端口,还有代理类服务地址和开放端口
conHost = '其他终端ip'
conPort = '80、8080等其他终端开放的端口'
#注意:使用rdp(windows远程桌面)只能是1024 否则会提示数据加密出错!!!
dataSize = 1024
proxyaddr = '代理类服务ip'
#解释:定义第一个socket,与代理类服务的开放端口80进行连接
#解释:实现被控制终端B(随机端口)---> 代理类服务(开放端口80)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((proxyaddr, 80))
#解释:利用代理类服务与其他终端的开放端口通信,实现:代理类服务(随机端口)---> 其他终端(开放端口)
s.send('CONNECT '+ conHost +':'+conPort+' HTTP/1.1rn Host: '+ conHost +':'+conPort+' rnConnection: closernrn')
print '隧道建立成功,详情如下:'
print s.recv(1024)
#解释:连接建立后,代理服务服务程序已自动完成 (开放端口)代理类服务(随机端口),我们无需关注。
#解释:定义第二个socket,实现攻击者(随机端口)-->被控制端B(开放端口,这里仅对本机127.0.0.1开放52345进行测试,也防止他人访问)
s2 = socket.socket()
host = socket.gethostname()
print host
port = 52345
print port
s2.bind(('127.0.0.1', port))
s2.listen(1)
d2,Myaddress = s2.accept()
print '接受完毕'
print d2.getpeername()
print d2.getsockname()
whilecount = 0
SendData = ''
#解释:定义本地socket发送和接收函数,并利用多线程将实现同步发送接收
#发送函数
def SendData(threadName):
SendData= d2.recv(dataSize) #从攻击者的随机端口接收数据
print '接收数据 '
print SendData
#开始发送数据
s.sendall(SendData)
#解释:将从攻击者的随机端口接收数据发送到已建立的socket1,这样就把第一个socket和第二个socket串起来了,实现 实现攻击者(随机端口)-->被控制端B(开放端口)<--->被控制端B(随机端口)--->其他终端(开放端口)
print 'send------------------------------------ rn'+ SendData
print threadName + time.ctime(time.time()) + ' donern'
#接收数据,原理同上
def RecvData(threadName):
returndate = s.recv(dataSize)
print 'from:------------------------------------rn'+conHost + ' '+returndate
d2.sendall(returndate)
print threadName + time.ctime(time.time()) + ' donern'
while 1:
try:
thread.start_new_thread(SendData, ("SendData Thread-1", ) )
thread.start_new_thread(RecvData, ("RecvData Thread-2", ) )
except:
print time.ctime(time.time()) + "Error: unable to start threadrn"
#rdp只可以大于1否则无法接受数据,报错
time.sleep(1)
端口转发的检测思路
知道了原理,那么检测思路其实就清晰了。
想实现端口转发,必须在被控终端存在一个进程,这个进程既可以与左边通信又可以与右边通信(参考原理图),并且左右通信量相同。但具体检测逻辑还要考虑很多可变因素,例如终端存在多个进程并且进程间通信、黑客使用压缩算法造成左右通信量不同等等。
欢迎各位大神共同探讨,谢谢!
【技术创作101训练营】
- EnterLib PIAB又一个BUG?[续]——这是一个致命的BUG
- Google工程师:谷歌翻译在几个月内效果明显提升的秘诀
- 回调与并发: 通过实例剖析WCF基于ConcurrencyMode.Reentrant模式下的并发控制机制
- EnterLib PIAB又一个BUG?[续]——这是一个致命的BUG
- 年终盘点2017年发生在上海的科技大新闻
- 数字供应链第六章-网络风险、知识产权盗窃、合规和数据挖掘业务合同
- 使命必达: 深入剖析WCF的可靠会话[实例篇](内含美女图片,定力差者慎入)
- 快速全面构建大数据认知体系
- 谈谈分布式事务之二:基于DTC的分布式事务管理模型[上篇]
- ConcurrencyMode.Multiple 模式下的WCF服务就一定是并发执行的吗:探讨同步上下文对并发的影响[下篇]
- 谈谈分布式事务之二:基于DTC的分布式事务管理模型[上篇]
- 学习SpringMVC——拦截器
- 学习SpringMVC——国际化+上传+下载
- 行业研究:大数据(一)
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 震惊!我三步就搞定了 Tomcat 源码环境搭建!
- 【小技巧】深度学习中的那些效率提升利器(附资源)
- 多个线程为了同个资源打起架来了,操作系统是如何让他们安分的?
- 学习链表,这些题你值得一刷!
- Gophish钓鱼测试
- 【位运算】只出现一次的数字 II,数电的知识终于用上了!
- Swaks伪造邮件发件人绕过SPF
- 某次网站的渗透测试
- phpMyAdmin 渗透利用总结
- 【C++简明教程】C++基本语法
- 【多目标跟踪】搞不懂MOT数据集,会跑代码有啥用!
- 手工 - 内网信息收集
- 使用ffmpeg压缩视频之烦和fun
- 一文学会 Web Service漏洞挖掘!
- 【实战项目代码分享】计算机视觉入门教程&实战项目代码