写点什么

Frp 流量隐匿对抗排查

  • 2023-01-12
    北京
  • 本文字数:3394 字

    阅读完需:约 11 分钟

Frp流量隐匿对抗排查

​前言

攻防场景中,当我们拿到入口机器的权限时,如果想进行后续的横向渗透,那么就需要把流量代理出来,目前内网渗透中市面上也有着各种各样的代理工具,比如:Frp、Nps、Ew、Venom、Regeorg 等。当然会根据不同的场景,使用的协议也各不相同,每款工具会存在或多或少的特征,故需要对相关工具进行改造。另外常见 DNS、ICMP 等协议也都会被一些杀软和态感所捕获。


Frp 简介

Frp 是一个开源、简洁易用、高性能的内网穿透和反向代理软件,经常用于运维。但在过去红蓝对抗中也是用的比较频繁。客户端服务端通信支持 TCP、KCP 以及 Websocket 等多种协议。采用 TCP 连接流式复用,在单个连接间承载更多请求,节省连接建立时间。代理组间的负载均衡。端口复用,多个服务通过同一个服务端端口暴露。多个原生支持的客户端插件(静态文件查看,HTTP、SOCK5 代理等),便于独立使用 Frp 客户端完成某些工作。高度扩展性的服务端插件系统,方便结合自身需求进行功能扩展。服务端和客户端 UI 页面。多种代理类型用于适用的不同的场景

TCP:单纯的 TCP 端口映射,服务端会根据不同的端口路由到不同的内网服务。UDP :单纯的 UDP 端口映射,服务端会根据不同的端口路由到不同的内网服务。HTTP :针对 HTTP 应用定制了一些额外的功能,例如修改 Host Header,增加鉴权。HTTPS :针对 HTTPS 应用定制了一些额外的功能。STCP :安全的 TCP 内网代理,需要在被访问者和访问者的机器上都部署 Frpc,不需要在服务端暴露端口。SUDP :安全的 UDP 内网代理,需要在被访问者和访问者的机器上都部署 Frpc,不需要在服务端暴露端口。XTCP :点对点内网穿透代理,功能同 STCP,但是流量不需要经过服务器中转。TCPMUX :支持服务端 TCP 端口的多路复用,通过同一个端口访问不同的内网服务。
复制代码



Frp 的使用

Frp 是一个专注于内网穿透的高性能的反向代理应用,支持 TCP、UDP、HTTP、HTTPS 等多种协议。可以将内网服务以安全、便捷的方式通过具有公网 IP 节点的中转暴露到公网。

https://github.com/fatedier/frp

2.1 常见流量特征

2.1.1 基本配置

# frpc.ini[common]server_addr = your vps server_port = 7000​# kcp监听的端口protocol = kcp​[plugin_socks5]type = tcpremote_port = 6005plugin = socks5plugin_user = admin888plugin_passwd = admin888
复制代码


# frps.ini[common]bind_addr = 0.0.0.0bind_port = 7000# 开启kcp模式kcp_bind_port = 7000
复制代码

这里在不使用任何安全配置,和该工具什么都没改的情况下,我们看下流量特征,使用 Socks5 的流量规则: tcp.port == 6005



可以看到在进行 Socks 的用户和密码(admin888/admin888)校验整体交互都是属于明文,能看到我们认证的账号密码



在攻防渗透中为了提高传输效率,可能会开启 KCP,那么这时候抓到的就是走 UDP 协议



另外 frpc 在连接认证 Frps 的时候,会进行三次握手,会把 Frp 的版本信息发给 frps 进行认证,如果是用的一个没有改过的 Frp 那么这时候只要建立连接,很容易就会被安全设备捕获到。如下可以看到该工具版本 Version、Arch、User、Privilege_key 等字段

这时候追踪 TCP 流可以看到我这个 Frp 版本为 0.38



很多安全设备也会基于 Frp 的相关特征进行流量识别,判断是否遭受黑客攻击



TLS 加密之后,对比在 frpc.ini 的[common]中配置 tls_enable = true 来启用此功能,这时候再看下流量发现整个流量过程都已经被加密了:



这时候再去看对应数据包,发现确实已经看不到明文信息了,但是有个新的问题,使用 tls_enable 加密后,首次连接会一个 0x17 的头部特征,并发送一个大小为 243 的数据包



2.1.2 特征改造

Frpc 的入口文件为 cmd/frpc/main.go,go build cmd/frpc/main.go。Frps 的入口文件为 cmd/frps。

2.1.2.1 流量特征改造

默认字节修改

上面提到的当使用了 TLS 加密之后,因为 frp 为了端口复用首次 frp 建立连接会出现一个 0x17 特征包,建立的第一个字节就是固定在 /pkg/util/net/t l s.go 处,这里对 FRPTLSHeadByte 进行修改,补充单字节为多字节。



