secure-software-engineering / FlowDroid

FlowDroid Static Data Flow Tracker

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Having problems defining flows for cryptographic functions

Olasergiolas opened this issue · comments

Hello everyone, I am trying to learn FlowDroid in order to create a crypto analysis tool for Android applications. Unfortunately, some issues arose while trying to create some proof of concepts. Below is the fragment of Jimple code of interest. This is a simple encryption of bytes using hard-coded parameters with SecretKeySpec:

        $r12 = new javax.crypto.spec.SecretKeySpec;

        r5 = $r12;

        r6 = "0123456789012345";

        r7 = <java.nio.charset.StandardCharsets: java.nio.charset.Charset UTF_8>;

     label01:
        $r8 = virtualinvoke r6.<java.lang.String: byte[] getBytes(java.nio.charset.Charset)>(r7);

        specialinvoke $r12.<javax.crypto.spec.SecretKeySpec: void <init>(byte[],java.lang.String)>($r8, "AES");

        $r9 = staticinvoke <javax.crypto.Cipher: javax.crypto.Cipher getInstance(java.lang.String)>("AES/ECB/PKCS5PADDING");

        virtualinvoke $r9.<javax.crypto.Cipher: void init(int,java.security.Key)>(1, r5);

     label02:
        r6 = "HELLOWORLD";

     label03:
        $r8 = virtualinvoke r6.<java.lang.String: byte[] getBytes()>();

        $r8 = virtualinvoke $r9.<javax.crypto.Cipher: byte[] doFinal(byte[])>($r8);

I would like to identify a flow between the initial creation of a SecretKeySpec (let's say, the first argument for the class constructor) and the Cipher instance used for encryption and decryption. The idea is being able to detect the usage of a hard-coded key to initialize a Cipher instance. For this, I created the following SourcesAndSinks XML file:

<sinkSources>
	<category id="NO_CATEGORY">	
        <method signature="&lt;javax.crypto.spec.SecretKeySpec: void &lt;init&gt;(byte[],java.lang.String)&gt;">
			<param index="0" type="byte[]">
				<accessPath isSource="true" isSink="false" />
			</param>
		</method>

        <method signature="&lt;javax.crypto.Cipher: void init(int,java.security.Key)&gt;">
			<param index="1" type="java.security.Key">
				<accessPath isSource="false" isSink="true" />
			</param>
		</method>
    </category>
</sinkSources>

When starting the analysis via CLI, sources and sinks are properly identified in the code but no flow is detected. Am I missing something? Furthermore, I would appreciate if you could provide any learning resources for this tool since I am having a hard-time trying to grasp the inner workings of FlowDroid just by looking at source-code.

I believe your source sink file doesn't match what you want to do. In your example, $r8 is derived from the zero fact at SecretKeySpec: void <init>(...). There is no flow from $r8 at that line to Cipher: void init(...). (Technically, $r8 passes by the sink but is not used, so there is also no leak).

In this case, you should try to mark the base object of SecretKeySpec: void <init>(...) as a source to find a flow. Though, I'm not sure whether this specification helps you to find hardcoded keys. By the way, there is also the CryptoGuard: High Precision Detection of Cryptographic Vulnerabilities in Massive-sized Java Projects paper that tries to do the same and discusses refinements to rule out false positive flows in section 5. You might be able to use some of their insights for your project.

After updating my SourcesAndSinks file with your suggestions the flow is now being identified! Although I need to specify the key attribute for the class, it does not seem to work otherwise:

<sinkSources>
	<category id="NO_CATEGORY">	
        <method signature="&lt;javax.crypto.spec.SecretKeySpec: void &lt;init&gt;(byte[],java.lang.String)&gt;">
			<base type="javax.crypto.spec.SecretKeySpec">
				<accessPath isSource="true" isSink="false">
				    <pathElement type="byte[]" field="key" />
				</accessPath>
			</base>
		</method>

        <method signature="&lt;javax.crypto.Cipher: void init(int,java.security.Key)&gt;">
			<param index="1" type="java.security.Key">
				<accessPath isSource="false" isSink="true" />
			</param>
		</method>
    </category>
</sinkSources>

imagen

Having reached this far, I have one question remaining regarding the suitability of FlowDroid for my interests. Wouldn't it be possible to identify a flow between a string statement (r6 = "...") and a method?

Lastly, thanks for leading me to CryptoGuard, I'll check it out.

Of course, that should be possible.

Of course, that should be possible.

How would I go around doing that? I did not find any examples while looking at the SourcesAndSinks files included in the repo.

Thank you for your help!

How would I go around doing that? I did not find any examples while looking at the SourcesAndSinks files included in the repo.

That cannot be expressed via configuration files. You'll have to write your own logic for that, probably by supplying your own SourceSinkManager.