In this post I’m going to be covering the process to scan a network behind a Firewall or NAT using Networking Pivoting via SSH without being limited to proxychains, specific ports and protocols. Essentially this will use SSH tunneling, virtual tap adapters, some routing and masquarding in IPtables. The beauty of this method is the prerequisites are very low, for the most part no additional packages or standalone tools are required, we can use what is shipped with most Linux builds.
There are many use cases for this, scanning an internal network without being on prem, cloud environments, various pentesting scenarios, which can often be the stumbling point once a shell has been landed. Traditionally this type of task would have been done with the use of proxy chains, through some form of shell access via a netcat listener, Metasploit or SSH dynamic port forward, which I have previous walked through here. However this is an extremely slow method and rely’s on being able to tunnel through a single port with proxy chains, I have never had any luck scanning with more complex tools like Nessus in this way. Full SYN scans (-sT) with nmap great, Nessus not so much.
Lets take the following scenario and set the pivot up:
We can use tunctl or ip tuntap, the difference being that ip tuntap is part of the iptools suite and therefore general supported on most Linux operating systems. Tunctl can usually be downloaded from your repo of choice ie with Ubuntu its part of the apt repository. In this example we will be working with Kali as the scanning system and a Ubuntu server as the pivot point, which has SSH accessible. (It is worth mentioning at this point it doesn’t matter which end the SSH connection is initiated from).
First we need to create a virtual tunnel and therefore need to create two virtual interfaces at both ends of the tunnel. For this we are going to use a tap interface. For reference a tap interface operates at layer 2 and a tun interface operates at layer 3.
Using tunctl: First we will need to install tunctl with apt install uml-utilities
# apt install uml-utilities
Create the virtual tap interface with the following command:
# tunctl -t tap0
Using ip tuntap: First verify your ip tools version installed supports tuntap, type ‘ip’ you will see if the command is available:
Create the virtual tap interface with the following command:
# ip tuntap add dev tap0 mod tap
Once this is setup assign it an ip address and raise the interface, assign a different address for each end of the tunnel:
So on the scanner:
# ip a a 10.100.100.100/24 dev tap0 && ip link set tap0 up
On the pivot server:
# ip a a 10.100.100.101/24 dev tap0 && ip link set tap0 up
On each end of the tunnel we will also need to make sure our SSH config will allow us to tunnel. Lets modify our /etc/ssh/sshd_config file by adding ‘ PermitTunnel=yes ‘ to the end and restart the service. More about this option can be found in SSH man page here.
Now for the magic, lets bring the tunnel up by establishing an SSH session, this will need to be done with a privileged account:
ssh -o Tunnel=ethernet -w 0:0 email@example.com
Lets cover off these options:
-o = allows us to specify options
Tunnel=ethernet = is our option for the tunnel
-w 0:0 = specifies the next available interface for the tunnel, and corresponds to each side of the tunnel.
Next lets take a moment to verify our tunnel is up with a couple of quick checks:
First verify the link is up with ethtool:
# ethtool tap0
You will notice the link is up, try this without the connection you will find the link is down.
Second verify you can ping the other end of the tunnel:
# ping 10.100.100.101
Again disconnect your SSH connection and watch icmp response drop.
Next in order to get our traffic to our destination servers/subnet we are going to need some routes adding to Kali to tell the system where to send the traffic, ie the other end of the tunnel, so, something similar to this where 192.168.1.0/24 being the network you are targeting:
# ip route add 192.168.1.0/24 via 10.100.100.101
# ip route add 192.168.2.0/24 via 10.100.100.101
Finally we need to setup some iptables rules and turn our pivot point into a router by enabling IPv4 forwarding:
# echo 1 > /proc/sys/net/ipv4/ip_forward
# iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
# iptables -t nat -A POSTROUTING -o tap0 -j MASQUERADE
# iptables -A INPUT -i eth0 -m state –state RELATED,ESTABLISHED -j ACCEPT
# iptables -A INPUT -i tap0 -m state –state RELATED,ESTABLISHED -j ACCEPT
# iptables -A FORWARD -j ACCEPT
At this point the pivot should be up and running, test this by doing some basic checks with a known host on your target network.
I thought I would share a couple of useful shortcuts I came across recently in searchsploit, the command line search tool for Exploit-DB . This might help someone out as well as a useful reminder to myself. For a long time now when using searchsploit in Kali Linux I have always searched for what I wanted then either manually copied the path to the script to my working directory. Likewise to review the script or text file I would type the path out with either less, more or cat etc. Until now.
I recently came across the shortcuts ‘-m’ for mirror and ‘-x’ for examine. ‘-m’ for mirror will copy that exploit to your current working directory like so:
‘-x’ will allow you to examine the text like this:
In this post I am going to highlight the risks of using self signed certificates with Remote Desktop Protocol (RDP). Why its a problem and what we can do to fix it! Hopeful by demonstrating the impact it will raise awareness of how serious an issue this can actually be.
On an internal network the issue stems from you connect to a computer or server that is using a self signed certificate through remote desktop your not able to verify the endpoint for its authenticity. ie it is who it says it is.
Unfortunately we are all too familiar with the classic rdp certificate warning prompt like this and most of the time blindly click on yes I accept. Often with out actually reading what the message is saying.
Ok, lets see what all the fuss is about then. Lets consider the following devices in our LAB
DC16: 192.168.1.10 – Windows Server 2016 Domain Controller
WEB16: 188.8.131.52 – Windows Server 2016 Web Server
W10 192.168.1.51 – Windows 10 Client
Kali 192.168.1.50 – Kali Linux our attacker.
The attacker can essentially sit on the same network and cause a Man In The Middle (MiTM) condition between the windows 10 client and Web Server when using self-signed certificate. If we expand on the scenario slightly. Imagine we have an admin logged in to our windows 10 client, he/she wants to investigate an issue on the web server, so goes to establish a remote desktop session to the server. Lets consider what can happen.
On our attacking machine we are going to start Seth:
Mean while our admin is going about his daily tasks on our windows 10 client, he/she then decides to connect to our web server via RDP:
The usual connection sequence takes place, the admin receives the usual all too familiar warning box and continues to establish the connection. In the meanwhile over on our attacking box the connection has been intercepted and the MiTM attack carried out successfully. Seth intercepts the connection and has captured the NTLMv2 hash as well as the clear text credentials. Oh dear.
As you can see this not an optimal configuration, and one which we would very much like to avoid. It can be avoided by using a signed certificate from your internal CA or other trusted certificate authority. Getting certificates installed on your devices isn’t all that too difficult to go through, I actually discuss this further here and linked to how to. In addition to this we can also stop our clients from connecting to anything we don’t trust via GPO. Remember we need to be connecting to our servers via name not IP. As the IP address is not what is on the certificate in the common name field and will therefore be untrusted.
Well I hope this has helped demonstrate the impact of self-signed certificates and why they should be addressed on the inside.
I thought I would walk through the process of generating a certificate for a non-domain joined device using an internal Active Directory Certificate Authority (AD CS). In this example, it is going to be for our web GUI for a pfsense firewall. I’v talked before about the challenges of self signed certificates in this post, so thought this would be useful to further demonstrate how this can be done for other devices that are not joined to a domain. Like most things if you have never experienced setting something like this up, you won’t necessarily know how to go about doing it. This post aims to fill that gap. Hopefully you will see this isn’t as difficult as it sounds.
For our lab we have AD CS setup and pfsense on the same network, its actually acting as the gateway for the network. Its a key piece of equipment on the network that we want technical security assurance around. Including being able to validate that when we connect to the device for management it is who we think it is, and importantly who its saying it is. And that we are not in a position to let ourselves be caught by a man in the middle attack!
Lets start on the pfsense web configurator page:
As we can see this is using a self signed certificate and is therefore untrusted. So we want a certificate on our firewall that is signed by a trusted certificate authority, one that is ideally already in our root certificate store. If you have an internal AD CS, the root CA certificate will most likely be already there.
Typically with a network device such as this we somehow want to first generate a Certificate Signing Request (CSR) to then take to our CA to be signed. You can usually achieve this via a shell session to the device or through the web GUI in most cases. Whilst the steps i’m going through with pfsense are specific to this device, the concept is the same for all devices. With pfsense we are able to do this here:
We can see in the above screen shot the self-signed certificate that comes with the device. To start the process we click on the green button at the bottom Add/Sign. As you can see below the method we want to use is ‘Create a Certificate Signing Request’.
Continue down the page adding all the relevant info. Three key areas to take note are the ‘Common Name’, ‘Alternative Names’ and selecting Server Certificate for the certificate type. These are important as you this is how we will identify the authenticity of the device. The ‘Comman Name’ is effectively its short name, and the ‘Alternative Names’ we will want to add as the Fully-Qualified-Domain-Name (FQDN). In this case I’m naming the firewall FW1, Jango.com is the domain name 🙂 .
Once at the end of the page select save and you should see our certificate request in a pending state, the screen should look like this:
Next export the CSR, download it to your local machine and open it in notepad. Highlight the text and copy it to your clipboard for later. The file should look like this:
Next we are going to find our way to the AD CS certificate enrollment web page. This is commonly the CA name followed by ‘certsrv/default.asp’ so in my lab the CA is held on the DC, so will be http://DC16/certsrv/default.asp, just like below:
Next we select ‘Request a certificate’:
Here we don’t have many options as this is a fairly default install of the certificate services however select ‘Advanced Certificate Request. On the next screen as below, paste in the CSR in the request window, and select the default ‘Web Server’ template from the ‘Certificate Template’ drop down menu and click submit:
Next we have the opportunity to download the signed certificate in various formats.
In this instance we are going to download the certificate in Base 64 encoded format . Open up the certificate file in notepad, highlight the contents and save it to the clipboard, it should look like this:
Next we go back to the pfsense web GUI, and complete the certificate signing request from the certificate page. This is under ‘System’ –> Certificate Manager’ –> ‘Certificates’. We do this by selecting the update CSR button, paste in the contents of the certificate into the ‘Final Certificate data’ like below and select ‘update’:
The certificate will be loaded and will look like this:
As we can see from the above screenshot our subject Alternate Names are listed as FW1 and FW1.jango.com, meaning when we access the page with these names the connection will be validated correctly. As opposed to accessing it via IP address and it will warn us that the browser has not been able to validate the endpoint and is therefore insecure.
Next change how the certificate is used. Essentially we are binding it to port 443, the web GUI itself, we do this in System –> Advanced –> Admin Access, select the descriptive name we gave it earlier and select ‘Save’ at the bottom of the page:
Next reload the web GUI page using your common name or subject alternate name. At this point bear in mind you mostly likely will need a manual DNS entry for FW1. So head over to the DNS console and quickly create one. Once you have done that reload the pfsense web GUI, and hey presto!
Now we have a certificate signed by our internal AD CA and can verify what we are connecting to is actually correct.
I hope this has helped demystify the process of obtaining an internally signed certificate from our AD CA for our weird and wonderful network devices that we have on the network.
Just a quick post on the LocalAccountTokenFilterPolicy setting. What it is why we have it. As a pentester and administering windows systems I’m bumping into this all the time. The classic scenario being your trying to access the C$ of machine with a local account, and being blocked. You check all the usuals; firewall, creds etc and are banging your head against a brick wall. Its more than likely to be the Remote User Account Control (UAC) LocalAccountTokenFilterPolicy setting in Windows that is stopping you. Depending on what type of account you are connecting with ie Domain or Local depends on whether the UAC access token filtering will take affect, it will not affect domain accounts in the local Administrators group, only Local accounts. Even if the Local account is in the Administrators group, UAC filtering means that the action being taken will run as a standard user until elevated. Think of when you launch CMD or PowerShell logged in as an Admin account, its run in the context of standard user until you elevate, or re launch as an Admin. So when we try to connect to the C$ with a Local account that is in the Administrator group we are blocked by UAC. Disabling LocalAccountTokenFilterPolicy will allow us to connect.
When the Remote User Account Control (UAC) LocalAccountTokenFilterPolicy value is set to 0, Remote UAC access token filtering is enabled. When it is set to 1, remote UAC is disabled. We can set this with the following one liner:
The same scenario can be said for running a credentialed or authenticated Nessus scan with a local account that is part of the Administrators group. For Nessus to enumerate the system it will connect to the C$. It will fail unless the LocalAccountTokenFilterPolicy is set to 1. There are other pre-requisites, these are out of scope of this post however.
Problems with VirtualBox Guest Additions in Kali. This post serves more of a reminder to myself however this might also serve as help to others. Troubleshooting problems/issues with VirtualBox Guest Additions. I think its safe to say I use VirtualBox a lot, I will be lucky if a day goes by where I’m not in VirtualBox using a VM. I also therefore use and rely on Guest Additions working correctly features such as, mapped drives back to the host, USB, display options are all useful to name a few. It can be frustrating sometimes when Guest Additions breaks, either a mapped network drive disappears or your display has shrunk. Once all the usual checks have been done to troubleshoot I normally move on to VirtualBox Guest Additions. I also use Kali, where its also fair to say I have the most issues, now this might be because I probably use it the most in terms of a VirtualBox VM or that Kali 2.0 is rolling and thus based on Debian Testing. As such we have a multitude of updates happening constantly both to packages and underlying operating system. The following is my usual check list and 99% of the time sorts out the issue for Kali 2:
Update VirtualBox to the latest version.
Then update VirtualBox Guest Additions to also the latest edition.
In this post we look at how we can automate our security updates and packages that can be updated for a Ubuntu Server 18.04.1 LTS including scheduled reboots. Automatic Updates in Ubuntu Server are a real win.
This is a fairly straight forward affair, we will be working in the unattended-upgrades package, this can used to automatically install updates to the system. We have granular control, being able to configure updates to all packages or just security updates, blacklisting packages, notifications and auto reboot. A very useful set of features.
Lets look at the main configuration file /etc/apt/apt.conf.d/50unattended-upgrades.
A couple of key lines in this file will want our attention. Firstly this will depending on what type of updates you want to automate. If you know the software that runs on the server well enough, and depending on the criticality of the service it provides you have the following options for the type of updates to automate, uncommenting ‘//’ the various lines will give you those type of updates:
This next section of the file dictates what packages should not be upgraded, ie if you have a certain set of dependencies and don’t want to the software to upgrade due to comparability issues list them here:
// List of packages to not update (regexp are supported)
To get notifications for any problems or package upgrades add your email address to the below section:
// Send email to this address for problems or packages upgrades
// If empty or unset then no email is sent, make sure that you
// have a working mail setup on your system. A package that provides
// 'mailx' must be installed. E.g. "firstname.lastname@example.org"
The next two sections dictate when the server should be rebooted and without confirmation. Here we have the Unattended-Upgrade::Automatic-Reboot option set to ‘true‘, and unattended-Upgrade::Automatic-Reboot-Time set to ‘02:00‘ am.
// Automatically reboot *WITHOUT CONFIRMATION*
// if the file /var/run/reboot-required is found after the upgrade
// If automatic reboot is enabled and needed, reboot at the specific
// time instead of immediately
// Default: "now"
To then enable the automatic updates edit the file /etc/apt/apt.conf.d/20auto-upgrades. Create the file if it doesn’t exist, add the below text, the frequency of the update procedure is dictated by the number in quotes next to each item. For example everything with a 1 in it will happen everyday and the 7 represents once a week.
A couple of useful log files to keep an eye on are: /var/log/unattended-upgrades/unattended-upgrades.log. This will give you information about the updates and whether a reboot is required. /var/log/unattended-upgrades/unattended-upgrades-shutdown.log and also issuing the command last reboot will also give you information about any restarts that are required or have happened.
I hope this been helpful and keeps you current with your patching!
Setting a static IP address in Ubuntu 18.04.1. Oh boy where to start. The name Bionic Beaver or netplan.
OK lets concentrate on netplan, and what’s happened with networking in Ubuntu 18.04.1. Setting a persistent static IP address has changed a little in the new release of Ubuntu, where as before we would have modified the interfaces file we now modify a .yaml file in /etc/netplan directory. Netplan is the new kid on the block for configuring networking in your Beaver. Its not all that different, or difficult once you know how. However the standard is pretty precise in terms of how we configure the file. If you look in your netplan directory you may have a 50-cloud-init.yaml file this is where the configuration is stored. Lets go ahead and modify the netplan directory to set a static IP address:
This is how our standard /etc/netplan/50-cloud-init.yaml file looks like:
To set a static IP address I’m going to copy the current config into a new file called 01-netcfg.yaml for further configuration.
Take care of the spacing within the yaml file. It will not take tab completion, and will require spaces for the indentation, the number of spaces will not matter, as long as each section is appropriately indented with spaces.
For example you could use this:
Indenting each section with 1 space also works:
All that’s left to do is to apply the netplan config with:
sudo netplan apply
If you do get errors you can use the debug feature:
I posted recently about implementing Linux password complexity here and wanted to follow it up by posting about account lockout policy. Linux account lockout policy is often overlooked, this post will show you how to implement simple controls to keep you in check. Brute force attacks are trivial to perform, not having a lockout policy (and password policy) could end you up in hot bother. With a lockout time configured this will at least slow down your adversaries and very least annoy the hell out of them. I would always suggest you use a public/private key pair for SSH access and disable password authentication specifically for this service.
Linux account lockout policy is controlled by Pluggable Authentication Modules (PAM) more specifically pam_tally and pam_tally2. These modules can be configured in Debain/Ubuntu in the /etc/pam.d/common-auth, and in RedHat and Centos based distros /etc/pam.d/system-auth. Pam_tally as the name might suggest is a count for logins (ie tallying up logins). The module has various options to configure, it will maintains a count of attempted logins, can reset counts, and deny access based on too many incorrect attempts, set lockout time etc.
Lets look at an example of how we might configure this within Ubuntu 18.04.1.
If we check what PAM modules are installed ‘man -k pam_’ we see that pam_tally and pam_tally2 are already installed.
I have added the highlighted line into the /etc/pam.d/common-auth file:
According to the Ubuntu man pages here normally failed attempts to access the root account will not cause the root account to become blocked, to prevent denial of service, this can be overriden with an optional argument which we will discuss later.
Our settings are:
onerror=fail : Upon an error issue a fail. deny=5 : Deny access if the count for this user exceeds 5 attempts. unlock_time=1200 : This will lock the user out for 1200 seconds (20 mins) if the max allowed attempts is exceeded. audit : This will log the user name into the sys log if the user is not found. even_deny_root : Careful with this one, this will lock the root account out. root_unlock_time=1200 : This will lock the root account out for 1200 seconds (20 mins) if the max allowed attempts is exceeded.
These changes are instant, no need to reboot or restart any service.
All that’s left to do now is to test our configuration on our test server. In the /var/log/auth.d file we can see pam_tally2 is racking up the login attempts and is denying access.