Blog post: Push notifs, security and privacy #22
blog/security-privacy into main @ -0,0 +21,4 @@
## Push notifications
Push notifications are relatively short messages sent by an application's server to the (usually) mobile application that can be disconnected, in order to wake it up to process the information. This method is very useful for obtaining "real-time" events efficiently, particularly used for instant messaging applications.
This sentence is hard to understand I think.
Maybe something like this would work better:
Push notifications are relatively short messages sent by an application's server to the (usually) mobile application that can be disconnected, in order to wake it up to process the information.
Push notifications are relatively short messages sent by an application's server to the (usually) mobile application through a push service. A push service is always reachable and forwards received messages to the mobile application, even if the application is not running.
@ -0,0 +23,4 @@
Push notifications are relatively short messages sent by an application's server to the (usually) mobile application that can be disconnected, in order to wake it up to process the information. This method is very useful for obtaining "real-time" events efficiently, particularly used for instant messaging applications.
Without push notifications, applications would either have less instant notifications, by fetching updates periodically, or would increase their battery consumption by maintaining a constant connection with their servers. The first solution is appropriate when events don't need to be instant - for example, it's acceptable to check for your phone updates every x hours. The second solution is appropriate when battery and data consumption are negligible compared to actual usage: maintaining the connection should be at a minimum efficient, and applications should be used on a daily basis. It's perfectly acceptable for the messaging app you use all day to drain a few percent of your battery a day for that connection, but it's different if you only receive one message a week on that app. What's more, we all have many applications that we rarely use.
it's acceptable to check for your phone updates every x hours
it's acceptable for your phone to check for system updates every x hours.
@ -0,0 +47,4 @@
- send fake push notifications to other applications
- obtain the secrets needed to send push notifications over the Internet to other applications
- unregister other applications
- rate limit other applications, if a rate limit exists, for example to refuse registration of other applications.
rate limit other applications, if a rate limit exists, for example to refuse registration of other applications.
rate limit other applications, if a rate limit exists, for example to refuse registrations of other applications.
@ -0,0 +66,4 @@
- Broadcast intents are used for IPC, and they reach the targeted application only. Other applications aren't able to read the content of IPC calls.
- Requests to the Play Services are sent with a [PendingIntent](https://developer.android.com/reference/android/app/PendingIntent.html). During registrations and unregistrations, the identity of the creator of the PendingIntent is used to get the sender of the request. But as stated per the documentation _the PendingIntent you receive from an application could actually be one it received from another application, meaning the result you get here will identify the original application_. This solution is not ideal, as PendingIntents sent for another reason can be used to unsubscribe their creator from push notifications, or to reach the rate limit.
- Requests to the subscribed applications rely on [permissions](https://developer.android.com/guide/topics/permissions/overview) (`com.google.android.c2dm.permission.SEND`) to be sure the push notifications come from the Play Services. It isn't possible to have 2 applications on the system providing the same permission. This is a good solution for Google notifications because it is designed to be provided by a single implementation of the service.
- The Play Services also relies on intent received from the system when applications are uninstalled, or when their data is wiped. These privileged intent can't be sent from regular applications.
The Play Services also relies on intent received from the system when applications are uninstalled, or when their data is wiped.
The Play Services also relies on intents received from the system when applications are uninstalled, or when their data is wiped.
These privileged intent can't be sent from regular applications.
These privileged intents can't be sent from regular applications.
@ -0,0 +69,4 @@
- The Play Services also relies on intent received from the system when applications are uninstalled, or when their data is wiped. These privileged intent can't be sent from regular applications.
On the (push) server side:
- Push messages to the FCM server usually follow the FCM API, and need to contain a secret token provided by Firebase. It prevent unauthorized actors to send push notifications to applications. It is also possible to send WebPush requests, then the request rely on [VAPID](https://www.rfc-editor.org/rfc/rfc8292), and the application server needs to have a private key. Using WebPush for Google notifications has been detailed in the blog post about [push notifications for decentralized services](../20250131_push_for_decentralized/).
It prevent unauthorized actors to send push notifications to applications
It prevents unauthorized actors to send push notifications to applications
It is also possible to send WebPush requests, then the request rely on
It is also possible to send WebPush requests, then the requests rely on
@ -0,0 +77,4 @@
**UnifiedPush**
UnifiedPush is a push notification protocol that allows users to choose the service they want to use. Therefore, users may install different applications providing push notifications (often called _distributors_). UnifiedPush is actually 2 different protocol, one for Android, another one for Linux.
UnifiedPush is actually 2 different protocol, one for Android, another one for Linux.
Write
UnifiedPush is actually 2 different protocols, one for Android, another one for Linux.
Write
@ -0,0 +81,4 @@
For Android, the IPC calls are protected by different means:
- As of Google notifications, broadcast intents are used for IPC and reach the targeted application only. Other applications aren't able to read the content of other IPC calls.
- For the registration, the application sends the intent with a flag that shares the sender real identity to the push service, if the device is recent enough. For older devices, the server identify the sender of the request using an attached [PendingIntent](https://developer.android.com/reference/android/app/PendingIntent.html). As said earlier, _the PendingIntent you receive from an application could actually be one it received from another application, meaning the result you get here will identify the original application_. PendingIntents could be passed to reach the registration rate limit of a distributor.
if the device is recent enough.
Maybe it's better to just say: Android >= 14 ?
For older devices, the server identify the sender of the
For older devices, the server identifies the sender of the
@ -0,0 +82,4 @@
For Android, the IPC calls are protected by different means:
- As of Google notifications, broadcast intents are used for IPC and reach the targeted application only. Other applications aren't able to read the content of other IPC calls.
- For the registration, the application sends the intent with a flag that shares the sender real identity to the push service, if the device is recent enough. For older devices, the server identify the sender of the request using an attached [PendingIntent](https://developer.android.com/reference/android/app/PendingIntent.html). As said earlier, _the PendingIntent you receive from an application could actually be one it received from another application, meaning the result you get here will identify the original application_. PendingIntents could be passed to reach the registration rate limit of a distributor.
- A secret token is generated and shared during the first registration call. This token is used to check requests' authorization from the push service, and to unsubscribe applications.
This token is used to check requests' authorization from the push service, and to unsubscribe applications.
This token is used to check the requests' authorization from the push service, and to unsubscribe applications.
@ -0,0 +83,4 @@
- As of Google notifications, broadcast intents are used for IPC and reach the targeted application only. Other applications aren't able to read the content of other IPC calls.
- For the registration, the application sends the intent with a flag that shares the sender real identity to the push service, if the device is recent enough. For older devices, the server identify the sender of the request using an attached [PendingIntent](https://developer.android.com/reference/android/app/PendingIntent.html). As said earlier, _the PendingIntent you receive from an application could actually be one it received from another application, meaning the result you get here will identify the original application_. PendingIntents could be passed to reach the registration rate limit of a distributor.
- A secret token is generated and shared during the first registration call. This token is used to check requests' authorization from the push service, and to unsubscribe applications.
- The Push services may also rely on intent received from the system when applications are uninstalled, or when their data is wiped. These privileged intent can't be sent from regular applications.
The Push services may also rely on intent received from the system when applications are uninstalled
The Push services may also rely on intents received from the system when applications are uninstalled
These privileged intent can't be sent from regular applications.
These privileged intents can't be sent from regular applications.
@ -0,0 +88,4 @@
For linux, IPC is based on [D-Bus](https://www.freedesktop.org/wiki/Software/dbus/):
- D-Bus calls reach the targeted application only too, and other applications aren't able to read the content of other calls.
- The push service can use sandbox properties to control the origin of registration requests. For instance it can get the caller PID and control the flatpak info. If this isn't implemented and the distributor implements rate limits for the registrations, another application may be able to reach the limit for another application.
- As of Android, a secret token is generated and shared during the first registration call. This token is used to check requests' authorization from the push service, and to unsubscribe applications.
This token is used to check requests' authorization from the push service
This token is used to check the requests' authorization from the push service
@ -0,0 +91,4 @@
- As of Android, a secret token is generated and shared during the first registration call. This token is used to check requests' authorization from the push service, and to unsubscribe applications.
On the push server side:
- Push endpoints, the URL where applications sends push messages, are [Capability URL](https://www.w3.org/TR/capability-urls/). This kind of URL works as a shared secret between the application and the push system. It usually contain a token and can be re-generated if necessary.
the URL where applications sends push messages
the URL where applications send push messages
It usually contain a token and can be re-generated if necessary.
It usually contains a token and can be re-generated if necessary.
@ -0,0 +92,4 @@
On the push server side:
- Push endpoints, the URL where applications sends push messages, are [Capability URL](https://www.w3.org/TR/capability-urls/). This kind of URL works as a shared secret between the application and the push system. It usually contain a token and can be re-generated if necessary.
- Push servers are supposed to support VAPID. VAPID is a standard ([RFC8292](https://www.rfc-editor.org/rfc/rfc8292)) providing access control based on asymmetric keys. All provider doesn't check VAPID authorizations, but UnifiedPush specifications even allow distributors to _require_ it. The application registers with the push service for a given public key, then the push server will only accept requests with a signature made with this private key, for the given push server. This is an additional protection, if the push endpoint is leaked, it cannot be used.
All provider doesn't check VAPID authorizations
Not all providers check VAPID authorizations
@ -0,0 +102,4 @@
Other aspects can be analyzed, such as the possibility of using push notifications as a DDOS amplification vector or for Server-Side Request Forgery (SSRF, a bug exploited to send requests from the server to resources inaccessible to the attacker, such as resources in the server LAN). For both these reasons, it is recommended that the application server:
- rejects push endpoints pointing to private IPs, with an option to allow some IP/hosts for self-hosters
- doesn't follow redirections for push requests
- sends a single push request with a token to validate a push subscription. Actual push notifications will be send once the subscription is validated. It's like what usually see to valide email addresses.
Actual push notifications will be send once the subscription is validated.
Actual push notifications will be sent once the subscription is validated.
@ -0,0 +103,4 @@
- rejects push endpoints pointing to private IPs, with an option to allow some IP/hosts for self-hosters
- doesn't follow redirections for push requests
- sends a single push request with a token to validate a push subscription. Actual push notifications will be send once the subscription is validated. It's like what usually see to valide email addresses.
- removes push subscriptions that returns a 404 HTTP code
removes push subscriptions that returns a 404 HTTP code
removes push subscriptions that return a 404 HTTP code
Thanks for your review @maximiliangalanis !
Related to an Android component
Something is not working
Contributions are very welcome, get started here
This issue or pull request already exists
New feature
Interested in contributing? Get started here.
Need some help
Something is wrong
Related to a linux component
More information is needed
Related to an upstream repository, already reported there
No due date set.
No dependencies set.
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?