Tag Archives: Tutoriales

Pfsense + UDM + VLANs: The perfect home network

A couple weeks ago I did a mayor reconfiguration on my home network, I migrated from a single flat insecure network in where any device was able to talk to any other to a more secure design in where the network is segmented (IoT devices, guests, home lab, etc) and where I control who has access to what resources via firewall rules and other tools.

My original home network consisted of a single Google Wifi router, if you are interested the device it’s limited but will get the job done. However I wanted to learn more about networking and in particular how to configure a couple of monitoring tools, network packet inspection, security, firewall rules, etc. So I started looking at networking appliances that will let me do more advanced configurations and I quickly found about Pfsense (Protectli Vault) so I got one.

Additionally, as a birthday gift from @perrohunter, I got The Dream Machine from Ubiquiti (usually you will use one or the other) so I had two routers now. 

I had to integrate them together but I faced a couple of issues during the process to the point where I got locked out from the network and I had to reset the devices multiple times, either the Pfsense or the UDM would work but not both of them at the same time but after some time it’s finally working so I decided to document the process in case it helps someone in the future.

Designing the network

The main goal was to have a clear separation between IoT devices, guest devices and my home devices so i came out with this design.

Disclaimer: I’m a security software engineer but I know a thing or two about networking, if you see something wrong or do you think this design can be improved in any way please let me know.

As you can see, I’m putting the Pfsense at the edge of the network so I have full control over the traffic. I’m using the UDM as an access point only because most of the routing and DNS resolution will be done by Pfsense. The home network consists of 3 VLANs.

IoT network VLAN 30

All my smart lights, roomba, smart locks, cameras will be here, these devices cannot communicate to the other networks or connect to the Internet. Only wireless devices will connect to this network.

Guests network VLAN 50

Occasionally I get visitors at my place, guests can connect to this network and enjoy access to the Internet however devices here will not be able to talk to devices on the IoT nor the LAN network. TODO: I want to put some rules in place so guests’ devices are fully isolated from each other. Only wireless devices will connect to this network.

LAN 

This is the main network and it’s a combination between wired and wireless devices, my work stations, laptops, mobile devices, home servers, smart tv, gaming consoles, etc. These are devices that I trust and most of them have static IPs and dns names.

Setup

I’m not going to explain in detail how to do the initial configuration for the Pfsense or the UDM, there are thousands of videos and tutorials that can guide you through that, instead I’ll focus on the parts I struggled the most and the “hacks” I applied to make this work.

Pfsense setup

These devices will usually come with two ports, WAN and LAN. I had to connect the Ethernet cable from the modem to the WAN port (also called an interface) and that will be enough for the device to talk to the internet in most cases. After that, during the initial configuration Pfsense asked me to configure the LAN interface, there I chose the network IP, IP range, etc In my case I selected 10.13.37.1/24 as my network IP range.

You can tweak and do some more advanced configurations under Services > DHCP Server > LAN

DHCP got configured automatically for this interface so I didn’t worry about it.

After that I grabbed another Ethernet cable and connected it into the Pfsense LAN port and the UDM WAN port.

The Dream Machine (UDM) setup

Here is where the issues begin, I connected the Ethernet cable to the UDM, the app guided my through the initial configuration, then I created the initial Wireless network and everything seemed to work fine however after looking at Status > DHCP Leases on my Pfsense I could not see any of my wireless devices, that was weird.

I logged in into the Dream Router management console and I could see my wireless network, the default network and the wan interface. I also could see all my connected devices, however the assigned IP addresses were in the 192.168.1.1/24 range not the 10.13.37.1/24. So I had some idea about what was happening, UDM had its own DHCP server and was assigning the IP addresses itself.

I start trying many different things, some of them were:

  • Disabling DHCP in the default network of the UDM didn’t work.
  • Changing the network range in the default network of the UDM to 10.13.37.1/24 didn’t work, UDM was complaining that the range conflicts with the IP assigned to it (10.13.37.2).
  • Created an additional network on the range I wanted 10.13.37.1/24 didn’t work, devices from here were not able to see the Pfsense.

