在针对目标系统进行渗透的过程中,如果目标服务器安全性很高,通过服务器很难获取目标权限时,通常会采用社工的方式对目标服务进行进一步攻击。邮件钓鱼攻击是常见的攻击方式之一。在进行钓鱼之前,需要针对目标相关人员的邮件信息进行全面采集。下面将带领大家一起编写一个邮件采集工具。
此处邮件采集工具主要通过国内常见的搜索引擎(百度、Bing等)进行搜集。针对搜索界面的相关邮件信息进行爬取、处理等操作之后。利用获得的邮箱账号批量发送钓鱼邮件,诱骗、欺诈目标用户或者管理员进行账号登录或者点击执行,进而获取目标系统的权限。该邮件采集工具所用到的相关库函数如下所示:
import sys import getopt import requests from bs4 import BeautifulSoup import re
1)在程序的起始部分,当执行过程中没有发生异常时,则执行定义的start()函数。通过sys.argv[]实现外部指令的接收。其中,sys.argv[0]表示代码本身的文件路径,sys.argv[1:]表示从第一个命令行参数到输入的最后一个命令行参数,存储形式为list类型:
if __name__ == '__main__': #定义异常 try: start(sys.argv[1:]) except KeyboardInterrupt: print("interrupted by user, killing all threads...")
2)编写命令行参数处理功能。此处主要应用getopt.getopt()函数处理命令行参数,该函数目前有短选项和长选项两种格式。短选项格式为“-”加上单个字母选项;长选项格式为“--”加上一个单词选项。opts为一个两元组列表,每个元素形式为“(选项串,附加参数)”。当没有附加参数时,则为空串。之后通过for语句循环输出opts列表中的数值并赋值给自定义的变量:
#主函数,传入用户输入的参数 def start(argv): url = "" pages = "" if len(sys.argv) < 2: print("-h 帮助信息;\n") sys.exit() #定义异常处理 try: banner() opts,args = getopt.getopt(argv,"-u:-p:-h") except getopt.GetoptError: print('Error an argument!') sys.exit() for opt,arg in opts: if opt == "-u": url = arg elif opt == "-p": pages = arg elif opt == "-h": print(usage()) launcher(url,pages)
3)输出帮助信息,增加代码工具的可读性和易用性。为了使输出信息更加美观简洁,可以通过转义字符设置输出字体颜色,从而实现需要的效果。开头部分包含三个参数:显示方式、前景色、背景色。这三个参数是可选的,可以只写其中的某一个参数。结尾部分可以省略,但是为了书写规范,建议以“\033[0m”结尾。其具体的输出格式如下所示:
开头:\033[显示方式;前景色;背景色m 结尾部分:\033[0m
示例代码如下:
print('\033[0;30;41m ms08067实验室欢迎你 \033[0m') print('\033[0;31;42m ms08067实验室欢迎你 \033[0m') print('\033[0;32;43m ms08067实验室欢迎你 \033[0m') print('\033[0;33;44m ms08067实验室欢迎你 \033[0m') print('\033[0;34;45m ms08067实验室欢迎你 \033[0m') print('\033[0;35;46m ms08067实验室欢迎你 \033[0m') print('\033[0;36;47m ms08067实验室欢迎你 \033[0m')
示例的输出效果如下所示:
该部分主要代码如下所示,先以图案的形式输出脚本出自MS08067实验室,然后输出有关该脚本使用的帮助信息,即可执行参数指令以及对应的功能简介。代码如下:
#banner信息 def banner(): print('\033[1;34m######################################################### ###############################\033[0m\n' '\033[1;34m######################################\033[1;32MMS08067实验室 \033[1;34m#####################################\033[0m\n' '\033[1;34m######################################################### ###############################\033[0m\n') #使用规则 def usage(): print('-h: --help 帮助;') print('-u: --url 域名;') print('-p: --pages 页数;') print('eg: python -u "www.baidu.com" -p 100'+'\n') sys.exit() ##未授权函数检测
输出效果如下所示:
当然,此处也可以根据自己的喜好设置输出不同类型的字体颜色或者图案。
4)确定搜索邮件的关键字,并调用bing_search()和baidu_search()两个函数,返回Bing与百度两大搜索引擎的查询结果。由获取到的结果进行列表合并,去重之后,循环输出。代码如下:
#漏洞回调函数 def launcher(url,pages): email_num = [] key_words = ['email','mail','mailbox','邮件','邮箱','postbox'] for page in range(1,int(pages)+1): for key_word in key_words: bing_emails = bing_search(url,page,key_word) baidu_emails = baidu_search(url,page,key_word) sum_emails = bing_emails + baidu_emails for email in sum_emails: if email in email_num: pass else: print(email) with open('data.txt', 'a+') as f: f.write(email + '\n') email_num.append(email)
5)用Bing搜索引擎进行邮件爬取。Bing引擎具有反爬防护,会通过限定referer、cookie等信息来确定是否是网页爬取操作。可以通过指定referer与requests.session()函数自动获取cookie信息,绕过Bing搜索引擎的防爬防护。代码如下:
def bing_search(url,page,key_word): referer = "http://cn.bing.com/search?q=email+site%3abaidu.com&qs=n&sp=-1& pq=emailsite%3abaidu.com&first=1&FORM=PERE1" conn = requests.session() bing_url = "http://cn.bing.com/search?q=" + key_word + "+site%3a" + url + "&qs=n&sp=-1&pq=" + key_word + "site%3a" + url + "&first=" + str( (page-1)*10) + "&FORM=PERE1" conn.get('http://cn.bing.com', headers=headers(referer)) r = conn.get(bing_url, stream=True, headers=headers(referer), timeout=8) emails = search_email(r.text) return emails
6)用百度搜索引擎进行邮件爬取。百度搜索引擎同样设定了反爬防护,相对于Bing搜索引擎来说,百度搜索引擎不仅对referer和cookie进行校验,还同时在页面中通过JavaScript语句进行动态请求链接,从而导致不能动态获取页面中的信息。可以通过对链接的提取,再进行request请求,从而绕过百度搜索引擎的反爬设置,具体代码如下所示:
def baidu_search(url,page,key_word): email_list = [] emails = [] referer = "https://www.baidu.com/s?wd=email+site%3Abaidu.com&pn=1" baidu_url = "https://www.baidu.com/s?wd="+key_word+"+site%3A"+url+"&pn= "+str((page-1)*10) conn = requests.session() conn.get(referer,headers=headers(referer)) r = conn.get(baidu_url, headers=headers(referer)) soup = BeautifulSoup(r.text, 'lxml') tagh3 = soup.find_all('h3') for h3 in tagh3: href = h3.find('a').get('href') try: r = requests.get(href, headers=headers(referer),timeout=8) emails = search_email(r.text) except Exception as e: pass for email in emails: email_list.append(email) return email_list
7)通过正则表达式获取邮箱号码。此处也可换成目标企业邮箱的正则表达式,代码如下:
def search_email(html): emails = re.findall(r"[a-z0-9\.\-+_]+@[a-z0-9\.\-+_]+\.[a-z]+",html,re.I) return emails def headers(referer): headers = {'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/ 20100101 Firefox/60.0', 'Accept': '*/*', 'Accept-Language': 'en-US,en;q=0.5', 'Accept-Encoding': 'gzip,deflate', 'Referer': referer } return headers
通过Python 3执行刚刚写完的脚本并通过-u参数指定域名,-p参数表示搜索引擎的页数,其输出效果如下所示:
此处也可以指定其他域名,并将爬取结果打印到页面中。