前言
在挖掘SRC漏洞以及HW收集资产的时候,子域名作为必备的一项信息收集工作。同时也是寻找到敏感资产、脆弱资产、获取突破口的一种方式。
子域名收集
目前市面上的关于收集子域名的文章、工具非常多。比如安恒的这篇,收集子域名就有20种方法。这里从收集子域名的不同原理上推荐几款常用的工具,本着安装方便、使用简单、受众多的原则。
DNS 域传送
在主备服务器之间同步数据库时,需要使用"DNS域传送"。
若DNS服务器配置不当,可能导致匿名用户获取某个域的所有记录。
测试是否存在域传送漏洞,大概nslookup、dig、nmap 三种方法。
详情参考 dns 域传送漏洞利用总结
暴力破解
基于字典,暴力枚举子域名。
推荐 subDomainsBrute、wydomain、ESD
证书透明度
因为SSL证书支持证书透明度,而SSL里包含子域名。
推荐在线网站https://crt.sh/ 从SSL证书收集子域名。
这里改写了大佬的代码,直接提取相关的子域名。
# !/usr/bin/env python3
# -*- coding: utf-8 -*-
# code by CSeroad
import sys
import urllib.request
import urllib.parse
import re
import ssl
ssl._create_default_https_context = ssl._create_unverified_context
def crt_domain(domains):
with urllib.request.urlopen('https://crt.sh/?q=' + domains) as f:
code = f.read().decode('utf-8')
for cert, domain in re.findall('(?:\s|\S)*?href="\?id=([0-9]+?)"(?:\s|\S)*?([*_a-zA-Z0-9.-]+?\.' + re.escape(domains) + ') (?:\s|\S)*? ', code, re.IGNORECASE):
domain = domain.split('@')[-1]
print(domain)
with open('crt_result.txt','a+') as f:
f.write(str(domain)+'\n')
if __name__ == '__main__':
if len(sys.argv) == 2:
domains=sys.argv[1]
crt_domain(domains)
else:
print('User: python3 crt_domain.py domain')
DNS数据聚合
virustotal 执行DNS解析来构建数据库,来检索子域名。
这里也有写好的从virustotal直接提取子域名的 脚本
js文件提取
JSFinder 从网站的js中提取url地址,发现子域名。
JSINFO-SCAN 一款递归爬取域名,以及递归从JS中获取信息的工具。
综合
还有一些综合性比较强的工具
Sublist3r 整合了subbrute,还使用了一些搜索引擎枚举子域名。
teemo 有众多模块,包括从各个接口、解析记录、crossdomain.xml、枚举等等收集子域名。
OneForAll 也是有多个模块,爆破模块、DNS解析模块等等。
子域名去重
然后将收集的子域名进行去重。
#!/usr/bin/env python3
#-*- coding:utf-8 -*-
import sys
# 去除文本中的重复行
def filedelrepeat(filename):
try:
file=open(filename,'r')
links=file.readlines()
file.close()
lines=set()
for link in links:
lines.add(link)
print('文件名: ' + filename)
print('原有行:' + str(len(links)))
file=open(filename,'w')
for line in lines:
file.write(line)
file.close()
print('去重后: ' + str(len(lines)))
except Exception as e:
print(e)
if __name__ == '__main__':
if len(sys.argv) == 2:
filename=sys.argv[1]
filedelrepeat(filename)
else:
print('User: python3 repeat.py repeat.txt')
子域名利用
当获取子域名后,怎么进一步漏洞挖掘呢?
- 访问域名直接获取title;
- 在域名后面添加端口访问获取title;
- 访问域名为nginx、apache、IIS、weblogic默认页面,或403、404等页面,尝试利用google、必应、github、fofa、shodan等获取资产;
- 某些资产必须更换浏览器才可以正常访问,如IE、微信内置浏览器等;
- 直接对域名进行暴力递归扫描目录,如dirsearch、dirmap等工具;
- 对目录进行fuzz扫描,或者利用burp的intruder 模块来爆破目录,该目录通过组合字母进行爆破,扫描域名的子目录;
扫描title
修改原来写的扫描C段获取title信息的代码。
注:只使用http或https进行访问
# !/usr/bin/env python3
# -*- coding: utf-8 -*-
# code by CSeroad
from optparse import OptionParser
import requests
import time
from bs4 import BeautifulSoup
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
def scan(host):
try:
for url in host:
url = url.strip('\n')
print(url)
https_url = "https://"+url
get_title(https_url)
http_url = "http://"+url
get_title(http_url)
except Exception as e:
print(e)
def save_result(filename,url_title):
with open(filename,'a+') as f:
f.write(str(url_title)+'\n')
def get_title(url):
try:
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36"}
r = requests.get(url,headers=headers,timeout=3,verify=False)
if r.status_code == 500:
pass
else:
response = r.text
soup = BeautifulSoup(response,'lxml')
span = soup.title.string
print("\033[1;37;40m"+url+"\ttitle:"+span+"\033[0m")
url_title = "%-27s %-30s\n" % (url,span)
save_result(result,url_title)
except Exception as e:
pass
if __name__ == '__main__':
parser = OptionParser("get_domain_title.py -d domain.txt -o result.txt")
parser.add_option("-d", "--domain",action="store",type="string",dest="domain",help="domain.txt")
parser.add_option("-o","--result",action="store",type="string",dest="result",default="result.txt",help="result")
(options, args) = parser.parse_args()
if options.domain:
t1 = time.time()
domain = options.domain
result = options.result
with open("domain.txt","r") as f:
domain_url = f.readlines()
scan(domain_url)
print('end time:',time.time()-t1)
else:
parser.error('incorrect number of arguments')
也可以添加端口列表获取title,使用多线程方式,再次修改该脚本。
注:增加了端口列表
# !/usr/bin/env python3
# -*- coding: utf-8 -*-
# code by CSeroad
from optparse import OptionParser
import requests
import time
import threading
from bs4 import BeautifulSoup
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
def scan(host,port):
try:
for url in host:
url = url.strip('\n')
if int(port) == 443:
https_url = "https://"+url
get_title(https_url)
elif int(port) == 4433:
https_url = "https://"+url+":"+str(port)
get_title(https_url)
elif int(port) == 8443:
https_url = "https://"+url+":"+str(port)
get_title(https_url)
else:
http_url = "http://"+url+":"+str(port)
get_title(http_url)
except Exception as e:
print(e)
def save_result(filename,url_title):
with open(filename,'a+') as f:
f.write(str(url_title)+'\n')
def get_title(url):
try:
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36"}
r = requests.get(url,headers=headers,timeout=3,verify=False)
if r.status_code == 500:
pass
else:
response = r.text
soup = BeautifulSoup(response,'lxml')
span = soup.title.string
print("\033[1;37;40m"+url+"\ttitle:"+span+"\033[0m")
url_title = "%-27s %-30s\n" % (url,span)
save_result(result,url_title)
except Exception as e:
pass
def thread(host):
thread_list = []
port_list = [80,81,82,443,4433,7001,8000,8001,8008,8009,8080,8081,8088,8089,8443,8800,8888,8889,9090,9999]
for port in port_list:
t = threading.Thread(target = scan,args = (host,port))
thread_list.append(t)
for t in thread_list:
t.start()
for t in thread_list:
t.join()
if __name__ == '__main__':
parser = OptionParser("get_domain_title.py -d domain.txt -o result.txt")
parser.add_option("-d", "--domain",action="store",type="string",dest="domain",help="domain.txt")
parser.add_option("-o","--result",action="store",type="string",dest="result",default="result.txt",help="result")
(options, args) = parser.parse_args()
if options.domain:
t1 = time.time()
domain = options.domain
result = options.result
with open("domain.txt","r") as f:
domain_url = f.readlines()
thread(domain_url)
print('end time:',time.time()-t1)
else:
parser.error('incorrect number of arguments')
效果图如下
搜索引擎
扫描目录
通过目录扫描工具,获取敏感资产。
一般看谁家的字典比较强了。大多数使用dirsearch、dirmap、webdirscan 自己构造字典 等扫描工具。
还可以对目录进行fuzz,推荐wfuzz这款神器。
也可以使用26个英文字母随机组合,形成字典,来爆破子目录。
这里选择的是1到4位的英文字母。
可以爆破到很多子目录。
总结
1.收集到几款工具大都是python编写的,安装运行都比较方便;
2.不同的姿势多收集子域名,多寻找隐藏的资产,有些接口fuzz甚至废弃的资产存在漏洞;