I tried many more things and after a couple weekends of trial and error I found the winning combination of steps, this is probably the most important part of this article.

  • Disconnect the Ethernet cable from the UDM WAN port, this cause the UDM to lose the IP assigned by the Pfsense
  • Change the default network configuration in the UDM to use the 10.13.37.3/24 network, this network will overlap with the 10.13.37.1/24 network in Pfsense but it’s ok, also set DHCP Mode to none.
  • In the UDM go to Internet > default WAN and select manual configuration, here I’m setting the primary DNS server as 10.13.37.1 (Pfsense) and IPv4 configuration has to be as follow

Here I’m telling UDM the next hop will be at 10.13.37.1 (Pfsense), also I want the UDM to use the static IP 10.13.37.2, and the subnet mask will be 255.255.255.248 which ended being the “hack” that allow me to use the 10.13.37.x range on the default network

Finally plug the Ethernet cable again into the UDM but this time into any of the LAN ports not the WAN (the little world icon), avoid the WAN port seriously!.

The reason why I want the default network in the UDM to be an overlap of the 10.13.37.1/24 network in the Pfsense was because otherwise I would lose access to the UDM management console, I’m still trying to figure out why is that but my guess is even if the UDM is accessible from the Pfsense network on 10.13.37.2 IP address when I try to go to there (if the default network range is configured to be 192.168.1.1 on UDM) it won’t let me in because of some validation on UDM, to avoid this I ended creating a dedicated wireless network just to recover access (after getting locked out multiple times).

Using the above configuration my devices in the 10.13.37.1/24 range are able to talk to Pfsense (10.13.37.1) and also the UDM (10.13.37.3) and finally I’m able to see and control my devices from the Pfsense as well.

VLANs

Network interfaces

The main network is working fine now what? I started creating additional VLANs and firewall rules for the guests and the IoT networks. On the Pfsense I went to  Interfaces > Assignments > VLANs and added the two VLANs. It’s very important to select LAN as the parent interface because all the traffic is going to come from that port.

For no particular reason I chose tag 30 for the IoT VLAN and tag 50 for the guest VLAN, don’t forget to assign the new VLANs to the LAN interface and create the new networks.

To be consistent I decided the guests network range will be 10.13.50.1/24 and the IoT will follow 10.13.30.1/24

DHCP Server

Now it was time to configure the DHCP server for the new networks, I went to Services > DHCP Server and made sure the enable DHCP box was checked, additionally I configured the assignable IP range. I did this for both networks.

Firewall rules

According to my original design the guests and IoT network have to be isolated from everything else and in particular the IoT devices should not have any access to the Internet, let’s do that very quickly by configuring firewall rules on Pfsense (Firewall > Rules).

These are the rules applied to the IoT_VLAN, here I’m telling Pfsense to block any incoming connection from the IoT network to the home or guests network, I’m also blocking the access to the Pfsense management console itself on port 8443 and 3000. This firewall by default will block any egress traffic in the network and because I’m not saying otherwise this network will not have access to the Internet.

The guest firewall rules are pretty much the same with the exception that I will allow users to access the Internet (see the last rule).

The Dream Machine

At this point I was done with the Pfsense part but I was missing one last import piece, configuring the access method for the IoT and guests devices so for that I had to return to the UDM management console and create a couple of wireless and network configurations.

Guest Network

I created the new guest network configuration, most of the default values were ok but I had to pay special attention to the VLAN ID section, this one has to match to the one I configured on Pfsense (tag 50). Also is very important to set DHCP Mode to None

I created the Wifi network and told UDM to use the guest network, all packets will be marked (tag 50) and managed by the guest VLAN.

IoT Network

I repeated the previous steps but this time for the IoT network, I proceeded to create the network, added the right VLAN (tag 30) and disabled DHCP, then configured the wifi network as well.

Testing

Once everything is configured the way I wanted I tested by connecting a couple of devices to the IoT network and monitored the traffic with the help of ntopng (maybe I will write a blogpost about it in the future), there I confirmed there was not a single request to a remote address.

Conclusion

Designing a network is one of the most fun things you can do in IT. The main reason for me to get the Pfsense was because I wanted to learn more about networking and have hands-on experience with several networking and security tools. VLANs, Firewall rules, DHCP, DNS, packet inspection etc are good skills for a security engineer but these are only the tip of the iceberg for a network engineer.

Build your own private cloud at home with a Raspberry Pi + Minio

Early this year I got one of those widescreen 5k monitors so I could work from home, the display is so cool but the sad thing is it only comes with 2 USB ports. I have a wired mouse and keyboard so when I wanted to connect an external hard drive for copying and backing up files it was always a pain in the neck.

I remembered I have an old Raspberry PI2 I brought with me from México so last weekend I decided to work on a small personal project for solving this issue once and for all, I finished it and it’s working very well so I thought on writing a blogpost about it so more people can build its own private cloud at home too.

Install Raspbian

The first thing was to install a fresh version of raspbian into the raspberry pi, I got it from https://www.raspberrypi.org/downloads/raspbian/, I wanted something minimal so I got the Raspbian Buster Lite image, this version of raspbian doesn’t come with a graphical interface but it’s fine because ssh it’s all what we need.

Insert the SD card into your machine, I’m using a macbook pro so I have to use an adapter, once the card is there you can verify using the df command, tip: you can easily identify your SD card by the size reported by df -h.

[bash]
df -h

Filesystem Size Used Avail Capacity iused ifree %iused Mounted on
/dev/disk1s5 466Gi 10Gi 246Gi 5% 487549 4881965331 0% /
devfs 338Ki 338Ki 0Bi 100% 1170 0 100% /dev

..
/dev/disk2s1 <————- my SD card
[/bash]

Before copying the image first you need to unmount the device using sudo umount /dev/disk2s1 after that you can use the dd command.

[bash]
sudo dd bs=1m if=./2020-02-13-raspbian-buster-lite.img of=/dev/disk2s1
[/bash]

Optionally you can do all this process in a more friendly way by installing Raspberry Pi imager tool https://www.raspberrypi.org/downloads/, you need to insert your sd card, choose the os, choose the sd card and the click the write button.

Once you have your fresh version of Raspbian installed it’s time to verify the Raspberry is working, the easiest way to do that is to connect a monitor and keyboard to it, so I did it.

When you connect the raspberry to the power the green led should start flashing, if that doesn’t happen is probably a sign of a corrupted EEPROM and you should look at the Recovery section of https://www.raspberrypi.org/downloads/.

Access the Raspberry Pi remotely

Alright, if you get to this point means your raspberry is fine, next step is to connect it to your network, I connected mine to my switch using an ethernet cable, before ssh into the raspberry first we need to get its IP, there are multiple ways to get the IP address assigned to your raspberry, I used nmap https://nmap.org/ to quickly scan my local network for new devices.

[bash]
nmap -sP 192.168.86.0/24

