0x00 前言

测试新写的脚本时发现一个好玩的事情:

lijiejietest.png

如图中所示,最后出现了一个 lijiejietest.h.ele.me 的域名。
刚开始还以为 lijiejie 控制了饿了么的 DNS 服务器,但直接访问这个域名显示 404,有点奇怪:

WechatIMG237.jpeg

不过再随便访问一个 justfortest.h.ele.me 这种不可能存在的域名返回一样的页面,差不多可以判断是做了域名泛解析(Wildcard DNS Record)了。

0x01 分析

因为脚本是用的 PassiveTotal 的 API 获取的子域名,按理说这种不存在的域名是不会被记录的。
突然想到 lijiejie 写过一个爆破子域名的工具,于是去 Github 查了下:

WX20170528-112106@2x.png

对应代码:

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。

WX20170528-132422@2x.png

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 服务器(或是旁路流量)的缘故。这方面地头蛇 360https://passivedns.cn 就详细多了。不少小伙伴喜欢在自己国外的 VPS 上搞事情,包括用 subDomainsBrute 跑子域名,这样就被 PassiveTotal 记在小本本上了。

0x03 总结

对于防御方而言,可以设置 DNS 黑名单,遇到请求 lijiejietest.* 的熊孩子就好好管教他。
对于攻击方而言,使用工具时记得修改特征,比如把 subDomainsBrute 里的 lijiejietest 换成随机字符串。

0x04 参考: