Taint tracking ============== Interesting aside about Tor (from last lecture). Tor now provides easy-to-use bridge node VMs to run on Amazon's EC2. Ref: https://cloud.torproject.org/ Main goal: make it difficult to block Tor bridge/OR nodes. Nice observation: will be hard to distinguish Tor VMs from other VMs in EC2. Blocking all of Amazon EC2 may be impractical. Good to be hard-to-distinguish from significant amount of important traffic. Assumes that it's hard to precisely enumerate all Tor bridges within EC2. --- What's the problem this paper is trying to solve? Applications can exfiltrate user's private data, send it out to some server. Why aren't Android permissions enough? Permissions used to control whether application can read data. Permissions used to control access to devices / resources (e.g., Internet). Hard to directly express policy like "user data cannot be sent over network". Would it help to never install applications that both read data & access net? Would prevent some obvious leaks, but would also break some legitimate apps. Many side channels, apps could collude. Can trick other apps into sending out data (e.g., send intent to Gmail app?) Would it help to have more fine-grained permissions? Not directly helpful for this problem, although generally useful. Helps decouple permissions app wants from perms app just has to request. Might allow app to request more precisely the set of permissions it needs. How important is this problem? What does Android malware actually do? Send SMS messages to premium numbers that cost you money. Most of the time, use location or IMEI for advertisements. Some apps send contact info to servers to run searches, find friends, .. Some recent malware extracts private information and uploads to servers. E.g., "DroidDream Light" uploads IMEI/IMSI, Android version, and list of apps. No disaster stories yet, but app could easily steal contacts for spam, etc. This paper's plan: taint tracking. Runtime version of taint analysis schemes we saw in earlier lectures. Track how sensitive data propagates through the system. Mark sources of private user data as "tainted". Propagate "tainted" annotation when data is copied. Look for tainted data to be sent out via some sink. Sources: sensor information, contacts, device identifiers. Sinks: network. Can we just examine inputs or outputs to look for sensitive data? Ultimately, our goal is to prevent sensitive data from leaking out. Could work as a heuristic, but not necessarily complete. TaintDroid authors resort to examining inputs/outputs to check their results. Hard to do in an automated fashion. Many ways for app to encode data (URL-quoting, binary vs text formats, etc). How else could you solve this problem of private data leakage? Perhaps avoid giving apps legitimate data in the first place. AppFence system: replace real data sources with anonymized / limited data. Works for cases when app didn't really need the data, or didn't really need the exact data. Not so great when app actually needs accurate information (e.g., location). Another possibility: trusted services to handle private data in well-known ways. E.g., is it possible to provide location-specific ads w/o such privacy risks? In the ad example, could have a "location-aware ad" service. This ad service would have permission to get location, send it to Internet. Would return back a location-specific ad to the calling app (via intents). The ad service is trusted, but all other apps wouldn't have to be so trusted. Similar to factoring out key functionality into services in zoobar. Back to taint tracking. Need several things for any taint tracking system: What does the taint metadata look like? What units of data get their own taint metadata? What are the propagation rules for different operations? How does TaintDroid represent taint metadata? 32-bit value ("tag"). Represents 32 possible independent types of private data. Is this good enough? What can / cannot we represent? What units of data get their own taint tags? Where is the taint tag stored? Variables in Java code (using Android's bytecode). Variable is anything that can store a primitive value or object type. Real variables, object fields, static fields, return values, ... For register variables, use an extra "shadow" register. For object fields, extend the object to store a tag for every field. Arrays treated specially: often hold the same type of tainted data. Performance optimization: store one taint tag for entire array. Why is it safe? Typically assume safe to increase taint, so just more false positives. Messages sent via the binder (intents). Not explicitly specified, but presumably an extra 32-bit field in message. Each file has a single taint tag (stored in the file's metadata). Is this safe? Efficient or slow? Accurate or has false positives? 32 types taint means coarse-grained categories. Entire contacts database probably contains just contacts-tainted data. How do taint tags propagate? For Java code: Table 1 from the paper. Typical propagation: move-op copies taint. Combining pieces of data: binary-op takes union of taints. Interesting case: why union for array index propagation (aget-op)? char uppercase[] = [ "A", "B", "C", ... ]; Code often makes char c uppercase by looking up uppercase[c]. Entry in uppercase[] array is not tainted, but result should be. Also union for aput-op, because we aren't overwriting the entire array. For native code accessible to Java via some JNI interface: Manually analyze the native code, provide a summary of its taint behavior. Effectively, need to specify how to copy taints from args to return values. How well does this scale? Authors argue this works OK for internal VM functions (e.g., arraycopy). For "easy" calls, can automate: if only integers / strings are passed, assign union of input taints to the return value. For messages: Each Android application process runs trusted JVM and binder library. Modified binder library adds union of taints to outgoing messages. Similarly, assign taint of incoming message to all extracted data. Why not do x86- or ARM-level taint tracking for native code? Too expensive. Too many false positives. Is it OK to track variables rather than objects? What happens with a shared object? Example: SomeObject b = a; b.foo = get_imei(); sendmsg(a.foo); Fields in an object count as "variables" in TaintDroid. Recall Android model does not trust JVM. Why is it OK to track Java variables? TaintDroid prohibits loading shared libraries that are not manually inspected. Presumably TaintDroid authors will prohibit libraries that run arbitrary code. Assume function is easy to summarize w/ taint propagation. Is it possible for an application to bypass TaintDroid's checks? Generally, two things that could go wrong (often together): - forgot to assign a taint tag to some piece of data - forgot to implement taint propagation for some dependency Control flow propagation? Data objects that do not have taint tags? Example: for (int i = 0; i < 32; i++) if (imei & (1 << i)) sendmsg("bit " + i + " is high"); What about null vs. non-null pointers? OK, tainted by variable's taint tag. What about the length of an array? (Recall that arrays are built-in.) Not tracked: array-length instruction doesn't return a tainted value. Note that if the array pointer itself was tainted, would propagate that. What about the length of a linked list implemented on top of Java? Suppose we insert tainted objects into a linked list. Adding to a linked list involves allocating fresh linked-list objects. Linked-list object has two components: "next" field and "data" field. The "next" fields are not tained, only the "data" fields would be. Counting the number of elements in a list would not touch tainted field. Thus, would return an untainted value. Why is control flow special? Does it have to be? Looks special because no explicit variable holds that state. Can think of control flow prop. as assigning a taint tag to program counter. Why not do this? Too many false positives, "taint explosion". How does TaintDroid's runtime tainting relate to taint analysis ideas? Similar at a high level.. Building a static model of how code can behave, vs. monitoring how it behaves. Can static taint analysis do better than runtime taint analysis? Control flow channels. May be able to reason about when the program counter's taint can be lowered. Need guarantee that all control flows past "tainted" point always converge. Can lower taint at the convergence point. Beware of infinite loops, exceptions, returns / gotos, etc. What are the performance overheads of TaintDroid? Additional memory to store taint tags. Additional CPU cost to assign, propagate, check taint tags. Overheads seem to be moderate. ~5% storage cost (amortized over a large benchmark). 3--29% CPU overhead for a set of 5 different operations. However, on phones users are strongly concerned about battery life. 29% less CPU performance may be tolerable, but 29% less battery life is bad. What are the security findings by TaintDroid authors? Apps often leak phone identifiers to app servers, location data to ad servers. Nothing too drastic (e.g., no leaks of all contacts). Some application actually tries to be careful with IMEI data, hashes it. Should hashing preserve taint information, or should it not propagate taint? Are their results believeable? What apps did they use? How did they look for suspect behavior? Pick 30 apps. Tag phone identifiers, location information, etc. Use taint tracking to check when it gets sent over the network. Manually inspect what's sent to figure out what happened. Do they get false positives? Main example: IMSI strings (section 8), containing country & network codes. Why did they get false positives if they marked the IMSI as tainted? Apparently many apps include the IMSI in intent messages, for config. Intent messages have one taint tag for entire message payload. As a result, IMSI's taint propagates to other parts of the message.. What are possible applications of a system like TaintDroid? Auditing data flow behavior of apps on your phone at all times. Enforcing policies at runtime. Helping app store developers audit / analyze apps. ... What considerations matter for these use cases? Performance / power consumption. Needed for runtime auditing or enforcement. Precision: at runtime, do we catch all possible data flows that happened? Needed for runtime enforcement, maybe less so for auditing / analysis. Coverage: in testing, do we trigger all data flows that can happen? Doesn't matter for runtime auditing/enforcement, matters for analysis. How well would TaintDroid work in these dimensions? OK but not great at performance. OK at precision, but probably not great for enforcement with malicious apps. Coverage is outside of the scope, but would require thorough testing somehow.. Where else could you apply similar ideas? Web browsers? OS? Hardware? Taint tracking often provides an interesting cross-layer perspective. Interesting application of taint tracking: keeping track of data copies. Often want to make sure sensitive data (keys, passwords) is erased promptly. Paper by Chow et al on using taint tracking to measure data lifetime. Do taint tracking at the x86 level using a software x86 emulator (bochs). Turns out many pieces of software keep around copies of data for a long time. E.g., keystroke data stays around in: - keyboard device driver's buffers - kernel's random number generator - X server's event queue - kernel socket/pipe buffers used to pass messages containing keystroke - tty buffers for terminal apps - packet buffers, for any data that goes over the network - string objects in application - stack variables that aren't reused or overwritten promptly - in general, memory reuse in application is not immediate References: AppFence paper: http://appfence.org/ccs210-hornyack.pdf DroidDream malware: http://blog.mylookout.com/2011/05/security-alert-droiddreamlight-new-malware-from-the-developers-of-droiddream/ Data lifetime paper: http://cs.stanford.edu/people/jchow/papers/taint-usenix04.pdf