# -*- coding: binary -*- module Msf ### # # This module provides methods for working with F5 equipment # ### module Auxiliary::F5 include Msf::Auxiliary::Report def f5_config_eater(thost, tport, config, store = true) credential_data = { address: thost, port: tport, protocol: 'tcp', workspace_id: myworkspace_id, origin_type: :service, private_type: :nonreplayable_hash, # https://support.f5.com/csp/article/K65081001 jtr_format: 'sha512,crypt', # default on the devices 11.4.0+ service_name: '', module_fullname: fullname, status: Metasploit::Model::Login::Status::UNTRIED } # Default SNMP to UDP if tport == 161 credential_data[:protocol] = 'udp' end if store store_loot('f5.config', 'text/plain', thost, config.strip, 'config.txt', 'F5 Configuration') end host_info = { host: thost, os_name: 'F5' } report_host(host_info) # generated by: tmsh list auth user # auth user admin { # description "Admin User" # encrypted-password $6$4FAWSZLi$VeSaxPM2/D1JOhMRN/GMkt5wHcbIVKaIC2g765ZD0VA9ZEEm8iyK40/ncGrZIGyJyJF4ivkScNZ59HWAIKMML/ # partition Common # partition-access { # all-partitions { # role admin # } # } # shell none # } config.scan(%r{auth user ([^ ]+) {\s*description "?([^\n"]+)"?\n\s*encrypted-password ([$\w\+\./]+)\n[\w\s\-{}]+\s+shell (tmsh|bash|none)\n}}mi).each do |result| username = result[0].strip description = result[1].strip hash = result[2].strip shell = result[3].strip cred = credential_data.dup cred[:username] = username cred[:jtr_format] = Metasploit::Framework::Hashes.identify_hash(hash) cred[:private_data] = hash create_credential_and_login(cred) print_good("#{thost}:#{tport} Username '#{username}' with description '#{description}' and shell #{shell} with hash #{hash}") end # generated by: tmsh list sys snmp communities # sys snmp { # communities { # comm-public { # community-name public # source default # } # ro { # community-name rocommunity # } # rw { # access rw # community-name rwcommunity # } # } # } config.scan(/(?:(access rw)?\n)\s+community-name (\w+)/).each do |result| if result[0].nil? access = 'RO' else access = 'RW' end cred = credential_data.dup cred[:port] = 161 cred[:protocol] = 'udp' cred[:service_name] = 'snmp' cred[:jtr_format] = '' cred[:private_data] = result[1].strip cred[:private_type] = :password cred[:access_level] = access create_credential_and_login(cred) print_good("#{thost}:#{tport} SNMP Community '#{result[1].strip}' with #{access} access") end # generated by: cat /config/bigip.conf # cm device /Common/f5bigip.ragegroup.com { # active-modules { "BIG-IP, VE Trial|VTFAAAA-AAAAAAA|Rate Shaping|External Interface and Network HSM, VE|SDN Services, VE|SSL, Forward Proxy, VE|BIG-IP VE, Multicast Routing|APM, Limited|SSL, VE|DNS (1K QPS), VE|Routing Bundle, VE|ASM, VE|Crytpo Offload, VE, Tier 1 (25M - 200M)|Max Compression, VE|AFM, VE|DNSSEC|Anti-Virus Checks|Base Endpoint Security Checks|Firewall Checks|Network Access|Secure Virtual Keyboard|APM, Web Application|Machine Certificate Checks|Protected Workspace|Remote Desktop|App Tunnel|VE, Carrier Grade NAT (AFM ONLY)|PSM, VE" } # base-mac 00:11:11:a1:a1:a1 # build 0.0.9 # cert /Common/dtdi.crt # chassis-id 164aaf79-aace-3494-1237671446c7 # configsync-ip 10.10.10.222 # edition "Point Release 2" # hostname f5bigip.home.com # key /Common/dtdi.key # management-ip 1.1.1.1 # marketing-name "BIG-IP Virtual Edition" # platform-id Z100 # product BIG-IP # self-device true # time-zone America/Los_Angeles # version 15.1.0.2 # } if /^cm device (?.+)}$/m =~ config if /hostname (?[\w\.-]+)$/i =~ content print_good("#{thost}:#{tport} Hostname: #{hostname}") host_info[:name] = hostname report_host(host_info) end if /base-mac (?[\d:a-f]+)$/i =~ content print_good("#{thost}:#{tport} MAC Address: #{mac}") host_info[:mac] = mac report_host(host_info) end if /management-ip (?[\d\.]+)$/ =~ content print_good("#{thost}:#{tport} Management IP: #{ip}") end if /product (?[\w-]+)$/i =~ content print_good("#{thost}:#{tport} Product #{product}") host_info[:os_name] = "F5 #{product}" report_host(host_info) end if /version (?[\d\.]+)$/i =~ content print_good("#{thost}:#{tport} OS Version: #{version}") host_info[:os_flavor] = version report_host(host_info) end end # generated by: cat /config/bigip.conf # sys file ssl-key /Common/f5_api_com.key { # cache-path /config/filestore/files_d/Common_d/certificate_key_d/:Common:f5_api_com.key_63086_1 # passphrase $M$iE$cIdy72xi7Xbk3kazSrpdfscd+oD1pdsXJbwhvhMPiss4Iw0RKIJQS/CuSReZl/+kseKpPCNpBWNWOOaBCwlQ0v4sl7ZUkxCymh5pfFNAjhc= # revision 1 # source-path file:///config/ssl/ssl.key/f5_api_com.key # } config.scan(%r{^sys file ssl-key (.+) \{.+passphrase ([$\w/\+=]+).+source-path file://([\w/\.]+)}mi).each do |result| username = result[0].strip # its not really a username, but we'll leave it as is since its a common name hash = result[1].strip file = result[2].strip cred = credential_data.dup cred[:username] = username cred[:jtr_format] = Metasploit::Framework::Hashes.identify_hash(hash) cred[:private_data] = hash create_credential_and_login(cred) print_good("#{thost}:#{tport} SSL Key '#{username}' and hash #{hash} for #{file}") end # generated by tmsh show sys crypto master-key # -------------------------------------------------------------------------------- # Sys::Master-Key # -------------------------------------------------------------------------------- # master-key hash # previous hash config.scan(%r{(master-key|previous) hash\s+<([\w\+/=]+)>}i). each do |result| key_type = result[0].strip key = result[1].strip cred = credential_data.dup cred[:username] = "F5 #{key_type} hash" cred[:jtr_format] = Metasploit::Framework::Hashes.identify_hash(key) # will come bacy empty cred[:private_data] = key create_credential_and_login(cred) print_good("#{thost}:#{tport} F5 #{key_type} hash #{key}") end end end end