从工具的代码角度学安全:Sublist3r子域名枚举神器源码阅读
作者:CQITer小编 时间:2018-09-23 21:23
*本文作者:mscb,本文属 FreeBuf 原创奖励计划,未经许可禁止转载。


Sublist3r是一款简单易用的子域名枚举利器。但是今天我不打算讲解它的使用教程,而是深入一层,从它的代码中窥探原理。也许有人可能很不理解,为什么不好好的使用工具而偏偏去深究它的代码实现细节。
从我个人角度来说,我觉得:
第一个层面,一位优秀的安全从业者,至少在读/写代码层面不能成为短柄。如果一味的只使用工具,不了解原理,那很容易成为大家口中的“脚本小子(script kiddie)”。
第二个层面,这是我个人推崇的的学习方法,从自己的学习道路中,我喜欢遵循3个W的学习原则,即(What->Why->What):
第一个What表示在初学阶段,需要学会哪些东西能干些什么,比如知道了Sublist3r工具可以用来枚举子域名。
第二个Why则表示在中级阶段,去了解这个东西的实现原理,以及为什么要这么实现,比如通过工具的代码学会它的底层细节,与此同时还能丰富知识体系。
第三个What表示在高级阶段,知道要干什么事情需要什么工具,不在细究技术细节,而是通过前期的学习,形成自己的知识网络,能精准的根据当前情况定位到具体的工具。
Sublist3r工具介绍从Sublist3r的GitHub主页(https://github.com/aboul3la/Sublist3r)上,我们可以了解到这是一款基于python开发使用OSINT技术的子域名枚举工具。帮助渗透测试者和bug捕获者收集目标域名的子域名。
什么是OSINTOSINT是英文名“Open-source intelligence”的缩写,中文名称叫“公开来源情报”。从公众可见的信息中,查找所需目标的信息。说的通俗易懂一点,就是我想知道某某东西的详细信息,我在公开的信息里查找、检索,找到有关这个东西的任何内容都提取出来,最后将这些内容汇总,得到较为详细的信息。再说的通俗易懂一点就是:查资料。再再通俗一点就是:找百度。最终目标信息的准确度、详细程度均依赖于查找源。所以Sublist3r的原理就是这样,但是Sublist3r的查找源很多,不仅仅是在个别搜索引擎上查找。搜索源包括有百度、Yahoo、Google、Bing、Ask、Netcraft等等除此之外使用通过查找SSL证书、DNS、暴力枚举等这些手段去查找子域名。
简单使用可以通过git clone https://github.com/aboul3la/Sublist3r.git安装Sublist3r。然后使用sudo pip install -r requirements.txt安装依赖库。最后通过一个简单的命令查找子域名,这里以freebuf为例子。python3 sublist3r.py -d freebuf.com网站内容越多查询时间越慢,可以加一个-v来实时显示找到的子域名。
代码细节 代码目录在Linux终端下,使用tree能打印当前目录等结构树:
. ├── LICENSE ├── README.md ├── requirements.txt ├── subbrute │ ├── init.py │ ├── names.txt │ ├── resolvers.txt │ ├── subbrute.py └── sublist3r.py 入口函数sublist3r的的主要代码实现在sublist3r.py文件中。可以使用你喜欢的代码编辑器,打开这个文件。为了便于阅读,我们把所有的代码块(def、class)合上。你大概会看到如下的场景:
import re import sys #......省略若干引用 def banner(): def paeser_error(errmsg): #......省略若干函数 class enumratorBase(object): class enumratorBaseThreaded(multiprocessing.Process, enumratorBase): class GoogleEnum(enumratorBaseThreaded): class YahooEnum(enumratorBaseThreaded): class AskEnum(enumratorBaseThreaded): class BingEnum(enumratorBaseThreaded): class BaiduEnum(enumratorBaseThreaded): #......省略若干 XXEnum 的类 def main(domain, threads, savefile, ports, silent, verbose, enable_bruteforce, engines): #...省略main内容 if name == "main": args = parse_args() domain = args.domain threads = args.threads savefile = args.output ports = args.ports enable_bruteforce = args.bruteforce verbose = args.verbose engines = args.engines if verbose or verbose is None: verbose = True banner() res = main(domain, threads, savefile, ports, silent=False, verbose=verbose, enable_bruteforce=enable_bruteforce, engines=engines)如果不是使用包引用,而是直接在控制台打开,会执行if name == "main":下的内容。这里我们可以大概的了解到这里的功能,主要是用于处理用户在控制台输入的参数,并将其作为参数去调用main函数。我们可以简单的了解一下这些参数,domain是用户输入的主域名,比如freebuf.com;savefile是用于指定查找结束后子域名数据的保存目;verbose就是我们前面说的-v参数,通过这个参数来控制是否实时输出信息;engines是查找引擎(搜索源),如果为空则表示查找全部的引擎,如果用户指定了某个引擎(比如baidu),则只使用指定的引擎(比如baidu)进行查找。
main函数

