RESEARCH | August 2, 2018

Discovering and Exploiting a Vulnerability in Android’s Personal Dictionary (CVE-2018-9375)

I was auditing an Android smartphone, and all installed applications were in scope. My preferred approach, when time permits, is to manually inspect as much code as I can. This is how I found a subtle vulnerability that allowed me to interact with a content provider that was supposed to be protected in recent versions of Android: the user’s personal dictionary, which stores the spelling for non-standard words that the user wants to keep.

While in theory access to the user’s personal dictionary should be only granted to privileged accounts, authorized Input Method Editors (IMEs), and spell checkers, there was a way to bypass some of these restrictions, allowing a malicious application to update, delete, or even retrieve all the dictionary’s contents without requiring any permission or user interaction.

This moderate-risk vulnerability, classified as elevation of privilege and fixed on June 2018, affects the following versions of Android: 6.0, 6.0.1, 7.0, 7.1.1, 7.1.2, 8.0, and 8.1.

User’s Personal Dictionary
Android provides a custom dictionary that can be customized manually or automatically, learning from the user’s typing. This dictionary can be usually accessed from “Settings → Language & keyboard → Personal dictionary” (sometimes under “Advanced” or slightly different options). It may contain sensitive information, such as names, addresses, phone numbers, emails, passwords, commercial brands, unusual words (may include illnesses, medicines, technical jargon, etc.), or even credit card numbers.

android custom personal dictionary

A user can also define a shortcut for each word or sentence, so instead of typing your full home address, you can add an entry and simply write the associated shortcut (e.g. “myhome”) for its autocompletion.

defining personal dictionary shortcut

Internally, the words are stored in a SQLite database which simply contains a table named “words” (apart from the “android_metadata”). This table’s structure has six columns:

  • _id (INTEGER, PRIMARY KEY)
  • word (TEXT)
  • frequency (INTEGER)
  • locale (TEXT)
  • appid (INTEGER)
  • shortcut (TEXT)

Our main interest will be focused on the “word” column, as it contains the custom words, as its name suggests; however, all remaining columns and tables in the same database would be accessible as well.

Technical Details of the Vulnerability
In older versions of Android, read and write access to the personal dictionary was protected by the following permissions, respectively:

  • android.permission.READ_USER_DICTIONARY
  • android.permission.WRITE_USER_DICTIONARY

