-
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
Exploit & Auxiliary modules for CVE-2023-20198 and CVE-2023-20273 (Cisco IOS XE) #18507
Conversation
…ugs (CVE-2023-20198 and CVE-2023-20273). This allows for unauthenticated remote CLI or OS command execution.
… of print_status for cleaner output.
documentation/modules/auxiliary/admin/http/cisco_ios_xe_cli_exec_cve_2023_20198.md
Outdated
Show resolved
Hide resolved
documentation/modules/auxiliary/admin/http/cisco_ios_xe_os_exec_cve_2023_20273.md
Outdated
Show resolved
Hide resolved
<wsse:Security xmlns:wsse="http://schemas.xmlsoap.org/ws/2002/04/secext"> | ||
<wsse:UsernameToken SOAP:mustUnderstand="false"> | ||
<wsse:Username>#{username}</wsse:Username> | ||
<wsse:Password>*****</wsse:Password> |
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.
<wsse:Password>*****</wsse:Password> | |
<wsse:Password>#{Rex::Text.rand_text_alpha(8)}</wsse:Password> |
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 string *****
comes from how the Cisco Lua code expects to pass the password, and a comment in the Lua code notes its purpose:
-- Mask the password. It is for audit purposes only and it doesnt use it for authentication
FString = string.gsub(FString,"#password","*****")
With this in mind I don't think we should change the string to a random alpha text. It makes more sense to leave it as the expected value.
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.
Wow, amazing. In a bad way. But still, amazing.
|
||
register_options( | ||
[ | ||
OptString.new('CMD', [ true, 'The Global configuration CLI command to execute. To drop to Privileged EXEC mode, preface your CMD with exit\\\\n, e.g "exit\\\\nshow version"', 'exit\\nshow version']) |
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 it'd be easier for users to have a "PrivilegedExec" boolean instead of having to manually add a prefix, wouldn't it?
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.
Yes, this is a good idea. I have implemented this via b286687
Co-authored-by: Julien Voisin <[email protected]>
Co-authored-by: Julien Voisin <[email protected]>
…. If set these admin creds are used to leverage CVE-2023-20273. If not set, then CVE-2023-20198 is used to create a new temp admin account before leveraging CVE-2023-20273
…'privileged', and 'global'.
Converting this pull request to a draft as I have figured out how to run a payload, so can write an additional exploit module |
I have added an RCE exploit module and tested it against IOS XE 17.3.2 and 16.12.3. I added support for both a Linux target (IOS XE is Linux based), but also Unix target, so a broader array of payloads are available (like python meterpreter or a bash shell). Native Linux Meterpreter (via fetch payloads)
Unix bash reverse shell
|
return false unless res&.code == 200 | ||
|
||
true |
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.
return false unless res&.code == 200 | |
true | |
return res&.code == 200 |
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.
good catch, thanks. resolved via 7024d4e (the trailing return can be removed also)
# (as the above call to run_cli_command succeeded), however maybe this firmware version uses a different format | ||
# for the version information so our regex wont work. | ||
# Note: Version numbers can have letters in them, e.g. 17.11.99SW or 16.12.1z2 | ||
if res =~ /(Cisco IOS XE Software, Version [\d\S]+\.[\d\S]+\.[\d\S]+)/ |
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.
if res =~ /(Cisco IOS XE Software, Version [\d\S]+\.[\d\S]+\.[\d\S]+)/ | |
if res =~ /(Cisco IOS XE Software, Version [^.]+\.[^.]+\.[\^.]+)/ |
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.
Thanks Julien. Looking at the current expression, the \d
is redundant so I think /(Cisco IOS XE Software, Version \S+\.\S+\.\S+)/
is probably the best expression. Using ^\.
will also include whitespace chars which I was trying to avoid.
I have removed the redundant \d
via 2a56c3f.
Testing (Cisco IOS XE Software, Version \S+\.\S+\.\S+)
:
Testing (Cisco IOS XE Software, Version [^\.]+\.[^\.]+\.[^\.]+)
:
Co-authored-by: Julien Voisin <[email protected]>
|
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 a quick question and I noticed that the docs might not have been updated after a change to the module.
documentation/modules/auxiliary/admin/http/cisco_ios_xe_os_exec_cve_2023_20273.md
Outdated
Show resolved
Hide resolved
ensure | ||
vprint_status("Removing user '#{admin_username}'") | ||
|
||
unless run_cli_command("no username #{admin_username}", Mode::GLOBAL_CONFIGURATION) |
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.
Would it ever be worthwhile to leave the user as a backdoor?
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.
Perhaps, I think as the aux module cisco_ios_xe_cli_exec_cve_2023_20198
would allow the creation of a new admin account via a CLI command, that is also an option.
|
…O_ADMINUSERNAME and CISCO_ADMIN_PASSWORD in the show options command output Co-authored-by: Brendan <[email protected]>
Release NotesThis PR adds three modules: |
This pull request add two auxiliary modules for the recent Cisco IOS XE vulnerabilities that have been exploited in the wild.
The module
auxiliary/admin/http/cisco_ios_xe_cli_exec_cve_2023_20198
leverages CVE-2023-20198 to perform unauthenticated remote CLI command execution. Horizion3ai have a two part writeup with technical details on the vuln.The module
auxiliary/admin/http/cisco_ios_xe_os_exec_cve_2023_20273
leverages both CVE-2023-20198 and CVE-2023-20273 to perform unauthenticated remote OS command execution. Leakix has a writeup with technical details on the second CVE. The reason this module is an aux module and not an exploit module is that, even though we get OS command execution, the OS seems to be hardened and running a Metasploit payload is non trivial (at least from some early testing on the device I have). I am investigating this further.Example Usage (CVE-2023-20198)
Example Usage (CVE-2023-20198 + CVE-2023-20273)