Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 7ad031c

Browse files
committed
Move to experimental and update qldoc
1 parent a491604 commit 7ad031c

12 files changed

Lines changed: 224 additions & 175 deletions

File tree

java/ql/src/Security/CWE/CWE-312/ClearTextStorageSharedPrefs.ql

Lines changed: 0 additions & 22 deletions
This file was deleted.

java/ql/src/Security/CWE/CWE-312/SensitiveStorage.qll

Lines changed: 0 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
11
import java
22
import semmle.code.java.frameworks.Properties
33
import semmle.code.java.frameworks.JAXB
4-
import semmle.code.java.frameworks.android.SharedPreferences
54
import semmle.code.java.dataflow.TaintTracking
65
import semmle.code.java.dataflow.DataFlow3
76
import semmle.code.java.dataflow.DataFlow4
8-
import semmle.code.java.dataflow.DataFlow5
97
import semmle.code.java.security.SensitiveActions
108

119
/** Test code filter. */
@@ -30,11 +28,6 @@ private class SensitiveSourceFlowConfig extends TaintTracking::Configuration {
3028
m.getMethod() instanceof PropertiesSetPropertyMethod and sink.asExpr() = m.getArgument(1)
3129
)
3230
or
33-
exists(MethodAccess m |
34-
m.getMethod() instanceof SharedPreferences::SharedPreferencesSetMethod and
35-
sink.asExpr() = m.getArgument(1)
36-
)
37-
or
3831
sink.asExpr() = getInstanceInput(_, _)
3932
}
4033

