Michał Rola Blog

Secure you communication through SSH pipes. [2/4]


Chapter 4 will introduce us remote targets using knowledge from previous chapters. First of all we will create target host in our local Lab which will be used to connect with. We know that we created image from Dockerfile of Centos system with ssh enabled and generating all keys. We will list images:
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
centos_ssh latest 631487ba8064 44 hours ago 523MB
...

That’s the one we will use to generate target system TARGET1 the same like JUMPBOX1 but now we will remember about port 22 😉
$ docker run -d -P -p 22:22 --name TARGET1 centos_ssh:latest

We will receive id of container we ran.

In this exercise we will try to communicate with TARGET1 using JUMPBOX1. First we need to connect to TARGET1 one using docker, let us list dockers and find TARGET1 container id or we can use TARGET1 name. No we are creating the same user and we copy public keys as shown in previous chapter. We can list contianers:
┌──(kali㉿kali)-[~]
└─$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f3f18d566cc1 centos_ssh:latest "/usr/sbin/sshd -D" About an hour ago Up 5 minutes 0.0.0.0:2201->22/tcp JUMPBOX1
5256f5bf1f93 centos_ssh:latest "/usr/sbin/sshd -D" 2 days ago Up 2 hours 0.0.0.0:22->22/tcp TARGET1`

There is two ways to login, by container id or by name:

┌──(kali㉿kali)-[~]
└─$ docker exec -it TARGET1 bash
[root@5256f5bf1f93 /]# exit

┌──(kali㉿kali)-[~]
└─$ docker exec -it 525 bash
[root@5256f5bf1f93 /]# adduser nemo
# su nemo

Create .ssh and add public keys from Kali authorized_keys
1 mkdir ~/.ssh
2 vim ~/.ssh/authorized_keys
3 vi ~/.ssh/authorized_keys
4 cat ~/.ssh/authorized_keys
5 chmod 700 ~/.ssh/
6 chmod 600 ~/.ssh/authorized_keys
7 exit

Check if everything work properly. We should ssh from Kali to our TARGER1 as nemo:
┌──(kali㉿kali)-[~]
└─$ ssh -p 22 [email protected]
[nemo@5256f5bf1f93 ~]$

Create Netcat chat from the papers. We ssh to the TARGET1 from Kali and start nc server:

┌──(kali㉿kali)-[~]
└─$ ssh -p 22 [email protected]
[nemo@5256f5bf1f93 ~]$ nc -nv -l 172.17.0.3 2222
Ncat: Version 7.50 ( https://nmap.org/ncat )
Ncat: Listening on 172.17.0.3:2222`

Forward port to remote target from new terminal:
┌──(kali㉿kali)-[~]
└─$ ssh -p 22 [email protected] -L 127.0.0.1:2000:172.17.0.3:2222 130
[nemo@f3f18d566cc1 ~]$

Last thing is to run nc from Kali:

┌──(kali㉿kali)-[~]
└─$ nc 127.0.0.1 2000 130
Hi TARGET!
Hi Kali !`

Send Hi TARGET! and from TARGET we typed Hi Kali !

┌──(kali㉿kali)-[~]
└─$ ssh -p 22 [email protected]
[nemo@5256f5bf1f93 ~]$ nc -nv -l 172.17.0.3 2222
Ncat: Version 7.50 ( https://nmap.org/ncat )
Ncat: Listening on 172.17.0.3:2222
Ncat: Connection from 172.17.0.2.
Ncat: Connection from 172.17.0.2:49376.
Hi TARGET!
Hi Kali !`

You can notice that nothing special happens on JUMPBOX1:

┌──(kali㉿kali)-[~]
└─$ ssh -p 22 [email protected] -L 127.0.0.1:2000:172.17.0.3:2222 130
[nemo@f3f18d566cc1 ~]$`

but you can type -vvv and see debug and logs.

If you get to this point we can move forward to SSH to Linux Target and use the connection described before to ssh into TARGET1 through JUMPBOX1. We will be able to run bash on TARGET1. First we need to do little change, change port 2222 to 22:
┌──(kali㉿kali)-[~]
└─$ ssh -p 22 [email protected] -L 127.0.0.1:2000:172.17.0.3:22 255
[nemo@f3f18d566cc1 ~]$

Now we can run this command (it will ask us to add fingerprint while first access):

┌──(kali㉿kali)-[~]
└─$ ssh -p 2000 [email protected]
[nemo@5256f5bf1f93 ~]$`

