Improper Input Validation on User's Location on PUT /WhoService/putLocation Could Affect Availability/Falsify Users
Medium
W
WHO COVID-19 Mobile App
Submitted None
Team Summary
Official summary from WHO COVID-19 Mobile App
This refers to sanitization of an API that is already scheduled to be deleted. It doesn't appear to be exploitable. https://github.com/WorldHealthOrganization/app/pull/1826
Actions:
Reported by
humayunalikhan
Vulnerability Details
Technical details and impact analysis
Summary:
Note: I noticed that that the team has fixed issues like an XSS that's caused only from a header value (typically OOS since it's not directly exploitable) https://github.com/WorldHealthOrganization/app/pull/855, so in the spirit of this I'm also reporting another "good-to-fix" issue.
On the WHO app, users send approximate location data to the WhoService API:
/app/client/flutter/lib/pages/onboarding/location_sharing_page.dart:
Future<void> _allowLocationSharing() async {
try {
await Location().requestPermission();
if (await Location().hasPermission() == PermissionStatus.granted) {
if (await Location().requestService()) {
LocationData location = await Location().getLocation();
Map jitteredLocationData = JitterLocation().jitter(
location.latitude, location.longitude,
5 /*kms refers to kilometers*/);
await WhoService.putLocation(
latitude: jitteredLocationData['lat'],
longitude: jitteredLocationData['lng']);
}
}
} catch(_) {
// ignore for now.
} finally {
_complete();
}
}
Which in turn translates to a call to https://staging.whocoronavirus.org/WhoService/putDeviceToken:
curl --request POST \
--url 'https://hackerone.whocoronavirus.org/WhoService/putLocation' \
--header 'content-type: application/json' \
--header 'who-client-id: ██████████' \
--header 'who-platform: ios' \
--data '{
"latitude": 22222222,
"longitude": "9999999"
}'
This returns a 200 OK response. On the server side, we see that it uses the following logic:
[@Override](/override) public Void putLocation(PutLocationRequest request) throws IOException {
Client client = Client.current();
client.latitude = request.latitude;
client.longitude = request.longitude;
S2LatLng coordinates = S2LatLng.fromDegrees(request.latitude, request.longitude);
client.location = S2CellId.fromLatLng(coordinates).id();
ofy().save().entities(client);
return new Void();
}
There is no validation on request.latitude, request.longitude before it is stored into the Google App Engine datastore. This is because the S2LatLng.fromDegrees (which transforms the values into a S2LatLng object) from the s2-geometry-library-java library specifically does not validate these values because, according to their comments at https://github.com/google/s2-geometry-library-java/blob/master/src/com/google/common/geometry/S2LatLng.java:
Like the rest of the "geometry" package, the
intent is to represent spherical geometry as a mathematical abstraction, so
functions that are specifically related to the Earth's geometry (e.g.
easting/northing conversions) should be put elsewhere.
Thus, even these values:
"latitude": 22222222,
"longitude": "9999999"
Are accepted and stored in the database even though they are technically non-existent coordinates on earth.
To reproduce, just run this request with different who-client-id UUID you generated yourself and impossible latitude and longitude.
curl --request POST \
--url 'https://hackerone.whocoronavirus.org/WhoService/putLocation' \
--header 'content-type: application/json' \
--header 'who-client-id: ████████' \
--header 'who-platform: ios' \
--data '{
"latitude": 22222222,
"longitude": "9999999"
}'
## Impact
An attacker can exploit this to affect the Availability or Integrity of the analytics data by injecting false location values and falsifying user data. A fix for this would be to implement a quick lat lng validator that is specifically meant to validate Earth geometry, instead of the S2LatLng class.
Report Details
Additional information and metadata
State
Closed
Substate
Resolved
Submitted
Weakness
Improper Input Validation