Starting Nmap 7.80 ( https://nmap.org ) at 2020-03-29 19:55 PDT
Nmap scan report for testwifi.here (192.168.86.1)

..
Nmap scan report for raspberrypi (192.168.86.84)
Host is up (0.0082s latency).

..
Nmap done: 256 IP addresses (10 hosts up) scanned in 2.55 seconds
[/bash]

Ok from now on I’m going to start referring to the raspberry as nstorage (network storage), on my local machine I added a new entry to /etc/hosts with this information.

[bash]
# Minio running in raspberry pi in home network
192.168.86.84 nstorage
192.168.86.84 raspberry
[/bash]

I also added a new entry on ~/.ssh/config so it is easier to connect via ssh.

[bash]
Host nstorage
User pi
Hostname nstorage
Port 22
ServerAliveInterval 120
ServerAliveCountMax 30
[/bash]

You can type on your terminal ssh nstorage, and login using the default credentials: pi / raspberry.

[bash]
ssh nstorage

Linux raspberrypi 4.19.97-v7+ #1294 SMP Thu Jan 30 13:15:58 GMT 2020 armv7l

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Mon Mar 30 03:27:49 2020 from 192.168.86.64
[email protected]:~ $
[/bash]

First thing you should do is change the default password using the passwd command http://man7.org/linux/man-pages/man1/passwd.1.html.

One thing I always like to do is to add the public ssh key of my machine (my macbook pro) to the list of authorized_keys on the remote server (nstorage), you can do this by copying your public key: cat ~/.ssh/id_rsa.pub | pbcopy and then in nstorage in the /home/pi/.ssh/authorized_keys (create the file if it doesn’t exist) file append the key to the end.

[bash]
[email protected]:~/.ssh $ cat authorized_keys
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCvxqCsC2RWVfWfix/KT1R8eZ9zN5SXoZ8xV8eCsk47AZUkZKBdCLxp0arhS2/+WpjRAFuR4+XgmnWlu/rQYzWGaqv/sm5420zaF6fpOaeFXEuLGVP7Nb4e1oPR1tNbzZ7OLJs1FVZIk8rBeTfLh2+UMU8Lut+rKtd9FbW4LdTimscg8ufeFZ1bKWTPih4+o3kYEdSFpMz0ntKDqKA7g3Kvq6PbhUxcICA/KrJbjxTjuOelfqsfTz7xrJW/sII5QETTqL93ny7DlPdVdM2Qw6C/1NZ1hV7ZgpihFlD+XKhdqdugG9DgjzgKvdNx63idswCRJKmdxHZN+oM33+bASHMT [email protected]
[/bash]

That way next time you ssh into nstorage (the raspberry) the login process will be automatic.

Install Minio

You are on a fresh raspbian system, first thing you should do is update the existing software.

[bash]
sudo apt-get update
sudo apt-get upgrade
[/bash]

After that lets download the minio server and the minio client, we also create symbolic links for both binaries.

[bash]
wget https://dl.minio.io/server/minio/release/linux-arm/minio
wget https://dl.minio.io/client/mc/release/linux-arm/mc
sudo ln -s /home/pi/minio /usr/bin/minio
sudo ln -s /home/pi/mc /usr/bin/mc
[/bash]

At this point you can start a simple minio server with:

[bash]
[email protected]:~ $ mkdir ~/data
[email protected]:~ $ minio server ~/data
Endpoint: https://192.168.86.84:9000 https://127.0.0.1:9000
AccessKey: minioadmin
SecretKey: minioadmin

Browser Access:
https://192.168.86.84:9000 https://127.0.0.1:9000

Command-line Access: https://docs.min.io/docs/minio-client-quickstart-guide
$ mc config host add myminio https://192.168.86.84:9000 minioadmin minioadmin

Object API (Amazon S3 compatible):
Go: https://docs.min.io/docs/golang-client-quickstart-guide
Java: https://docs.min.io/docs/java-client-quickstart-guide
Python: https://docs.min.io/docs/python-client-quickstart-guide
JavaScript: https://docs.min.io/docs/javascript-client-quickstart-guide
.NET: https://docs.min.io/docs/dotnet-client-quickstart-guide

Detected default credentials ‘minioadmin:minioadmin’, please change the credentials immediately using ‘MINIO_ACCESS_KEY’ and ‘MINIO_SECRET_KEY’
[/bash]

In your local machine go to http://nstorage:9000/minio and you will see the following screen.

We are almost there, you have a minio server running in your raspberry pi, you can start uploading files and creating buckets if you want, but first let’s add some security.

Securing your Minio

Right now all the traffic between you and nstorage (your minio server) is unencrypted, let’s fix that quickly, I used mkcert https://github.com/FiloSottile/mkcert by Filippo Valsorda for quickly generate certificates signed by a custom certificate authority, sounds scary but is actually quite simple.

In the raspberry we are going to create the following folders to hold the certificates.

[bash]
mkdir ~/.minio/certs/CAs
mkdir ~/.mc/certs/CAs
[/bash]

In your local machine we generate and push the certificates to the raspberry, dont forget to also push the public key of your local certificate authority created by mkert under /Users/$USER/Library/Application Support/mkcert/rootCA.pem.

[bash]
$ mkcert nstorage
Using the local CA at "/Users/alevsk/Library/Application Support/mkcert" ✨

Created a new certificate valid for the following names 📜
– "nstorage"

The certificate is at "./nstorage.pem" and the key at "./nstorage-key.pem" ✅

$ ls nstorage*
nstorage-key.pem nstorage.pem
$ scp ./nstorage* [email protected]:~/.minio/certs
$ scp ./rootCA.pem [email protected]:~/.minio/certs/CAs
$ scp ./rootCA.pem [email protected]:~/.mc/certs/CAs
[/bash]

That’s it, you have now a secure connection with your Minio, if you go to your browser you can HTTPS this time.

Nstorage certificate is valid and trusted by your system because was generated by your local certificate authority, every device that wants to access this server need to trust the CA as well, otherwise it will get a trust error.

Mount external drive

Alright, so far you have a secure Minio running on the raspberry pi, in my case I used a 16GB SD card, which was not enough for storing all my data and the whole point was to access my external drive files remotely, so let’s do that now. But first instead of start Minio manually let’s create a bash script and change the default credentials.

Create a new file using vim or your editor of choice: vim start.sh

[bash]
#!/bin/bash

export MINIO_ACCESS_KEY=SuperSecretAccessKey
export MINIO_SECRET_KEY=SuperSecretSecretKey
export MINIO_DOMAIN=nstorage
export MINIO_DISK_USAGE_CRAWL=off

minio server ~/data
[/bash]

Save the above lines and then give execution permissions to the script: chmod +x start.sh
Now you can start your Minio running ./start.sh

[bash]
[email protected]:~ $ ./start.sh
Endpoint: https://192.168.86.84:9000 https://127.0.0.1:9000
AccessKey: SuperSecretAccessKey
SecretKey: SuperSecretSecretKey

Browser Access:
https://192.168.86.84:9000 https://127.0.0.1:9000

Command-line Access: https://docs.min.io/docs/minio-client-quickstart-guide
$ mc config host add myminio https://192.168.86.84:9000 SuperSecretAccessKey SuperSecretSecretKey

Object API (Amazon S3 compatible):
Go: https://docs.min.io/docs/golang-client-quickstart-guide
Java: https://docs.min.io/docs/java-client-quickstart-guide
Python: https://docs.min.io/docs/python-client-quickstart-guide
JavaScript: https://docs.min.io/docs/javascript-client-quickstart-guide
.NET: https://docs.min.io/docs/dotnet-client-quickstart-guide
[/bash]

Now connect your external hard drive to one of the USB ports, I had some issues while doing this, Raspbian was not listing the device under /dev so make sure to increase the USB ports power via configuration in /boot/config.txt, add max_usb_current=1 to the end of the file.

[bash]
[email protected]:~ $ cat /boot/config.txt
# For more options and information see
# http://rpf.io/configtxt
# Some settings may impact device functionality. See link above for details

..
# Increase power available to USB ports
max_usb_current=1
[/bash]

Reboot the raspberry and plug your drive again, if everything went right you should be able to see your external drive using fdisk.

[bash]
$ sudo fdisk -l
Disk /dev/sda: 4.6 TiB, 5000981077504 bytes, 9767541167 sectors
Disk model: Expansion Desk
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disklabel type: gpt
Disk identifier: 24A09C07-313E-43B6-A811-FAF09DAB962C

Device Start End Sectors Size Type
/dev/sda1 34 262177 262144 128M Microsoft reserved
/dev/sda2 264192 9767540735 9767276544 4.6T Microsoft basic data
[/bash]

You can mount the device using the mount command https://linux.die.net/man/8/mount.

[bash]
[email protected]:~ $ sudo mount -t ntfs /dev/sda2 /home/pi/data
[email protected]:~ $ ls -la data
total 9032
drwxrwxrwx 1 root root 8192 Mar 30 08:19 .
drwxr-xr-x 9 pi pi 4096 Mar 30 08:27 ..
drwxrwxrwx 1 root root 65536 Mar 26 22:53 anime
drwxrwxrwx 1 root root 20480 May 5 2019 anime_movies
drwxrwxrwx 1 root root 0 Jan 4 2019 backup
drwxrwxrwx 1 root root 4096 Jan 4 2019 books
drwxrwxrwx 1 root root 4096 Jan 4 2019 dev
drwxrwxrwx 1 root root 16384 Feb 12 2017 documents
drwxrwxrwx 1 root root 0 Feb 6 2017 download
drwxrwxrwx 1 root root 12288 Feb 12 2017 games
drwxrwxrwx 1 root root 4096 Jan 4 2019 images
drwxrwxrwx 1 root root 4096 Feb 10 2017 manga
drwxrwxrwx 1 root root 4096 Mar 29 07:48 .minio.sys
drwxrwxrwx 1 root root 65536 Mar 30 01:41 movies
drwxrwxrwx 1 root root 0 Jan 4 2019 music
drwxrwxrwx 1 root root 0 Feb 6 2017 pentest
drwxrwxrwx 1 root root 12288 Jun 2 2019 series
drwxrwxrwx 1 root root 4096 Jun 2 2019 software
drwxrwxrwx 1 root root 0 Jan 25 20:51 .Trashes
drwxrwxrwx 1 root root 0 Jun 21 2019 videos
[email protected]:~ $
[/bash]

Restart your minio server and this time when you go to the browser you will see all your files there.

You can list all the files and buckets using the minio client (mc) from your local machine or using the mc binary inside the nstorage raspberry.

[bash]
$ mc config host add nstorage https://nstorage:9000 SuperSecretAccessKey SuperSecretSecretKey
$ mc ls nstorage

[2020-03-26 15:53:09 PDT] 0B anime/
[2019-05-04 18:25:59 PDT] 0B anime_movies/
[2019-01-03 23:00:08 PST] 0B backup/
[2019-01-03 23:04:29 PST] 0B books/
[2019-01-03 23:48:04 PST] 0B dev/
[2017-02-11 17:09:28 PST] 0B documents/
[2017-02-05 16:45:21 PST] 0B download/
[2017-02-11 16:03:31 PST] 0B games/
[2019-01-03 23:06:48 PST] 0B images/
[2017-02-10 11:50:31 PST] 0B manga/
[2020-03-29 17:41:41 PDT] 0B movies/
[2019-01-03 22:48:15 PST] 0B music/
[2017-02-05 22:14:30 PST] 0B pentest/
[2019-06-02 14:33:34 PDT] 0B series/
[2019-06-01 21:29:46 PDT] 0B software/
[2019-06-20 20:20:56 PDT] 0B videos/
[/bash]

You can download every file you want, upload files and also stream media. Go to your Minio browser and select any video you like, click on the “3 dots” icon on the right and click the share icon.

Minio will generate a pre-signed URL that you can use on VLC, click on File > Open Network and paste the video URL.

Click the open button and enjoy your videos.

Everything is great so far, you are able to access all your files from any device in your network but if your raspberry loses power and reboot you will need to mount the external drive and start the Minio server manually again so let’s automate that.

Mount the external drive with fstab

On linux by default every drive listed in /etc/fstab will be mounted on startup, there are many ways to mount drives but the recommended way is using UUID or PARTUUID instead of the name.

[bash]
[email protected]:~ $ sudo blkid



/dev/sda2: LABEL="Arael" UUID="62F048D0F048AC5B" TYPE="ntfs" PTTYPE="atari" PARTLABEL="Basic data partition" PARTUUID="5206da84-ded1-43b6-abf2-14b5950c4d7c"
[/bash]

Locate the PARTUUID of your own drive, mine was 5206da84-ded1-43b6-abf2-14b5950c4d7c, and then add it at the end of your /etc/fstab file.

[bash]
$ cat /etc/fstab

proc /proc proc defaults 0 0
PARTUUID=738a4d67-01 /boot vfat defaults 0 2
PARTUUID=738a4d67-02 / ext4 defaults,noatime 0 1
# a swapfile is not a swap partition, no line here
# use dphys-swapfile swap[on|off] for that
PARTUUID=5206da84-ded1-43b6-abf2-14b5950c4d7c /home/pi/data ntfs defaults,errors=remount-ro 0 1
[/bash]

Reboot your raspberry and verify your drive was mounted automatically under /home/pi/data.

Start the Minio server with systemctl

Finally, the last piece of the puzzle is to make minio to start automatically, again, there’s many ways to do this but in this tutorial we will do it with init system or systemctl, let’s create a file called minio.service with the following content.

[bash]
[Unit]

Description=Minio Storage Service

After=network-online.target home-pi-data.mount

[Service]

ExecStart=/home/pi/start.sh

WorkingDirectory=/home/pi

StandardOutput=inherit

StandardError=inherit

Restart=always

User=pi

[Install]

WantedBy=multi-user.target
[/bash]

ExecStart points to the start.sh bash script, After directive will tell the Minio server to wait until the network service is online and the /dev/sda2 drive is mounted by fstab, home-pi-data.mount is a systemd mount unit you can get using the systemctl list-units command.

[bash]
$ systemctl list-units | grep ‘/home/pi/data’ | awk ‘{ print $1 }’
home-pi-data.mount
[/bash]

Copy the file to the /etc/systemd/system directory.

[bash]
cp ./minio.service /etc/systemd/system/minio.service
[/bash]

Start minio as a systemd service using the start command and verify is running with the status command.

[bash]
[email protected]:~ $ sudo systemctl start minio
[email protected]:~ $ sudo systemctl status minio
● minio.service – Minio Storage Service
Loaded: loaded (/etc/systemd/system/minio.service; enabled; vendor preset: enabled)
Active: active (running) since Mon 2020-03-30 10:12:22 BST; 4s ago
Main PID: 1453 (start.sh)
Tasks: 16 (limit: 2200)
Memory: 156.2M
CGroup: /system.slice/minio.service
├─1453 /bin/bash /home/pi/start.sh
└─1456 minio server /home/pi/data

Mar 30 10:12:22 raspberrypi systemd[1]: Started Minio Storage Service.
[/bash]

If everything looks fine, enable the service, Minio will start automatically every time your Raspberry pi boot.

[bash]
sudo systemctl enable minio
[/bash]

Reboot your raspberry pi one last time and verify everything is working as expected, if you are able to see the minio browser at https://nstorage:9000/minio without you having to do anything congratulations you now have your own private cloud at home powered by Minio :).

Happy hacking.

CTF OverTheWire: Natas9

Continuing with the CTF Natas series, now is the turn for natas9

[bash]
Natas Level 8 → Level 9
Username: natas9
URL: http://natas9.natas.labs.overthewire.org
[/bash]

Using the flag obtained in the previous challenge, we go to the URL showed in the description and we will see the following screen.

It’s just a simple web page with a basic input form, if we type nonsense nothing happens, we proceed to click the View sourcecode and we are redirected to index-source.html

This is supposed to be the backend code of the html form.

[php]
<?
$key = "";

if(array_key_exists("needle", $_REQUEST)) {
$key = $_REQUEST["needle"];
}

if($key != "") {
passthru("grep -i $key dictionary.txt");
}
?>
[/php]

The vulnerability in this code happens when calling the passthru function, we are reading user input directly from the needle request parameter, then saving it into the $key variable and using it without any kind of sanitization when calling the function, that’s essentially command injection. We are going to try to execute commands in the web server by exploiting this vulnerability.

Sending ;ls -la;

Results in all files on the current directory to be listed

I was a little bit lost at this point but then I remember the CTF instructions.

Each level has access to the password of the next level. Your job is to somehow obtain that next password and level up. All passwords are also stored in /etc/natas_webpass/. E.g. the password for natas5 is stored in the file /etc/natas_webpass/natas5 and only readable by natas4 and natas5.

So we do ;cat /etc/natas_webpass/natas10;

The flag for the next level, natas10, is: nOpp1igQAkUzaI1GUUjzn1bFVj7xCNzu

As mentioned before, this challenge we exploit a command injection vulnerability that essentially allow us to execute arbitrary commands on the server, depending on the privileges of the user running the web server we might read, write or delete files.

Happy hacking 🙂

CTF OverTheWire: Natas8

After a break we continue with the CTF Natas series, now is the turn for natas8

[bash]
Natas Level 7 → Level 8
Username: natas8
URL: http://natas8.natas.labs.overthewire.org
[/bash]

Using the flag obtained in the previous challenge, we go to the URL showed in the description and we will see the following screen.

It’s just a simple web page with a basic input form, if we type nonsense we get an error message displaying Wrong secret, we proceed to click the the View sourcecode

[php]
<html>
<head>
<!– This stuff in the header has nothing to do with the level –>
<link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css">
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/jquery-ui.css" />
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/wechall.css" />
<script src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"></script>
<script src="http://natas.labs.overthewire.org/js/jquery-ui.js"></script>
<script src=http://natas.labs.overthewire.org/js/wechall-data.js></script><script src="http://natas.labs.overthewire.org/js/wechall.js"></script>
<script>var wechallinfo = { "level": "natas8", "pass": "<censored>" };</script></head>
<body>
<h1>natas8</h1>
<div id="content">

<?

$encodedSecret = "3d3d516343746d4d6d6c315669563362";

function encodeSecret($secret) {
return bin2hex(strrev(base64_encode($secret)));
}

if(array_key_exists("submit", $_POST)) {
if(encodeSecret($_POST[‘secret’]) == $encodedSecret) {
print "Access granted. The password for natas9 is <censored>";
} else {
print "Wrong secret";
}
}
?>

<form method=post>
Input secret: <input name=secret><br>
<input type=submit name=submit>
</form>

<div id="viewsource"><a href="index-source.html">View sourcecode</a></div>
</div>
</body>
</html>
[/php]

This is supposed to be the backend code of the HTML page we just saw, the important part of this challenge is in the PHP code functions, taking a quick look the data flow looks like this:

  • Check if submit key exists on $_POST
  • Pass $_POST[‘secret’] to encodeSecret function
  • encodeSecret function will apply some transformation to the secret and return it
  • The transformed secret must be equal to 3d3d516343746d4d6d6c315669563362, otherwise we are getting the Wrong secret error we saw already

As I say before, the important part is happening inside the encodeSecret function, the code is basically doing this:

secret -> base64_encode -> strrev -> bin2hex -> 3d3d516343746d4d6d6c315669563362

So we need to perform exactly the same operations but in reverse order to obtain the original secret, ie: the old bin2hex should be hex2bin, I don’t know if we should call this reverse engineering, anyway ¯\_(ツ)_/¯

3d3d516343746d4d6d6c315669563362 -> hex2bin -> strrev -> base64_encode -> secret

We can use PHP from the command line and do this:

[bash]
$ php -r "echo base64_decode(strrev(hex2bin(‘3d3d516343746d4d6d6c315669563362’)));"
oubWYf2kBq
$
[/bash]

We get the secret: oubWYf2kBq, we try it on the input form.

The flag for the next level, natas9, is: W0mMhUcRRnG8dcghE4qvk3JA9lGt8nDl

In this challenge we take advantage of a security vulnerability called Source code disclosure and then we did basic reverse engineering on the PHP code.

Happy hacking 🙂

CTF OverTheWire: Natas6

Continuamos con la serie de tutoriales del CTF Natas, ahora toca el turno de natas6.

[bash]
Natas Level 5 → Level 6
Username: natas6
URL: http://natas6.natas.labs.overthewire.org
[/bash]

Utilizamos la bandera obtenida en el reto anterior y accedemos a la URL indicada en las instrucciones del reto, veremos una pantalla como la siguiente.

Es solo un formulario donde nos piden ingresar una contraseña o secreto, al introducir cualquier cosa obtenemos un mensaje de error.

En la misma pagina hay un enlace que dice view sourcecode (ver código fuente), damos clic y veremos lo siguiente.

La parte importa es:

[php]
<?

include "includes/secret.inc";

if(array_key_exists("submit", $_POST)) {
if($secret == $_POST[‘secret’]) {
print "Access granted. The password for natas7 is <censored>";
} else {
print "Wrong secret";
}
}
?>
[/php]

Es un código php muy sencillo, podemos ver que obtiene un parámetro via POST (el que enviamos mediante el formulario) y lo compara con la variable $secret, ademas hace include de un archivo interesante includes/secret.inc

Accedemos a ese archivo usando el navegador.

Y utilizamos el secret que acabamos de descubrir en el formulario inicial.

La bandera para acceder a natas7 es 7z3hEENjQtflzgnT29q7wAvMNfZdh0i9

En este reto aprovechamos un fallo de seguridad llamado Source code disclosure, en donde tenemos acceso a código que solo debería ser consumido del lado del servidor.

Happy hacking 🙂