漏洞挖掘-子域名

前言

在挖掘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')

子域名利用

当获取子域名后,怎么进一步漏洞挖掘呢?

  1. 访问域名直接获取title;
  2. 在域名后面添加端口访问获取title;
  3. 访问域名为nginx、apache、IIS、weblogic默认页面,或403、404等页面,尝试利用google、必应、github、fofa、shodan等获取资产;
  4. 某些资产必须更换浏览器才可以正常访问,如IE、微信内置浏览器等;
  5. 直接对域名进行暴力递归扫描目录,如dirsearch、dirmap等工具;
  6. 对目录进行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')

效果图如下

效果图

搜索引擎

google
biying

扫描目录

通过目录扫描工具,获取敏感资产。
一般看谁家的字典比较强了。大多数使用dirsearch、dirmap、webdirscan 自己构造字典 等扫描工具。

还可以对目录进行fuzz,推荐wfuzz这款神器。

image.png

也可以使用26个英文字母随机组合,形成字典,来爆破子目录。

image.png
image.png

这里选择的是1到4位的英文字母。

image.png

可以爆破到很多子目录。

总结

1.收集到几款工具大都是python编写的,安装运行都比较方便;
2.不同的姿势多收集子域名,多寻找隐藏的资产,有些接口fuzz甚至废弃的资产存在漏洞;

你可能感兴趣的:(漏洞挖掘-子域名)