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.
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.
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.
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.
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.
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.
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
andephemeral id
(token) and their relationship and can build a full contact network.Even if the
public keys
and theephemeral 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
andephemeral id
of each other. This is not necessary.The
ephemeral id
is only 32bit long and is enough to ask the p2pkit api for apublic keys
,kanka_id
/p2pkit uuid
of a third person. Brute forcing this small space and getting allpublic keys
seams feasable. This information could be used to send fakeinfection-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
Ref: https://www.roteskreuz.at/fileadmin/user_upload/Bericht_Datenschutzfolgeabschaetzung_StoppCorona_App.pdf
On page 10/13 with the data flow chart there is an issue.
pink 4a
andpink 4b
also contains thekanka_id
(P2P ID
) and theephemeral ids
(rollierende ID
) from the other enduser, This leads to be able to identify everyone by thiskanka_id
that is static over the lifetime of the app installation.Analysis of other contact tracing app concepts
Analysis PEPP-PT https://github.com/DP-3T/documents/blob/master/Security%20analysis/PEPP-PT_%20Data%20Protection%20Architechture%20-%20Security%20and%20privacy%20analysis.pdf
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:
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
Also the timestamps in the zip matches with that.
Maven repo has not https support https://github.com/austrianredcross/stopp-corona-android/issues/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
andrecipientProxyId
during automatic handshake by p2pkit.internal_p2pkit_preferences.xml Alice
internal_p2pkit_preferences.xml Bob
creation of the static P2Pkit-UUID
The P2PKit UUID is generated ones and stored as
kanka_id
in theshared preferences
fileinternal_p2pkit_preferences.xml
of the app.o.a.b.j:
websocket secret from java util random
Source: https://developer.android.com/reference/java/util/Random
https://android.googlesource.com/platform/libcore.git/+/android-4.4.4_r1.0.1/luni/src/main/java/java/util/Random.java
Code in the p2p-sdk n.a.a.v:
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)
UUID / kanka_id / senderProxyId of of Bob
UUID / kanka_id / senderProxyId of of Alice
Ephemeral ID of Bob
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')
BLE/GATT
Service UUID
m.b.k.s:
BluetoothLeAdvertise
https://developer.android.com/reference/android/bluetooth/le/BluetoothLeAdvertiser
o.a.b.m.b.a.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: