-
Notifications
You must be signed in to change notification settings - Fork 68
3. Templates
All templates are JSON files. Android templates have four main sections (i.e., first level keys):
The METADATA
section AND at least one of MANIFESTPARAMS
and CODEPARAMS
are required. The GRAPH
section is required if the output is to be presented in a neo4j/visjs graph.
Each section is described in detail below. See Sample Template for, well, a sample template, with an explanation of the various sections. See Links for information on linking bugs together to create exploit chains. See Tips for some suggestions for creating good templates.
Important note: every keyword specified here is case-sensitive.
Even more important: the templates that have been included with Jandroid can probably be improved upon by someone with better knowledge of logic bugs. Use them only after checking that they serve your purpose.
This has one required parameter, NAME
, which must be a unique name for the bug/template. If more than one template uses the same name, then an error will be thrown and the second (and subsequent) templates with the same name will be ignored.
Do not use any name ending with "Start" or "End" as a template name. These are used for identifying start and end nodes in trace chains.
An object used for specifying requirements of AndroidManifest files. It has the following subkeys:
-
BASEPATH
: string. Only present at the root level of the MANIFESTPARAMS object. It specifies the starting level for the search. Can have multiple options separated by OR. If this value is specified, then the manifest analysis will start from the specified point rather than from the root. e.g., aBASEPATH
ofmanifest->application->activity
would skip the levels corresponding tomanifest
andapplication
and start directly from theactivity
level. -
SEARCHPATH
: object. Only present at the root level of the MANIFESTPARAMS object. Specifies the path to take within the manifest tree. Must follow the structure of the AndroidManifest.xml (including similar nesting). See the sample template on this page for an idea of the structure of this key. Any level within this key can haveLOOKFOR
and/orRETURN
keys. -
LOOKFOR
: object. Can be present at any level within theSEARCHPATH
or root. Has one or more of the following keys:-
TAGEXISTS
: string or list. String can specify a single tag to match, or ONE (or more) OF a number of tags separated by "OR". If ALL OF a number of tags are to be matched, they should be specified as individual elements within a list. -
TAGNOTEXISTS
: string or list. String can specify a single tag to match. String CANNOT have multiple options separated by "OR". If ALL OF a number of tags are to be matched, they should be specified as individual elements within a list. -
TAGVALUEMATCH
: string or list. String can specify a single value to match, or at least ONE OF a number of values separated by "OR". Note that you cannot specify a number of tag-value pairs within an "OR" clause; you can only specify a number of possible values corresponding to a single tag. If ALL of a number of tags are to be matched, they should be specified as individual elements within a list. -
TAGVALUENOMATCH
: string or list. String can specify a single tag to match. String CANNOT have multiple options separated by "OR". If ALL OF a number of tags are to be matched, they should be specified as individual elements within a list. At least one tag must have a value that is not equal to the string or list.
-
-
RETURN
: string or list. Can be present at any level within theSEARCHPATH
or root. String specifies a single return item. List specifies multiple. ARETURN
item must have a unique identifier specified after theAS
keyword. The identifier must begin with an@
. The returned value can be graphed or used in subsequent searches (within the same bug template). See the section on RETURNs for more information.
NOTES:
-
RETURN
can be present at multiple levels, but cannot be a subkey of aLOOKFOR
object. -
LOOKFOR
can also be present at multiple levels, but cannot be a subkey of aLOOKFOR
orRETURN
object. - A
RETURN
will return tag values for the level at which it is specified. - If the RETURNed item is an activity name that is to be used in code searches, then specify that it is to be converted to smali representation using the
<smali>:
modifier. - If using a
LOOKFOR
andRETURN
at the same level, make sure theLOOKFOR
is specified first.
An object used for specifying parameters for code searches/traces. Contains one or both of the following subkeys: SEARCH
and TRACE
.
-
SEARCH
: a single search can be specified as a dictionary object. Multiple searches (all of which must be satisfied) can be specified as a list of objects. The objects must have one or more of the following keys:-
SEARCHFORMETHOD
: object. Look for existence of method.-
METHOD
(Required): string. Method of interest. See rules forTRACEFROM
below.
-
-
SEARCHFORCALLTOMETHOD
: object. Look for existence of calls to this method. Possible subkeys:-
METHOD
(Required): string. Method of interest. See rules forTRACEFROM
below. -
SEARCHLOCATION
: string. Used to determine whether the call to the method was from a specific class or method. -
RETURN
: string. Of the format "x AS y", where x is one of<class>
or<method>
, indicating the class or method from which this method was called, and y is a (unique) identifier. The identifier must begin with@
. This value can be graphed or used in subsequent searches (within the same bug template). See the section on RETURNs for more information.
-
-
SEARCHFORCLASS
: object. Look for existence of class.-
CLASS
(Required): string. Class of interest. See rules forTRACEFROM
below.
-
-
SEARCHFORCALLTOCLASS
: object. Look for existence of calls to this class. Possible subkeys:-
CLASS
(Required): string. Class of interest. See rules forTRACEFROM
below. -
SEARCHLOCATION
: string. Used to determine whether the call to the method was from a specific class or method. -
RETURN
: string. Of the format "x AS y", where x is one of<class>
or<method>
, indicating the class or method from which this method was called, and y is a (unique) identifier. The identifier must begin with@
. This value can be graphed or used in subsequent searches (within the same bug template). See the section on RETURNs for more information.
-
-
SEARCHFORSTRING
: object. Look for existence of string.-
STRING
(Required): string. String to search for.
-
-
SEARCHFORCALLTOSTRING
: object. Look for existence of calls to this class. Possible subkeys:-
STRING
(Required): string. String to search for. -
SEARCHLOCATION
: string. Used to determine whether the call to the method was from a specific class or method. -
RETURN
: string. Of the format "x AS y", where x is one of<class>
or<method>
, indicating the class or method from which this method was called, and y is a (unique) identifier. The identifier must begin with@
. This value can be graphed or used in subsequent searches (within the same bug template). See the section on RETURNs for more information.
-
-
SEARCHFORANNOTATION
: object. Look for a method annotation-
ANNOTATION
(Required): string. Annotation to search for. -
SEARCHLOCATION
: string. Used to determine whether the annotated method was from a specific class or method. -
RETURN
: string. Of the format "x AS y", where x is one of<class>
or<method>
, indicating the class or method from which this method was called, and y is a (unique) identifier. The identifier must begin with@
. This value can be graphed or used in subsequent searches (within the same bug template). See the section on RETURNs for more information.
-
-
-
TRACE
: single trace requires object. Multiple traces (all of which must be satisfied) can be specified as list of objects. Object subkeys:-
TRACEFROM
(Required): string. Starting point in smali representation or linked items, or combination thereof. String can specify multiple possible classes/methods separated by theOR
keyword. If we are tracing from a previously RETURNed value, then we can specify sub-parts by using[]
. That is, if a method is returned and we want to use only the class part for theTRACEFROM
, then we can specify this as@prev_return[<class>]
. If the entire value is to be used, we still need to use[]
as@prev_return[]
. -
TRACETO
(Required): string. As forTRACEFROM
. -
TRACEDIRECTION
: string. Must be eitherFORWARD
orREVERSE
, depending on how you want data to be traced. Default isREVERSE
. -
TRACELENGTHMAX
: integer. Specifies the maximum length for a trace chain/path. Overrides the value in the config file for this trace object only. -
RETURN
: string. If specified, must be of the format<tracepath> AS @tracepath_<unique_identifier>
. See the section on RETURNs for more information. -
TRACETYPE
(Experimental): string. One ofBASIC
orADVANCED
. If the type isADVANCED
, then the following additional keywords can be used with theTRACEFROM
andTRACETO
options. DefaultBASIC
.-
ARGTO
: Trace to/from the argument to a function. -
ARGINDEX
: Only valid ifARGTO
is specified. Index of the register used as an argument to the function of interest. Default 0. -
RESULTOF
: Trace to/from the output of a function.
- A valid
TRACEFROM
/TRACETO
string inADVANCED
trace mode could be:
ARGTO <method>:Landroid/webkit/WebView;->loadUrl(Ljava/lang/String;)V ARGINDEX 1
or
RESULTOF Landroid/content/Intent;->getData()Landroid/net/Uri;
-
-
Note: Forward tracing can only begin from a
RESULTOF
and can end inARGTO
or general method. Reverse tracing starts with anARGTO
and ends inRESULTOF
or general method. - Note: Forward tracing can take a very long time in some cases. Opt for reverse tracing wherever possible.
-
A string used for specifying graphable elements. All elements must be the result of the preceding analysis.
A graphable template string is of the format
x WITH a AS attribute=p, b AS label, c AS attribute=r ...
- Here,
x
is the element that is graphed. It must be a linked item. There are a number of possibilities:-
x
= "@tracepath_xx": this would graph an entire chain. Note that@tracepath_xx
must be the identifier of a returned tracepath. -
x
= "@app": this would return a single node with the application package name. -
x
is something else beginning with @: any previously declared identifier output from aRETURN
element.
-
- The remaining are attributes and labels.
- Attributes are specified as
<value> AS attribute=<attribute_name>
. - Labels are specified as
<value> AS label
.
- Attributes are specified as
-
p
is a special type of attribute. It is the node identifier, which is an attribute that must be present for every node. The node identifier can be thought of as being similar to a primary key in a SQL database. -
a
tells the graphing tool which aspect ofx
to use as the node identifier. This can have a value of<self>
, which would return the value ofx
as-is. It can also be any pattern created using<class>
,<method>
and<desc>
. For example, ifa
is specified as<method>-<desc>-<class>
, then the method callLcom/xxxx/yyyy/zzzz;-><init>()V
would be rendered as<init>-()V-Lcom/xxxx/yyyy/zzzz;
.
You can have as many attributes and labels as you like for a graphable element (subject to any restrictions imposed by Neo4j). However, fewer is generally better. Also, it's easier if none but the first attribute/label is a linked element. If other attributes are linked, they will simply be added as a list to a single node (which can make everything look a bit untidy).
RETURNs are items that are output from a particular analysis block. While the rules for RETURNs differ based on the type of analysis (i.e., Manifest vs. Code Search vs. Code Trace), there are some elements that all RETURNs have in common.
Every RETURN
item must have some way to uniquely identify it. That is, it must have a "name" of sorts. This name or identifier is specified using the AS
keyword.
The AS
identifier used with a RETURN
item must begin with an '@'. RETURNs that are output from one analysis can be graphed or used as input to a subsequent analysis (within the same bug template). When used in another analysis, RETURNs may be referred to (within the code) as links.
Do not use the whole words @app
or @tracepath
as identifiers. These are keywords and have specific meanings within the code. If returning trace chains, you must use an identifier beginning with @tracepath_
. Do not use @tracepath
as a substring in any other identifier, as it will lead to it being processed incorrectly.
Note that there is a strict top-to-bottom processing, so any RETURN
item can only be used in subsequent searches.
To illustrate, the below will work (@web_view is used after it has been RETURNed. Tool will look for the string "ABCD" within all web views that have been identified as having a call to the WebView->addJavascriptInterface
method).
{
"CODEPARAMS": {
"SEARCH": {
"SEARCHFORCALLTOMETHOD": {
"METHOD": "Landroid/webkit/WebView;->addJavascriptInterface",
"RETURN": "@method AS @web_view"
},
"SEARCHFORSTRING": {
"STRING": "ABCD",
"SEARCHLOCATION": "@method:@web_view"
}
}
}
But this will not (an attempt is made to use @location_abcd before it has actually been RETURNed):
{
"CODEPARAMS": {
"SEARCH": {
"SEARCHFORCALLTOMETHOD": {
"METHOD": "Landroid/webkit/WebView;->addJavascriptInterface",
"SEARCHLOCATION": "@method:@location_abcd"
},
"SEARCHFORSTRING": {
"STRING": "ABCD",
"RETURN": "@method AS @location_abcd"
}
}
}
Manifest Analysis
With RETURN
s from a Manifest Analysis, if the returned value is something like an Activity name (which would correspond to a class within the app code), and if it to be used as a link for subsequent searches, then prefix the RETURN value with <smali>:
. This tells the script to convert the Activity name to the equivalent smali representation.
Right now, a Manifest Analysis can only return values. It cannot use values returned by other analyses. If a use case presents itself for using a linked RETURN item as input in a Manifest Analysis, please raise an enhancement issue and we can look at adding the required functionality.
Code Trace
The RETURN
s from a code trace can only have one format: <tracepath> as @tracepath_<unique_identifier>
, e.g., <tracepath> as @tracepath_browsable_intent
This returns the entire trace chain as a string, with chain links separated by commas.
Code Search
This is probably the type of analysis that allows for the most flexibility with RETURN
s. No special rules, apart from the restrictions mentioned in the "General Rules for RETURNs" section above.
Below is a valid template:
{
"METADATA": {
"NAME": "JSbridgeBrowsable"
},
"MANIFESTPARAMS": {
"BASEPATH": "manifest->application->activity OR manifest->application->activity-alias",
"SEARCHPATH": {
"intent-filter": {
"action": {
"LOOKFOR": {
"TAGVALUEMATCH": "<NAMESPACE>:name=android.intent.action.VIEW"
}
},
"category": {
"LOOKFOR": {
"TAGVALUEMATCH": "<NAMESPACE>:name=android.intent.category.BROWSABLE"
}
},
"data": {
"RETURN": ["<NAMESPACE>:host AS @host", "<NAMESPACE>:scheme AS @scheme"]
}
}
},
"RETURN": ["<smali>:<NAMESPACE>:name AS @activity_name"]
},
"CODEPARAMS": {
"SEARCH": {
"SEARCHFORCALLTOMETHOD": {
"METHOD": "Landroid/webkit/WebView;->addJavascriptInterface",
"RETURN": "<class> AS @web_view"
}
},
"TRACE": {
"TRACEFROM": "<method>:@web_view[]->loadUrl(Ljava/lang/String;)V",
"TRACETO": "<class>:@activity_name",
"TRACELENGTHMAX": 10,
"RETURN": "<tracepath> AS @tracepath_browsablejsbridge"
}
},
"GRAPH": "@tracepath_browsablejsbridge WITH <method>:<desc>:<class> AS attribute=nodename"
}
}
This might seem like a confusing mess, so let's break it down.
First, the goal of this template is to identify browsable activities that call the loadUrl
method of web views that have JavaScript Interfaces defined on them.
Identifying browsable activities is something that requires a manifest analysis.
- We specify the paths leading upto the
activity
level (oractivity-alias
) asBASEPATH
because we don't care about anything at higher levels. - Within
SEARCHPATH
, we reconstruct the structure of the AndroidManifest.xml. - Since browsable activities are identified via
intent-filters
(under thecategory
tag), we specify aLOOKFOR
within theintent-filters->category
key. - For the activity to be browsable, the
name
tag must have the valueandroid.intent.category.BROWSABLE
, so we specify this as aTAGVALUEMATCH
requirement. - Note that we use a
<NAMESPACE>
placeholder, rather thanandroid:name
as the tag. This is because in rare cases, the namespace is not actuallyandroid
. By using the<NAMESPACE>
placeholder, we let Jandroid know that it should identify the namespace and replace the placeholder with the actual value. - We want the activity or activities that satisfy the browsable requirement to be used later, so we RETURN the
name
of the activity with the identifier@activity_name
. Because the code analysis section doesn't work with Java-formatted class names, we specify that the activity name should be converted to smali format using the<smali>
modifier. - Note: We specify the
<NAMESPACE>:name=android.intent.action.VIEW
for theaction
tag, but not 100% certain that it's needed...
Next, we want to identify web views that have JavaScript Interfaces defined on them, and a path between a loadUrl
call on these web views and the activities returned by the manifest analysis. This is something that requires code analysis.
- To identify web views with JavaScript Interfaces, we use a code search. We specify
Landroid/webkit/WebView;->addJavascriptInterface
and RETURN any class that satisfies this condition as@web_view
. Jandroid will also look for subclasses that may satisfy this requirement. - We then tell the code to trace backwards from the
@web_view
classes'loadUrl(Ljava/lang/String;)V
method and see if it reaches the@activity_name
. We also tell the code to store the trace chain as@tracepath_browsablejsbridge
. We limit the trace chain length to 10 links, to reduce trace times.
Finally, we want to graph the output.
- We tell Jandroid to graph the trace chain, where every node should have the name formatted as method:descriptor:class.
If you know that certain bugs must be exploited in a certain order, then you can specify this in a .links file. Jandroid will then create :EXPLOITS edges from one bug to another.
A valid .links file will look something like this:
{
"BasicBrowsableIntents": ["StartActivityServiceExportedStart", "ExportedJSBridgeStart"],
"ExportedJSBridgeEnd": ["ArbitraryDownloadsStart"]
}
Each primary key denotes the "source" template name, and each element in the list attached to the key is a bug (template) that can be exploited after the source bug. That is, "BasicBrowsableIntents": ["StartActivityServiceExportedStart", "ArbitraryDownloadsExportedStart"]
indicates that you first exploit BasicBrowsableIntents
and then, from that point, you can exploit StartActivityServiceExported
or ArbitraryDownloadsExported
.
If the bug templates that are referenced result in trace chains rather than individual nodes, then you need to specify Start
and End
to indicate that an exploit should begin at the End of a trace chain or go to the Start of a trace chain. That is, let's say you have 3 templates: T1, T2, T3, where T1 outputs a single node and T2/T3 output chains. Let's say the possible exploit chain is T1->T2->T3. This would be specified in the .links file as:
{
"T1": ["T2Start"],
"T2End": ["T3Start"]
}
If, on the other hand, the exploit chain was T2->T1->T3, the .links file would look like:
{
"T2End": ["T1"],
"T1": ["T3Start"]
}
Start
and End
are case-sensitive.
Note that, in the event that some templates are matched to a large number of APKs, the resultant graph can be slow to render and look very messy if links are also specified. In such cases, it might be better not to specify a .links file, but instead identify APKs for each bug separately.
- If specifying traces in a template, and one trace endpoint is fully-defined (i.e., an Android method signature) and the other makes use of RETURNed/linked items, then specify the fully-defined endpoint as
TRACETO
and the other asTRACEFROM
.