@@ -250,111 +243,3 @@ class Marshallable extends ClassStore {
250243
)
251244
}
252245
}
253-
254-
/* Holds if the method call is a setter method of `SharedPreferences`. */
255-
private predicate sharedPreferencesInput(DataFlow::Node sharedPrefs, Expr input) {
256-
exists(MethodAccess m |
257-
m.getMethod() instanceof SharedPreferences::SharedPreferencesSetMethod and
258-
input = m.getArgument(1) and
259-
not exists(EncryptedValueFlowConfig conf | conf.hasFlow(_, DataFlow::exprNode(input))) and
260-
sharedPrefs.asExpr() = m.getQualifier()
261-
)
262-
}
263-
264-
/* Holds if the method call is the store method of `SharedPreferences`. */
265-
private predicate sharedPreferencesStore(DataFlow::Node sharedPrefs, Expr store) {
266-
exists(MethodAccess m |
267-
m.getMethod() instanceof SharedPreferences::SharedPreferencesStoreMethod and
268-
store = m and
269-
sharedPrefs.asExpr() = m.getQualifier()
270-
)
271-
}
272-
273-
/* Flow from `SharedPreferences` to either a setter or a store method. */
274-
class SharedPreferencesFlowConfig extends TaintTracking::Configuration {
275-
SharedPreferencesFlowConfig() { this = "SensitiveStorage::SharedPreferencesFlowConfig" }
276-
277-
override predicate isSource(DataFlow::Node src) {
278-
src.asExpr() instanceof SharedPreferencesEditor
279-
}
280-
281-
override predicate isSink(DataFlow::Node sink) {
282-
sharedPreferencesInput(sink, _) or
283-
sharedPreferencesStore(sink, _)
284-
}
285-
}
286-
287-
/**
288-
* Method call of encrypting sensitive information.
289-
* As there are various implementations of encryption (reversible and non-reversible) from both JDK and third parties, this class simply checks method name to take a best guess to reduce false positives.
290-
*/
291-
class EncryptedSensitiveMethodAccess extends MethodAccess {
292-
EncryptedSensitiveMethodAccess() {
293-
getMethod().getName().toLowerCase().matches(["%encrypt%", "%hash%"])
294-
}
295-
}
296-
297-
/* Flow configuration of encrypting sensitive information. */
298-
class EncryptedValueFlowConfig extends DataFlow5::Configuration {
299-
EncryptedValueFlowConfig() { this = "SensitiveStorage::EncryptedValueFlowConfig" }
300-
301-
override predicate isSource(DataFlow5::Node src) {
302-
exists(EncryptedSensitiveMethodAccess ema | src.asExpr() = ema.getAnArgument())
303-
}
304-
305-
override predicate isSink(DataFlow5::Node sink) {
306-
exists(MethodAccess ma |
307-
ma.getMethod() instanceof SharedPreferences::SharedPreferencesSetMethod and
308-
sink.asExpr() = ma.getArgument(1)
309-
)
310-
}
311-
312-
override predicate isAdditionalFlowStep(DataFlow5::Node n1, DataFlow5::Node n2) {
313-
exists(EncryptedSensitiveMethodAccess ema |
314-
n1.asExpr() = ema.getAnArgument() and
315-
n2.asExpr() = ema
316-
)
317-
}
318-
}
319-
320-
/* Flow from the create method of `androidx.security.crypto.EncryptedSharedPreferences` to its instance. */
321-
private class EncryptedSharedPrefFlowConfig extends DataFlow3::Configuration {
322-
EncryptedSharedPrefFlowConfig() { this = "SensitiveStorage::EncryptedSharedPrefFlowConfig" }
323-
324-
override predicate isSource(DataFlow::Node src) {
325-
src.asExpr().(MethodAccess).getMethod() instanceof
326-
SharedPreferences::EncryptedSharedPrefsCreateMethod
327-
}
328-
329-
override predicate isSink(DataFlow::Node sink) {
330-
sink.asExpr().getType() instanceof SharedPreferences::TypeSharedPreferences
331-
}
332-
}
333-
334-
/** The call to get a `SharedPreferences.Editor` object, which can set shared preferences or be stored to device. */
335-
class SharedPreferencesEditor extends MethodAccess {
336-
SharedPreferencesEditor() {
337-
this.getMethod() instanceof SharedPreferences::SharedPreferencesGetEditorMethod and
338-
not exists(
339-
EncryptedSharedPrefFlowConfig config // not exists `SharedPreferences sharedPreferences = EncryptedSharedPreferences.create(...)`
340-
|
341-
config.hasFlow(_, DataFlow::exprNode(this.getQualifier()))
342-
)
343-
}
344-
345-
/** Gets an input, for example `input` in `editor.putString("password", password);`. */
346-
Expr getAnInput() {
347-
exists(SharedPreferencesFlowConfig conf, DataFlow::Node n |
348-
sharedPreferencesInput(n, result) and
349-
conf.hasFlow(DataFlow::exprNode(this), n)
350-
)
351-
}
352-
353-
/** Gets a store, for example `editor.commit();`. */
354-
Expr getAStore() {
355-
exists(SharedPreferencesFlowConfig conf, DataFlow::Node n |
356-
sharedPreferencesStore(n, result) and
357-
conf.hasFlow(DataFlow::exprNode(this), n)
358-
)
359-
}
360-
}

java/ql/src/Security/CWE/CWE-312/ClearTextStorageSharedPrefs.java renamed to java/ql/src/experimental/Security/CWE/CWE-312/CleartextStorageSharedPrefs.java

File renamed without changes.

java/ql/src/Security/CWE/CWE-312/ClearTextStorageSharedPrefs.qhelp renamed to java/ql/src/experimental/Security/CWE/CWE-312/CleartextStorageSharedPrefs.qhelp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
<p>
2121
In the second and third examples, the code encrypts sensitive information before saving it to the device.
2222
</p>
23-
<sample src="ClearTextStorageSharedPrefs.java" />
23+
<sample src="CleartextStorageSharedPrefs.java" />
2424
</example>
2525

