Press "Enter" to skip to content

渗透小工具—对子域名爆破结果进行有效性验证和内容抽取

在渗透过程中,主站安全性往往比较好,所以要爆破子域名并试图从旁站开始下手。常用的获取子域名的工具有subDomainBrute和Layer子域名挖掘机,但是这两个工具的结果只是把域名及IP导出,并不知道是否能够连通、该子域名对应的网站内容是什么。一般的站点子域名往往能达到几十个,这时候一个一个手动去试太麻烦了,于是我写了下面这个脚本(Python3),分享给大家。

#coding=utf-8

"""
在使用subDomainBrute和Layer子域名挖掘机后得到包含域名及其对应IP的文件
本脚本读取类似格式文件,访问其域名并抽取title值
目的是验证可访问性并提供描述性信息方便确认下一步要进行测试的网站
@author: www.hupeiwei.com
@line_format: domain  ip1,ip2,...
"""

from optparse import OptionParser
import os
import re
import requests
from multiprocessing import Pool
from time import sleep

#_SEPARATOR can be defined according to line format,it's used to separate domain and ips
_SEPARATOR_ = '\s+|,\s'
_REGEX_ = '<title>(.*)</title>'

def getPara():
    parser = OptionParser(usage='python extractTitle.py -o outputfile target_file1 target_file2 ...')
    parser.add_option('-o','--outfile',action='store',dest='output',help='file path of output result')
    (options,args) = parser.parse_args()
    if len(args) == 0 :
        parser.print_help()
    if options.output == None:
        parser.print_help()
    return (options,args)

def getTitle(url):
    try:
        txt = requests.get(url)
        s = requests.session()
        s.keep_alive = False
    except Exception as e:
        print("[Warning]:访问" + url + "失败...")
        return '访问失败'
    try:
        pattern = re.compile(_REGEX_,flags=re.IGNORECASE)
        return re.findall(pattern,txt.content.decode())[0]
    except Exception:
        try:
            pattern = re.compile(_REGEX_, flags=re.IGNORECASE)
            return re.findall(pattern, txt.text)[0]
        except Exception as e:
            print('[Warning]:' + url + '查找title失败...')
            return '未找到title'

def solvePart(domain,line):
    str = ''
    print('[+]Start judge: ' + domain +'\n')
    title = getTitle('http://' + domain)
    str += ('%s%s' % (domain.ljust(30), title.strip().ljust(80)))
    while line:
        str += (line.pop(0) + ', ').strip().ljust(50)
    str += ('\n')
    return str

#read files and remove duplicate domains
def readFiles(options,args):
    output = options.output
    files = set()
    # validate file existence
    for i in range(len(args)):
        if not os.path.exists(args[i]):
            print('[-]Error: file %s not exists!' % args[i])
            exit(-1)
        else:
            files.add(args[i])
    #merge file content and remove duplicate lines
    domains = set()
    p = Pool()
    res = []
    for f in files:
        print('b')
        with open(f,'r') as handle:
            for line in handle.readlines():
                line = line.strip()
                line = re.split(_SEPARATOR_,line)
                domain = line.pop(0)
                if domain not in domains:
                    domains.add(domain)
                    res.append(p.apply_async(solvePart,args=(domain,line,)))
                else:
                    print('检测到重复域名:' + domain)
    p.close()
    p.join()
    with open(output,'w+') as f:
        for _ in res:
            f.write(_.get())

if __name__ == '__main__':
    (options,args) = getPara()
    readFiles(options,args)

输出效果:

在这里插入图片描述

Be First to Comment

发表评论

电子邮件地址不会被公开。 必填项已用*标注

To create code blocks or other preformatted text, indent by four spaces:

    This will be displayed in a monospaced font. The first four 
    spaces will be stripped off, but all other whitespace
    will be preserved.
    
    Markdown is turned off in code blocks:
     [This is not a link](http://example.com)

To create not a block, but an inline code span, use backticks:

Here is some inline `code`.

For more help see http://daringfireball.net/projects/markdown/syntax