var (        //FRPTLSHeadByte = 0x17​        // 修改后        FRPTLSHeadByte = 0x16)​func WrapTLSClientConn(c net.Conn, tlsConfig *tls.Config, disableCustomTLSHeadByte bool) (out net.Conn) {        if !disableCustomTLSHeadByte {                //c.Write([]byte{byte(FRPTLSHeadByte)})​                //修改后                c.Write([]byte{byte(FRPTLSHeadByte), byte(0x71), byte(0x72)})        }        out = tls.Client(c, tlsConfig)        return}​func CheckAndEnableTLSServerConnWithTimeout(        c net.Conn, tlsConfig *tls.Config, tlsOnly bool, timeout time.Duration,) (out net.Conn, isTLS bool, custom bool, err error) {​        //sc, r := gnet.NewSharedConnSize(c, 2)        //修改后        sc, r := gnet.NewSharedConnSize(c, 4)        //buf := make([]byte, 1)        //修改后        buf := make([]byte, 3)        var n int        c.SetReadDeadline(time.Now().Add(timeout))        n, err = r.Read(buf)        c.SetReadDeadline(time.Time{})        if err != nil {                return        }​        //if n == 1 && int(buf[0]) == FRPTLSHeadByte        //修改之后        if n == 3 && int(buf[0]) == FRPTLSHeadByte {                out = tls.Server(c, tlsConfig)                isTLS = true                custom = true        } else if n == 1 && int(buf[0]) == 0x16 {                out = tls.Server(sc, tlsConfig)                isTLS = true        } else {                if tlsOnly {                        err = fmt.Errorf("non-TLS connection received on a TlsOnly server")                        return                }                out = sc        }        return}
复制代码

这里改完只要能重新编译那就没什么问题,这时候就可以看到成功后的值,从一个字节变成了 3 个字节。



代理特征修改

如果不开启 TLS 选项的话,避免配置代理时暴露服务器 IP 和本机 IP 的话,修改 server/proxy/proxy.go 文件。把源地址和目的地址写死 114.114.114.114,这里可以任意修改。



记录的 src_addr 和 dst_addr 地址已经变成 114.114.114.114 了。



2.1.3 功能改造

2.1.3.1 配置文件自删除

正常情况在客户端启动时会去加载配置文件,这样就会导致我们的 vps 服务器地址泄露。故可以使用以下几种方法:

1. 加上命令行参数,这种就是将配置文件内容全部写入代码中,实现带参执行,但是这种还是比较容易被发现;

2. 远程去加载配置文件,这样需要通过域名或者 ip 去解析,这样隐藏也不是太好;

3. 在客户端执行之后直接删除 frpc.ini,这样的话直接在代码中写死即可。这样较为隐蔽

修改文件 /frp/cmd/frpc/sub/root.go 文件

添加一个变量,



然后在 RegisterCommonFlags 函数中去进行修改,

cmd.PersistentFlags().BoolVarP(&delEnable, "delEnable", "", true, "remove frpc.ini")
复制代码

默认运行之后直接将配置文件进行删除



最终只需要在启动函数中加上即可



没有报错就可以直接进行交叉编译生成



运行前



运行之后,只剩下 frpc.exe,配置文件自动删除



成功连接



2.1.4 总结

这里只是做了一个初步的改造,比如后续可以考虑本身免杀问题、功能上还可以添加端口转发、以及利用 cdn 隐藏 ip,带参数版加密执行等。企业在遭受到黑客攻击进入到后渗透阶段隧道的搭建和流量隐匿是常用的基础手段,安全设备在原有的流量检测设备中进行规则判断是远远不够的,需要针对 Frp 等隧道工具流量特征细节化进行更加深入的研究,针对隧道流量进行更详细的规则提取,不断完善企业威胁流量监测,提高企业安全建设能力。



关于领创集团(Advance Intelligence Group)

领创集团成立于 2016 年,致力于通过科技创新的本地化应用,改造和重塑金融和零售行业,以多元化的业务布局打造一个服务于消费者、企业和商户的生态圈。集团旗下包含企业业务和消费者业务两大板块,企业业务包含 ADVANCE.AI 和 Ginee,分别为银行、金融、金融科技、零售和电商行业客户提供基于 AI 技术的数字身份验证、风险管理产品和全渠道电商服务解决方案;消费者业务 Atome Financial 包括亚洲领先的先享后付平台 Atome 和数字金融服务。2021 年 9 月,领创集团完成超 4 亿美元 D 轮融资,融资完成后领创集团估值已超 20 亿美元,成为新加坡最大的独立科技创业公司之一。


发布于: 刚刚阅读数: 4
用户头像

智慧领创美好生活 2021-08-12 加入

AI技术驱动的科技集团,致力于以技术赋能为核心,通过科技创新的本地化应用,改造和重塑金融和零售行业,以多元化的业务布局打造一个服务于消费者、企业和商户的生态圈,带来个性化、陪伴式的产品服务和优质体验。

评论

发布
暂无评论
Frp流量隐匿对抗排查_内网渗透_领创集团Advance Intelligence Group_InfoQ写作社区