2626
<references>
Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
/**
2+
* @name Cleartext storage of sensitive information using `SharedPreferences` on Android
3+
* @description Cleartext Storage of Sensitive Information using SharedPreferences on Android allows access for users with root privileges or unexpected exposure from chained vulnerabilities.
4+
* @kind path-problem
5+
* @id java/android/cleartext-storage-shared-prefs
6+
* @tags security
7+
* external/cwe/cwe-312
8+
*/
9+
10+
import java
11+
import semmle.code.java.dataflow.DataFlow4
12+
import semmle.code.java.dataflow.DataFlow5
13+
import semmle.code.java.dataflow.TaintTracking
14+
import semmle.code.java.frameworks.android.Intent
15+
import semmle.code.java.frameworks.android.SharedPreferences
16+
import semmle.code.java.security.SensitiveActions
17+
import DataFlow::PathGraph
18+
19+
/** Holds if the method call is a setter method of `SharedPreferences`. */
20+
private predicate sharedPreferencesInput(DataFlow::Node sharedPrefs, Expr input) {
21+
exists(MethodAccess m |
22+
m.getMethod() instanceof SharedPreferences::SetPreferenceMethod and
23+
input = m.getArgument(1) and
24+
not exists(EncryptedValueFlowConfig conf | conf.hasFlow(_, DataFlow::exprNode(input))) and
25+
sharedPrefs.asExpr() = m.getQualifier()
26+
)
27+
}
28+
29+
/** Holds if the method call is the store method of `SharedPreferences`. */
30+
private predicate sharedPreferencesStore(DataFlow::Node sharedPrefs, Expr store) {
31+
exists(MethodAccess m |
32+
m.getMethod() instanceof SharedPreferences::StorePreferenceMethod and
33+
store = m and
34+
sharedPrefs.asExpr() = m.getQualifier()
35+
)
36+
}
37+
38+
/** Flow from `SharedPreferences` to either a setter or a store method. */
39+
class SharedPreferencesFlowConfig extends TaintTracking::Configuration {
40+
SharedPreferencesFlowConfig() {
41+
this = "CleartextStorageSharedPrefs::SharedPreferencesFlowConfig"
42+
}
43+
44+
override predicate isSource(DataFlow::Node src) {
45+
src.asExpr() instanceof SharedPreferencesEditor
46+
}
47+
48+
override predicate isSink(DataFlow::Node sink) {
49+
sharedPreferencesInput(sink, _) or
50+
sharedPreferencesStore(sink, _)
51+
}
52+
}
53+
54+
/**
55+
* Method call of encrypting sensitive information.
56+
* As there are various implementations of encryption (reversible and non-reversible) from both JDK and third parties, this class simply checks method name to take a best guess to reduce false positives.
57+
*/
58+
class EncryptedSensitiveMethodAccess extends MethodAccess {
59+
EncryptedSensitiveMethodAccess() {
60+
getMethod().getName().toLowerCase().matches(["%encrypt%", "%hash%"])
61+
}
62+
}
63+
64+
/** Flow configuration of encrypting sensitive information. */
65+
class EncryptedValueFlowConfig extends DataFlow5::Configuration {
66+
EncryptedValueFlowConfig() { this = "CleartextStorageSharedPrefs::EncryptedValueFlowConfig" }
67+
68+
override predicate isSource(DataFlow5::Node src) {
69+
exists(EncryptedSensitiveMethodAccess ema | src.asExpr() = ema.getAnArgument())
70+
}
71+
72+
override predicate isSink(DataFlow5::Node sink) {
73+
exists(MethodAccess ma |
74+
ma.getMethod() instanceof SharedPreferences::SetPreferenceMethod and
75+
sink.asExpr() = ma.getArgument(1)
76+
)
77+
}
78+
79+
override predicate isAdditionalFlowStep(DataFlow5::Node n1, DataFlow5::Node n2) {
80+
exists(EncryptedSensitiveMethodAccess ema |
81+
n1.asExpr() = ema.getAnArgument() and
82+
n2.asExpr() = ema
83+
)
84+
}
85+
}
86+
87+
/** Flow from the create method of `androidx.security.crypto.EncryptedSharedPreferences` to its instance. */
88+
private class EncryptedSharedPrefFlowConfig extends DataFlow4::Configuration {
89+
EncryptedSharedPrefFlowConfig() {
90+
this = "CleartextStorageSharedPrefs::EncryptedSharedPrefFlowConfig"
91+
}
92+
93+
override predicate isSource(DataFlow4::Node src) {
94+
src.asExpr().(MethodAccess).getMethod() instanceof SharedPreferences::CreateEncryptedPrefsMethod
95+
}
96+
97+
override predicate isSink(DataFlow4::Node sink) {
98+
sink.asExpr().getType() instanceof SharedPreferences::TypePrefs
99+
}
100+
}
101+
102+
/** The call to get a `SharedPreferences.Editor` object, which can set shared preferences or be stored to device. */
103+
class SharedPreferencesEditor extends MethodAccess {
104+
SharedPreferencesEditor() {
105+
this.getMethod() instanceof SharedPreferences::GetEditorMethod and
106+
not exists(
107+
EncryptedSharedPrefFlowConfig config // not exists `SharedPreferences sharedPreferences = EncryptedSharedPreferences.create(...)`
108+
|
109+
config.hasFlow(_, DataFlow::exprNode(this.getQualifier()))
110+
)
111+
}
112+
113+
/** Gets an input, for example `input` in `editor.putString("password", password);`. */
114+
Expr getAnInput() {
115+
exists(SharedPreferencesFlowConfig conf, DataFlow::Node n |
116+
sharedPreferencesInput(n, result) and
117+
conf.hasFlow(DataFlow::exprNode(this), n)
118+
)
119+
}
120+
121+
/** Gets a store, for example `editor.commit();`. */
122+
Expr getAStore() {
123+
exists(SharedPreferencesFlowConfig conf, DataFlow::Node n |
124+
sharedPreferencesStore(n, result) and
125+
conf.hasFlow(DataFlow::exprNode(this), n)
126+
)
127+
}
128+
}
129+
130+
private class SensitiveSharedPrefsFlowConfig extends TaintTracking::Configuration {
131+
SensitiveSharedPrefsFlowConfig() {
132+
this = "CleartextStorageSharedPrefs::SensitiveSharedPrefsFlowConfig"
133+
}
134+
135+
override predicate isSource(DataFlow::Node src) { src.asExpr() instanceof SensitiveExpr }
136+
137+
override predicate isSink(DataFlow::Node sink) {
138+
exists(MethodAccess m |
139+
m.getMethod() instanceof SharedPreferences::SetPreferenceMethod and
140+
sink.asExpr() = m.getArgument(1)
141+
)
142+
}
143+
}
144+
145+
/** Class for shared preferences that may contain 'sensitive' information */
146+
class SensitiveSharedPrefsSource extends Expr {
147+
SensitiveSharedPrefsSource() {
148+
// SensitiveExpr is abstract, this lets us inherit from it without
149+
// being a technical subclass
150+
this instanceof SensitiveExpr
151+
}
152+
153+
/** Holds if this source flows to the `sink`. */
154+
predicate flowsTo(Expr sink) {
155+
exists(SensitiveSharedPrefsFlowConfig conf |
156+
conf.hasFlow(DataFlow::exprNode(this), DataFlow::exprNode(sink))
157+
)
158+
}
159+
}
160+
161+
from SensitiveSharedPrefsSource data, SharedPreferencesEditor s, Expr input, Expr store
162+
where
163+
input = s.getAnInput() and
164+
store = s.getAStore() and
165+
data.flowsTo(input)
166+
select store, "'SharedPreferences' class $@ containing $@ is stored here. Data was added $@.", s,
167+
s.toString(), data, "sensitive data", input, "here"

0 commit comments

Comments
 (0)