Saturday, September 7, 2019

Fine, I'll enable IPv6

This is a follow up to my previous post on preparing my Ubuntu 19 system for travel. I've had to re-enable IPv6 on my Ubuntu laptop for a couple reasons which I'll discuss below. This wouldn't normally be post-worthy, except to help anyone else seeing the same errors due to disabling IPv6.

GPSd wants it

I've needed to run GPSd recently to work with a USB GPS device. Apparently GPSd really wants to bind to an IPv6 address. There's probably a way to make it not want this, but since I have other reasons to use IPv6 anyway, I'll just go ahead and enable it.

Just in case someone else comes across this error, here are the log messages that tipped me off:
gpsd.socket: Failed to listen on sockets: Cannot assign requested address
and
gpsd:ERROR: can't bind to IPv6 port gpsd, Cannot assign requested address

6LoWPAN

The 6 in 6LoWPAN means IPv6. There are some 6LoWPAN challenges at the Wireless CTF, and I'll need to be able to speak IPv6 to complete them (at least the challenges that require TX).

FYI: the device I'm using for 6LoWPAN is the openlabs 802.15.4 radio for the Raspberry Pi.

Do The Thing

Anyway, if you've disabled IPv6 via sysctl.conf, make sure the following lines are commented:
#net.ipv6.conf.all.disable_ipv6=1
#net.ipv6.conf.default.disable_ipv6=1
#net.ipv6.conf.lo.disable_ipv6=1

Sunday, July 28, 2019

Preparing Ubuntu 19 for travel

These are the steps I take to prepare my Ubuntu system for travel. It's far from a complete list, but I think these preparations will help reduce risks before using your system away from home.

I'm assuming you've already done the basic cyber hygiene stuff like FDE, strong passwords, lock-screen, etc.

1. Disable Avahi

Avahi is an MDNS service. Here's a description from avahi.org:
Avahi is a system which facilitates service discovery on a local network via the mDNS/DNS-SD protocol suite. This enables you to plug your laptop or computer into a network and instantly be able to view other people who you can chat with, find printers to print to or find files being shared.
Yeah, no thanks.  Let's disable that.
sudo systemctl disable avahi-daemon.service
sudo systemctl disable avahi-daemon.socket

2. Disable CUPS

I don't print from this computer so I don't need CUPS. CUPS runs a listening socket that I don't need and it also tries to start Avahi, so it's an unnecessary risk; Let's disable it.

sudo systemctl disable cups.service
sudo systemctl disable cups-browsed.service

3. Disable the NetworkManager connectivity check

By default, NetworkManager is configured to check for captive portals by periodically making HTTP GET requests. In Wireshark you'll a DNS query for connectivity-check.ubuntu.com, followed by an HTTP GET to http://connectivity-check.ubuntu.com/. This is a dead giveaway to anyone monitoring your traffic that your system runs Ubuntu and and NetworkManager.


This can be disabled by adding the text below to /var/lib/NetworkManager/NetworkManager-intern.conf
[connectivity] 
.set.enabled=false

4. Disable IPv6

I have no use for IPv6 on this machine, and since the addresses are ridiculous their presence makes traffic monitoring more difficult. I think the normal way to disable this is in the kernel via sysctl or sysctl.conf.

net.ipv6.conf.all.disable_ipv6=1
net.ipv6.conf.default.disable_ipv6=1
net.ipv6.conf.lo.disable_ipv6=1

Interestingly, these are already present at the bottom of my /etc/sysctl.conf, but my network interfaces still get IPv6 addresses. Why? If I check the values using sysctl, I can see that it's set for all, default, and lo, but not for my actual interfaces.

ted@a17:~$ sysctl net.ipv6.conf.all.disable_ipv6
net.ipv6.conf.all.disable_ipv6 = 1

ted@a17:~$ sysctl net.ipv6.conf.wlp69s0.disable_ipv6
net.ipv6.conf.wlp69s0.disable_ipv6 = 0

The suggestion in this bug report to add a line to /etc/rc.local didn't work for me at first, but then I found a more complete solution here. Add the following to /etc/rc.local to disable IPv6 at boot time (and make sure the file is executable).

#!/bin/bash
# /etc/rc.local

/etc/sysctl.d
/etc/init.d/procps restart

exit 0

5. Disable geoclue

This service attempts to geo-locate the host system and shares that information with local applications (including web browsers) over DBUS. If that's not bad enough, it also sends MDNS queries looking for NMEA-0183 servers on the local network. Presumably this means it would connect to such a server if it found one?


I'm pretty surprised this is enabled by default (and more people aren't complaining about it).

