Initialen











Change color to default
Change color to red
Change color to blue
Change color to green
Change color to yellow
Change color to cyan
Change color to magenta
Change color to orange
Change color to b/w

fuschlberger.net

Change color to default
Change color to red
Change color to dark red
Change color to blue
Change color to dark blue
Change color to green
Change color to dark green
Change color to yellow
Change color to dark yellow
Change color to cyan
Change color to dark cyan
Change color to magenta
Change color to dark magenta
Change color to magenta
Change color to dark orange
Change color to grey
Change color to b/w

Printme!

Ubiqiti / Ubnt stuff

Setting up unifi devices

If you don't want to ssh to all new devices on their default IP address of 192.168.1.20 (and for that purpose create an alias ethernet interface in that subnet) there is a very easy solution.

The default inform URL of unifi devices is http://unifi:8080/inform.
To make devices automatically connect with your individual unifi controller server, you have to configure your DNS server so it resolves unifi to the IP address of your controller
example for the /etc/hosts file: 123.123.123.123 unifi

After that change I restarted my OpenWRT router and all the new unifi devices connected instantly with the controller.

They showed as Pending adoption. I clicked on adopt and the adoption was done without any problems.

Unifi with SSL certificate from letsencrypt

I had nothing else running on the server, so I installed lighttpd and used the webroot module to install a certificate. I will not cover that here since there is enough documentation for letsencrypt/certbot out there.

Then I added (as always) a line into /etc/cron.d/certbot 37 5 * * * root /opt/certbot/certbot-auto renew --quiet

Next I need a script to automatically take the updated certificate and key files, put them into the unifi controller directory and restart unifi:

#!/bin/sh

HOSTNAME=uctrl.fqdn.domain

openssl pkcs12 -export -in /etc/letsencrypt/live/$HOSTNAME/fullchain.pem -inkey /etc/letsencrypt/live/$HOSTNAME/privkey.pem -out /etc/ssl/private/cloudkey.p12 -name unifi -password pass:aircontrolenterprise

keytool -importkeystore -noprompt -deststorepass aircontrolenterprise -destkeypass aircontrolenterprise -destkeystore /usr/lib/unifi/data/keystore -srckeystore /etc/ssl/private/cloudkey.p12 -srcstoretype PKCS12 -srcstorepass aircontrolenterprise -alias unifi

rm -f /etc/ssl/private/cloudkey.p12
sleep 3
/etc/init.d/unifi restart


/opt/certbot/certbot-auto renew --dry-run --force-renewal --agree-tos --rsa-key-size 4096

When run from renew-hook for several hostnames it might work like this:

#!/bin/sh

UPDATEDOMAINDIR=$RENEWED_LINEAGE
openssl pkcs12 -export -in $UPDATEDOMAINDIR/fullchain.pem -inkey $UPDATEDOMAINDIR/privkey.pem -out /etc/ssl/private/cloudkey.p12 -name unifi -password pass:aircontrolenterprise

The problem is to make that script only run when the certifcate for the unifi-controller is updated. Of course I could run it each time the cronjob for updating the certificates is run, but that's not what I want (unifi controller takes some time to restart, so it would be offline every day in the morning for some seconds/minutes).
As far as I understand the letsencrypt documentation, the option renew-hook can only be used in the main config file


It should work like that
letsencrypt renew | tee | grep -q "/etc/letsencrypt/live/<domain>/fullchain.pem (success)" && /usr/local/bin/update-unifi-cert

