Blog: Vulnerability Advisory
eyeDisk. Hacking the unhackable. Again
Last year, about the time we were messing around with a virtually unheard-of hardware wallet we got a bit excited about the word “unhackable”. Long story short, I ended up supporting a selection of kickstarters that had the word “unhackable” or similar in their title.
Of these, at least one got funded and got distributed from China’s far shores to my house. The “unhackable” USB stick called eyeDisk was in my sweaty hand.
Here’s the claim from the Kickstarter project page:
EyeDisk’s thing is that it uses iris recognition to unlock the drive, to quote their kickstarter campaign:
With eyeDisk you never need to worry about losing your USB or the vulnerability of your data stored in it. eyeDisk features AES 256-bit encryption for your iris pattern. We develop our own iris recognition algorithm so that no one can hack your USB drive even [if] they have your iris pattern. Your personal iris data used for identification will never be retrieved or duplicated even if your USB is lost.
So, can we hack it?
Initial investigation
Upon getting it, the first thing to do was to plug it into a Windows VM to see how it runs and whether it pings back to base.
Upon initial connection, it came up as three devices:
- A USB camera
- A read-only flash volume
- A removable media volume
The USB camera could be interacted with directly from Windows as a normal camera, although it had had the infra-red filter removed, which is inline with what the kickstarter describes. It probably uses infra-red to aid in iris recognition to minimise differences caused by different eye colours and to aid detection of a photo.
The image does look a tad weird though, totally hiding my beard:
The read-only flash volume contained the software (Windows and Mac) that managed the device and allow the enrolling of the device with iris and an optional password protection.
In terms of functionality, it did what it was meant to: it unlocked with a password and the iris detection worked about two times in every three. Simple experiments to fool the iris unlock, using my sprogs’ eyes (both roughly the same shade of blue as mine) and a photo of my eyes (now that was freaky) failed.
So, sounds good for them and bad for a blog post. Time to look at the hardware.
The hardware
At this point I had a little conversation with @2sec4u, who had bought a device, took it apart and bricked it. He sent me some photos of his device so I could get an idea of what the internals looked like.
These were enough to show me that it may be worth dissecting my own one. Unfortunately, the device was ultrasonically welded meaning that I couldn’t use a simple spudger to open it. I had to break out the grips of over indulgence to pop some of the clips through force. This does mean that it is unlikely to go back together again. Anyway, I could get some clear shots of the internal gubbins.
Below is the “back” of the device, which has one large MCU looking chip (highlighted in red) and a NAND flash chip (in green) hidden under a barcode sticker. We can also see the connector for the camera and the back of the camera unit (in purple.
Breaking a few of the plastic pegs allowed the “front” of the device to be seen:
Here we can see another MCUy type chip (in red); a third MCUy chip (in green), the camera with a quite reddy lens or filter on the outside (in blue) and two tssop8 chips (in purple).
Next step it to dig out the microscope to get some serial numbers and work out what these chips do.
For the back:
The red highlighted chip is a Genesys GL3523 USB 3.1 hub controller, I suspect this to handle the different USB modes. This was my first suspicion for a controlling MCU, but it is too dumb to handle what the device does.
The green highlighted chip has the right form factor for NAND flash, but has a generic code on it. As we’ll see later, through USB it enumerates as a Kingston device.
For the front:
The red highlighted chip is a Phison PS2251-09-V; this is a NAND to USB convertor. It is a common chip in USB sticks and is the most likely to be used as a main controller:
The green highlighted chip is a SONIX SN9C525GAJG which is the camera controller. I can’t find a datasheet for this, but it appears to be a slot in chip to convert a webcam to USB.
Finally, we have the purple highlighted chips, these surprised me, I was expecting a MOSFET or a voltage regulator, but no, they’re PUYA P25Q040H SPI NOR Flash. Unfortunately, being in a TSSOP8 package I don’t have a clip to read them in circuit and soldering to the pins will probably be beyond my ability, so I’d have to remove them from the circuit to get a sensible read. This will be done, but not until I’m happy to kill the device:
The interesting bit, from a hardware side is that there is not real central MCU – the Phison NAND controller has the most flexibility; but each chip is specific to a role.
What we have here is, literally, a USB stick with a hub and camera attached. That means most of the brains are in the software.
The software, or How It Works
This is where it gets difficult, the software was written in Visual C++, so it’s not easy to decompile; I had a neb over it in both IDA and Ghidra, but x86 is not my thing: I prefer efficient, well-designed machines code such as ARM.
So I took the lazy way – at some point when I authenticate to it, it must pass something to the device to unlock the private volume. If I could sniff this, I could maybe replay it. Normally I would dig out the Beagle USB sniffer, but I wasn’t anywhere near our office, so I was lazy: I used Wireshark.
Later versions of Wireshark support USBPcap, which is a version of WinPcap for USB – basically it allows me to sniff the USB traffic in Wireshark, rather than having to use a spliced cable and a logic analyser (as I have in the past).
As a bit of a segue: USB mass storage is a wrapper over SCSI commands; yes, for those of you over forty who remember the pain and agony of getting SCSI to work, this is probably already giving you flashbacks. Don’t worry, you don’t need to terminate these SCSI chains.
For those who’ve never had to fight SCSI, you don’t need to worry, there’s a few things you need to understand, the first is a LUN (Logical Unit Number), this is just a number used to identify a device. These are used by CDBs (Command Descriptor Block), a CDB is the format used to send commands, these can be of several pre-defined sizes and can be thought of as similar to opcodes in assembler or other wire protocols, such as SPI.
A common pattern of packets would be:
Where the top packet is sending a SCSI command with an opcode of 0x06 and receiving a response from the device. The direction follows USB terminology, from the host – i.e. “In” is to the host and “Out” is to the device.
If we look at the two above packets we can see the command is:
And the response is:
So obviously the command 06 05 00 00 00 00 00 00 00 00 00 00 is an information request which dumps information about the device.
The next step is to sniff whilst unlocking the device, and this is what I saw. First a SCSI command:
Followed by a transferring of data from the host to the device:
That string in red, that’s the password I set on the device. In the clear. Across an easy to sniff bus. The bit in blue is a 16 byte hash, which is about the right size for md5 and doesn’t match the hash of the password, so it could be the iris hash.
Let me just repeat this: this “unhackable” device unlocks the volume by sending a password through in clear text.
So what happens if I enter the wrong password? I’ll give you a clue: exactly the same thing. Let me just let you go “huh?” for a second. Yep, no matter what you enter it sends the same packet to the device. This means that the app itself must read this from the device and then resend it when it unlocks it. A quick search for my password in the sniff, shows me where it gets it from the device:
So, a SCSI command of 06 0a 00 00 00 00 00 00 80 56 52 00 returns the password in clear?
What else can we do. At this point it was time for some research.
Attacking the controller
There are a lot of different USB controllers out there, each offer different facilities, including passworded partitions, encrypted partitions etc. Phison is a common one which offers (according to its datasheets) private partitions and encryption.
The way it manages these is to use custom SCSI commands, mainly the opcode 06; this is followed by a sub opcode, in the above we can see opcodes 0b, 0a and 05. These are proprietary and not documented anywhere. But, this is the Internets, people have reversed some of these codes in the past. One of the most important resources here was https://github.com/brandonlw/Psychson which includes a tool to read firmware and memory from a Phison device.
Analysis of the code revealed a number of possible sub operation codes that could be used to improve the attack. Most of these didn’t work as expected (that repo is 5 years old), but information could be gleaned.
But first, some background: the CPU core at the heart of the Phison chip is an Intel 8051 clone. This chip, which is older than a lot of our consultants is quite commonly used in embedded hardware as it is relatively simple. Unlike x86 or ARM it uses the Harvard Architecture. This architecture splits memory into distinct program and data segments that cannot interact.
This makes little difference other than having to know that about the memory regions that can be accessed:
- SRAM is 256 bytes of RAM which include bit mapping and the memory mapped CPU registers
- XDATA is (slow) external memory
- CODE is the programmable memory (i.e. the firmware)
We are at the mercy of the SCSI extensions as to what we can access, but we need to know about the different memory areas to piece stuff together.
I have filtered out a lot of trial and error (and swearing) here; the worst bit that if you hit a bad code you got a 60 second time out and there was the potential to brick the device.
For this I used the linux utility sg_raw which can send raw command to a SCSI device. DO NOT USE THIS UTILITY UNLESS YOU KNOW WHAT YOU’RE DOING: IT CAN TRASH YOUR SCSI DRIVE.
Anyway, the sub opcode 05 appears to dump XDATA; this being what I think is one of the NOR flash chips. The command being:
06 05 52 41 HH LL 00 00 00 00 00 00
Where HH is the address high byte and LL is the address low byte. For some reason it hung at when HH was 225, so a simple command to dump all of XDATA was, 256 bytes at a time:
for i in `seq 0 224`;do sudo sg_raw -b -r 256 /dev/sdb 06 05 52 41 $(printf “%0x” $i) 00 00 00 00 00 00 00 2>/dev/null >>/tmp/out.bin;done
The password appears to be stored at 0x01b0, so the following script should dump it:
echo $(sudo sg_raw -b -r 16 /dev/sdb 06 05 52 41 01 b0 00 00 00 00 00 00 2>/dev/null)
Other sub opcodes are quite flaky and though appear to work, don’t return much of use. I found a number of ways to dump the bit of XDATA with the password in it.
Conclusion
So, a lot of complex SCSI commands were used to understand the controller side of the device, but obtaining the password/iris can be achieved by simply sniffing the USB traffic to get the password/hash in clear text.
The software collects the password first, then validates the user-entered password BEFORE sending the unlock password. This is a very poor approach given the unhackable claims and fundamentally undermines the security of the device.
Disclosure timeline
- Initial disclosure 4th April 2019
- Immediate response from vendor
- Full details provided 4th April 2019
- Chase on the 8th April as no response or acknowledgement of issues
- 9th April vendor acknowledges and advises they will fix – no date given
- 9th April ask when they expect to fix, notify customers and pause distribution due to fundamental security issue. Advised public disclosure date 9th May 2019 – no response
- 8th May final chase before disclosure
- 9th May disclosed
Advice
In the absence of a fix or any advice from EyeDisk, our advice to users of the device is to stop relying on it as a method of securing your data- unless you apply additional controls such as encrypting your data before you copy it to the device.
Our advice to vendors who wish to make the claim their device is unhackable, stop, it is a unicorn. Get your device tested and fix the issues discovered.