0x00 前言
测试新写的脚本时发现一个好玩的事情:
如图中所示,最后出现了一个 lijiejietest.h.ele.me
的域名。
刚开始还以为 lijiejie
控制了饿了么的 DNS 服务器,但直接访问这个域名显示 404
,有点奇怪:
不过再随便访问一个 justfortest.h.ele.me
这种不可能存在的域名返回一样的页面,差不多可以判断是做了域名泛解析
(Wildcard DNS Record)了。
0x01 分析
因为脚本是用的 PassiveTotal
的 API 获取的子域名,按理说这种不存在的域名是不会被记录的。
突然想到 lijiejie 写过一个爆破子域名的工具,于是去 Github
查了下:
if answers:
ips = ', '.join(sorted([answer.address for answer in answers]))
if ips in ['1.1.1.1', '127.0.0.1', '0.0.0.0']:
continue
if (_sub, ips) not in self.ip_dict:
self.ip_dict[(_sub, ips)] = 1
else:
self.ip_dict[(_sub, ips)] += 1
if ips not in self.ip_dict:
self.ip_dict[ips] = 1
else:
self.ip_dict[ips] += 1
if self.ip_dict[(_sub, ips)] > 3 or self.ip_dict[ips] > 6:
continue
if self.ignore_intranet and SubNameBrute.is_intranet(answers[0].address):
continue
self.found_count += 1
msg = cur_sub_domain.ljust(30) + ips
self._print_msg(msg)
self._print_msg('status')
self.outfile.write(cur_sub_domain.ljust(30) + '\t' + ips + '\n')
self.outfile.flush()
try:
self.resolvers[j].query('lijiejietest.' + cur_sub_domain)
except dns.resolver.NXDOMAIN, e:
self.queue.put((999999999, '{next_sub}.' + sub))
except:
pass
能看到当某个子域名(如 xxx.ele.me
)的下一级(如 1.xxx.ele.e
, 2.xxx.ele.me
)有 3 个以上指向相同的 IP,或者 6 个以上的子域名 IP 相同,则判断是泛解析,不计入结果。
不过最后 self.resolvers[j].query('lijiejietest.' + cur_sub_domain)
的目的没看懂。
如果是为了用 lijiejietest
这个关键字来探测目标域名是否使用了泛解析的话,当域名解析成功时应该有相应操作,而这里却没有。
找了一下 issue,发现已经有人提到过这个问题,可参考 1.0.3 版的历史 commit。
lijiejie 回答说是为了检查恶意 DNS 服务器,但在最新的代码中这个功能已经重构到了另一个函数:
def _test_server(self, server):
resolver = dns.resolver.Resolver()
resolver.lifetime = resolver.timeout = 10.0
try:
resolver.nameservers = [server]
answers = resolver.query('public-dns-a.baidu.com') # test lookup a existed domain
if answers[0].address != '180.76.76.76':
raise Exception('incorrect DNS response')
try:
resolver.query('test.bad.dns.lijiejie.com') # Non-existed domain test
with open('bad_dns_servers.txt', 'a') as f:
f.write(server + '\n')
self._print_msg('[+] Bad DNS Server found %s' % server)
except:
self.dns_servers.append(server)
self._print_msg('[+] Check DNS Server %s < OK > Found %s' % (server.ljust(16), len(self.dns_servers)))
except:
self._print_msg('[+] Check DNS Server %s <Fail> Found %s' % (server.ljust(16), len(self.dns_servers)))
(大概是作者忘了把旧代码里无用的部分删除吧,或是以后还会有优化……)
0x02 PassiveDNS
扯远了,所以可以猜想一下,因为用 subDomainsBrute
爆破子域名的人太多,每当爆破时都会请求 lijiejietest.*
,而且 ele.me
做了域名泛解析返回了 IP,最终这个 DNS 就被 PassiveTotal 记录下来了。
那为啥就没有其他的不存在的域名被记录下来呢?虽然概率小,但肯定还是有的。
根据我的经验,PassiveTotal 记录国外请求的域名比较完整,如果是在国内请求的 DNS,数量少的话很可能就没有记录,应该是在国内没有自己的 DNS 服务器(或是旁路流量)的缘故。这方面地头蛇 360
的 https://passivedns.cn 就详细多了。不少小伙伴喜欢在自己国外的 VPS 上搞事情,包括用 subDomainsBrute 跑子域名,这样就被 PassiveTotal 记在小本本上了。
0x03 总结
对于防御方而言,可以设置 DNS 黑名单,遇到请求 lijiejietest.*
的熊孩子就好好管教他。
对于攻击方而言,使用工具时记得修改特征,比如把 subDomainsBrute 里的 lijiejietest 换成随机字符串。