We are in! You can notice container id starts with 525, that’s our TARGET1 machine. In the papers they instruct us to use ifconfig to see machine ip address, on my machine we will use different command to display ip:
$ hostname -I
172.17.0.3

This is the ip of our TARGET1 machine.

Next step id to use double tunnels together. For this exercise I will modify Dockerfile to have more automatic image.

Here is image that will create ready JUMPBOX1 for us:

┌──(kali㉿kali)-[~/DockerFiles/centos]
└─$ cat Dockerfile 1 ⚙
FROM centos/systemd:latest

RUN yum update -y && yum -y install openssh openssh-server openssh-clients sudo initscripts

RUN ssh-keygen -q -N "" -t rsa -f /etc/ssh/ssh_host_rsa_key
RUN ssh-keygen -q -N "" -t rsa -f /root/.ssh/id_rsa
RUN adduser nemo
RUN mkdir /home/nemo/.ssh
RUN chmod 700 /home/nemo/.ssh
RUN chown nemo /home/nemo/.ssh/
RUN chgrp nemo /home/nemo/.ssh
RUN touch /home/nemo/.ssh/authorized_keys
RUN chmod 600 /home/nemo/.ssh/authorized_keys
RUN chown nemo /home/nemo/.ssh/authorized_keys
RUN chgrp nemo /home/nemo/.ssh/authorized_keys

EXPOSE 22

CMD ["/usr/sbin/sshd", "-D"]`

We can now save Dockerfile and run build:
┌──(kali㉿kali)-[~/DockerFiles/centos]
└─$ docker build -t ready_centos_ssh .

Here we have results how image build looks like:
└─$ docker build -t ready_centos_ssh . 1 ⚙
Sending build context to Docker daemon 2.56kB
Step 1/15 : FROM centos/systemd:latest
---> 05d3c1e2d0c1
Step 2/15 : RUN yum update -y && yum -y install openssh openssh-server openssh-clients sudo initscripts
---> Using cache
---> c9a84358517c
Step 3/15 : RUN ssh-keygen -q -N "" -t rsa -f /etc/ssh/ssh_host_rsa_key
---> Using cache
---> b1d24455552f
Step 4/15 : RUN ssh-keygen -q -N "" -t rsa -f /root/.ssh/id_rsa
---> Using cache
---> 2352efdcb371
Step 5/15 : RUN adduser nemo
---> Running in 2d4528b66310
Removing intermediate container 2d4528b66310
---> 3f7748750341
Step 6/15 : RUN mkdir /home/nemo/.ssh
---> Running in daa6364267f6
Removing intermediate container daa6364267f6
---> 59339ba72742
Step 7/15 : RUN chmod 700 /home/nemo/.ssh
---> Running in 9eea213cb1cc
Removing intermediate container 9eea213cb1cc
---> bcd1e8eaca8c
Step 8/15 : RUN chown nemo /home/nemo/.ssh/
---> Running in bb90969852ca
Removing intermediate container bb90969852ca
---> ac84458934f5
Step 9/15 : RUN chgrp nemo /home/nemo/.ssh
---> Running in 636c361348b0
Removing intermediate container 636c361348b0
---> 5c6cdb3ad134
Step 10/15 : RUN touch /home/nemo/.ssh/authorized_keys
---> Running in cf2c56177955
Removing intermediate container cf2c56177955
---> 83a4646f2a24
Step 11/15 : RUN chmod 600 /home/nemo/.ssh/authorized_keys
---> Running in d96045371c99
Removing intermediate container d96045371c99
---> b853ba4078ce
Step 12/15 : RUN chown nemo /home/nemo/.ssh/authorized_keys
---> Running in ec3bfffd644f
Removing intermediate container ec3bfffd644f
---> 2149ad463725
Step 13/15 : RUN chgrp nemo /home/nemo/.ssh/authorized_keys

---> Running in 749d96f207ee
Removing intermediate container 749d96f207ee
---> 8d425721fe05
Step 14/15 : EXPOSE 22
---> Running in 3b23146029f2
Removing intermediate container 3b23146029f2
---> 0cdad8836360
Step 15/15 : CMD ["/usr/sbin/sshd", "-D"]
---> Running in 61757a8571fc
Removing intermediate container 61757a8571fc
---> 8fd761404691
Successfully built 8fd761404691
Successfully tagged ready_centos_ssh:latest

Next step we can run our image to build JUMPBOX2:
┌──(kali㉿kali)-[~/DockerFiles/centos]
└─$ docker run -d -P -p 22:22 --name JUMPBOX2 ready_centos_ssh:latest 1 ⚙
784e2ed7582be217ff19bf1939ca377565f01fc8af9385fd71c19e09bfe061cf

Copy Kali public key to our JUMPBOX2 using docker exec and bash command:
┌──(kali㉿kali)-[~]
└─$ docker exec -it JUMPBOX2 bash -c "echo '$(cat .ssh/id_rsa.pub)' >> /home/nemo/.ssh/authorized_keys"

Ssh into JUMPBOX2 (ip address you can found out with docker inspect)
┌──(kali㉿kali)-[~/DockerFiles/centos]
└─$ ssh [email protected] 1 ⚙
[nemo@784e2ed7582b ~]$

Create another two JUMPBOXes and move one with the rest of the chapter.
Preparing the whole infrastructure (without windows for now) should look like this:

┌──(kali㉿kali)-[~]
└─$ docker run -d -P -p 2200:22 --net plumbernet --ip 192.168.1.200 --name TARGET1 ready_centos_ssh:latest
7931295c3fcf2ddc21cbf374d301581bcf465432ea4de5086c83caecc1493b30

┌──(kali㉿kali)-[~]
└─$ docker run -d -P -p 2220:22 --net plumbernet --ip 192.168.1.220 --name JUMPBOX1 ready_centos_ssh:latest
4f627cb01f6b7c88a32e77152fdff0b8250ef46139e65814bd4d0a5dc7f97f5d

┌──(kali㉿kali)-[~]
└─$ docker run -d -P -p 2221:22 --net plumbernet --ip 192.168.1.221 --name JUMPBOX2 ready_centos_ssh:latest
9638750b56c4549c90af6be7a524f2fcc66f4f7ad5f440991f4330787e9aee28

┌──(kali㉿kali)-[~]
└─$ docker run -d -P -p 2222:22 --net plumbernet --ip 192.168.1.222 --name JUMPBOX3 ready_centos_ssh:latest
57d1ff913f3a9980497eed10cecf48e6d002fae266bc8a195c80956ee749dda0

┌──(kali㉿kali)-[~]
└─$ docker run -d -P -p 2223:22 --net plumbernet --ip 192.168.1.223 --name JUMPBOX4 ready_centos_ssh:latest
fd6f583492e156a5bc27da2099e99a54d4492e1ec9c5457c8516675fdc65488a`

