Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

dumping existing firmware and showing cryptographic hashes #15

Closed
hodefoting opened this issue Jun 24, 2015 · 7 comments
Closed

dumping existing firmware and showing cryptographic hashes #15

hodefoting opened this issue Jun 24, 2015 · 7 comments

Comments

@hodefoting
Copy link

Given the scope of fwupd and the code it needs to communicate with various types of hardware with firmware, it seems natural to extend the functionality to be able to read back the existing firmwares (and apply a cryptographic hash to the dumped contents). This would permit running this on a booted system, and then later check against a reference dump. Or even compare with dumps on other machines of the same model. Such a preventive measure does not protect against malicious firmware that might be altering the readback behavior of the device; presenting a valid image. It will however raise the bar for writers of malicious firmwares. Like keyloggers in the embedded controllers of thinkpad as demonstrated in this talk: https://media.ccc.de/browse/congress/2010/27c3-4174-en-the_hidden_nemesis.html#video

@hughsie
Copy link
Member

hughsie commented Jun 25, 2015

I had a play at implementing this last night. It's trivial to do for ColorHug (which isn't so interesting) but kinda hard for BIOS -- which is probably the most useful thing :(

I tried using flashrom -r dump.bin on both my desktop and my laptop, but neither could work (active ME and unsupported laptop) which was my first thing to play with. Using dd if=/dev/mem I had to guess the offset and length and I couldn't find any values that could work for all hardware, and even if I did, the firmware doesn't need to expose all of itself in those ranges and can copy from shadow ram.

Video ROM is easily accessible find /sys/devices -name "rom" but I'm guessing this isn't so useful for hiding malicious firmware. I think co-operation with the hardware vendors is probably the only way to get proper access to read and write to the hardware properly. Ideas welcome :(

@hughsie
Copy link
Member

hughsie commented Jun 29, 2015

I've pushed some test code to master, which gives the following output when doing fwupdmgr verify:

 * Verifying firmware from device
969b5b9d-a475-f36b-fdf5-60f405d3dd4b    f21e1d2c969dedbefcf5acfdab4fa0c5ff111a57    No metadata
2082b5e0-7a64-478a-b1b2-e3404fab6dad    39efec8eb324085843376073c7c65c0a5f42c4c8    Failed: for v2.0.3 expected 40b59e37cb918f3241f65bc5ac2b90ab47b34e8c

This is with my ATI graphics card (no vendor support) and a ColorHug2 with a non-official image flashed. Is this something like what you envisaged?

@hodefoting
Copy link
Author

Yes - this is along the lines of what I was thinking, and I believe both NICs and GPUs might be suitable locations for hiding malicious code; these peripherals might have access to all of RAM and snoop/take screenshots and do other curious things.

@hughsie
Copy link
Member

hughsie commented Jun 30, 2015

We now support ATI, Nvidia and Intel graphics VBIOS -- there is a slight complication as some vendors have started putting the device serial number in the flash, and we probably also need to regenerate the internal checksums to make the hashes the same for identical hardware. We can also us the new NVIDIA signing certificates in the blob to verify the firmware too, although I don't know what is actually being signed (assumed just the option rom segment...).

@hughsie
Copy link
Member

hughsie commented Jul 1, 2015

You can also do:

$ fwupdmgr verify
e9b8eebd-b5f8-18d4-9fbd-d7da7711985c    f21e1d2c969dedbefcf5acfdab4fa0c5ff111a57    No metadata
$ find /sys/devices -name rom -exec sudo fwupdmgr verify-update /var/cache/app-info/xmls/fwupd-verify.xml {} \;
$ fwupdmgr verify
e9b8eebd-b5f8-18d4-9fbd-d7da7711985c    f21e1d2c969dedbefcf5acfdab4fa0c5ff111a57    OK
$ # flash the firmware
$ fwupdmgr verify
e9b8eebd-b5f8-18d4-9fbd-d7da7711985c    5c946b3950deaf7b102e75be488052afd4dcf16 Failed: for v013.012.000.019.000000 expected f21e1d2c969dedbefcf5acfdab4fa0c5ff111a57

Or you can generate metadata using .rom files from something like http://www.techpowerup.com/vgabios/ -- although we don't actually trust the data there, so I'm hesitant to add it. What we really need is vendors to securely add known-good hashes to the database, or to get them to ship signing certificates like Nvidia have started doing (although, we still need to RE the NVGI format...)

@comotion
Copy link

comotion commented Jul 1, 2015

Nice. Research supports the feasability of firmware attacks on NICs, GPUs and harddrives among other devices, see for instance http://ids.cs.columbia.edu/sites/default/files/ndss-2013.pdf

@hughsie
Copy link
Member

hughsie commented Jul 22, 2015

I'll close this issue now we have all the pieces in place; I'll add support for more hardware as this becomes available. I'm still super-keen to be able to dump the thinkpad EC.

@hughsie hughsie closed this as completed Jul 22, 2015
superm1 pushed a commit that referenced this issue Feb 13, 2019
The order of events when casting causes an access to unintended memory.

```
0x00007ffff7bc19df in fwupd_guid_to_string (guid=0x8000000090d0, flags=FWUPD_GUID_FLAG_MIXED_ENDIAN) at ../libfwupd/fwupd-common.c:550
550		memcpy (&gnat, guid, sizeof(gnat));
(gdb) bt
 #0  0x00007ffff7bc19df in fwupd_guid_to_string (guid=0x8000000090d0, flags=FWUPD_GUID_FLAG_MIXED_ENDIAN) at ../libfwupd/fwupd-common.c:550
 #1  0x00007fffdbddd195 in fu_nvme_device_get_guid_safe (buf=0x7fffffffce70 "\\\034\\\034FI83Q060610103M66   BC501 NVMe SK hynix 128GB", ' ' <repeats 15 times>, "80001C0T\004", <incomplete sequence \344\254>, addr_start=3110) at ../plugins/nvme/fu-nvme-device.c:83
 #2  0x00007fffdbddd60c in fu_nvme_device_parse_cns_maybe_dell (self=0x5555558cc8a0, buf=0x7fffffffce70 "\\\034\\\034FI83Q060610103M66   BC501 NVMe SK hynix 128GB", ' ' <repeats 15 times>, "80001C0T\004", <incomplete sequence \344\254>) at ../plugins/nvme/fu-nvme-device.c:201
 #3  0x00007fffdbddda64 in fu_nvme_device_parse_cns (self=0x5555558cc8a0, buf=0x7fffffffce70 "\\\034\\\034FI83Q060610103M66   BC501 NVMe SK hynix 128GB", ' ' <repeats 15 times>, "80001C0T\004", <incomplete sequence \344\254>, sz=4096, error=0x7fffffffe008) at ../plugins/nvme/fu-nvme-device.c:295
 #4  0x00007fffdbddde68 in fu_nvme_device_setup (device=0x5555558cc8a0, error=0x7fffffffe008) at ../plugins/nvme/fu-nvme-device.c:376
 #5  0x0000555555587850 in fu_device_setup (self=0x5555558cc8a0, error=0x7fffffffe008) at ../src/fu-device.c:2076
 #6  0x0000555555587412 in fu_device_open (self=0x5555558cc8a0, error=0x7fffffffe008) at ../src/fu-device.c:1920
 #7  0x000055555558aa88 in fu_device_locker_new_full (device=0x5555558cc8a0, open_func=0x5555555872cb <fu_device_open>, close_func=0x555555587424 <fu_device_close>, error=0x7fffffffe008)
    at ../src/fu-device-locker.c:154
 #8  0x000055555558a925 in fu_device_locker_new (device=0x5555558cc8a0, error=0x7fffffffe008) at ../src/fu-device-locker.c:104
 #9  0x00007fffdbddc4cd in fu_plugin_udev_device_added (plugin=0x5555558a6420, device=0x5555558c6300, error=0x7fffffffe008) at ../plugins/nvme/fu-plugin-nvme.c:24
 #10 0x0000555555592cbf in fu_plugin_runner_udev_device_added (self=0x5555558a6420, device=0x5555558c6300, error=0x7fffffffe070) at ../src/fu-plugin.c:1281
 #11 0x000055555557f0a8 in fu_engine_udev_device_add (self=0x5555557f9840, udev_device=0x5555558e5900) at ../src/fu-engine.c:3491
 #12 0x000055555557f480 in fu_engine_enumerate_udev (self=0x5555557f9840) at ../src/fu-engine.c:3555
 #13 0x0000555555580fc6 in fu_engine_load (self=0x5555557f9840, error=0x7fffffffe2c8) at ../src/fu-engine.c:4117
 #14 0x0000555555566567 in fu_util_start_engine (priv=0x5555557eeb20, error=0x7fffffffe2c8) at ../src/fu-tool.c:138
 #15 0x00005555555674e2 in fu_util_get_devices (priv=0x5555557eeb20, values=0x7fffffffe5d8, error=0x7fffffffe2c8) at ../src/fu-tool.c:490
 #16 0x0000555555566aff in fu_util_run (priv=0x5555557eeb20, command=0x7fffffffe81a "get-devices", values=0x7fffffffe5d8, error=0x7fffffffe2c8) at ../src/fu-tool.c:242
 #17 0x000055555556a514 in main (argc=2, argv=0x7fffffffe5c8) at ../src/fu-tool.c:1445

```
hughsie pushed a commit that referenced this issue Feb 13, 2019
The order of events when casting causes an access to unintended memory.

```
0x00007ffff7bc19df in fwupd_guid_to_string (guid=0x8000000090d0, flags=FWUPD_GUID_FLAG_MIXED_ENDIAN) at ../libfwupd/fwupd-common.c:550
550		memcpy (&gnat, guid, sizeof(gnat));
(gdb) bt
 #0  0x00007ffff7bc19df in fwupd_guid_to_string (guid=0x8000000090d0, flags=FWUPD_GUID_FLAG_MIXED_ENDIAN) at ../libfwupd/fwupd-common.c:550
 #1  0x00007fffdbddd195 in fu_nvme_device_get_guid_safe (buf=0x7fffffffce70 "\\\034\\\034FI83Q060610103M66   BC501 NVMe SK hynix 128GB", ' ' <repeats 15 times>, "80001C0T\004", <incomplete sequence \344\254>, addr_start=3110) at ../plugins/nvme/fu-nvme-device.c:83
 #2  0x00007fffdbddd60c in fu_nvme_device_parse_cns_maybe_dell (self=0x5555558cc8a0, buf=0x7fffffffce70 "\\\034\\\034FI83Q060610103M66   BC501 NVMe SK hynix 128GB", ' ' <repeats 15 times>, "80001C0T\004", <incomplete sequence \344\254>) at ../plugins/nvme/fu-nvme-device.c:201
 #3  0x00007fffdbddda64 in fu_nvme_device_parse_cns (self=0x5555558cc8a0, buf=0x7fffffffce70 "\\\034\\\034FI83Q060610103M66   BC501 NVMe SK hynix 128GB", ' ' <repeats 15 times>, "80001C0T\004", <incomplete sequence \344\254>, sz=4096, error=0x7fffffffe008) at ../plugins/nvme/fu-nvme-device.c:295
 #4  0x00007fffdbddde68 in fu_nvme_device_setup (device=0x5555558cc8a0, error=0x7fffffffe008) at ../plugins/nvme/fu-nvme-device.c:376
 #5  0x0000555555587850 in fu_device_setup (self=0x5555558cc8a0, error=0x7fffffffe008) at ../src/fu-device.c:2076
 #6  0x0000555555587412 in fu_device_open (self=0x5555558cc8a0, error=0x7fffffffe008) at ../src/fu-device.c:1920
 #7  0x000055555558aa88 in fu_device_locker_new_full (device=0x5555558cc8a0, open_func=0x5555555872cb <fu_device_open>, close_func=0x555555587424 <fu_device_close>, error=0x7fffffffe008)
    at ../src/fu-device-locker.c:154
 #8  0x000055555558a925 in fu_device_locker_new (device=0x5555558cc8a0, error=0x7fffffffe008) at ../src/fu-device-locker.c:104
 #9  0x00007fffdbddc4cd in fu_plugin_udev_device_added (plugin=0x5555558a6420, device=0x5555558c6300, error=0x7fffffffe008) at ../plugins/nvme/fu-plugin-nvme.c:24
 #10 0x0000555555592cbf in fu_plugin_runner_udev_device_added (self=0x5555558a6420, device=0x5555558c6300, error=0x7fffffffe070) at ../src/fu-plugin.c:1281
 #11 0x000055555557f0a8 in fu_engine_udev_device_add (self=0x5555557f9840, udev_device=0x5555558e5900) at ../src/fu-engine.c:3491
 #12 0x000055555557f480 in fu_engine_enumerate_udev (self=0x5555557f9840) at ../src/fu-engine.c:3555
 #13 0x0000555555580fc6 in fu_engine_load (self=0x5555557f9840, error=0x7fffffffe2c8) at ../src/fu-engine.c:4117
 #14 0x0000555555566567 in fu_util_start_engine (priv=0x5555557eeb20, error=0x7fffffffe2c8) at ../src/fu-tool.c:138
 #15 0x00005555555674e2 in fu_util_get_devices (priv=0x5555557eeb20, values=0x7fffffffe5d8, error=0x7fffffffe2c8) at ../src/fu-tool.c:490
 #16 0x0000555555566aff in fu_util_run (priv=0x5555557eeb20, command=0x7fffffffe81a "get-devices", values=0x7fffffffe5d8, error=0x7fffffffe2c8) at ../src/fu-tool.c:242
 #17 0x000055555556a514 in main (argc=2, argv=0x7fffffffe5c8) at ../src/fu-tool.c:1445

```
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

3 participants