This is no longer true for newer versions. According to the official documentation1: “Starting on API 23, the user dictionary is only accessible through IME and spellchecker”. The previous permissions were replaced by internal checks so, theoretically, only privileged accounts (such as root and system), the enabled IMEs, and spell checkers could access the personal dictionary content provider (content://user_dictionary/words).

We can check the AOSP code repository and see how in one the changes2, a new private function named canCallerAccessUserDictionary was introduced and was invoked from all the standard query, insert, update, and delete functions in the UserDictionary content provider to prevent unauthorized calls to these functions.

While the change seems to be effective for both query and insert functions, the authorization check happens too late in update and delete, introducing a security vulnerability that allows any application to successfully invoke the affected functions via the exposed content provider, therefore bypassing the misplaced authorization check.

In the following code for the UserDictionaryProvider class3, pay attention to the highlighted fragments and see how the authorization checks are performed after the database would be already altered:

@Override

public int delete(Uri uri, String where, String[] whereArgs) {
   SQLiteDatabase db = mOpenHelper.getWritableDatabase();
   int count;
   switch (sUriMatcher.match(uri)) {
      case WORDS:
          count = db.delete(USERDICT_TABLE_NAME, where, whereArgs);
          break;
 
      case WORD_ID:
          String wordId = uri.getPathSegments().get(1);
          count = db.delete(USERDICT_TABLE_NAME, Words._ID + "=" + wordId
               + (!TextUtils.isEmpty(where) ? " AND (" + where + ')' : ""), whereArgs);
          break;
 
       default:
          throw new IllegalArgumentException("Unknown URI " + uri);
   }
 
   // Only the enabled IMEs and spell checkers can access this provider.
   if (!canCallerAccessUserDictionary()) {
       return 0;
   }

   getContext().getContentResolver().notifyChange(uri, null);
   mBackupManager.dataChanged();
   return count;
}


@Override

public int update(Uri uri, ContentValues values, String where, String[] whereArgs) {
   SQLiteDatabase db = mOpenHelper.getWritableDatabase();
   int count;
   switch (sUriMatcher.match(uri)) {
      case WORDS:
         count = db.update(USERDICT_TABLE_NAME, values, where, whereArgs);
         break;

      case WORD_ID:
         String wordId = uri.getPathSegments().get(1);
         count = db.update(USERDICT_TABLE_NAME, values, Words._ID + "=" + wordId
+ (!TextUtils.isEmpty(where) ? " AND (" + where + ')' : ""), whereArgs);
         break;

      default:
         throw new IllegalArgumentException("Unknown URI " + uri);
   }

   // Only the enabled IMEs and spell checkers can access this provider.
   if (!canCallerAccessUserDictionary()) {
      return 0;
   }

   getContext().getContentResolver().notifyChange(uri, null);
   mBackupManager.dataChanged();
   return count;
}

Finally, notice how the AndroidManifest.xml file does not provide any additional protection (e.g. intent filters or permissions) to the explicitly exported content provider:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
       package="com.android.providers.userdictionary"
       android:sharedUserId="android.uid.shared">

   <application android:process="android.process.acore"
       android:label="@string/app_label"
       android:allowClearUserData="false"
       android:backupAgent="DictionaryBackupAgent"
       android:killAfterRestore="false"
       android:usesCleartextTraffic="false"
       >

       <provider android:name="UserDictionaryProvider"
          android:authorities="user_dictionary"
          android:syncable="false"
          android:multiprocess="false"
          android:exported="true" />

   </application>
</manifest>

It is trivial for an attacker to update the content of the user dictionary by invoking code like the following from any malicious application, without the need to ask for any permission:

ContentValues values = new ContentValues();
values.put(UserDictionary.Words.WORD, "IOActive");

getContentResolver().update(UserDictionary.Words.CONTENT_URI, values,
        null, null);

It would be also trivial to delete any content, including the entire personal dictionary:

getContentResolver().delete(UserDictionary.Words.CONTENT_URI, null, null);

Both methods (update and delete) are supposed to return the number of affected rows, but in this case (for non-legitimate invocations) they will always return zero, making it slightly more difficult for an attacker to extract or infer any information from the content provider.

At this point, it may appear that this is all we can do from an attacker perspective. While deleting or updating arbitrary entries could be a nuisance for the end user, the most interesting part is accessing personal data.

Even if the query function is not directly affected by this vulnerability, it is still possible to dump the entire contents by exploiting a time-based, side-channel attack. Since the where argument is fully controllable by the attacker, and due to the fact that a successful update of any row takes more time to execute than the same statement when it does not affect any row, the attack described below was proven to be effective.

Simple Proof of Concept
Consider the following code fragment running locally from a malicious application:

ContentValues values = new ContentValues();
values.put(UserDictionary.Words._ID, 1);

long t0 = System.nanoTime();
for (int i=0; i<200; i++) {
    getContentResolver().update(UserDictionary.Words.CONTENT_URI, values,
                    "_id = 1 AND word LIKE 'a%'", null);
}
long t1 = System.nanoTime();

Invoking the very same statement enough times (e.g. 200 times, depending on the device), the time difference (t1-t0) between an SQL condition that evaluates to “true” and the ones that evaluate to “false” will be noticeable, allowing the attacker to extract all the information in the affected database by exploiting a classic time-based, Boolean blind SQL injection attack.

Therefore, if the first user-defined word in the dictionary starts with the letter “a”, the condition will be evaluated to “true” and the code fragment above will take more time to execute (for example, say 5 seconds), compared to the lesser time required when the guess is false (e.g. 2 seconds), since no row will actually be updated in that case. If the guess was wrong, we can then try with “b”, “c”, and so on. If the guess is correct, it means that we know the first character of the word, so we can proceed with the second character using the same technique. Then, we can move forward to the next word and so on until we dump the entire dictionary or any filterable subset of rows and fields.

To avoid altering the database contents, notice how we updated the “_id” column of the retrieved word to match its original value, so the inner idempotent statement will look like the following:

UPDATE words SET _id=N WHERE _id=N AND (condition)

If the condition is true, the row with identifier “N” will be updated in a way that doesn’t actually change its identifier, since it will be set to its original value, leaving the row unmodified. This is a non-intrusive way to extract data using the execution time as a side-channel oracle.

Because we can replace the condition above with any sub-select statement, this attack can be extended to query any SQL expression supported in SQLite, such as:

  • Is the word ‘something’ stored in the dictionary?
  • Retrieve all 16-character words (e.g. credit card numbers)
  • Retrieve all words that have a shortcut
  • Retrieve all words that contain a dot

Real-world Exploitation
The process described above can be fully automated and optimized. I developed a simple Android application to prove its exploitability and test its effectiveness.

The proof-of-concept (PoC) application is based on the assumption that we can blindly update arbitrary rows in the UserDictionary database through the aforementioned content provider. If the inner UPDATE statement affects one or more rows, it will take more time to execute. This is essentially all that we will need in order to infer whether an assumption, in the form of a SQL condition, is evaluated to true or false.

However, since at this initial point we don’t have any information about the content (not even the values of the internal identifiers), instead of iterating through all possible identifier values, we’ll start with the row with the lowest identifier and smash the original value of its “frequency” field to an arbitrary number. This step could be done using different valid approaches.

Because several shared processes will be running at the same time in Android, the total elapsed time for the same invocation will vary between different executions. Also, this execution time will depend on each device’s processing capabilities and performance; however, from a statistical perspective, repeating the same invocation a significant amount of iterations should give us a differentiable measure on average. That’s why we’ll need to adjust the number of iterations per device and current configuration (e.g. while in battery saving mode).

Although I tried with a more complex approach first to determine if a response time should be interpreted as true or false, I ended up implementing a much simpler approach that led to accurate and reliable results. Just repeat the same number of requests that always evaluate to “true” (e.g. “WHERE 1=1”) and “false” (e.g. “WHERE 1=0”) and take the average time as the threshold to differentiate them. Measured times greater than the threshold will be interpreted as true; otherwise, as false. It’s not AI or big data, nor does it use blockchain or the cloud, but the K.I.S.S. principle applies and works!

differentiate the correct and wrong assumptions

Once we have a way to differentiate between correct and wrong assumptions, it becomes trivial to dump the entire database. The example described in the previous section is easy to understand, but it isn’t the most efficient way to extract information in general. In our PoC, we’ll use the binary search algorithm4 instead for any numeric query, using the following simple approach:

  • Determine the number of rows of the table (optional)
    • SELECT COUNT(*) FROM words
  • Determine the lowest identifier
    • SELECT MIN(_id) FROM words
  • Determine the number of characters of the word with that identifier
    • SELECT length(word) FROM words WHERE _id=N
  • Iterate through that word, extracting character by character (in ASCII/Unicode)
    • SELECT unicode(substr(word, i, 1)) FROM words WHERE _id=N
  • Determine the lowest identifier which is greater than the one we got and repeat
    • SELECT MIN(_id) FROM words WHERE _id > N

Remember that we can’t retrieve any numeric or string value directly, so we’ll need to translate these expressions into a set of Boolean queries that we can evaluate to true or false, based on their execution time. This is how the binary search algorithm works. Instead of querying for a number directly, we’ll query: “is it greater than X?” repeatedly, adjusting the value of X in each iteration until we find the correct value after log(n) queries. For instance, if the current value to retrieve is 97, an execution trace of the algorithm will look like the following:

Iteration Condition Result Max Min Mid
255 0 127
1 Is N > 127? No 127 0 63
2 Is N > 63? Yes 127 63 95
3 Is N > 95? Yes 127 95 111
4 Is N > 111? No 111 95 103
5 Is N > 103? No 103 95 99
6 Is N > 99? No 99 95 97
7 Is N > 97? No 97 95 96
8 Is N > 96? Yes 97 96 96

 

The Proof-of-Concept Exploitation Tool
The process described above was implemented in a PoC tool, shown below. The source code and compiled APK for this PoC can be accessed from the following GitHub repository: https://github.com/IOActive/AOSP-ExploitUserDictionary

Let’s have a look at its minimalistic user interface and explain its singularities.

proof of concept exploitation tool

The first thing the application does is attempt to access the personal dictionary content provider directly, querying the number of entries. Under normal circumstances (not running as root, etc.), we should not have access. If for any reason we achieve direct access, it doesn’t make sense to exploit anything using a time-based, blind approach, but even in that case, you’ll be welcome to waste your CPU cycles with this PoC instead of mining cryptocurrencies.

As described before, there are only two parameters to adjust:

  • Initial number of iterations: How many times will the same call be repeated to get a significant time difference.
  • Minimum time threshold (in milliseconds): How much time will be considered the lowest acceptable value.

Although the current version of the tool will adjust them automatically for us, in the very first stage everything was manual and the tool was simply taking these parameters as they were provided, so this is one of the reasons why these controls exist.

In theory, the larger these numbers are, the better accuracy we’ll get, but the extraction will be slower. If they are smaller, it will run faster, but it’s more likely to obtain inaccurate results. This is why there is a hardcoded minimum of 10 iterations and 200 milliseconds.

If we press the “START” button, the application will start the auto-adjustment of the parameters. First, it will run some queries and discard the results, as the initial ones were usually quite high and not representative. Then, it will execute the initial number of iterations and estimate the corresponding threshold. If the obtained threshold is above the minimum we configured, then it will test the estimated accuracy by running 20 consecutive queries, alternating true and false statements. If the accuracy is not good enough (only one mistake will be allowed), then it will increase the number of iterations and repeat the process a set number of times until the parameters are properly adjusted or give up and exit if the conditions couldn’t be satisfied.

Once the process is started, some controls will be disabled, and we’ll see the current verbose output in the scrollable log window below (also via logcat) where we can see, among other messages, the current row identifier, all SQL subqueries, the total time, and the inferred trueness. The retrieved characters will appear in the upper line as soon as they’re extracted.

verbise output of scrollable log window

Finally, the “UPD” and “DEL” buttons on the right are completely unrelated to the time-based extraction controls, and they simply implement direct calls to the content provider to perform an UPDATE and DELETE, respectively. They were intentionally limited to affect the words starting with “123” only. This was done to avoid accidental deletions of any personal dictionary, so in order to test these methods, we’ll need to add this entry manually, unless we had it already.

Demo
Probably the easiest way to summarize the process is watching the tool in action in the following videos, recorded in a real device.

Additional Considerations
There is usually a gap between theory and practice, so I’d also like to share some of the issues I faced during the design and development of this PoC. First, bear in mind that the tool is simply a quick and dirty PoC. Its main goal was to prove that the exploitation was possible and straightforward to implement, and that’s why it has several limitations and doesn’t follow many of the recommended programming best practices, as it’s not meant to be maintainable, efficient, offer a good user experience, etc.

In the initial stages, I didn’t care about the UI and everything was dumped to the Android log output. When I decided to show the results in the GUI as well, I had to run all the code in a separate thread to avoid blocking the UI thread (which may cause the app to be considered unresponsive and therefore killed by the OS). The accuracy dropped considerably with this simple change, because that thread didn’t have much priority, so I set it to “-20”, which is the maximum allowed priority, and everything worked fine again.

Updating the UI from a separate thread may lead to crashes and it’s generally detected and restricted via runtime exceptions, so in order to show the log messages, I had to invoke them using calls to runOnUiThread. Bear in mind that in a real exploit, there’s no need for a UI at all.

If the personal dictionary is empty, we can’t use any row to force an update, and therefore all queries will take more or less the same time to execute. In this case there’ll be nothing to extract and the tool shouldn’t be able to adjust the parameters and will eventually stop. In some odd cases, it might be randomly calibrated even with an empty database and it will try to extract garbage or pseudo-random data.

In a regular smartphone, the OS will go to sleep mode after a while and the performance will drop considerably, causing the execution time to increase way above the expected values, so all calls would be evaluated as true. This could have been detected and reacted in a different manner, but I simply opted for a simpler solution: I kept the screen turned on and acquired a wake lock via the power manager to prevent the OS from suspending the app. I didn’t bother to release it afterwards, so you’ll have to kill the application if you’re not using it.

Rotating the screen also caused problems, so I forced it to landscape mode only to avoid auto-rotating and to take advantage of the extra width to show each message in a single line.

Once you press the “START” button, some controls will be permanently disabled. If you want to readjust the parameters or run it multiple times, you’ll need to close it and reopen it.

Some external events and executions in parallel (e.g. synchronizing the email, or receiving a push message) may interfere with the application’s behavior, potentially leading to inaccurate results. If that happens, try it again in more stable conditions, such as disabling access to the network or closing all other applications.

The UI doesn’t support internationalization, and it wasn’t designed to extract words in Unicode (although it should be trivial to adapt, it wasn’t my goal for a simple PoC).

It was intentionally limited to extract the first 5 words only, sorted by their internal identifiers.

Remediation
From a source code perspective, the fix is very simple. Just moving the call to check if the caller has permissions to the beginning of the affected functions should be enough to fix the issue. Along with the advisory, we provided Google a patch file with the suggested fix and this was the commit in which they fixed the vulnerability:
https://android.googlesource.com/platform/packages/…

Since the issue has been fixed in the official repository, as end users, we’ll have to make sure that our current installed security patch level contains the patch for CVE-2018-9375. For instance, in Google Pixel/Nexus, it was released on June 2018:
https://source.android.com/security/bulletin/pixel/2018-06-01

If for any reason it’s not possible to apply an update to your device, consider reviewing the contents of your personal dictionary and make sure it doesn’t contain any sensitive information in the unlikely event the issue becomes actively exploited.

Conclusions
Software development is hard. A single misplaced line may lead to undesirable results. A change that was meant to improve the security and protection of the user’s personal dictionary, making it less accessible, led to the opposite outcome, as it inadvertently allowed access without requiring any specific permission and went unnoticed for almost three years.

Identifying a vulnerability like the one described here can be as easy as reading and understanding the source code, just following the execution flow. Automated tests may help detect this kind of issue at an early stage and prevent them from happening again in further changes, but they aren’t always that easy to implement and maintain.

We also learned how to get the most from a vulnerability that, in principle, only allowed us to destroy or tamper with data blindly, increasing its final impact to an information disclosure that leaked all the data by exploiting a side-channel, time-based attack.

Always think outside the box, and remember: time is one of the most valuable resources. Every nanosecond counts!

EDITORIAL | July 13, 2018

Secure Design Remains Critical

From time to time, a technically astute person challenges me around some area of secure design. Not too long ago, a distinguished engineer opined that “Threat modeling doesn’t do anything.” A CTO asked why there was any need for security architects, arguing, “We pay for static analysis. That should fix our secure development problems.”

I’m not making these comments up. The people who made them are not clueless idiots, but rather, very bright individuals. These are worthy questions. If we, security architects (that is, those of us trying to create designs that embody and enact security principles), cannot articulate what it is that we do and why it’s important, then we’re literally “out of business”; harried execs aren’t going to pay for something whose value cannot be explained, let alone quantified.

The essential problem with security architecture is that success will result in resiliency, in longevity, in plasticity in the face of change (particularly, a changing threat landscape). These are hard things to measure, and they have a time element. It can take a rather long time to demonstrate effectiveness and realize the benefits of investment. It’s what my friend, Srikanth Narasimhan (one of Cisco’s Distinguished Engineers) terms, “the long tail of architecture.” There may be no Immediate results from secure design efforts.

Every once in while, we see a good example of the art in practice. Chrome’s recent release of “Site Isolation” provides an interesting example of the application of secure design. https://security.googleblog.com/2018/07/mitigating-spectre-with-site-isolation.html

Site Isolation is a large change to Chrome’s architecture that limits each renderer process to documents from a single site.” Charlie Reis, Google Security Blog, July 11, 2018, https://security.googleblog.com/2018/07/mitigating-spectre-with-site-isolation.html. The highlight is mine.

The so-called “Spectre” technique, if you recall, is a new set of techniques that misuse speculative execution (the CPU pipeline that executes multiple potential branches of code in parallel) cache to bypass operating system and firmware restrictions. Spectre has been used by real-world attackers. Operating system and CPU vendors have been scrambling to close these avenues since January 2018. At the same time, security researchers have been finding ever more ingenious methods to expand upon the techniques. Meltdown and Spectre continue to be important security issues1.

I’m not going to dig into the technical details of site isolation here. Instead, let’s focus on the secure design improvement to Chrome.

Of course, Chrome Site Isolation is ultimately coded, which means that it may suffer from any of the security horrors that code might contain. That is, what are commonly called, “vulnerabilities.” Presumably, the Chrome team did their best to find and fix any secure coding errors (on a side note, I spent some time studying Chrome’s secure development processes and commitment to security in a past role, and I’ve no doubt that if they’ve followed their stated processes, they’ve done their utmost to write secure code and to test it well).

Secure coding aside, the Chrome team faces a significant problem: It is demonstrable that JavaScript (and potentially other web-loaded, client-side browser code) can be used to exploit Spectre2. Spectre protection cannot rely solely on coding. Because Spectre does not exploit a coding error, it cannot be “fixed” in code. Hence, in response to that CTO I quoted earlier, static analysis cannot solve this problem. Protection against Spectre in a browser must be designed. That is precisely my point.

All the vulnerability scanning tools in the world will not provide a mitigation nor fix Spectre browser exploitation. It has to be designed. That is the art of security architecture.

The threat model for attacking Chrome via Spectre exploitation is mercifully simple, in that we know the attack and its method; we have example code against which to test3.

In order to conceive of Site Isolation, its designers had to understand Spectre thoroughly, especially JavaScript/client-side code exploitation. Then, they had to weigh that knowledge against potential defenses that would be possible to build. At some point, they chose Site Isolation as the best solution from the pool of potentials, and from that point, they had to build and test Site Isolation.

Site Isolation at a very high level, confines communications and data from each website to a strictly controlled sandbox process dedicated to that site. You can read more here.

We won’t know the effectiveness of Site Isolation until it faces attacks. How long a real-world challenge will take to emerge depends upon a number of factors: adoption amongst Chrome users, metrics on defended attacks, perceived value of exploitation by real-world attackers, etc.

In the meantime, I suspect that the security research community will examine Site Isolation in great detail against its promised protection. That examination, in and of itself, must be part of a robust secure design process: independent review and the resulting dialog around the design, as threat modeling author, Adam Shostack, so wisely opines, (my response).

In any event, as events unfold for Site Isolation, we can immediately note that this is a potential success for security architecture and secure design practices. I doff my hat to the prudent Chrome folks who’ve tried to defend against Spectre directly, thus, protecting us all and perhaps offering a ray of hope (and codable technique!) to other browser makers.


1When I was at McAfee, I contributed to this early analysis of the techniques: https://www.mcafee.com/blogs/mcafee-labs/decyphering-the-noise-around-meltdown-and-spectre/
2I believe that Alex Ionescu was the first to demonstrate JavaScript Spectre exploitation in January of 2018.
3The usual threat model is not so lucky, in that the credible attacks have to be generated (which is the art and science of threat modeling. Please see my book, Securing Systems, or one of the other books on threat modeling for more information on attack trees and identifying which attacks are relevant.)
ADVISORIES |

HooToo Security Advisory

HT-TM05 is vulnerable to unauthenticated remote code execution in the /sysfirm.csp CGI endpoint, which allows an attacker to upload an arbitrary shell script that will be executed with root privileges on the device. (more…)

RESEARCH | March 9, 2018

Robots Want Bitcoins too!

Ransomware attacks have boomed during the last few years, becoming a preferred method for cybercriminals to get monetary profit by encrypting victim information and requiring a ransom to get the information back. The primary ransomware target has always been information. When a victim has no backup of that information, he panics, forced to pay for its return.
(more…)

EDITORIAL | January 31, 2018

Security Theater and the Watch Effect in Third-party Assessments

Before the facts were in, nearly every journalist and salesperson in infosec was thinking about how to squeeze lemonade from the Equifax breach. Let’s be honest – it was and is a big breach. There are lessons to be learned, but people seemed to have the answers before the facts were available.

It takes time to dissect these situations and early speculation is often wrong. Efforts at attribution and methods take months to understand. So, it’s important to not buy into the hysteria and, instead, seek to gain a clear vision of the actual lessons to be learned. Time and again, these supposed “watershed moments” and “wake-up calls” generate a lot of buzz, but often little long-term effective action to improve operational resilience against cyber threats.


At IOActive we guard against making on-the-spot assumptions. We consider and analyze the actual threats, ever mindful of the “Watch Effect.” The Watch Effect can be simply explained:  you wear a watch long enough, you can’t even feel it.
I won’t go into what third-party assessments Equifax may or may not have had because that’s largely speculation. The company has probably been assessed many times, by many groups with extensive experience in the prevention of cyber threats and the implementation of active defense. And they still experienced a deep impact cyber incursion.

The industry-wide point here is: Everyone is asking everyone else for proof that they’re secure.

The assumption and Watch Effect come in at the point where company executives think their responses to high-level security questions actually mean something.

Well, sure, they do mean something. In the case of questionnaires, you are asking a company to perform a massive amount of tedious work, and, if they respond with those questions filled in, and they don’t make gross errors or say “no” where they should have said “yes”, that probably counts for something.

But the question is how much do we really know about a company’s security by looking at their responses to a security questionnaire?

The answer is, “not much.”

As a company that has been security testing for 20 years now, IOActive has successfully breached even the most advanced cyber defenses across countless companies during penetration tests that were certified backwards and forwards by every group you can imagine. So, the question to ask is, “Do questionnaires help at all? And if so, how much?”
 
Here’s a way to think about that.

At IOActive we conduct full, top-down security reviews of companies that include business risk, crown-jewel defense, and every layer that these pieces touch. Because we know how attackers get in, we measure and test how effective the company is at detecting and responding to cyber events – and use this comprehensive approach to help companies understand how to improve their ability to prevent, detect, and ever so critically, RESPOND to intrusions. Part of that approach includes a series of interviews with everyone from the C-suite to the people watching logs. What we find is frightening.

We are often days or weeks into an assessment before we discover a thread to pull that uncovers a major risk, whether that thread comes from a technical assessment or a person-to-person interview or both.

That’s days—or weeks—of being onsite with full access to the company as an insider.

Here’s where the Watch Effect comes in. Many of the companies have no idea what we’re uncovering or how bad it is because of the Watch Effect. They’re giving us mostly standard answers about their day-to-day, the controls they have in place, etc. It’s not until we pull the thread and start probing technically – as an attacker – that they realize they’re wearing a broken watch.

Then they look down at a set of catastrophic vulnerabilities on their wrist and say, “Oh. That’s a problem.”

So, back to the questionnaire…

If it takes days or weeks for an elite security firm to uncover these vulnerabilities onsite with full cooperation during an INTERNAL assessment, how do you expect to uncover those issues with a form?

You can’t. And you should stop pretending you can. Questionnaires depend far too much upon the capability and knowledge of the person or team filling it out, and often are completed with impartial knowledge. How would one know if a firewall rule were updated improperly to “any/any” in the last week if it is not tested and verified?

To be clear, the problem isn’t that third party assessments only give 2/10 in security assessment value. The problem is that executives THINK it’s giving them 6/10, or 9/10.

It’s that disconnect that’s causing the harm.

Eventually, companies will figure this out. In the meantime, the breaches won’t stop.

Until then, we as technical practitioners can do our best to convince our clients and prospects to understand the value these types of cursory, external glances at a company provide. Very little. So, let’s prioritize appropriately.

EDITORIAL | January 24, 2018

Cryptocurrency and the Interconnected Home

There are many tiny elements to cryptocurrency that are not getting the awareness time they deserve. To start, the very thing that attracts people to cryptocurrency is also the very thing that is seemingly overlooked as a challenge. Cryptocurrencies are not backed by governments or institutions. The transactions allow the trader or investor to operate with anonymity. We have seen a massive increase in the last year of cyber bad guys hiding behind these inconspicuous transactions – ransomware demanding payment in bitcoin; bitcoin ATMs being used by various dealers to effectively clean money.

Because there are few regulations governing crypto trading, we cannot see if cryptocurrency is being used to fund criminal or terrorist activity. There is an ancient funds transfer capability, designed to avoid banks and ledgers called Hawala. Hawala is believed to be the method by which terrorists are able to move money, anonymously, across borders with no governmental controls. Sound like what’s happening with cryptocurrency? There’s an old saying in law enforcement – follow the money. Good luck with that one.

Many people don’t realize that cryptocurrencies depend on multiple miners. This allows the processing to be spread out and decentralized. Miners validate the integrity of the transactions and as a result, the miners receive a “block reward” for their efforts. But, these rewards are cut in half every 210,000 blocks. A bitcoin block reward when it first started in 2009 was 50 BTC, today it’s 12.5. There are about 1.5 million bitcoins left to mine before the reward halves again.

This limit on total bitcoins leads to an interesting issue – as the reward decreases, miners will switch their attention from bitcoin to other cryptocurrencies. This will reduce the number of miners, therefore making the network more centralized. This centralization creates greater opportunity for cyber bad guys to “hack” the network and wreak havoc, or for the remaining miners to monopolize the mining.

At some point, and we are already seeing the early stages of this, governments and banks will demand to implement more control. They will start to produce their own cryptocurrency. Would you trust these cryptos? What if your bank offered loans in Bitcoin, Ripple or Monero? Would you accept and use this type of loan?

Because it’s a limited resource, what happens when we reach the 21 million bitcoin limit? Unless we change the protocols, this event is estimated to happen by 2140.  My first response  – I don’t think bitcoins will be at the top of my concerns list in 2140.

The Interconnected Home

So what does crypto-mining malware or mineware have to do with your home? It’s easy enough to notice if your laptop is being overused – the device slows down, the battery runs down quickly. How can you tell if your fridge or toaster are compromised? With your smart home now interconnected, what happens if the cyber bad guys operate there? All a cyber bad guy needs is electricity, internet and CPU time. Soon your fridge will charge your toaster a bitcoin for bread and butter. How do we protect our unmonitored devices from this mineware? Who is responsible for ensuring the right level of security on your home devices to prevent this?

Smart home vulnerabilities present a real and present danger. We have already seen baby monitors, robots, and home security products, to name a few, all compromised. Most by IOActive researchers. There can be many risks that these compromises introduce to the home, not just around cryptocurrency. Think about how the interconnected home operates. Any device that’s SMART now has the three key ingredients to provide the cyber bad guy with everything he needs – internet access, power and processing.

Firstly, I can introduce my mineware via a compromised mobile phone and start to exploit the processing power of your home devices to mine bitcoin. How would you detect this? When could you detect this? At the end of the month when you get an electricity bill. Instead of 50 pounds a month, its now 150 pounds. But how do you diagnose the issue? You complain to the power company. They show you the usage. It’s correct. Your home IS consuming that power.

They say that crypto mining is now using as much power as a small country. That’s got a serious impact on the power infrastructure as well as the environment. Ahhhh you say, I have a smart meter, it can give me a real time read out of my usage. Yes, it’s a computer. And, if I’m a cyber bad guy, I can make that computer tell me the latest football scores if I want. The key for a corporation when a cyber bad guy is attacking is to reduce dwell time. Detect and stop the bad guy from playing in your network. There are enterprise tools that can perform these tasks, but do you have these same tools at home? How would you Detect and React to a cyber bad guy attacking your smart home?

IOActive has proven these attack vectors over and over. We know this is possible and we know this is almost impossible to detect. Remember, a cyber bad guy makes several assessments when deciding on an attack – the risk of detection, the reward for the effort, and the penalty for capture. The risk of detection is low, like very low. The reward, well you could be mining blocks for months without stopping, that’s tens of thousands of dollars. And the penalty… what’s the penalty for someone hacking your toaster… The impact is measurable to the homeowner. This is real, and who’s to say not happening already. Ask your fridge!!

What’s the Answer –  Avoid Using Smart Home Devices Altogether?

No, we don’t believe the best defense is to avoid adopting this new technology. The smart and interconnected home can offer its users fantastic opportunities. We believe that the responsibility rests with the manufacturer to ensure that devices are designed and built in a safe and secure way. And, yes, everything is designed; few things are designed well.IOActive researchers spend 99% of their time trying to identify vulnerabilities in these devices for the safety of everyone, not just corporations. The power is in the hands of the consumer. As soon as the consumer starts to purchase products based not only on their power efficiency, but their security rating as well, then we will see a shift into a more secure home.

In the meantime, consider the entry point for most cyber bad guys. Generally, this is your desktop, laptop or mobile device. Therefore, ensure you have suitable security products running on these devices, make sure they are patched to the correct levels, be conscious of the websites you are visiting. If you control the available entry points, you will go a long way to protecting your home.
RESEARCH | January 17, 2018

Easy SSL Certificate Testing

tl;dr: Certslayer allows testing of how an application handles SSL certificates and whether or not it is verifying relevant details on them to prevent MiTM attacks: https://github.com/n3k/CertSlayer.

During application source code reviews, we often find that developers forget to enable all the security checks done over SSL certificates before going to production. Certificate-based authentication is one of the foundations of SSL/TLS, and its purpose is to ensure that a client is communicating with a legitimate server. Thus, if the application isn’t strictly verifying all the relevant details of the certificate presented by a server, it is susceptible to eavesdropping and tampering from any attacker having a suitable position in the network.
The following Java code block nullifies all the certificate verification checks:
 
X509TrustManager local1 = new X509TrustManager()
{
       public void checkClientTrusted(X509Certificate[]
       paramAnonymousArrayOfX509Certificate,
       String paramAnonymousString)
       throws CertificateException { }
 
       public void checkServerTrusted(X509Certificate[]
       paramAnonymousArrayOfX509Certificate,
       String paramAnonymousString)
       throws CertificateException { }
 
       public X509Certificate[] getAcceptedIssuers()
       {
              return null;
       }

 

}
 
Similarly, the following python code using urllib2 disables SSL verification:
 
import urllib2
import ssl
 
ctx = ssl.create_default_context()
ctx.check_hostname = False
ctx.verify_mode = ssl.CERT_NONE
 
urllib2.urlopen(“https://www.ioactive.com”, context=ctx)
 
These issues are not hard to spot while reading code, but what about a complete black box approach? Here is where Certslayer comes to the rescue.
 
How does it work?
 
Proxy Mode
Certslayer starts a proxy server and monitors for specified domains. Whenever a client makes a request to a targeted domain, the proxy redirects the request to an internal web server, presenting a special certificate as a test-case. If the internal web server receives the request, it means the client accepted the test certificate, and the connection was successful at the TLS level. On the other hand, if the internal web server doesn’t receive a request, it means the client rejected the presented certificate and aborted the connection.
 
For testing mobile applications, the proxy mode is very useful. All a tester needs to do is install the certificate authority (Certslayer CA) in the phone as trusted and configure the system proxy before running the tool. Simply by using the application,  generates requests to its server’s backend which are trapped by the proxy monitor and redirected accordingly to the internal web server. This approach also reveals if there is any sort of certificate pinning in place, as the request will not succeed when a valid certificate signed by the CA gets presented.
 
A simple way to test in this mode is to configure the browser proxy and navigate to a target domain. For example, the next command will start the proxy mode on port 9090 and will monitor requests to www.ioactive.com:
C:\CertSlayerCertSlayer>python CertSlayer.py -d www.ioactive.com -m proxy -p 9090
 
 

Currently, the following certificate test-cases are available (and will run in order):

  • CertificateInvalidCASignature
  • CertificateUnknownCA
  • CertificateSignedWithCA
  • CertificateSelfSigned
  • CertificateWrongCN
  • CertificateSignWithMD5
  • CertificateSignWithMD4
  • CertificateExpired
  • CertificateNotYetValid
 
Navigating with firefox to https://www.ioactive.com will throw a “Secure Connection Failed”:
 
The error code explains the problem: SEC_ERROR_BAD_SIGNATURE, which matches the first test-case in the list. At this point, Certslayer has already prepared the next test-case in the list. By reloading the page with F5, we get the next result.
 
 
At the end, a csv file will generate containing the results of each test-case. The following table summarizes them for this example:
 

Stand-alone Mode

Proxy mode is not useful when testing a web application or web service that allows fetching resources from a specified endpoint. In most instances, there won’t be a way to install a root CA at the application backend for doing these tests. However, there are applications that include this feature in their design, like, for instance, cloud applications that allow interacting with third party services.

 

In these scenarios, besides checking for SSRF vulnerabilities, we also need to check if the requester is actually verifying the presented certificate. We do this using Certslayer standalone mode. Standalone mode binds a web server configured with a test-certificate to all network interfaces and waits for connections.

 

I recently tested a cloud application that allowed installing a root CA to enable interaction with custom SOAP services served over HTTPS. Using the standalone mode, I found the library in use wasn’t correctly checking the certificate common name (CN). To run the test-suite, I registered a temporary DNS name (http://ipq.co/) to my public IP address and ran Certslayer with the following command:
 
C:CertSlayerCertSlayer>python CertSlayer.py -m standalone -p 4444 -i j22d1i.ipq.co
 
+ Setting up WebServer with Test: Trusted CA Invalid Signature
>> Hit enter for setting the next TestCase
 
The command initialized standalone mode listening on port 4444. The test certificates then used j22d1i.ipq.co as the CN. 

After this, I instructed the application to perform the request to my server:
 
POST /tools/soapconnector HTTP/1.1
Host: foo.com
Content-Type: application/json; charset=utf-8
X-Requested-With: XMLHttpRequest
Content-Length: 55
Cookie: –
Connection: close
 
 
{“version”:”1.0″,”wsdl”:”https://j22d1i.ipq.co:4444/”}
 
 
Server response:
{“status”:500,”title”:”Problem accessing WSDL description”,”detail”:”We couldn’t open a connection to the service (Describe URL: https://j22d1i.ipq.co:4444/). Reason: Signature does not match. Check the availability of the service and try again”}
 
 
The connection was refused. The server error described the reason why: the CA signature didn’t match. Hitting enter in the python console made the tool prepare the next test case:
 
+ Killing previous server
j22d1i.ipq.co,Trusted CA Invalid Signature,Certificate Rejected,Certificate Rejected
+ Setting up WebServer with Test: Signed with CertSlayer CA
>> Hit enter for setting the next TestCase
 

Here, the connection succeeded because the tool presented a valid certificate signed with Certslayer CA:

 

Server Response:
 
{“status”:500,”detail”: “We couldn’t process the WSDL https://j22d1i.ipq.co:4444/. Verify the validity of the WSDL file and that it’s available in the specified location.”}
 
Certslayer output:
j22d1i.ipq.co,Signed with CertSlayer CA,Certificate Accepted,Certificate Accepted
xxx.yyy.zzz.www – – [14/Dec/2017 18:35:04] “GET / HTTP/1.1” 200 –
 
When the web server is configured with a certificate with a wrong CN, the expected result is that the client will abort the connection. However, this particular application accepted the certificate anyway:
+ Setting up WebServer with Test: Wrong CNAME
>> Hit enter for setting the next TestCase
xxx.yyy.zzz.www – – [14/Dec/2017 18:35:54] “GET / HTTP/1.1” 200 –
j22d1i.ipq.co,Wrong CNAME,Certificate Rejected,Certificate Accepted
 
 
As before, a csv file was generated containing all the test cases with the actual and expected results. For this particular engagement, the result was:
 

A similar tool exists called tslpretense, the main difference is that, instead of using a proxy to intercept requests to targeted domains, it requires configuring the test runner as a gateway so that all traffic the client generates goes through it. Configuring a gateway host this way is tedious, which is the primary reason Certslayer was created.
 
I hope you find this tool useful during penetration testing engagements 🙂

 

RESEARCH | January 11, 2018

SCADA and Mobile Security in the IoT Era

Two years ago, we assessed 20 mobile applications that worked with ICS software and hardware. At that time, mobile technologies were widespread, but Internet of Things (IoT) mania was only starting. Our research concluded the combination of SCADA systems and mobile applications had the potential to be a very dangerous and vulnerable cocktail. In the introduction of our paper, we stated “convenience often wins over security. Nowadays, you can monitor (or even control!) your ICS from a brand-new Android [device].”


Today, no one is surprised at the appearance of an IIoT. The idea of putting your logging, monitoring, and even supervisory/control functions in the cloud does not sound as crazy as it did several years ago. If you look at mobile application offerings today, many more ICS- related applications are available than two years ago. Previously, we predicted that the “rapidly growing mobile development environment” would redeem the past sins of SCADA systems.
The purpose of our research is to understand how the landscape has evolved and assess the security posture of SCADA systems and mobile applications in this new IIoT era.

SCADA and Mobile Applications
ICS infrastructures are heterogeneous by nature. They include several layers, each of which is dedicated to specific tasks. Figure 1 illustrates a typical ICS structure.

Figure 1: Modern ICS infrastructure including mobile apps

Mobile applications reside in several ICS segments and can be grouped into two general families: Local (control room) and Remote.


Local Applications

Local applications are installed on devices that connect directly to ICS devices in the field or process layers (over Wi-Fi, Bluetooth, or serial).

Remote Applications
Remote applications allow engineers to connect to ICS servers using remote channels, like the Internet, VPN-over-Internet, and private cell networks. Typically, they only allow monitoring of the industrial process; however, several applications allow the user to control/supervise the process. Applications of this type include remote SCADA clients, MES clients, and remote alert applications. 

In comparison to local applications belonging to the control room group, which usually operate in an isolated environment, remote applications are often installed on smartphones that use Internet connections or even on personal devices in organizations that have a BYOD policy. In other words, remote applications are more exposed and face different threats.

Typical Threats And     Attacks

In this section, we discuss the typical threats to this heterogeneous landscape of applications and how attacks could be conducted. We also map the threats to the application types.
 
Threat Types
There are three main possible ICS threat types:
  • Unauthorized physical access to the device or “virtual” access to device data
  • Communication channel compromise (MiTM)
  • Application compromise

Table 1 summarizes the threat types.

Table 1: SCADA mobile client threat list
 
Attack Types
Based on the threats listed above, attacks targeting mobile SCADA applications can be sorted into two groups.
 
Directly/indirectly influencing an industrial process or industrial network infrastructure
This type of attack could be carried out by sending data that would be carried over to the field segment devices. Various methods could be used to achieve this, including bypassing ACL/ permissions checks, accessing credentials with the required privileges, or bypassing data validation.
 
Compromising a SCADA operator to unwillingly perform a harmful action on the system
The core idea is for the attacker to create environmental circumstances where a SCADA system operator could make incorrect decisions and trigger alarms or otherwise bring the system into a halt state.
 
Testing Approach
Similar to the research we conducted two years ago, our analysis and testing approach was based on the OWASP Mobile Top 10 2016. Each application was tested using the following steps:
  • Perform analysis and fill out the test checklist
  • Perform client and backend fuzzing
  • If needed, perform deep analysis with reverse engineering
We did not alter the fuzzing approach since the last iteration of this research. It was discussed in depth in our previous whitepaper, so its description is omitted for brevity.
We improved our test checklist for this assessment. It includes:
  • Application purpose, type, category, and basic information 
  • Permissions
  • Password protection
  • Application intents, exported providers, broadcast services, etc.
  • Native code
  • Code obfuscation
  • Presence of web-based components
  • Methods of authentication used to communicate with the backend
  • Correctness of operations with sessions, cookies, and tokens 
  • SSL/TLS connection configuration
  • XML parser configuration
  • Backend APIs
  • Sensitive data handling
  • HMI project data handling
  • Secure storage
  • Other issues
Reviewed Vendors
We analyzed 34 vendors in our research, randomly selecting  SCADA application samples from the Google Play Store. We did, however, favor applications for which we were granted access to the backend hardware or software, so that a wider attack surface could be tested.
 
Additionally, we excluded applications whose most recent update was before June 2015, since they were likely the subject of our previous work. We only retested them if there had been an update during the subsequent two years.
 
Findings
We identified 147 security issues in the applications and their backends. We classified each issue according to the OWASP Top Ten Mobile risks and added one additional category for backend software bugs.
 
Table 4 presents the distribution of findings across categories. The “Number of Issues” column reports the number of issues belonging to each category, while the “% of Apps” column reports how many applications have at least one vulnerability belonging to each category.
Table 4. Vulnerabilities statistics

In our white paperwe provide an in-depth analysis of each category, along with examples of the most significant vulnerabilities we identified. Please download the white paper for a deeper analysis of each of the OWASP category findings.

Remediation And Best Practices
In addition to the well-known recommendations covering the OWASP Top 10 and OWASP Mobile Top 10 2016 risks, there are several actions that could be taken by developers of mobile SCADA clients to further protect their applications and systems.

In the following list, we gathered the most important items to consider when developing a mobile SCADA application:

  • Always keep in mind that your application is a gateway to your ICS systems. This should influence all of your design decisions, including how you handle the inputs you will accept from the application and, more generally, anything that you will accept and send to your ICS system.
  • Avoid all situations that could leave the SCADA operators in the dark or provide them with misleading information, from silent application crashes to full subverting of HMI projects.
  • Follow best practices. Consider covering the OWASP Top 10, OWASP Mobile Top 10 2016, and the 24 Deadly Sins of Software Security.
  • Do not forget to implement unit and functional tests for your application and the backend servers, to cover at a minimum the basic security features, such as authentication and authorization requirements.
  • Enforce password/PIN validation to protect against threats U1-3. In addition, avoid storing any credentials on the device using unsafe mechanisms (such as in cleartext) and leverage robust and safe storing mechanisms already provided by the Android platform.
  • Do not store any sensitive data on SD cards or similar partitions without ACLs at all costs Such storage mediums cannot protect your sensitive data.
  • Provide secrecy and integrity for all HMI project data. This can be achieved by using authenticated encryption and storing the encryption credentials in the secure Android storage, or by deriving the key securely, via a key derivation function (KDF), from the application password.
  • Encrypt all communication using strong protocols, such as TLS 1.2 with elliptic curves key exchange and signatures and AEAD encryption schemes. Follow best practices, and keep updating your application as best practices evolve. Attacks always get better, and so should your application.
  • Catch and handle exceptions carefully. If an error cannot be recovered, ensure the application notifies the user and quits gracefully. When logging exceptions, ensure no sensitive information is leaked to log files.
  • If you are using Web Components in the application, think about preventing client-side injections (e.g., encrypt all communications, validate user input, etc.).
  • Limit the permissions your application requires to the strict minimum.
  • Implement obfuscation and anti-tampering protections in your application.

Conclusions
Two years have passed since our previous research, and things have continued to evolve. Unfortunately, they have not evolved with robust security in mind, and the landscape is less secure than ever before. In 2015 we found a total of 50 issues in the 20 applications we analyzed and in 2017 we found a staggering 147 issues in the 34 applications we selected. This represents an average increase of 1.6 vulnerabilities per application. 

We therefore conclude that the growth of IoT in the era of “everything is connected” has not led to improved security for mobile SCADA applications. According to our results, more than 20% of the discovered issues allow attackers to directly misinform operators and/or directly/ indirectly influence the industrial process.

In 2015, we wrote:

SCADA and ICS come to the mobile world recently, but bring old approaches and weaknesses. Hopefully, due to the rapidly developing nature of mobile software, all these problems will soon be gone.

We now concede that we were too optimistic and acknowledge that our previous statement was wrong.

Over the past few years, the number of incidents in SCADA systems has increased and the systems become more interesting for attackers every year. Furthermore, widespread implementation of the IoT/IIoT connects more and more mobile devices to ICS networks.

Thus, the industry should start to pay attention to the security posture of its SCADA mobile applications, before it is too late.

For the complete analysis, please download our white paper here.

Acknowledgments

Many thanks to Dmitriy Evdokimov, Gabriel Gonzalez, Pau Oliva, Alfredo Pironti, Ruben Santamarta, and Tao Sauvage for their help during our work on this research.
 
About Us
Alexander Bolshev
Alexander Bolshev is a Security Consultant for IOActive. He holds a Ph.D. in computer security and works as an assistant professor at Saint-Petersburg State Electrotechnical University. His research interests lie in distributed systems, as well as mobile, hardware, and industrial protocol security. He is the author of several white papers on topics of heuristic intrusion detection methods, Server Side Request Forgery attacks, OLAP systems, and ICS security. He is a frequent presenter at security conferences around the world, including Black Hat USA/EU/UK, ZeroNights, t2.fi, CONFIdence, and S4.
 
Ivan Yushkevich
Ivan is the information security auditor at Embedi (http://embedi.com). His main area of interest is source code analysis for applications ranging from simple websites to enterprise software. He has vast experience in banking systems and web application penetration testing.
 
IOActive
IOActive is a comprehensive, high-end information security services firm with a long and established pedigree in delivering elite security services to its customers. Our world-renowned consulting and research teams deliver a portfolio of specialist security services ranging from penetration testing and application code assessment through to semiconductor reverse engineering. Global 500 companies across every industry continue to trust IOActive with their most critical and sensitive security issues. Founded in 1998, IOActive is headquartered in Seattle, USA, with global operations through the Americas, EMEA and Asia Pac regions. Visit for more information. Read the IOActive Labs Research Blog. Follow IOActive on Twitter.
 
Embedi
Embedi expertise is backed up by extensive experience in security of embedded devices, with special emphasis on attack and exploit prevention. Years of research are the genesis of the software solutions created. Embedi developed a wide range of security products for various types of embedded/smart devices used in different fields of life and industry such as: wearables, smart home, retail environments, automotive, smart buildings, ICS, smart cities, and others. Embedi is headquartered in Berkeley, USA. Visit for more information and follow Embedi on Twitter.