-
Notifications
You must be signed in to change notification settings - Fork 6
Exploit Generation
This document describes the process of generating exploit HTML markups based on a taint flow trace. The exploit will be loaded through initial DOM-clobberable lookup, converting type of controlled value from DOM nodes to string, and leading them to the sink by leveraging operations recorded in the trace.
Unlike typical exploit generation, where the attacker's input is usually a string and only the string constraints need to be tracked from input to sink, our context involves input in the form of DOM nodes (or HTMLCollections). This requires leveraging operations along the trace to secondary load the attacker-controlled string into the program and guide its flow to the sink. Therefore, we perform symbolic execution of DOM nodes on the taint trace to collect constraints that enables conversions from DOM nodes to other DOM nodes or from DOM nodes to strings. Once the attacker-controlled value is converted to a string, we apply existing symbolic execution techniques for strings to fullfill the string-related constraints on the last stage.
Next, we will describe our approach in three steps: 1/ Taint Dependency Graph Construction, 2/ Operation Capability Inference and 3/ Constraints modeling and Solving. First, we construct a Taint Dependency Graph (TDG) based on the collected taint trace, detailing how the attacker-controlled value is used in each operation, along with value snapshots at the time of execution. Given that the complete exploit requires at least one type conversion from DOM to String, we assign objectives to each operation based on its capabilities and the type requirements of subsequent operations. Finally, we traverse the TDG in a top-down manner to collect constraints for each operation's input based on its assigned objective, then solve these constraints to generate a set of satisfying DOM trees as input.
For the operations that can be recorded in the taint trace, we define the operation objectives are DOCUMENT2DOM, WINDOW2DOM, DOM2DOM, DOM2STRING, STRING2STRING.
Here, we formally define a simplified DOM Tree as a ranked alphabet, which is a couple
In this formalism:
- Strings(^*) represents the set of possible string values within the DOM, such as text node contents or attribute values.
-
Attribute Names includes all possible attribute names that can appear in a DOM node (e.g.,
id,class,href). -
DOM Node Names represents all possible DOM node types (e.g.,
div,span,a). - hasAttribute is a ternary operation that checks if a DOM node has a specific attribute with specific value.
- hasType is a binary operation that verifies the type of a DOM node.
- hasChild is a binary operation that checks the parent-child relationship between two DOM nodes.
- hasSibling is a binary operation that checks the sibling relationship between two DOM nodes.
- isRoot is a unary operation that set the symbol as the root node.
Then, we define the constraints for each operation with objectives on the DOM tree document.x operation with a DOCUMENT2DOM objective, only a limited set of DOM trees can be used, such as a DOM node of type iframe with the name attribute set to x. The following constraints can be applied:
Even with these constraints, the symbol still represents a variety of trees. For instance, arbitrary valid DOM nodes can be nested, and additional attributes with any values can be present as long as they don't conflict with the imposed constraints.
Considering the operation document.prop, all the following constraints should add the shared constraint:
-
iframetag withnameattribute$(\text{ isRoot }\ R\ ) \land (\text{ hasType }\ R\ \text{ "iframe" }) \land (\text{ hasAttribte }\ R\ \text{ "name" } \text{ x })$
-
TS4,Embed,formtag withnameattribute$(\text{ isRoot }\ R\ ) \land ((\text{ hasType }\ R\ \text{ TS4 }) \lor (\text{ hasType }\ R\ \text{ "embed" }) \lor (\text{ hasType }\ R\ \text{ "form" }))\land (\text{ hasAttribte }\ R\ \text{ "name" } \text{ x })$
-
objecttag withidattribute$(\text{ isRoot }\ R\ ) \land (\text{ hasType }\ R\ \text{ "object" }) \land (\text{ hasAttribte }\ R\ \text{ "id" } \text{ x })$
Refer to the "Named Access Window" section for the Table 2 in the It's clobbering time paper.
Refer to the "Form Parent-Child", "Nested Window Proxy", and "HTMLCollection" section for the Table 2 in the It's clobbering time paper.
Considering the operation base.prop, all the following constraints should add the shared constraint:
-
formparent andinputchild$(\text{ isRoot }\ R\ ) \land (\text{ hasChild }\ R\ \ C\ ) \land (\text{ hasType }\ R\ \text{ "form" }) \land (\text{ hasType }\ C\ \text{ "input" }) \land (\text{ hasAttribte }\ R\ \text{ "id" } \text{ y }) \land (\text{ hasAttribte }\ C\ \text{ "form" } \text{ y }) \land (\text{ hasAttribte }\ C\ \text{ "id" } \text{ x })$
Here, we summarize a list of property lookups for each DOM nodes type which can be used to load string value from attributes.
Implicit toString method call during binary operation '+'.
Here, we document the function call whose base or arguments can be DOM nodes and the return value is based on the DOM nodes in type of String. There are different cases:
- DOM nodes and JavaScript builtins objects have shared method name and signature (arguments and return value).
- Different DOM node type have shared method name, for example,
getAttributebetweeniframeandscriptelement. The developer may assume thedocument.scriptsreturn all the script tags in the document but can be clobbered by the attacker-injectediframeelement. Since they are sharing the samegetAttributemethod call, the method call onscriptto get attribute might also works for injected theiframeelement. - Implicit
toStringcall onbaseorargs. For example,[].join(arg0)wherearg0's toString function will be implicitly called.
-
getAttributefunction-
base.getAttribute(arg0)wherebaseis the attacker-controlled value $(\text{ isRoot }\ R\ ) \land (\text{ hasAttribte }\ R\ \text{ arg0 } \text{ x })$
-
![]()
- Related Works
- HTML Injection
- DOM Clobbering
- Evaluation
- Discussion
- Others