This is only one directory of three that I extracted from the base firmware zip file, so this is not all the
data stored in the firmware file. Now with that said...
If the '.ppc' file didn't give it away, the 'file' command sure did: This firmware runs on a PowerPC architecture CPU. The last 'file' command output indicates a 32-bit big Endian processor as well.
Also worth noting here: if my memory serves me correctly, ActiveX controls were wrapped up in .ocx files.
I
thought OCX files were just basically DLL files, but I don't think I ever actually confirmed that,
so I'm not sure if the .ocx file below being gzip'd is weird or not... Time for some research.
aj@aj-laptop:~/sec_stuff/firmware_re/Avertx_nvr/upd_900s/tgz_data$ ls
total 47420
-rw-r--r-- 1 aj aj 2676927 May 21 2018 d9b15-00345.ker
-rwxr--r-- 1 aj aj 12374600 May 21 2018 d9b15-00855.ocx
-rw-r--r-- 1 aj aj 27060522 May 21 2018 d9b15-0H330.rfs
-rwxr-xr-x 1 aj aj 6435312 May 21 2018 d9b15-11224.ppc
aj@aj-laptop:~/sec_stuff/firmware_re/Avertx_nvr/upd_900s/tgz_data$ file *
d9b15-00345.ker:
u-boot legacy uImage, Linux-2.6.25.00345, Linux/PowerPC, OS Kernel Image (gzip), 2676863 bytes, Wed Jan 21
07:32:54 2015, Load Address: 0x00000000, Entry Point: 0x00000000, Header CRC: 0x0B14FB09, Data CRC: 0x96A4C618
d9b15-00855.ocx:
gzip compressed data, last modified: Mon May 21 05:36:29 2018, from Unix, original size modulo 2^32 13629440
d9b15-0H330.rfs:
u-boot legacy uImage, ver:0H330 initrd glibc, Linux/PowerPC, RAMDisk Image (gzip), 27060458 bytes, Mon Aug 28
03:02:39 2017, Load Address: 0x00000000, Entry Point: 0x00000000, Header CRC: 0x89CBCC3B, Data CRC: 0x40B0FB7D
d9b15-11224.ppc:
ELF 32-bit MSB executable, PowerPC or cisco 4500, version 1 (SYSV), dynamically linked, interpreter /lib/ld.so.1, for GNU/Linux 2.6.10, stripped
[Some research later...]
So, I found an old 32-bit ocx file from around the WinXP days, here's what 'file' says for that file:
aj@aj-laptop:~$ file ./comdlg32.ocx
./comdlg32.ocx: PE32 executable (DLL) (GUI) Intel 80386 (stripped to external PDB), for MS Windows
Ok, so I confirmed that ocx files are indeed just DLL files with a different name. So, let's see what I get if I decompress that OCX file...
So upon further inspection, the OCX file is not an OCX file at all. It's a .tar.gz file that someone just renamed...
So, here's a listing of our 'OCX' tar file:
aj@aj-laptop:~/sec_stuff/firmware_re/Avertx_nvr/upd_900s/tgz_data$ tar --list -f d9b15-00855.ocx.tar.gz
./
./conf/
./conf/http-up.sh
./conf/httpd.conf
./conf/users.db
./QT/
./QT/img/
./QT/dyna.rcc
./QT/fonts/
./QT/fonts/[fonts cut out for space reasons]
./http.ver
./Certs/
./Certs/netguard-hd-apns-key.pem
./Certs/netguard-apns-key.pem
./Certs/netguard-hd-apns-cert.pem
./Certs/netguard-apns-cert.pem
./web/
./web/md5.js
./web/RemoteWeb.cab
./web/logo.htm
./web/Components.inf
./web/liveview.html
./web/VideoViewer.inf
./web/DVRPlayer.zip
./web/favicon.ico
./web/RemoteWeb.inf
./web/images/
./web/images/ie-logo.jpg
./web/images/avertx-logo.png
./web/images/app-store.png
./web/images/google-play.png
./web/login.html
./web/logo.jpg
./web/Components.cab
./web/icons/
./web/icons/[icons cut out for space reasons]
We're definitely headed in the right direction here. You can see some interesting files already:
Everything in ./conf/:
* http-up.sh - This is probably the script that brings the web server up.
* httpd.conf - Probably a web server config...
* users.db - Should probably contain the factory default user (admin). Couldn't hurt to do a quick
check for "undocumented" accounts...
./Certs:
* Are those private key files I see? If those are actually used for securing the session
and they're not changed automatically (such as during the first boot-up), This would
mean we could now use these keys to decrypt traffic to ANY AvertX NVR of this model (at least).
Cab/zip files: ./web/RemoteWeb.cab, ./web/DVRPlayer.zip, ./web/Components.cab
* These files are what you are required to download upon your first visit to the NVR web page.
One of these files should contain the ActiveX control...
First, let's take a look at our Conf files:
httpd.conf:
ServerRoot "/etc/appWeb"
DocumentRoot "/var/www/cgi-video"
Listen 0.0.0.0:80
TypesConfig mime.types
LoadModulePath /lib ./bin ../bin ../bin/Debug ../bin/Release
LoadModule admin libadminModule
LoadModule auth libauthModule
LoadModule cgi libcgiModule
LoadModule copy libcopyModule
LoadModule egi libegiModule
LoadModule upload libuploadModule
AddHandler authHandler
AddHandler egiHandler .vdo .get .set index help viewer login Components
AddHandler copyHandler
AddHandler uploadHandler
<Directory $DOCUMENT_ROOT/auth>
AuthDigestQop auth
AuthUserFile users.db
AuthType digest
AuthName "DVR"
Require user admin user max Admin User
</Directory>
LimitRequestBody 614400
KeepAlive on
Timeout 60
FileUploadDir "/upgrade/net"
Group nobody
User nobody
DirectoryIndex index
Looks like an Apache config file to me. I'm a bit surprised, systems like this usually run servers like lighttpd and other "micro" web servers.
http-up.sh:
Mmmkay, so the name of this script is a bit deceptive. It doesn't seem to start a web server at all, it just copies
some data around. Interesting to note here is the FTP server address and credentials hardcoded into this file. Huge
mistake - they can
NEVER change that username/password or risk every single customer (that uses products with
these credentials) not receiving any more updates. This is a classic example of security through obscurity, and a very
good example of why it is bad. Don't hard-code credentials, kids.
users.db:
1: admin: DG200: c754d474ae5aca8294aabd0c3674e5fe
1: user: DG200: 041e78b9348e48b872d62ba8f64cc5fc
So the good news is there are no backdoor accounts here. Looking in the manual for the NVR, you can find the following:
Logging In To the Recorder
1.Right-click in the Live screen.
2.Click admin or user, depending on your account.
3.Use the on-screen keyboard or a USB keyboard to type your password.
The default password for the admin account is 1234.
The default password for the user account is 4321.
4.Click OK.
However, I have run into something concerning; I know both the plaintext and hashed password for the admin user.
Doing a search for this hash value (the hash of '1234') returns nothing, which is odd for any common hash algorithm.
So, they've either rolled their own hash algorithm (oh god, I hope not...), implemented an existing hash algorithm
incorrectly, or they are perhaps transforming the output hash value somehow (even just a simple xor encryption would
work). Alternatively, they could be using a lesser-known hash algorithm, though I feel this is unlikely.
I do know that these password hashes don't match MD5, MD4, or double MD5 hashes. This may require further investigation.
Now, let's take a look at those PEM files:
aj@aj-laptop:~/sec_stuff/firmware_re/Avertx_nvr/upd_900s/tgz_data/ocx/Certs$ ls
total 24
-rw-r--r-- 1 aj aj 2000 May 21 2018 netguard-apns-cert.pem
-rw-r--r-- 1 aj aj 4286 May 21 2018 netguard-apns-key.pem
-rw-r--r-- 1 aj aj 2009 May 21 2018 netguard-hd-apns-cert.pem
-rw-r--r-- 1 aj aj 4306 May 21 2018 netguard-hd-apns-key.pem
aj@aj-laptop:~/sec_stuff/firmware_re/Avertx_nvr/upd_900s/tgz_data/ocx/Certs$ for i in $(echo *); do echo -en "\n$i:\n\t"; grep -A3 "BEGIN" $i; done
netguard-apns-cert.pem:
-----BEGIN CERTIFICATE-----
MIIFmDCCBICgAwIBAgIIWBFJqT7Bx24wDQYJKoZIhvcNAQEFBQAwgZYxCzAJBgNV
BAYTAlVTMRMwEQYDVQQKDApBcHBsZSBJbmMuMSwwKgYDVQQLDCNBcHBsZSBXb3Js
ZHdpZGUgRGV2ZWxvcGVyIFJlbGF0aW9uczFEMEIGA1UEAww7QXBwbGUgV29ybGR3
netguard-apns-key.pem:
-----BEGIN CERTIFICATE-----
MIIFmDCCBICgAwIBAgIIWBFJqT7Bx24wDQYJKoZIhvcNAQEFBQAwgZYxCzAJBgNV
BAYTAlVTMRMwEQYDVQQKDApBcHBsZSBJbmMuMSwwKgYDVQQLDCNBcHBsZSBXb3Js
ZHdpZGUgRGV2ZWxvcGVyIFJlbGF0aW9uczFEMEIGA1UEAww7QXBwbGUgV29ybGR3
--
-----BEGIN PRIVATE KEY-----
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDmKdZKmOLkRFcm
MGpXJ1Jn2lLgXOvL0ESexgcCHjqdUfM2w1wmQUKN17BwHt7IB0YyOUm/21qdyh4u
87PBjEaerc6ItTZbbwsFdSPeLzqNPlCe+DumyD9RK8LrfX/gAh5GXTDjJnbFhuiD
netguard-hd-apns-cert.pem:
-----BEGIN CERTIFICATE-----
MIIFnjCCBIagAwIBAgIIGB8DpxmaefcwDQYJKoZIhvcNAQEFBQAwgZYxCzAJBgNV
BAYTAlVTMRMwEQYDVQQKDApBcHBsZSBJbmMuMSwwKgYDVQQLDCNBcHBsZSBXb3Js
ZHdpZGUgRGV2ZWxvcGVyIFJlbGF0aW9uczFEMEIGA1UEAww7QXBwbGUgV29ybGR3
netguard-hd-apns-key.pem:
-----BEGIN CERTIFICATE-----
MIIFnjCCBIagAwIBAgIIGB8DpxmaefcwDQYJKoZIhvcNAQEFBQAwgZYxCzAJBgNV
BAYTAlVTMRMwEQYDVQQKDApBcHBsZSBJbmMuMSwwKgYDVQQLDCNBcHBsZSBXb3Js
ZHdpZGUgRGV2ZWxvcGVyIFJlbGF0aW9uczFEMEIGA1UEAww7QXBwbGUgV29ybGR3
--
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCmT+6o+PP7P3rf
N9E/7Bcdxuw71tGymOLMUJyoT3wDAereFjrWhwWKhJXBP1n8Xo/tzOmVUtObqjh9
uza0kjHawicntwhF8hHI8lYYwZb/e9fFPCqlWeWULmuDH/flQyhEWGkWVPowtEQH
aj@aj-laptop:~/sec_stuff/firmware_re/Avertx_nvr/upd_900s/tgz_data/ocx/Certs$
There are no words this, just head shaking. Moving on...
Checking just the DVRPlayer.zip file, we see this list:
aj@aj-laptop:~/sec_stuff/firmware_re/Avertx_nvr/upd_900s/tgz_data/zipcab$ unzip -l DVRPlayer.zip
Archive: DVRPlayer.zip
Length Date Time Name
--------- ---------- ----- ----
570408 2018-05-21 10:27 DVR_Player.exe
0 2015-12-04 17:13 resource/
74 2014-01-14 10:18 resource/autorun.inf
445166 2018-05-21 10:39 resource/Components.cab
12720 2016-04-06 17:01 resource/Components.inf
18944 2014-01-14 10:19 resource/expand
3783672 2008-07-29 08:05 resource/mfc90u.dll
1857 2014-11-14 10:12 resource/Microsoft.VC90.CRT.manifest
2354 2014-11-14 10:12 resource/Microsoft.VC90.MFC.manifest
572928 2008-07-29 08:05 resource/msvcp90.dll
348160 2013-12-26 13:23 resource/msvcr71.dll
655872 2008-07-29 08:05 resource/msvcr90.dll
7278 2014-01-14 10:18 resource/Player.ico
18048 2014-01-14 10:18 resource/PlayerLogo.jpg
5596712 2018-05-21 10:27 resource/Remote200Web.ocx
3069992 2018-05-21 10:27 resource/VideoViewer.ocx
Yeah, I think we found our real ActiveX control(s) this time ^_^
However, the target has now changed. My whole purpose here was to dig into
why the password input validation is so fucky. Initially, I thought the issue was in the ActiveX
controller, but I realized that actually makes no sense. You have to log in the very first time, before
downloading the ActiveX control, so it makes sense the ActiveX control doesn't handle logins.
I'm not sure why I didn't catch that before...
Anyway, when we found the users.db file above, we discovered that the web server is handling the authentication.
We also found that the hash algorithm they're using seems to be very uncommon or modified in a way to be
unrecognizable. Given that the web server does such a poor job at sanitizing password input, I have a hard time
believing we're running Apache here. It feels like they just mimicked the Apache config format and wrote their own web
server? Let's take a look...
Before going to find the rest of the filesystem, I decided to check on the 'ppc' binary that was in the same folder as
our "tar.gz" "ocx" file: d9b15-11224.ppc. I won't post the entire string dump (which is quite long), but the language
found in the binary tells me that this file is most likely the NVR UI application - the one that runs after bootup and
is displayed if you have an actual screen plugged into the NVR box. However, there was an interesting string I found
in the string dump:
aj@aj-laptop:~/sec_stuff/firmware_re/Avertx_nvr/upd_900s/tgz_data$ strings -n8 d9b15-11224.ppc | sort | less
[... other string dump data ...]
401 - Unauthorized: Access is denied due to invalid credentials.
[... other string dump data ...]
This makes me wonder, is the web server built into this binary? Let's load it up in a debugger/reversing tool, such as
radare2. Apparently, this binary has been stripped (according to the 'file' command), so it may be a bit difficult to
determine if it's opening a port on port 80 or 443. Let's see...
Yes. I am fairly certain that this binary actually is also the web server. Unfortunately, this binary gave
the Radare2 analyzer some problems (the analyzer never finished analyzing the program). Since the analyzer doesn't
work, I'm unable to find any cross-references to function calls or data within the program. However, even without the
analysis, I was able to see that the "socket, bind, listen, accept" functions were all imported. I also found a string in the string dump referring to users.db. There are also various strings in the binary referring to things such as the document root, "appWeb", etc.
I can't be bothered to figure out why this binary is hanging up the Radare2 analyzer, otherwise I would totally look
for the code that handles the password input in the binary. But, I just can't be bothered to put that much effort
into this endeavour when I don't even have the hardware anymore and my tools aren't working right for this binary
Anyway, I decided to go ahead and release the name of the system. For fairly obvious reasons, I did not want to
disclose information about a security system currently used by my previous employer. However, I have reason to believe they are no longer using this system, so here you go:
The system in question here is the AvertX NV160-P2B Network Video Recorder system:
https://www.avertx.com/downloads/" onclick="window.open(this.href);return false;" onclick="window.open(this.href);return false; Downloads page
https://www.avertx.com/nvr-firmware-11224/" onclick="window.open(this.href);return false;" onclick="window.open(this.href);return false; Firmware download
https://www.avertx.com/content/recorder ... Manual.pdf" onclick="window.open(this.href);return false;" onclick="window.open(this.href);return false; User manual
If anyone wants to pick up where I left off, I'd love to see what you find!
¯\_(ツ)_/¯ It works on my machine...