Vulnerabilities—If you can’t beat them, hide them
For hackers to attack an application, they first must know where to look in the code. Unless flaws are obvious, hackers need to reverse engineer the binary to mount the attack. The general attack flow is depicted below.
First, they need to find some vulnerability in the application, which usually requires reverse engineering. They can use off-the-shelf tools to perform the reverse engineering, converting the compiled binary application back into its source code. Then, they craft an exploit that takes advantage of that vulnerability—if it is a known vulnerability, an exploit may even already be developed and available for purchase on the black market. Finally, they attack by launching the exploit to the application. In a remote attack, like the popular SQL injection attack, this may involve sending a specially constructed message to the server application over the Internet. But if they have physical access to the device, such as a mobile phone or IoT device, then they can directly tamper with its storage, code, and memory.
The diagram above makes it evident that if the application had no vulnerabilities, attackers would be stopped in their tracks. In an ideal world, we’d eliminate all vulnerabilities and the security problem would largely be solved. Unfortunately, vulnerabilities are not going away any time soon.
Why is it so hard to get rid of vulnerabilities?
There is no shortage of vulnerabilities. At last count, the National Vulnerability Database managed by NIST contained over 134,801 vulnerabilities. Most large product development organizations have dedicated teams that track vulnerabilities and issue alerts accordingly. Even the most diligent of development teams still produce applications with vulnerabilities.
Eliminating vulnerabilities has proven to be a fundamentally difficult problem to solve. Even the best developers write code with bugs. Studies have shown that most software has 15-50 bugs per 1000 lines of code. It is not unusual for modern applications to contain millions of lines of code, meaning thousands of potential vulnerabilities to be exploited.
Vulnerabilities are not just due to bugs. Design flaws can be exploited, too. While some design flaws arise from poor security considerations during the design process, many are subtle and can go unnoticed for years, like the Heartbleed vulnerability. This attack on OpenSSL relied on exploiting a heartbeat mechanism built into the SSL protocol and existed in the wild for at least two years, although how long it was exploited is unknown.
The cost and complexity of eliminating vulnerabilities
Clearly, we want to identify known vulnerabilities in software and eliminate them. Application security testing tools can help with this problem and play an important role in a secure development lifecycle. But the discovery of a vulnerability in an application is only the first step toward mitigation. A patch needs to be created to fix the vulnerability, then that patch must be deployed. All of this takes time and money. According to a White Hat Security study, it takes an average of 150 days to fix vulnerabilities, with some industries taking significantly longer. Moreover, even if you have a patch, finding all of the systems with that vulnerability might not be possible.
Of course, we can only fix the vulnerabilities that we know about. Arguably, the most dangerous vulnerabilities are those which are still unknown to developers and users, but can be discovered by attackers. You can’t create and deploy a patch for a vulnerability that you don’t know about. But there is something you can do!
Dealing with unknown vulnerabilities—application shielding
The reality is that your software will always contain vulnerabilities whether you know about them or not. While it’s preferable to eliminate them entirely, application shielding plays an important role in protecting vulnerabilities that exist but are not yet known or cannot yet be patched. How so?
Instead of hoping that attackers won’t find exploits, and patching them when, inevitably, they do, application shielding makes it more difficult for attackers to achieve their objectives in the first place. It embeds defenses into the application to proactively prepare for attacks. For example, since hackers often rely on static analysis of the application code, obfuscation is one of the primary countermeasures against reverse engineering and discovery of vulnerabilities in code. When advanced obfuscation is applied, even if a hacker manages to reverse engineer the code, the information revealed is unreadable and essentially useless. So, even if vulnerabilities exist, they would be almost impossible to find. In other words, obfuscation adds a secure layer on top of the targeted code, which makes the exploitable parts of code indistinguishable from those that are bug-free.
Obfuscation is just one of the fundamental pillars of application shielding. Anti-tampering and other in-app protections, such as integrity protection, binary packing, anti-debug protection, and rooting detection, can greatly improve the security level of your application.
Learn more about application shielding techniques and methods in The practical guide to application hardening.
About Juris Olekss
A seasoned security professional, Juris has spent more than 17 years in the IT and security industries, with the majority dedicated to software security. Juris currently serves as a Senior Technical Writer for Intertrust’s whiteCryption application shielding solutions.