sudo systemctl disable geoclue.service

6. Block outbound SSDP

Some applications use SSDP to discover things they can interact with on the network, like IOT TVs and Refrigerators and stuff. Chromium sends out lots of SSDP messages while it's running. Since this isn't a service that can be disabled, and I don't want to configure each application not to send SSDP, let's make a firewall rule to block outboung SSDP.


All the SSDP traffic I'm seeing from my machine has a UDP destination port of 1900. Execute the following command to add a firewall rule to block it.

sudo ufw deny out 1900/udp

7. Remove saved WiFi networks

This serves two purposes. First, to prevent your system from sending out 802.11 probe requests, which leak information about where you've been and the networks you've connected to. Second, to prevent your system from automatically connecting to any networks. To do this, we'll remove all saved network connections at boot time.

Add the following to /etc/rc.local to remove all saved 802.11 network connections at startup:

while IFS=\: read -r type uuid
do
    if [ $type == 802-11-wireless ]; then
        nmcli con delete uuid "$uuid"
    fi

done < <(nmcli -t -f TYPE,UUID conn)

Note: I adapted the above from this stackoverflow answer.

8. Make sure Bluetooth and WiFi are disabled at boot

Bluetooth is probably the bigger risk of the two, but let's play it safe and rfkill both at startup. Add the following to /etc/rc.local.
rfkill block all

9. Disable crash reporting

This step is probably optional, but like the previous steps it helps reduce the amount of information your system is leaking about itself.

sudo systemctl disable apport.service

There's probably more we can do to protect a Ubuntu system from threats while away from home. If I think of anything else I'll make a follow up post.

Sunday, June 23, 2019

TV WiFi Adaptor Hax

I was looking for a cheap 802.11ac USB adaptor based on an MT76 chip when I found some ZDGFMT7612U WiFi boards on eBay. The ZDGFMT7612U is meant to add networking capabilities to a TV, but it includes a USB interface and seems conveniently packaged, so I decided to see if I could it would work as a normal USB/WiFi adaptor for use with Kismet, etc.

The eBay item description read:
Sharp ZDGFMT7612U P/N: 1178206 Wifi Module Board for LC-55P6000U
Not super helpful, but the back of the board clearly shows the FCC ID 2AJVQ-ZDGFMT7612U.  If you didn't already know, the FCC equipment authorization database contains useful documents about electronic equipment authorized for RF transmission in the United States, including user manuals and internal photographs.
Using the FCC Equipment Authorization Search (EAS) I was able to find the exhibits for this device's authorization application, which include a user manual and internal photos (the search page is a little weird, and I ended up searching by the Grantee Code 2AJVQ and scrolling through the results until I found it).  The internal photos reveal that the ZDGFMT7612U is based on the MT7612U chip from MediaTek, and the user manual has a somewhat helpful pinout for the board's connector.
Looking at the pinout and the wiring harness that came with the board, it looks like pins 3-6 are the USB connection to the host, and pin 7 is the shield for USB cable.  Unfortunately only USB 2 pins are connected.  I de-pinned the pins I don't care about from the white connector going to the board, and spliced a USB A male connector to the other end.  All the colors matched up, so this was pretty easy.
When I plugged the resulting thing into a computer, nothing happened.  No smoke, which is good, but also no wireless device.  After some guesswork and some help from the folks in the Wireless Village Discord, I figured out that the WIFI_REG_ON pin turns on the voltage regulator that converts the 5 volts supplied by USB to the 3.3 volts required by the WiFi chip.  I used a 4.3k resistor to make a pull-up connecting pin 1 to the 5v pad on the board.

Note: The resistor value I chose probably isn't right, and there are probably better ways to do this, but I'm not an EE and it's working so far.  If you have any advice please leave a comment!
After adding the pullup, the device is seen by the Linux kernel and a new wireless interface is added using the mt76x2u driver.  Yay!

[758511.999389] usb 1-1: new high-speed USB device number 5 using xhci_hcd
[758512.150403] usb 1-1: New USB device found, idVendor=0e8d, idProduct=7612, bcdDevice= 1.00
[758512.150409] usb 1-1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[758512.150412] usb 1-1: Product: 802.11a㜵呃䴷NA
[758512.150415] usb 1-1: Manufacturer: MediaTek Inc.
[758512.150417] usb 1-1: SerialNumber: 000000000
[758512.323849] usb 1-1: reset high-speed USB device number 5 using xhci_hcd
[758512.500874] mt76x2u 1-1:1.0: ASIC revision: 76120044
[758512.534205] mt76x2u 1-1:1.0: ROM patch build: 20141115060606a
[758512.871760] mt76x2u 1-1:1.0: Firmware Version: 0.0.00
[758512.871761] mt76x2u 1-1:1.0: Build: 1
[758512.871762] mt76x2u 1-1:1.0: Build Time: 201507311614____
[758513.913630] ieee80211 phy1: Selected rate control algorithm 'minstrel_ht'
[758513.914392] usbcore: registered new interface driver mt76x2u

