-
Notifications
You must be signed in to change notification settings - Fork 14.1k
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
Updates to the AutoCheck mixin #19140
Conversation
I feel like this PR might be trying to solve a mixture of user error, and the module in question not being runnable without the i.e. if the user chooses to ignore the In this case - it feels like the module itself should be updated to gracefully handle the |
I think there are cases where it is reasonable to require the check method be run to, for example, initiate a connection. These changes make it easier for the module author to express the guarantees they expect of the state the module instance to be in at the point the main method is run. What you're proposing would require the module to either duplicate a fair bit of code to initiate the connection or to place it into a method. What complicates placing it in a new method called from both the check and run methods is the desire to not raise unhandled exceptions from check methods. If it'd be helpful, I can dig out another module I'd previously written that would have benefited from this feature that inspired the idea. |
I believe the
That'd be good to share to understand the scenario a bit better 💯 |
Alright, here's more examples of where this would come in handy: vmware_workspace_one_access_vmsa_2022_0011_chain.rbIn this one, the vulnerability is leveraged to leak the authentication token as part of a bypass. You can see in the atlassian_confluence_rce_cve_2023_22527.rbThis one uses the vulnerability to leak the target platform so the command injection can be properly formatted. Again, the exploit author needs to ensure that the target platform can be identified, and work around it with a cached instance variable. A second instance of this pattern is present in another Confluence OGNL injection exploit, atlassian_confluence_namespace_ognl_injection.rb. cve_2020_1472_zerologon.rbZerologon would be another excellent example if it weren't for the fact that there's another action that doesn't require leveraging the vulnerability ( Based on these examples, the pattern is that this would simplify things for the module author in cases where the vulnerability can be safely leveraged in the
|
This is fixes modules that don't call update_info for their module info.
Here's another example of a module that's effectively inlining this functionality. The apache_normalize_path_rce is basically using AUTO_CHECK_LEVEL_BYPASSABLE here.
|
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 have the same feeling about this. The check method will have a new meaning now, if set as mandatory to setup some requirements for the exploit. I believe the AutoCheck
mixin is here to glue together the #exploit
(or #run
) method with the #check
easily. I'm not sure if #check
should now be used as a required pre-exploit setup.
I think using an instance variable is still good to me. This state-machine-like logic seems to already be used in many modules, including the VMware module you linked.
def setup_connection
return if @connected
# setup things
@connected = true
end
def leak_token
return @leak_token if @leak_token
@leak_token = ... # do something to leak the token
end
def check
setup_connection
leak_token
rescue CustomException::Error => e
return Exploit::CheckCode::Unknown
rescue CustomException::TokenNotLeaked => e
return Exploit::CheckCode::Safe
end
def exploit
begin
setup_connection unless @connected
leak_token unless @leak_token
rescue CustomException::Error => e
fail_with(...)
rescue CustomException::TokenNotLeaked => e
fail_with(...)
end
...
end
def merge_info_autochecklevel(info, val) | ||
info['AutoCheckLevel'] = val |
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.
It looks like this method is not used and I cannot find a reference to the info
hash.
I'm in favor of Christophe's mental model too; Potentially we're missing verification steps in our testing approach to ensure that the exploit method works in isolation, i.e. verify:
|
This updates the AutoCheck mixin to allow the module author to rely on some guarantees regarding it's execution. It adds a new
AutoCheckLevel
module info option which the module author can use to reliably ensure that thecheck
method at least runs (LEVEL_BYPASSABLE) or runs and returns a result implying that the target is vulnerable (LEVEL_REQUIRED). This makes it a lot easier to rely on module instance state set within the check method. If the connection is established in the check method, and required in the exploit, it might make sense to use LEVEL_BYPASSABLE, which guarantees that at least the check method ran and presumably connected. If the exploit's check method maybe gathers a sensitive token that's then used in the exploit and determines the vulnerable state based on whether it could leak the token, then it makes sense for the check method to be a hard requirement and abort execution if the required token couldn't be leaked.This fixes the stack trace in #19123 by preventing the user from bypassing the check method which as failing due to a connection error. The check method in printnight makes sense to be a requirement. There's a fair bit of setup to access the DCERPC interface and the response to the method can be used to reliably fingerprint whether or not the target is vulnerable.
Verification