Remove P2Pkit
Closed this issue · 1 comments
P2Pkit is a SDK that allows you to find nearby persons that also use this sdk over
different P2P-Channels(BLE/GATT, WIFI-Direct), it does not have a audo P2P-Channel.
More information found on https://p2pkit.io .
The internal workflow is used to exchange a UUID (kanka_id) over the P2Pkit-Channels. This is later on used to exchange data (in this case public keys
) over the p2pkit cloud via WebSocket (wss://p2pkit-api-v5-prod.uepaa.ch
)
Problem summary
The p2pkit api server knows ALL public keys
, kanka_id
/p2pkit uuid
and ephemeral id
(token) and their relationship and can build a full contact network.
Even if the public keys
and the ephemeral ids
change the relationship is still visible for the server because the p2pkit UUIDs never change. For details see 'Local UUIDs'
In addition Alice and Bob have both the public keys
, kanka_id
/p2pkit uuid
and ephemeral id
of each other. This is not necessary.
The ephemeral id
is only 32bit long and is enough to ask the p2pkit api for a public keys
, kanka_id
/p2pkit uuid
of a third person. Brute forcing this small space and getting all public keys
seams feasable. This information could be used to send fake infection-messages
to the red cross server (rca-coronaapp-rcp-fd.azurefd.net
).
Impact
The app always sends the public key to the nearby devices in combination with a static UUID from p2pkit-sdk to a ueppa server (p2pkit-api-v5-prod.uepaa.ch
) (hosted in Amazon EC2 cloud in Frankfurt/Germany).
This leads to a privacy breach, when someone uses the data that is send over the p2pkit api server.
Also a new key rolling every day would not fix this problem,
because the UUID stays the same for an app until it gets deinstalled and not reinstalled from a backup.
It is possible to track the person pseudonymised. This gives advertise tracker a perfect identifier for each person. This can be used to measure user behavior. Also the advertise industrie show that they are able to invest already more in similar technics like face recognition and bluetooth mac address tracker.
Proposed Solution
Remove p2pkit and forget it for these kind of apps.
Analysis of the Datenschutzfolgeabschaetzung
On page 10/13 with the data flow chart there is an issue.
pink 4a
and pink 4b
also contains the kanka_id
(P2P ID
) and the ephemeral ids
(rollierende ID
) from the other enduser,
This leads to be able to identify everyone by this kanka_id
that is static over the lifetime of the app installation.
Analysis of other contact tracing app concepts
Contact Tracing Joint Statement
https://www.esat.kuleuven.be/cosic/sites/contact-tracing-joint-statement/
Data Privacy Policy from P2Pkit
This is a quote from the data policy from p2pkit.
Source: http://p2pkit.io/pdf/160718_PrivacyPolicy.pdf
P2PDataexchange:
Your Applications using our Service may send data such as
Application levelIDs, Application leveldata, or EndUserdata. This data is sent both
over the online channel (if available) through our Cloud Service and the P2Pchannel.
The data exchanges are not encrypted and we recommend Application developers to not
send sensitive data using our Service.
Last release 2017-08-24
http://p2pkit.io/maven2/ch/uepaa/p2p/p2pkit-android/maven-metadata.xml
http://p2pkit.io/maven2/ch/uepaa/p2p/p2pkit-android-lib/maven-metadata.xmln
<metadata>
<groupId>ch.uepaa.p2p</groupId>
<artifactId>p2pkit-android</artifactId>
<versioning>
<latest>2.0.6</latest>
<release>2.1.3</release>
<versions>
<version>2.0.4</version>
<version>2.0.6</version>
<version>2.1.2</version>
<version>2.1.3</version>
</versions>
<lastUpdated>20170824120556</lastUpdated>
</versioning>
</metadata>
Also the timestamps in the zip matches with that.
Maven repo has not https support #54
Local UUIDs
P2Pkit uses internal UUIDs called kanka_id
. These are saved in the app_data folder eg. /data/data/at.roteskreuz.stopcorona/shared_prefs/
at first system start.
The UUIDs are used as senderProxyId
and recipientProxyId
during automatic handshake by p2pkit.
internal_p2pkit_preferences.xml Alice
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<map>
<string name="kanka_id">bab450e9-472e-4cbc-a3bc-ec9908bac107</string>
</map>
internal_p2pkit_preferences.xml Bob
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<map>
<string name="kanka_id">b3d3d4a1-7b73-457e-81b3-5bbe0b574629</string>
</map>
creation of the static P2Pkit-UUID
The P2PKit UUID is generated ones and stored as kanka_id
in the shared preferences
file internal_p2pkit_preferences.xml
of the app.
o.a.b.j:
static synchronized void a(Context context) {
synchronized (b.class) {
SharedPreferences sharedPreferences = context.getSharedPreferences("internal_p2pkit_preferences", 0);
String string = sharedPreferences.getString("kanka_id", null);
if (string == null) {
string = UUID.randomUUID().toString();
sharedPreferences.edit().putString("kanka_id", string).apply();
}
h = UUID.fromString(string);
}
}
websocket secret from java util random
Source: https://developer.android.com/reference/java/util/Random
Instances of java.util.Random are not cryptographically secure. Consider instead using SecureRandom to get a cryptographically secure pseudo-random number generator for use by security-sensitive applications.
public Random() {
// Note: Using identityHashCode() to be hermetic wrt subclasses.
setSeed(System.currentTimeMillis() + System.identityHashCode(this));
}
Code in the p2p-sdk
n.a.a.v:
public class v extends Thread {
public final ByteBuffer A;
public final Socket B;
public OutputStream C;
public Handler D;
public final Random x = new Random(); // 🤬
....
stringBuilder3 = new StringBuilder("Sec-WebSocket-Key: ");
byte[] bArr2 = new byte[16];
vVar.x.nextBytes(bArr2); // 🤬
sb.append(Base64.encodeToString(bArr2, 2));
sb.append("\r\n");
byteBuffer.put(sb.toString().getBytes());
P2Pkit WS data dump
We did the analysis of the App with the version 1.1.4.
The captured data is the actual data that is transfered over the network in a TLS websocket connection.
More detail dumps: https://gist.github.com/TuxCoder/875fd5de7bfff4272f0a0651a9b3eb56
Sample DiscoveryMessage Response from Bob to Alice
This following message is generated while a contact is exchanged between Alice and Bob.
Raw package before send to websocket (w/o websocket header)
00000000: 0000 000a 0000 0190 0000 00f4 0072 26df .............r&.
00000010: 0000 0024 6261 6234 3530 6539 2d34 3732 ...$bab450e9-472
00000020: 652d 3463 6263 2d61 3362 632d 6563 3939 e-4cbc-a3bc-ec99
00000030: 3038 6261 6331 3037 0000 0024 6233 6433 08bac107...$b3d3
00000040: 6434 6131 2d37 6237 332d 3435 3765 2d38 d4a1-7b73-457e-8
00000050: 3162 332d 3562 6265 3062 3537 3436 3239 1b3-5bbe0b574629
00000060: 0000 000b 0000 0004 2f1a 24e3 0000 008c ......../.$.....
00000070: 3081 8902 8181 00cc 4eaa 3b43 7763 f1f4 0.......N.;Cwc..
00000080: 7000 6303 4085 9f5f ca35 06a8 3eff ea76 p.c.@.._.5..>..v
00000090: 527f 7809 acd1 0419 1d61 5dc8 e1aa a2d6 R.x......a].....
000000a0: 5361 7c26 514d 7bed 1e52 0b8d 38fe f437 Sa|&QM{..R..8..7
000000b0: 569c de2e 3cf1 53bc c7cd 6fec 292f 7ea0 V...<.S...o.)/~.
000000c0: 5996 2869 45ef ef83 e890 b6e0 b17e f56b Y.(iE........~.k
000000d0: 46e0 3856 b19c 0cfe a4b7 6650 28fa 1df9 F.8V......fP(...
000000e0: 9514 2c19 0f19 5126 c010 be83 a186 2bd9 ..,...Q&......+.
000000f0: 109f 043b 5974 3702 0301 0001 0000 0000 ...;Yt7.........
UUID / kanka_id / senderProxyId of of Bob
bab450e9-472e-4cbc-a3bc-ec9908bac107
UUID / kanka_id / senderProxyId of of Alice
b3d3d4a1-7b73-457e-81b3-5bbe0b574629
Ephemeral ID of Bob
2f1a 24e3
The ephemeral ID of Alice is known to the server by the ProxyConnectRequest when the app connects to p2pkit api.
Public key in this message fetched from local app database ('automatic_discovery')
30818902818100cc4eaa3b437763f1f4
7000630340859f5fca3506a83effea76
527f7809acd104191d615dc8e1aaa2d6
53617c26514d7bed1e520b8d38fef437
569cde2e3cf153bcc7cd6fec292f7ea0
5996286945efef83e890b6e0b17ef56b
46e03856b19c0cfea4b7665028fa1df9
95142c190f195126c010be83a1862bd9
109f043b5974370203010001
BLE/GATT
Service UUID
m.b.k.s:
public static UUID a(UUID uuid) {
return UUID.fromString("0000FFFF-0000-1000-8000-00805F9B34FB".replace("FFFF", uuid.toString().substring(4, 8)));
}
BluetoothLeAdvertise
https://developer.android.com/reference/android/bluetooth/le/BluetoothLeAdvertiser
o.a.b.m.b.a.a:
AdvertiseSettings build = new AdvertiseSettings.Builder().setAdvertiseMode(2).setTxPowerLevel(3).setConnectable(true).build();
AdvertiseData build2 = new AdvertiseData.Builder().setIncludeDeviceName(false).setIncludeTxPowerLevel(false).addServiceUuid(new ParcelUuid(uuid)).addServiceData(new ParcelUuid(a2), cVar.a()).build();
AdvertiseData build3 = new AdvertiseData.Builder().setIncludeTxPowerLevel(true).addServiceUuid(new ParcelUuid(uuid)).addServiceData(new ParcelUuid(a2), cVar.a()).build();
AdvertiseCallback aVar = new a();
StringBuilder stringBuilder = new StringBuilder("Start advertising service: ");
stringBuilder.append(uuid.toString());
stringBuilder.append(" with packet bytes: ");
stringBuilder.append(Arrays.toString(cVar.a()));
Build in Analytics
url: p2pkit-analytics-v5-prod.uepaa.ch
The apps calls this server on start of the automatic discovery. In the response the wss address of the p2pkit api server p2pkit-api-v5-prod.uepaa.ch
is announced.
TLS settings from p2pkit-api-v5-prod.uepaa.ch
testssl.sh is used for testing, full report: https://cpad.milliways.info/code/#/2/code/view/xJHP+QVt8zA1bjJkDUAbl18HVrBV1RkkwexEMB67aZY/present/
Result is not good not terrible.
Found problems:
Tested Server: 63.33.213.0:443 (p2pkit-api-v5-prod.uepaa.ch)
TLS 1 offered (deprecated)
TLS 1.1 offered (deprecated)
Has server cipher order? no (NOT ok)
Obsolete: SEED + 128+256 Bit CBC cipher offered
OCSP stapling not offered
Closing as duplicate of austrianredcross/meta#3
See also the comment I left here: #66 (comment)