[758513.951582] mt76x2u 1-1:1.0 wlx40cd7a083350: renamed from wlan0

My next step is to do some performance testing against the venerable AWUS-036AC and see how well it works in monitor mode.  I think the small on-board antennas may put it at a disadvantage (I have no idea what the beam pattern for those things would look like).

Sunday, July 22, 2018

802.11n monitoring

Today I learned that from the perspective of monitoring wireless networks, 802.11n differs from 802.11b/g in a couple of important ways:

First, there's an option to use 40 MHz channels, where, if I understand correcty, 802.11b/g are limited to 20 MHz.

Second, there's the option to use multiple data streams to increase performance.

Why am I talking about this?

I'm talking about these differences because if you want to monitor 802.11n communications, you need to match the negotiated capabilities between the AP and client you intend to monitor. I've been doing some work involving monitoring a wireless network, and I spent longer than I'd like to admit trying to understand why my AWUS036NH/airmon-ng/wireshark monitoring setup was failing to capture all of the packets. Eventually I came across this question on Superuser about a similar topic. Some smart person responded with a wonderful enumeration of some reasons why I may not see all of the traffic, which made me remember that I used a different client for my initial work.

Specifically, using my AWUS036NH I'm able to capture all wireless traffic from the AP to/from a Samsung Galaxy Tab A (SM-T280), but almost none of the traffic (except some TCP retransmits once in a while) to/from a Motorola Z. My guess is that the Moto Z has more advanced capabilities than the AWUS036NH has, which means the AWUS036NH can't see all of the traffic. As soon as I switched back to the Tab A, I was able to see all of the traffic again.

I'd like to dig up the details of these devices to try to confirm my suspicion, but a quick googling didn't turn up the specifications I was looking for.

Thursday, July 19, 2018

Phantom 3 telemetry post 2

In my last post I documented my progress with decoding the DJI Phantom 3 telemetry protocol between the controller, aircraft, and DJI Go app. This post picks up where I left off, attempting to reverse engineer the Phantom 3 protocol, focusing on data stream from the controller. Unfortunately the controller data is minimally useful for my goal of writing a ground station program, but it's interesting and it helps me further understand the protocol.

Follow-up


A fellow named David was kind enough to leave a comment on my previous post, linking his own protocol reverse engineering work with the DJI Phantom 3. He seems to have discovered some additional details about the protocol through reverse engineering the DJI Go Android app, which I've used to accelerate my work.

Message Header