Let’s check created and running containers:
┌──(kali㉿kali)-[~]
└─$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
fd6f583492e1 ready_centos_ssh:latest "/usr/sbin/sshd -D" 11 seconds ago Up 10 seconds 0.0.0.0:2223->22/tcp JUMPBOX4
57d1ff913f3a ready_centos_ssh:latest "/usr/sbin/sshd -D" 31 seconds ago Up 31 seconds 0.0.0.0:2222->22/tcp JUMPBOX3
9638750b56c4 ready_centos_ssh:latest "/usr/sbin/sshd -D" 43 seconds ago Up 42 seconds 0.0.0.0:2221->22/tcp JUMPBOX2
4f627cb01f6b ready_centos_ssh:latest "/usr/sbin/sshd -D" 59 seconds ago Up 59 seconds 0.0.0.0:2220->22/tcp JUMPBOX1
7931295c3fcf ready_centos_ssh:latest "/usr/sbin/sshd -D" About a minute ago Up About a minute 0.0.0.0:2200->22/tcp TARGET1
f3f18d566cc1 centos_ssh:latest "/usr/sbin/sshd -D" 27 hours ago Exited (0) 19 hours ago JUMPBOX1_old
5256f5bf1f93 centos_ssh:latest "/usr/sbin/sshd -D" 3 days ago Exited (0) 19 hours ago TARGET1_old

Copy public key to every container:
┌──(kali㉿kali)-[~]
└─$ docker exec -it TARGET1 bash -c "echo '$(cat .ssh/id_rsa.pub)' >> /home/nemo/.ssh/authorized_keys"

┌──(kali㉿kali)-[~]
└─$ docker exec -it JUMPBOX1 bash -c "echo '$(cat .ssh/id_rsa.pub)' >> /home/nemo/.ssh/authorized_keys"