but the more elegant way would be to have the renew-hook parameter available in each single file in /etc/letsencrypt/renewal/*

/opt/certbot/certbot-auto renew --agree-tos | tee | grep -q "/etc/letsencrypt/live/uctrl.hostname.at/fullchain.pem (success)" && /usr/local/bin/update-unifi-cert

Another way I found to automate that is https://github.com/amagical-net/certbot-renew-hook
Not tested since the other method worked for me.


The portal files are (at least in controller version 5.4.11 here) not located in /var/lib/unifi/sites/<sitename>/portal. <sitename> is not the name of the site but a random 8 alphanumeric string.

If you know a way how to find out the name of this directory for each site (in another way than trial and error) send me a mail.


Settings in bundle/message.properties for free trial:

## package 3
# this is a free trial package (with amount 0)
package.3.amount=0
# behind the comma it's a fraction of an hour, not minutes
package.3.hours=0.18
package.3.name=Free Trial
# whether to overwrite the user group policy per WLAN/User, default is false
package.3.limit_overwrite=true
# kbps, default is unlimited
package.3.limit_down=4096
# kbps, default is unlimited
package.3.limit_up=1024
# Mbytes, default is unlimited
package.3.limit_quota=1024
# allow free trial again after hours:
package.3.trial_reset=24


Server Port Problem

There is a Problem with Aircontrol 1 (version 1.4.2-beta.3839), that the HTTP connection from antenna to server tries to connect to port 22 on the serverside, no matter what is configured in the Aircontrol server settings (there port 9080 was configured).

Settings in Aircontrol Server
Admin / System Settings
Default Device SSH Port 22
AirControl Server Address name-of-the-server.domain
AirControl Server HTTP Port 9080

After provisioning the antenna we check the settings on the antenna via CLI:
$ mca-ctrl -t status
http://name-of-the-server.domain:22/heartbeat
$

So the correct server port is not set, instead the server sets (server) port 22. Of course on the server on port 22 nothing is listening for the connection from the antenna.
The heartbeat gets through if I manually set the correct port on the antenna

$ mca-ctrl -t connect -s http://name-of-the-server.domain:9080/heartbeat

After that the antenna comes online instantly. Of course the setting is lost as soon as the antenna is disconnected / unprovisioned, each time after reconnecting the correct port has to be set again. That is of course too complicated (and the mere heartbeat doesn't help for provisioning antennas anyway).

The easier way is to make the server listen on port 22. Since there is no way (I know of) to change the server port it is easier to create a port redirect with iptables.

On the server run (adapted if necessary):
# iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 22 -j REDIRECT --to-port 9080
After that all antennas come online by themselves. Yeehaaaah!
The heartbeat can then also be set with
mca-ctrl -t connect -s http://name-of-the-server.domain:22/heartbeat



How to change password and admin user on AirOS device via command line interface and ssh

Such a change might be necessary if the password is not accepted by the login of the webinterface, e.g. because it is too long.

If you make these changes yourself step by step it is important to sync all changes, otherwise you can easily lock out yourself of your antenna (and having to drive to a remote place for resetting your antenna is never what you want). This is exactly what is done by the webinterface if you change username or password there.

Add a new line for the new admin into /etc/passwd, copy & paste from another device, hash type / length should be the same (to be on the safe side). The line for the old admin can stay there, it will be deleted automatically later.

Edit /tmp/system.cfg and look for the lines
users.1.name=adminusername
users.1.password=HeReIsThEhAsH

Edit users.1.name to correspond with the username added to /etc/passwd
copy&paste the password hash from this user's line in /etc/passwd to /tmp/systemf.cfg
run cfgmtd -p /etc/ -w
reboot


The public key authentication set up previously (as a backup in case something went wrong with the passwords) will automatically work for the new admin user name.

You can log in via ssh with all usernames that are listed in /etc/passwd.
When rebooting all other admin usernames apart from the one set as users.1.name will be removed from /etc/passwd



How to remove the motherfucker virus / worm

It is written rather simple and can be removed without any major problems.

The virus does (at least) the following things:

  • Create a system account (mother, moth3r, motherfucker or similar)
  • store and camouflage its files somewhere on the filesystem
  • make sure it gets loaded at every reboot
  • scan the network around him to distribute itself aka infect other devices
  • set aliases for the shell so it gets run / loaded e.g. when the user runs the ps command (nice one! :) )

There are 3 variants of the motherfucker virus (known to me after cleaning several antennas (don't ask, fortunately I wasn't responsible for them))

Variant 1

All the files of the virus are located in /etc/persistent
mf.tar the virus itself
rc.poststart startscript to load and run itself at every boot
.ssh/ directory for dropbear settings, public keys etc

Commands to remove the worm
cd /etc/persistent/
rm mf.tar
rm rc.poststart
rm -R .mf
sed -i "/^mother/d" /etc/passwd

(or open it in vi and delete the respective line)
cfgmtd -p /etc/ -w
reboot

Variant 2

All the files of the virus are located in /var/lib/dhcp
Probably motherfucker can use /var/lib/dhcp/.ssh/authorized_keys, so you have to write your own key (via exploit) into that file to be able to login, if your password doesn't work
rm /etc/persistent/rc.poststart
rm -r /var/lib/dhcp

Variant 3

The virus writes itself to /var/bin/cgi and runs itself at every boot from /etc/persistent/rc.prestart
rm /etc/persistent/rc.prestart
rm /var/bin/cgi


Variant 3

most sophisticated variant

XM.v5.5.6# ls -la .mf drwxrwxr-x 2 moth3r admin 240 May 28 2013 .
drwxr-xr-x 4 moth3r admin 200 May 28 2013 ..
-rwxrwxr-x 1 moth3r admin 1529 Jun 3 2016 download
-rwxr-xr-x 1 moth3r admin 1517 Dec 12 19:19 infect
-rw------- 1 moth3r admin 806 May 25 2016 mfid
-rw-r--r-- 1 moth3r admin 395 May 25 2016 mfid.pub
-rwxrwxr-x 1 moth3r admin 2847 Jun 3 2016 mother
-rwxrwxr-x 1 moth3r admin 577 Jun 1 2016 p
-rw-rw-r-- 1 moth3r admin 161 May 30 2016 passlst
-rw-rw-r-- 1 moth3r admin 84 May 25 2016 passwd
-rwxrwxr-x 1 moth3r admin 1206 May 31 2016 scan
-rwxrwxr-x 1 moth3r admin 411 May 30 2016 sprd


download: download itself
infect: infect other vulernable devices
mother: run discover to find devices, write result to file, infect found devices, change SSID and do other fancy stuff
p: check if account moth3r exists, if not create it, modify startscripts, empty authorized_keys, write config, reboot
passlst: password file for brute force attack
passwd: passwd file to be copied to /etc/passwd
scan: scan and infect my own subnet
sprd: infect other random IP addresses

Run the following to remove the worm:

killall mother
killall sleep
killall sh
cd /etc/persistent
rm mf.tgz
rm rc.poststart
rm -r .mf
cd /tmp
rmdir down
reboot



After successful cleaning update your firmware immediately! Otherwise your device will be infected soon again.


Attention:
I have found several devices that had open ssh connections originating in China and Argentinia that were (due to the high traffic usage) obviously used as a proxy for whatever illegal purpose.

Since the motherfucker worm had been removed and the firmware updated to a (hopefully) not vulnerable version the only option how the ssh-tunnel could have been established is via public/private key authentication.

So I had a look at /etc/dropbear/authorized_keys, this file was empty.
Then I had a look at

XM.v6.0# find / -maxdepth 99 -iname autho*
/sys/devices/platform/ar7240-ehci.0/usb1/authorized
/sys/devices/platform/ar7240-ehci.0/usb1/authorized_default
/var/etc/dropbear/authorized_keys
/var/etc/persistent/mcuser/.ssh/authorized_keys

Delete all public keys from there and change username/password (see above).

Links:

https://www.root.cz/clanky/motherfucker-virus-v-bezdratovych-zarizenich-ubiquiti-airos/


Written 2016-12-09 - last update 2017-10-31


Change color to defaultChange color to redChange color to blueChange color to greenChange color to yellowChange color to cyanChange color to magentaChange color to orangeChange color to b/w

© by wf
webslave (at) fuschlberger.net
Medieninhaber:
Wolfgang Fuschlberger, Salzburg