In my preliminary analysis, I observed that byte 3 seems to correlate with message length. This made me think it may have been a message ID field, but apparently it's an 8-bit CRC of the first three bytes of the message. This makes sense, since the only field in the header that varies is message length! This also explains my observation that byte 2 never changes; It's mostly a version number and the most significant bits of the message length (which are usually zero, since I haven't observed any messages with lengths greater than 255).

Here's the structure of the four-byte DJI message header, thanks to David:
+-------+----------+------------+--------+----------+
| Bit   | 00000000 | 0011111111 | 112222 | 22222233 |
|       | 01234567 | 8901234567 | 890123 | 45678901 |
+-------+----------+------------+--------+----------+
| Field | magic    | length     | ver    | CRC      |
+-------+----------+------------+--------+----------+

Message Source/Target


The first two bytes of the payload describe the source and target systems for this message.

Source/Destination fields:
+-------+----------+-----------+
| Bit   | 00000000 | 001111111 |
|       | 01234567 | 890123456 |
+-------+----------+-----------+
| Field | msg src  | msg tgt   |
+-------+----------+-----------+

The source/target bytes contain two fields: system and subsystem. The system field is 7 bits wide and the subsystem field is 3 bits wide. The system field describes a major component in the system. This includes things like the hand controller, flight controller, camera, mobile app, etc. I'm not really sure what the subsystem field means yet.

Sequence Number


The next field in the payload is a 16-bit counter that seems to increment independently for different types of messages. For example, I've observed that each source/target combination has a distinct counter. In some cases, this counter seems to be used as an acknowledgement.

Flags


The next field contains 8 bits of flags. Two of these seem to have somewhat clear meanings, but the rest I'm not sure about. The flag in bit 0 seems to indicate that the message is an acknowledgement to a previous message, and the flag in bit 1 seems to indicate that this message requires an acknowledgement.

I'm guessing about these meanings because of observations like the following:
Message N:
Source(sub-source): 3(3)
Target(sub-target): 2(0)
Sequence Number: 429
Flags: 0100 0000

Message N+1:
Source(sub-source): 2(0)
Target(sub-target): 3(3)
Sequence Number: 429
Flags: 1000 0000

Command Set/Command


Following the Flags byte, there are two bytes that represent a Command Set and Command, respectively. It seems reasonable that a system/subsystem may have more than one type of message to send (or receive), but I haven't tried to make sense of this field yet. So far the messages that I've looked closely at are defined well-enough by the source, target, and length.

Payload


The payload field is a variable length string of bytes whose meaning changes depending on the context. I've only been able to fully decode one of these, which I'll talk about shortly.

CRC


Finally there's the CRC. I had the right idea initially with the 16-bit CRC field following the payload field, but I couldn't seem to find a match for a CRC algorithm and initialization value. I tried using some online CRC calculators (this one, and this one) by manually entering the byte sequences for some small packets that I had observed, but I couldn't find a match. It turns out that DJI actually has the code for their CRC algorithm on Github.

Discovering Field Boundaries - The Controller


I've never really attempted protocol reverse engineering before this project, but in my fumbling around in the dark I learned something: My assumption that decoding static data would be easier than dynamic data was wrong. The problem with static data (e.g. things like switch positions, camera mode, and other status information that doesn't often change) is that it's very hard to see the field boundaries in the data, particularly in the case of fields that cross byte boundaries.

In order to find field boundaries in the data streams, I need to make the data change. Ideally, I need to make it change one field at a time so that I can see the field boundaries and begin decoding the data. Where should I start? I need some data that I can control. Aircraft position and attitude are really the targets that I want to go after, but I think those are going to be changing pretty much constantly. The buttons and joysticks on the controller are an obvious choice, since these won't change unless I move them, and I can make them change one at a time.

By playing with the controller one axis at a time, I was able to determine the following payload layout for messages with source 6(1) and a length of 26 bytes:
+--------+-------------------------------+
| Bytes  | Field                         |
+--------+-------------------------------+
| 12, 13 | right stick - left/right axis |
+--------+-------------------------------+
| 14, 15 | right stick - up/down axis    |
+--------+-------------------------------+
| 16, 17 | left stick - up/down axis     |
+--------+-------------------------------+
| 18, 19 | left stick - left/right axis  |
+--------+-------------------------------+
| 20, 21 | camera elevation              |
+--------+-------------------------------+

Next Steps


Now that I have a technique for discovering field boundaries for fields that I can control, I'd like to try to find the aircraft attitude fields next. I should be able to control pitch, roll, and compass heading fairly easily.

Monday, May 28, 2018

Living with NetwokManager: Configuring an 802.11 Monitoring Interface

Background


In a previous post about reverse engineering a network protocol, I included some information about monitoring 802.11 wireless networks. After configuring a monitoring interface more than a few times, I started looking for ways to streamline the setup.

I'm using an EliteBook 8570p running Fedora 27 for my analysis work. I'd like to use my laptop's internal wifi card to stay connected to my home wifi network while monitoring another network with a USB wifi adapter. After reading some blog posts [1] and the terrible NetworkManager documentation, I was able to get this working and I thought I'd share. These modifications are probably specific to Fedora, but I suspect any distribution using NetworkManager could be configured similarly.

When I connect my USB adapter, the output from nmcli dev status indicates that NetworkManager wants to control it.



The first time I tried to automate disabling NetworkManager control of a wireless device, I went down the path of configuring NetworkManager to ignore the device by its MAC address. In order to do that, I had to disable NetworkManager's built-in MAC randomization for wireless devices, and after some thought I decided I'd rather not do that. The method described below uses a UDEV rule to tell NetworkManager to leave my USB wifi adapter alone, which seems simpler and safer.

UDEV Rule


First I gathered some info about the device by running udevadm info /sys/class/net/wlp0s20u4 (replace wlp0s20u4 with the name of your interface). The parts I'm interested in are ID_VENDOR_ID and ID_MODEL_ID.

