 Hello everyone, thank you for attending the talk. I'm Slava, I've been doing security research at Checkpoint for many years, Roberts Engineering and Vulnerability Research is my daily work. Today I want to share my experience of hacking Amazon Kindle reader devices using a crafted ebook. Personally, I use Kindle a lot, but I've never heard about the malicious book. It was a reason for me to research how to create such a book that could be used remotely and take full control of a Kindle device. Amazon has announced that since 2007 they have sold tens of millions of Kindle devices. It's impressive. I tried to find some statistics about that and yes, the Amazon Kindle is the most widely owned e-reading device in the USA. There were 10 generations of Kindle readers on the market and almost all of them are still supported. Typically, users connect their Kindle devices to a Wi-Fi network and Wi-Fi protocol stack can be used as entry point to attack the Kindle, but using an ebook to reach a device is much easier and mass attacks are possible. What ways does Amazon offer to send a book to a Kindle? If we are talking about your open device, you can log into your Amazon account and use the prepared Chrome extension, PC or Android applications or just use USB cable to transfer the file. Another way is to use the Send to Kindle by email Amazon service to send a book as an email attachment. In this case, you should know the unique email address of the targeted Kindle device, including six random characters, so it's difficult to brute force. In addition, the ability to spoof was fixed by Amazon a year ago and now the recipient needs to confirm the transfer if it was sent from an unapproved email address. All of the above suggests that efficient campaign is only way for the attacker to reach your Kindle. Dozens of free online libraries are open to upload and download ebooks. An attacker can easily upload a malicious book for free access because no one expects to see malware targeting the Kindle. Most libraries only care about the correctness of the metadata or the uploaded book. So when downloading an ebook from an online library, you can never be sure of its content. Now let's deal with the Kindle device itself. The latest version of the Kindle reader firmware is publicly available on the official Amazon website. The source code is also partially available there, but there is no source code for components responsible for parsing and rendering books. In addition, iJail broke one of my Kindles. It's clear that the research will go faster if you can see running processes and can debug Kindle services. The most general way to jailbreak is through the serial port. Let's take a quick look at the Kindle architecture. Basically, the Kindle OS is the Linux kernel with a set of native programs, mainly provided by Busybox, the Lipsy subsystem for inter-process communication, and the Java and WebKit subsystem for user interface and services. The Lipsy is a D-Bus-based IPC library and its environment that links all Kindle components together. A Kindle process can use this library to start apps, expose application settings, listen for or emit events. For example, a WebKit application can use the Lipsy to interact with a Java service or a native application. Most of the UI is written in Java and the Java subsystem, the framework, implements Lipsy handlers for providing services and for providing a user interface, so-called booklets. The WebKit subsystem, I mean HTML5 and JavaScript, is another way to create UI elements. The built-in experimental browser is a part of the WebKit subsystem. The pillow is a library that allows access to the Lipsy from JavaScript. Good. Who passes e-books? You put a new book on your Kindle device. Who is going to handle the file first? The scanner service periodically scans the documents directory for new files and, depending on the file extension, uses one of the extractor libraries to extract metadata from the e-book. All extractors are listed in the app registry database and there is a handler for each of the supported Kindle e-book formats. If the scanner does not manage file extension or a parsing error occurs, the book will not be shown to the user. I did not go deep into the scanning process because extracting metadata is too simple an operation to suggest parsing errors. All that matters to me is that the malware book must have the correct metadata. After the scanner does the job, a thumbnail of the new book is displayed on the home screen and from this moment on the Java framework is responsible for opening the book when you click on it. The archive files that implement the logic for opening and rendering e-books can be found in the Opt Amazon e-book lib directory. Primarily, these are just listed on the slide. In this research, I decided to focus my attention on the PDF file format as it is one of the most common and yet the same time complex formats. On this slide you can see the function to open PDF books implemented in the PDF Reader Implejars. It is only a wrapper over the native open PDF document function with a body in the libpdf client-genise-all library. The libpdf client-genise-all IP starts the PDF reader service forking the process and synchronously sends it an open-book message. via the open-source HTTP client-server-library-libs-soup-soap. In fact, it sends a GET request to a specific local host URL. The PDF Reader service defines dozens of soup-handlers for the high-level PDF operations, including open-book and start rendering once we are interested in. The libfoxit-wrapper-so, written by Amazon, provides an API for working with PDF files. I want to note only three significant functions on the libfoxit-wrapper-so library. These functions are good entry points for fuzzing a PDF tree structure, but I was lucky to find only a lot of now-de-references. As the name implies, libfoxit-wrapper-so is a wrapper over the popular foxypdf SDK, presented on Kindle devices by libpdf-embedded-so. This is a closed-source library, proprietary to foxy software incorporated. Next, I decided to focus my attention on PDF stream filters and I tried to fuzz the foxypdf SDK library. This is the fuzzing model I used, it's pretty classic, I used a combination of American fuzzing loop and quick emulator, the host machine is Ubuntu. A simple search for the word cpdf and codec in the foxypdf library allowed me to find all the possible stream filters. Let's take a look at one of them as an example. As you can see, an image in one with JBIG-2 filter is declared, JBIG-2 is an image compression standard for B-level images. The JBIG-2 segments the input page into regions, text, halftone image, refinement and others. These regions are held in the JBIG-2 global stream. When rendering a PDF page, the library parses the JBIG-2 global stream and reconstructs the image. The JBIG-2 model object defined in the foxyp library is responsible for decoding JBIG-2 compressed images. Its start-decode method is declared as shown on the slide and I used the start-decode function as the fuzzing entry point and permuted the image size, the image stream and the JBIG-2 global stream. As a result, available vulnerability in the JBIG-2 decoding algorithm was found. Let's take a look at the following JBIG-2 global stream. Two page regions are defined here, the image information region and the refinement region. The refinement region contains the information needed to refine the image, including coordinates of the refining rectangle. In our case, an oversized rectangle is defined, what's happened in this case. The JBIG-2 algorithm tries to expand the base image to new dimensions. The height of the new image is recalculated as old height plus y and old height plus y multiplied by the stride. Hip memory is allocated for the resized image. But there is a mistake in the expanding function and missed check for int max. The 32-bit register overflows and 100 bytes is allocated for the image instead of 4000000. By using refinement regions, we can refine the data outside of the image and get the arbitrary write primitive. In the following example, the second refinement region overrides 16 bytes as offset 12340 bytes from the beginning of the image in the heap. The indicated data envelope will be decompressed by the JBIG-2 algorithm and then xort with the heap content. We can create any number of refinement regions and overwrite parts of memory that are at distance from each other. In addition, the fact that the writing is done through a xor operation allows us to fix on specific bits of memory and bypass ACLR protection if required. As I mentioned, the Foxit library is part of the PDF reader process. The data and heap segments of this process are read, write, execute. ACLR is built into the Linux kernel and is controlled by the parameter ProxySkernel randomize via space. Its default value on Kindle devices is 1, which means the base address of the data segment is located immediately after the end of the executable code segment. In other words, there is no randomization for the data segment and the heap. These two facts make exploiting the vulnerability trivial. Let's start up the PDF reader service lowers itself to the permission of the framework user. To prove permissions of our payload, I create the following simple bash file in the framework working directory and launch it. The UIT 9000 of the framework user was printed. Well, now we have remote code execution vulnerability in the context of the PDF reader process, which operates with the framework user writes. We can send libc messages, access special internal files, but we are still limited. We want to be a route to reset all restrictions, so the second stage of the research was to find a local privilege escalation vulnerability that allows the framework user to run a code under the root user. The framework user has read write access to the app registry database. It means that we can fix a database entry using the libsqlite.so library or by simply editing the file. We need to patch one of the command entries in the properties table. For example, I patched the browser-related entry I set in the value field the path to the payload script created using the first PDF vulnerability. Next, the framework user can request the app manager represented by the app MGRD service to start an arbitrary application. We can send a libc message to open the browser using the libc.so library. The presented shell command will do the same. The app manager is responsible for launching built-in apps. To do this, it listens for the appropriate libc events. And to start the browser app, it reads the relevant entry from the application registry and executes the command specified in the value field. As we patched this database entry, our payloadsh script will be launched. The app manager service has root writes and the uit0 will be printed by the payload script. So by combining these two discovered vulnerabilities, any malicious payload can be run as root. Now let's take a look at a small demo in which I use a reverse shell to remotely control a Kindle device. On the left, you can see a Kindle device. The book called a book is our malicious file. On the right, you can see the Metasploit server that I opened on Google Cloud. The user clicked on the book and at that point the payload hidden in the book connects the remote server providing the reverse shell and then locks the user screen with a window. As you can see, we gained the root permissions so we can do whatever we want. For example, we can steal Amazon account cookies and we can take a look at device private keys. Here we go. To summarize, I demonstrated how an ebook can be malware. As the malware code is executed with root user writes, just opening such a book can lead to irreparable damage. That attacker can delete or sell your ebooks, taking money for themselves, can break your Kindle or convert to a bot. Attack other devices in your local network and more. The discovered vulnerabilities were reported to Amazon in February 2021 and now both are fixed. Thank you for your attention. You can find many good security researchers on the Checkpoint Research blog.