Researching The FAX Machine Attack Surface
FAX machines, although being a reminiscent of a not-so-far past, are still present in lots of office spaces and can be frequently used for business and legal communications. Most of its technology was developed decades ago and, quite probably, remained mostly unchanged over the years.
Legacy boxes, accessible via a phone call through the phone line and, frequently, connected to local networks via Ethernet. It sounds like a good plan for summer time research!
To be honest, we had no idea about how FAX communications worked. A pile of documents describing standards were not making things easier and we didn’t feel ready for jumping into hardware reversing just yet. Luckily, a bunch of free software projects implement exactly what a FAX machine usually does plus a bunch of additional features, with the bonus of having full access to the source code.
Armed with our code auditing hat, a handful of fuzzers and enough coffee stocked (just in case unexpected riots interrupt our caffeine supply), we were ready for our summer research. Off we go!
Software Faxing for Kids
So, faxes! They look like weird printers with a phone cord attached, make funny noises and can transfer page scans over the phone line at low speeds, what else could anybody need?
While FAX machines can be still spotted in any random office space around the world, software faxes could be their unpopular friends. A quick search around the interwebs did reveal a few projects that have been around for quite a long time. HylaFAX and its more frequently updated fork: HylaFAX+ seem to be the tool of trade for enterprise-class software faxing. eFAX and mgetty + sendFAX would be more lightweight alternatives for commandline faxing, while a whole range of other projects would contribute to the software faxing ecosystem: ICTFAX as a web-based solution, IAXmodem as a software modem bridging IAX-supporting PBXs (as Asterisk) and your FAX client, or spandsp as a library of DSP functions for telephony.
Roughly speaking, we could identify three communication layers:
- data layer, where the modems make noises and stablish a data channel between two parties, allowing them to exchange symbols,
- session layer, where the faxes negotiate the communication parameters (like the page format, page transmission speed, image compression),
- image/page layer, where the faxes encode/decode the page information, compress/decompress it, applies and check error-correction and compose the resulting document.
Depending how many of these layers are handled by the modem (either physical or emulated) we can identify different classes of devices:
- Class 1 modems handle the data layer, while relying on the FAX software for all the session and page processing,
- Class 2 modems handle the data and session layer, and leaves the image processing to the software side.
There are additional classes that bring additional capabilities (like different speeds). As we focused on Class 1 devices, we leave them out of this introduction.
So, armed with a faxing software (as HylaFAX) and a FAX modem that gives access to the phone line (either physically or software emulated) anybody can send and receive faxes from their commandline.
When sending a fax, all that’s required is an input document (as an image or a pdf file) and a destination phone number, while your chosen software would take care of dialing the remote party, encoding and transferring the data. When receiving a fax, a process would usually listen to incoming calls signaled through the modem serial port, receive all the information and drop it at the local filesystem or mail it to a user.
We were ready to uncover the secrets hidden at every layer of software faxing. For this, we packed a few components together:
- 2x old-school FAX machines from the 90s,
- 2x USB FAX modem,
- Cisco SPA112,
- HylaFAX, eFAX and mgetty,
Our setup would allow us to deploy a bunch of different configurations. Asterisk would be the main PBX and would be in charge of routing calls, providing a private phone network that would let our different components to dial each other without going to the public telephony network (PSTN). The Cisco SPA enabled us to physically connect the FAX machines and the usb modems to our Asterisk network, while IAXmodem modem emulation was perfect for an all-software setup. Finally, gdb and vim allowed us to spend countless hours reading source code and stepping through assembly.
In the meantime, a bunch of afl fuzzers were running during most of our research time, trying to abuse different blocks of code of the components we were studying. Our fuzzers were specially useful to test parts of the code that were complex and suspicious enough while we could continue reading code. Nonetheless, they were quick and efficient on finding crashes and weak code paths that needed our attention.
The Summer CVE Collection
During the last weeks we have been reporting to the software maintainers and requesting CVEs, with patches being shortly released.
Multiple vulnerabilities in Mgetty
This is a list of the vulnerabilities found and reported:
- CVE-2018-16741: shell injection via job description in Mgetty
- CVE-2018-16742: stack based buffer overflow via cli parameter in Mgetty
- CVE-2018-16743: stack based buffer overflow via cli parameter in Mgetty
- CVE-2018-16744: stack based buffer overflow via config parameter in Mgetty
- CVE-2018-16745: buffer overflow via config parameter in Mgetty
See https://www.x41-dsec.de/lab/advisories/x41-2018-007-mgetty/ for more.
Remote Code Execution in Hylafax
We were much less prolific while searching for vulnerabilities in Hylafax, although managed to find a remotely exploitable bug.
- CVE-2018-17141: a remote attacker can write to an unitialized pointer during a FAX reception session in Hylafax
See https://www.x41-dsec.de/lab/advisories/x41-2018-008-hylafax/ for more.
During our research, we found HylaFAX and HylaFAX+ quite featureful and complete solutions for FAX comms. They feel robust and smooth and got to communicate without problems with almost any use case we decided to throw at them. Their source code is (mostly) easy to read, and allowed us to better understand how all this FAX thingy works. It also revealed complex and crazy sometimes, as when you reach the point of ECM page transmissions.
It was while reading around those pieces of code related with page data transmission that we stumbled upon these lines:
A nice pattern for a buffer overflow, right? It was a promising bug that we tried to isolate and reach. This lines belong to FaxModem::recvPageDLEData(), and they are there for handling FAX reception when JPEG transmission is enabled. No boundary checks where there while buffering the whole received page.
// I don’t know, lets find out :)
Reaching The Vulnerable Code
We were hoping to trigger this bug while sending a FAX to the victim, transmit until reaching the out of bounds write to the heap-allocated buffer and, eventually, profit.
To be honest, we couldn’t.
Long story short:
HylaFAX does not officially support JPEG reception, and explicitly has this feature disabled while announcing its capabilities during the handshake that happens at the beginning of a FAX sessiom,
A malicious attacker could choose not to follow the protocol and enable the JPEG bit for the session parameters, whatever the receiving party announced as its capabilities,
HylaFAX would happily accept JPEG as the session transmission format and follow those codepaths it implements to handle this,
But it would also enable ECM (Error Correction Mode), following a completely different execution flow that does not include invoking FaxModem::recvPageDLEData(), but goes to FaxModem::writeECMData().
Kinda disappointed, we were ready to strike our vuln out of the bug list. But taking a look at the code that handles JPEG reception in ECM mode, it looked like this:
Does it look familiar? Lets make that thing explode! We prepared our proof of concept that would enable the JPEG flag, send enough data to overflow the buffer and, hopefully, overwrite some nice heap metadata on the go. We target our poc at the victim, hook gdb and wait for the magic to happen. The FAX transmission begins, the victim process crashes much faster than expected and, surprise, a segfault while trying to write to memory position 0.
Something was not as we expected it to be. In the end, the switch block responsible for (m)allocating memory for recvRow was not being executed, leaving recvRow uninitialized and pointing to whatever value was there before object construction.
Uninitialized pointers are interesting, as they won’t implicitly take a safe value during object construction, but will take their value from whatever garbage is present in their memory location when the object is instantiated.
Sadly, our summer research time was reaching its end. It was time for wrapping up and reporting to the vendors.
Vulnerability research in the FAX software field helped us better understand this technology and revealed the degree of complexity some of these systems can reach. Working with free software projects was a good recipe for quickly understanding every layer of FAX comms, while also made easier messing with interesting and suspicius pieces of code. As a side effect of our quest of better understanding this technology, those vulnerabilities found would be reported and (hopefully) fixed.
FAX systems have been around for decades. It was designed for reliably transmitting images over unreliable and noisy phone lines, and it reached this goal decades ago. Probably in legacy maintenance mode since then, not much innovation is required in the field and industry has shifted focus and efforts to other fields.
Bug hunting in codebases that have not suffered much attention since the 90s was fun but also challenging. While our research was very limited in scope and time, more persistent attackers with enough resources will surely find their way to reach reliable exploitability of these omnipresent, connected, legacy communication boxes.
So, have you already checked if your FAX machine whispers secrets at night?