On Tuesday March 24th 2020, the president of Guatemala Alejandro Giammattei announced that his government was releasing a mobile application named Alerta Guate. This application would have 3 main features:

  • Receive alert notifications: Users would receive notifications about emergency situations.
  • Dedicated button to call 1715: At the time of this writing is the Coronavirus hotline in Guatemala.
  • Send information: Users would be able to send messages to the government institutions at the moment mainly about Coronavirus.

Some people were arguing about the amount and type of permissions the application was asking for when installing, (read the replies to the president's tweet). However, sadly, those permissions are very common nowadays and I wanted to gather more information about the application behaviour before I could determine if the application had some hidden purpose. Here's what I found:

It's a white-label application

The company distributing the application is named 'In-telligent Properties LLC' and they also distribute similar applications for countries like Costa Rica, Mexico, El Salvador, Kenya, Ghana, Indonesia, India and Pakistan among others. They are basically the same application with different images, a.k.a. white-label applications. Most of the applications have a generic icon but the Guatemalan version has an icon of the Guatemalan flag, I guess it's because this one is officially backed by the president.

Initial Launch

When the user launches it for the first time, they are presented with a "Registration" screen and immediately an alert shows up asking for location permissions. More on this later.

Alert Guate Location Permission

Registration

The registration screen only has one field where the user can enter their Email or Phone number or leave it blank. If the user doesn't provide an Email or Phone number, one will be assigned by the application.

When the user taps on the 'Next' button, a network call to api.in-telligent.com/api/auth/signup is made with the following parameters:

Alert Guate Signup Network Call

There is a password (and password confirmation password2) field that's part of the network call but the user can only provide an Email or Phone number. I wanted to see if that password was dynamically generated by the application to provide a stronger password than a user would choose and automatically store it in the Keychain or iCloud Keychain to make the whole registration process seamless and secure.

I then grabbed another test device and registered a second user. Much to my surprise, it had the exact same password as the first one. This let me to think the application had this password hardcoded somewhere.

Indeed, that was the case. Inspecting the application's Info.plist I found the hardcoded value and source of this password:

Alerta Guate Hardcoded Password

This means every single registered user has the exact same password and it's hardcoded in plaintext within the application. yay security!

Permissions

On iOS the developers have to provide a string justifying the request of a permission. These are the reasons presented to the users for requesting access to Bluetooth, Location, Microphone, Motion and Photo Library:

Alerta Guate Location Permission Strings

If the image text is litte hard to read:

<key>NSBluetoothAlwaysUsageDescription</key>
<string>Alerta Guate uses your bluetooth to localize alerts.</string>

<key>NSBluetoothPeripheralUsageDescription</key>
<string>Alerta Guate uses bluetooth accessories for localize alerts.</string>

<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>Alerta Guate uses your location to send you location relevant
messages and to allow you to connect to the closest emergency services
team when you are in danger.</string>

<key>NSLocationAlwaysUsageDescription</key>
<string>Alerta Guate uses your location to send you location relevant
messages and to allow you to connect to the closest emergency services
team when you are in danger.</string>

<key>NSLocationWhenInUseUsageDescription</key>
<string>Alerta Guate uses your location to send you location relevant
messages and to allow you to connect to the closest emergency services
team when you are in danger.</string>

<key>NSMicrophoneUsageDescription</key>
<string>Alerta Guate uses your microphone to make calls.</string>

<key>NSMotionUsageDescription</key>
<string>Alerta Guate uses your motion to localize alerts.</string>

<key>NSPhotoLibraryUsageDescription</key>
<string>Alerta Guate uses your photos to add attachments.</string>

This is why the application asks for these permissions:

  • Bluetooth: In the application binary I found a class named Alerta_Guate.BeaconWatcher, strings like "Stopped tracking beacons for" and "beaconRegions", references to CLBeacon and methods like "locationManager:didRangeBeacons:inRegion:" and their iBeacon UUID 937DDCBE-[redacted]-[redacted]-[redacted]-[redacted]. All of this combined with the request for Bluetooth, makes a strong case for the application having some iBeacon functionality that allows the application to use an indoor positioning system (IPS) with BLE devices. An IPS is like a GPS inside buildings. For example if you are in a shopping mall and there are iBeacons on the pillars of the building, the shopping mall could create an application that could guide you to the nearest food court based on your location.
  • Location: I'll explain this in more detail later, but it's used to periodically send the user's location to a server.
  • Microphone: The application allows you to make phone calls (over the Internet) using a 3rd party called Twilio, this is why it requires access to the microphone.
  • Motion: This grants the application access to the device's accelerometer, why would they need this for "localizing alerts"? I don't know.
  • Photo Library: Users can send an attachment when they send an alert that something is happening.

Network Calls

After the user is registered, they land on the "Home" screen. The Home screen is very simple and the user can only see if there are any alerts posted by the government. It's boring so I'm going to focus on the network calls the application makes while the user uses it.

URL: api.in-telligent.com/api/subscribers/ad?appId=alerta-guate
Description: Requests the information of an image to display in a banner at the bottom of the Home screen.
Response (example):

{
  "success": true,
  "data": {
    "bannerAd": {
      "id": 163,
      "image": "322118f8b1aed3848f75fff6491d1fe5_CINTILLO_GUATE_jpg.png",
      "url": "",
      "impressions": 213152,
      "clicks": 0,
      "app_filter": ""
    }
  }
}

URL: api.in-telligent.com/api/subscribers/me
Description: Requests the user's information, including the 'Buildings' they are subscribed to. In this case "Gobierno de Guatemala 3" and "CONRED"
Response (example):

{
  "success": true,
  "Subscriber": {
    "id": [redacted],
    "name": "[redacted]",
    "email": "[redacted]",
    "gender": "",
    "zipcode": "",
    "age": 0,
    "language": null,
    "languageName": null,
    "weatherAlertEnabled": true,
    "lightningAlertEnabled": true,
    "lightningAlertConfirmed": false,
    "betaEnabled": false,
    "User": {
      "canSendLSA": false,
      "Buildings": []
    },
    "PersonalCommunity": [],
    "Buildings": [
      {
        "id": 17491,
        "name": "Gobierno de Guatemala",
        "description": "",
        "status": 1,
        "isVoipEnabled": 1,
        "isTextEnabled": 1,
        "created": "2020-03-24T22:09:42.000Z",
        "subscriberId": null,
        "website": "",
        "BuildingAddress": {
          "lat": 0,
          "lng": 0,
          "radius": 40,
          "isVirtual": 1,
          "City": {
            "id": 0,
            "stateId": 0,
            "name": ""
          },
          "State": {
            "id": 0,
            "countryId": 0,
            "name": "",
            "shortName": ""
          },
          "Country": {
            "id": 0,
            "name": "",
            "shortName": ""
          }
        },
        "BuildingCategory": {
          "id": 3384,
          "buildingId": null,
          "name": "Gobierno de Guatemala 3",
          "BuildingCategoryImages": [
            {
              "id": 7075,
              "buildingCategoryId": 3384,
              "image": "751611f0a82a1a52d406c105477b8edf_IconoAplicadoGuatemalaGob_png.png"
            }
          ]
        },
        "BuildingsSubscriber": {
          "id": 58696312,
          "alertsSubscription": "a",
          "offersSubscription": "a",
          "automatic": 0
        }
      },
      {
        "id": 17492,
        "name": "CONRED",
        "description": "",
        "status": 1,
        "isVoipEnabled": 1,
        "isTextEnabled": 1,
        "created": "2020-03-24T22:10:13.000Z",
        "subscriberId": null,
        "website": "",
        "BuildingAddress": {
          "lat": 0,
          "lng": 0,
          "radius": 40,
          "isVirtual": 1,
          "City": {
            "id": 0,
            "stateId": 0,
            "name": ""
          },
          "State": {
            "id": 0,
            "countryId": 0,
            "name": "",
            "shortName": ""
          },
          "Country": {
            "id": 0,
            "name": "",
            "shortName": ""
          }
        },
        "BuildingCategory": {
          "id": 3245,
          "buildingId": null,
          "name": "CONRED",
          "BuildingCategoryImages": [
            {
              "id": 6909,
              "buildingCategoryId": 3245,
              "image": "48470e01f0249206af83d2fbf680509c_27532e8a-13e1-4037-8240-c5de01df0492_JPG.png"
            }
          ]
        },
        "BuildingsSubscriber": {
          "id": 58696313,
          "alertsSubscription": "a",
          "offersSubscription": "a",
          "automatic": 0
        }
      }
    ],
    "SubscriberAutoSubscribeOptOuts": [],
    "Interests": []
  }
}

URL: api.in-telligent.com/api/subscribers/notifications
Description: Requests the whether there are any alert notifications from the 2 subscribed buildings (17491 & 17492).
Response (example):

{
  "notifications": {
    "17491": [],
    "17492": []
  },
  "Notifications": {
    "17491": [],
    "17492": []
  }
}

These 3 calls are made periodically every 15 seconds. This is still pretty boring, but that's because when the application asked for my location I said 'Don't Allow'. When the user enables location tracking there's a 4th request made:

Alerta Guate Geolocation Network Request

If the application is in the foreground, every 15 seconds the application will send the user's precise location (in this case within 65mts) to the server. I modified my data to show I'm in the middle of nowhere: Spitsbergen, Svalbard. lol enjoy my outlier data points.

This behaviour itself is already suspicious. Although the creators of the application claim they do this to provide relevant information based on your current/last known location and this justifies the geolocation tracking. For example if there's a disaster in a particular area of the country and the user happens to be there, they'd receive a notification about it and avoid sending the alert to users that might not care because they are far away. Fair point, and I get it.

However I needed to know more about the application and kept digging. By going through the disassembly of the application I found a few more interesting points and one that potentially explains the use of the user data (specifically the geolocation data).

Developer's Location

It's very common that during the compilation process there are some paths to files added to the binary. In this case when I searched for strings beginning with /Users I found several references including a full name (first and last name). I'm guessing this is the name of one developers of the application:

Alert Guate - Potential Developer

A quick online search showed it's a very unique name as there were only a few results, including their LinkedIn profile that showed they are based in India:

Alert Guate - Potential Developer's LI

Hardcoded in the binary were also a few development/staging server addresses, one of them was a public IP:

The theory that the development is done from India grew stronger when I found out where this server was located: Hyderabad, Telangana, India.

(Potential) Business Model - Monetization

As with all online services, after paying for the development someone has to pay for the infrastructure: servers and code maintenance. In this case there's no public information about this. The simplest answer is that the Guatemalan government is paying a monthly fee for these services, but there's no way to know for sure. Although there might be another way the company is getting funds to run the infrastructure.

While reviewing the assembly code of the application I found an interesting method:

/* @class WebOCNetworkDriver */
-(void)postRequestWithUrl:(void *)arg2 apiKey:(void *)arg3 body:(struct vector<unsigned char, std::__1::allocator<unsigned char> > *)arg4 responseMessage:(struct EngineMessage *)arg5 {
    r31 = r31 - 0x80;
    r24 = arg4;
    r23 = self;
    r19 = [arg2 retain];
    r20 = [arg3 retain];
    r21 = [NSMutableURLRequest alloc];
    r0 = [NSURL URLWithString:r19];
    r25 = [r0 retain];
    asm { scvtf      d0, w8 };
    r21 = [r21 initWithURL:r25 cachePolicy:0x1 timeoutInterval:r4];
    [r25 release];
    r25 = [[NSData dataWithBytes:r25 length:*(int128_t *)(r24 + 0x8) - *(int128_t *)r24] retain];
    r24 = [[r23 gzipData:r25] retain];
    [r25 release];
    [r21 setHTTPMethod:@"POST"];
    [r21 setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
    [r21 setValue:@"gzip" forHTTPHeaderField:@"Content-Encoding"];
    [r21 setHTTPBody:r24];
    r26 = [sub_10013bbbc(0x100488330) retain];
    [r21 setValue:r26 forHTTPHeaderField:@"X-Factual-Lib"];
    [r26 release];
    [r21 setValue:r20 forHTTPHeaderField:@"X-Factual-API-Key"];
    [r23 startNetworkRequest];
    r26 = r23->_queue;
    var_50 = [r23 retain];
    [NSURLConnection sendAsynchronousRequest:r21 queue:r26 completionHandler:&var_70];
    [var_50 release];
    [r24 release];
    [r21 release];
    [r20 release];
    [r19 release];
    return;
}

The method itself is somewhat interesting, there are some bits of information that caught my eye. It's a network request to some URL with an HTTP body that is some zipped data (gzip) and it mentions Factual-Lib in the headers of the request. What's Factual-Lib and what's it used for?

I searched within the application binary to see if there were more references to this library and indeed, there were a lot of methods:

And finally I found where was the root of the requests made by this library:

int sub_1001428f0(int arg0) {
    :
    :
    r0 = operator new();
    *(arg0 + 0x10) = r0;
    *(int128_t *)(arg0 + 0x18) = 0x2d;
    *(int128_t *)(arg0 + 0x20) = 0x8000000000000030;
    *(int128_t *)(r0 + 0x1d) = *(int128_t *)("https://api.factual.com/engine/configuration/" + 0x1d);
    q0 = *(int128_t *)"https://api.factual.com/engine/configuration/";
    q1 = *(int128_t *)("https://api.factual.com/engine/configuration/" + 0x10);
    *(int128_t *)r0 = q0;
    *(int128_t *)(r0 + 0x10) = q1;
    :
    :
}

Then after a quick search for Factual iOS API I found their iOS API documentation. As part of the setup process Factual requires the developers to add the Location Strings (the ones I showed before):

Factual iOS SDK Setup

The setup instructions and the "Place", "Visit", "Ingress" and "Egress" keywords on the methods let me to believe this library was handling location data. Time to find out what this company does by visiting Factual's main website: factual.com.

It's very, very clear what their business is. Taken from their website:
"Empowering the world’s leading marketers with high quality location data and actionable insights to better understand, reach and engage consumers".

After searching them online, I found a public AWS S3 bucket with a bunch of PDFs containing their marketing material, which they probably use to show their services to potential customers. (There was nothing sensitive in that S3 bucket). Having read all the marketing information I could find about Factual it became very clear that this is the key player within the "Alert {Country}" applications.

One of the PDFs is named "Factual Consumers Data Privacy Perceptions Report". It compares generically who's concerned about their privacy and how different generations think about their online privacy and what generation is more likely to share their data (specifically their location data) if they'd see a benefit from it, like personalized experiences. For example I found this direct quote "While the majority of consumers surveyed stated they have at least some concerns around data privacy, 20% aren’t worried, 6% aren’t concerned at all, and 14% are neutral on the issue.".

Another PDF named "2019 Q3 Location Strategy Guide" shows Factual has data about "Where do the biggest [NFL] fans live?" and they show a heatmap on a US map divided by states of where the fans live. In this same PDF they have this "valuable" tip: "Tip: Target Shoppers Who Live Or Work Near Your Stores".

Note: I purposely avoided adding any screenshots from those PDFs.

To wrap things up, Factual is gathering the location data of who-knows-how-many users and they offer it to big companies for targeted advertisements. This makes an application like 'Alerta Guate' a perfect match for their goals. 'Alerta Guate' requests the location of its users and sends them periodically to their servers.

My final question is, why is a library of a company that collects user location for ads embedded in a mobile application backed by the government of Guatemala?

Conclusions

  • The application still delivers its main features even if the user doesn't enable location services.
  • The application 'Alerta Guate' (and the other white-label'd ones) need some upgrades when it comes to security patterns.
  • I understand the argument for querying the user's location periodically but I'd encourage the users to think if it's worth sharing your location all the time in order to get geo-localized notifications.
  • Finally, based on the information published by the Guatemalan government, it's not really clear what the involvement of Factual is and why is their library embedded within the 'Alerta Guate' application.