P: /devices/pci0000:00/0000:00:14.0/usb3/3-4/3-4:1.0/net/wlp0s20u4
E: DEVPATH=/devices/pci0000:00/0000:00:14.0/usb3/3-4/3-4:1.0/net/wlp0s20u4
E: DEVTYPE=wlan
E: ID_BUS=usb
E: ID_MM_CANDIDATE=1
E: ID_MODEL=802.11_n_WLAN
E: ID_MODEL_ENC=802.11\x20n\x20WLAN
E: ID_MODEL_FROM_DATABASE=RT2870/RT3070 Wireless Adapter
E: ID_MODEL_ID=3070
E: ID_NET_DRIVER=rt2800usb
E: ID_NET_LINK_FILE=/usr/lib/systemd/network/99-default.link
E: ID_NET_NAME=wlp0s20u4
E: ID_NET_NAME_MAC=wlx00c0ca96aee3
E: ID_NET_NAME_PATH=wlp0s20u4
E: ID_OUI_FROM_DATABASE=ALFA, INC.
E: ID_PATH=pci-0000:00:14.0-usb-0:4:1.0
E: ID_PATH_TAG=pci-0000_00_14_0-usb-0_4_1_0
E: ID_REVISION=0101
E: ID_SERIAL=Ralink_802.11_n_WLAN_1.0
E: ID_SERIAL_SHORT=1.0
E: ID_TYPE=generic
E: ID_USB_DRIVER=rt2800usb
E: ID_USB_INTERFACES=:ffffff:
E: ID_USB_INTERFACE_NUM=00
E: ID_VENDOR=Ralink
E: ID_VENDOR_ENC=Ralink
E: ID_VENDOR_FROM_DATABASE=Ralink Technology, Corp.
E: ID_VENDOR_ID=148f
E: IFINDEX=36
E: INTERFACE=wlp0s20u4
E: SUBSYSTEM=net
E: SYSTEMD_ALIAS=/sys/subsystem/net/devices/wlp0s20u4 /sys/subsystem/net/devices/wlp0s20u4
E: TAGS=:systemd:
E: USEC_INITIALIZED=129405399440

I used this info to write the following UDEV rule, which I saved in a file called /etc/udev/rules.d/99-alfa.rules, that sets the NM_UNMANAGED environment variable to 1:

SUBSYSTEM=="net", ACTION=="add", ENV{ID_VENDOR_ID}=="148f", ENV{ID_MODEL_ID}=="3070", ENV{NM_UNMANAGED}="1"

That's it. Now when I plug my USB wifi adapter in, NetworkManager shows it as "unmanaged".


Follow up


Now that my USB wifi adapter won't be misconfigured by NetworkManager, I should have an easier time setting up my system for monitoring. As a follow up, I'm working on configuring UDEV to execute a script to automatically put this interface into monitor mode as soon as it's connected. I'll share that in my next post.

Sunday, April 29, 2018

Oracle JDK on Fedora 27

This post explains how I install the Oracle JDK on Fedora 27.

1. Download


Validate the checksum against the published values listed here: https://www.oracle.com/webfolder/s/digest/10-0-1checksum.html
$ shasum -a 256 jdk-10.0.1_linux-x64_bin.tar.gz

2. Install

I like to install the JDK in /opt/java.
$ cd /opt/java
$ tar -xf jdk-10.0.1_linux-x64_bin.tar.gz

Now there should be a directory on the system that looks like /opt/java/jdk-10.0.1. In order to make updating the JDK easier in the future, create a symlink at /opt/java/latest that points to the latest installed version. This way we won't have to update the alternatives every time we update!
$ ln -s jdk-10.0.1 latest

3. Update alternatives

Fedora ships with OpenJDK installed by default and there are a bunch of packages that depend on it. However, we can use the alternatives command to allow the Oracle JDK and OpenJDK to coexist.

First let's tell alternatives about the Oracle JDK binaries:
$ alternatives --install /usr/bin/java java /opt/java/latest/bin/java 1000
$ alternatives --install /usr/bin/javaws javaws /opt/java/latest/bin/javaws 1000
$ alternatives --install /usr/bin/javac javac /opt/java/latest/bin/javac 1000
$ alternatives --install /usr/bin/jar jar /opt/java/latest/bin/jar 1000

Now we can make sure the correct version of the java command is selected, and update the configuration if necessary:
$ alternatives --config java

4. Verify

Let's make sure the Oracle JDK version of /usr/bin/java is being used:
$ java -version
java version "10.0.1" 2018-04-17
Java(TM) SE Runtime Environment 18.3 (build 10.0.1+10)
Java HotSpot(TM) 64-Bit Server VM 18.3 (build 10.0.1+10, mixed mode)

Final Thoughts

When a new Oracle JDK is released, we can just install it in /opt/java and update the symlink!