┌──(kali㉿kali)-[~]
└─$ docker exec -it JUMPBOX2 bash -c "echo '$(cat .ssh/id_rsa.pub)' >> /home/nemo/.ssh/authorized_keys"

┌──(kali㉿kali)-[~]
└─$ docker exec -it JUMPBOX3 bash -c "echo '$(cat .ssh/id_rsa.pub)' >> /home/nemo/.ssh/authorized_keys"

┌──(kali㉿kali)-[~]
└─$ docker exec -it JUMPBOX4 bash -c "echo '$(cat .ssh/id_rsa.pub)' >> /home/nemo/.ssh/authorized_keys"

In the next step we follow from chapter 4 point 4.5.
While we have running JUMPBOX1…4 and TARGET1 we will shh into JUMPBOX1:
┌──(kali㉿kali)-[~]
└─$ ssh -p 22 [email protected] -L 127.0.0.1:1111:192.168.0.221:22 130 ⨯
[nemo@4f627cb01f6b ~]$

We can notice that we are in JUMPBOX1 as hostname is the same as container id of JUMPBOX1. Now we will open new terminal in Kali and jump into JUMPBOX2 through tunnel 1111:

┌──(kali㉿kali)-[~]
└─$ ssh -p 1111 [email protected] -L 127.0.0.1:2222:192.168.0.222:22
[nemo@9638750b56c4 ~]$

and next 2222, 3333 and 4444:
┌──(kali㉿kali)-[~]
└─$ ssh -p 2222 [email protected] -L 127.0.0.1:3333:192.168.0.223:22
[nemo@57d1ff913f3a ~]$

┌──(kali㉿kali)-[~]
└─$ ssh -p 3333 [email protected] -L 127.0.0.1:4444:192.168.0.200:22
[nemo@fd6f583492e1 ~]$

now we will open next new terminal and access TARGET1:
┌──(kali㉿kali)-[~]
└─$ ssh -p 4444 [email protected]
[nemo@7931295c3fcf ~]$

TARGET1 container id is 7931295c3fcf. We are in! You can open new terminal and look all ports open:
┌──(kali㉿kali)-[~]
└─$ netstat -nat

This is one way described in handbook, let’s do it with another one. We will take all port forwards into one string. We will gather all user@host:port from JUMPHOSTs and TARGET1 separated by comma:

┌──(kali㉿kali)-[~]
└─$ ssh -J [email protected]:22,[email protected]:22,[email protected]:22,[email protected]:22,[email protected].`200
usage: ssh [-46AaCfGgKkMNnqsTtVvXxYy] [-B bind_interface]
[-b bind_address] [-c cipher_spec] [-D [bind_address:]port]
[-E log_file] [-e escape_char] [-F configfile] [-I pkcs11]
[-i identity_file] [-J [user@]host[:port]] [-L address]
[-l login_name] [-m mac_spec] [-O ctl_cmd] [-o option] [-p port]
[-Q query_option] [-R address] [-S ctl_path] [-W host:port]
[-w local_tun[:remote_tun]] destination [command]

If we take example from handbook it should work but you have to remember that versions of ssh might differ on OS and versions itself. So I tried to execute one JUMPBOX and it was the same message about parameters of ssh. I tried without commas and it worked.
┌──(kali㉿kali)-[~]
└─$ ssh -J 192.168.0.220 192.168.0.221 192.168.0.222 192.168.0.223 192.168.0.200 255 ⨯
[email protected]'s password:

If we take the shortest example we will see that Kali user is not found, that’s correct as we need to use nemo user. Let’s take extended version without commas:

┌──(kali㉿kali)-[~]
└─$ ssh -J [email protected]:22 [email protected]:22 [email protected]:22 [email protected]:22 `[email protected]`
channel 0: open failed: administratively prohibited: open failed
stdio forwarding failed
kex_exchange_identification: Connection closed by remote host
Connection closed by UNKNOWN port 65535`

We get connection administratively prohibited. I managed to enable this connection changing ssh_config and went into another errors regarding user permission, requesting root user for creating tunnel. I think that this is blocked because port 22 is automatically selected and it’s lover that 1024 which requires root. 

Examples how to use Jumpbox in real situations can be found in last subjects of the chapter.

Making those tests I came up with scripts that will automate creations of our environment, they will be available on github.

 Those information might be very useful for learning  

 

Let’s get in touch.

m

And make it together.

Contact me
LinkedIn