-
Notifications
You must be signed in to change notification settings - Fork 6
Cross Boundary Dataflows
In this document, we answer the following questions:
- What kinds of cross-boundary dataflows can TheHulk handle?
- How do we handle the cross-boundary dataflows?
In client-side JavaScript execution, we have identified that JavaScript values may be passed to other components, such as the DOM, which are no longer processed by V8 or stored on the V8 heap. When cross-bounary dataflow occurs, usually through API calls, our wrapped value need to be stripped before passing it to the APIs. However, to maintain its stored taint or symbolic information, we needs special handling of them.
Cross-boundary dataflows typically start through API calls. When this happens, any tainted values need to be stripped before being passed to these APIs. This ensures our taint won't affect the execution of original builtins. And then, we update the taint information between the arguments and results accordingly. There are two types of cross-bounary dataflow:
- Immediate Cross-Boundary Dataflow: In this type, the computed data is immediately returned to the V8 engine, even though the builtins function is not implemented by V8. These APIs are treated similarly to V8 builtins.
- Stored Cross-Boundary Dataflow: This type involves data being stored outside the V8 heap and possibly passed back later. It requires more complex handling to ensure data integrity and taint propagation.
DOM Operations
Stored cross-boundary dataflows involve data being stored outside the V8 heap, such as when interacting with the DOM or using local storage mechanisms. These operations may require separate function calls to access or modify the data. In these cases, creating a standalone data representation in our analysis is essential to effectively track these data flows.
In the following code snippet case, in the JavaScript string HelloWorld will be saved in the DOM nodes. Before setting it to the .innerText property of a DOM node, any wrapped value (e.g., the userInput variable) should be stripped, and the passed variable should be of type String. If not handled properly, when the value is retrieved back from the DOM nodes, we will lose its taint propagation from userInput to fromUserInput.
// Case Two
let userInput = "HelloWorld";
document.getElementById("greeting").innerText = userInput;
let fromUserInput = document.getElementById("greeting").innerText;
Local Storage and Database:
-
LocalStorage and SessionStorage
- These storage mechanisms accept only string values, requiring data to be converted to a suitable format before storage. It is essential to track data flows accurately to maintain taint information across storage and retrieval operations.
-
Databases
- Similar to the above storage.
For example, in the following code snippet, the function exported from wasmInstance is seen as an external party since Jalangi2 cannot instrument functions written in WebAssembly. To handle this, we can create a specific rule for the processToken function and apply it during the function call. Most of the methods installed on built-in objects fall into this category, as the methods themselves are written in C++ or Assembly language. However, these methods return immediately to the JavaScript world as the return value of the method call. Therefore, to handle these kinds of cross-boundary dataflows, we create rules for them. (TODO: Replace this case one as the processToken function looks like a user-written function.)
let wasmBinary = new Uint8Array([...]);
let wasmModule = new WebAssembly.Module(wasmBinary);
let wasmInstance = new WebAssembly.Instance(wasmModule, {});
let userToken = "abc123";
let result = wasmInstance.exports.processToken(userToken);
let processedToken = result;
![]()
- Related Works
- HTML Injection
- DOM Clobbering
- Evaluation
- Discussion
- Others