Security for FMD Server
This page describes the security considerations that went into FMD Server.
Threat model
-
Malicious backend: We assume that the server is compromised. That is, the adversary can read and write the database, can read and write all incoming and outgoing network requests, and can change the backend code.
-
Network adversary: Since the adversary has access to the server, they also have all properties of a Dolev-Yao adversary. That is, they can read, modify, reorder, replay, and drop messages sent over the network.
-
Secure client: We assume that the adversary cannot compromise the client. That is, the client adheres to the protocol and does not reveal secrets to the adversary.
For the Android app, the "secure client" assumption can be ensured by means of inspecting the open source code and reproducible builds.
For the web client, the "secure client" assumption is a huge, not currently realistic simplification. This is because the web client frontend code is served by the same server that also serves the backend code. And that server we assumed above to be compromised!
Therefore, the "secure client" assumption only holds for the web client if the server is compromised by a passive adversary who cannot change the frontend code. For example, an adversary who obtains a database dump or a VM disk image.
Security goals
- Confidentiality: The adversary does not learn sensitive data (like device locations).
- Command authenticity: The adversary cannot cause the device to execute a command of their choosing.
Cryptographic protections
In order to achieve the security goals under the given threat model, FMD Server roughly works as follows:
- A symmetric key is derived from the user's password using Argon2id.
- FMD Android generates an RSA-3072 keypair.
- The private key is encrypted with AES-GCM under the symmetric key derived above and uploaded together with the public key to FMD Server.
- Whenever FMD Android uploads a location or a picture, this data is encrypted under the private key with RSA-OAEP before upload.
- When the user logs into the web client, the local Javascript retrieves the encrypted private key, and decrypts it using the symmetric key derived from the user's password.
- The web client then uses the private key to decrypt the locations and pictures.
- When the web client sends a command to FMD Android, it signs it using the private key with RSA-PSS.
- FMD Android verifies the signature before executing the command. To prevent replay attacks, the signature contains a timestamp that must be strictly increasing.
In the browser, all cryptographic operations are done using the Web Crypto API. On Android, BouncyCastle is used.
The cryptographic protections hinge on the user's password being secret. You need to choose a strong passphrase!
The FMD Server protocol is historically grown. It is not as "nice" as if a cryptographer would design it from scratch in 2025. For example, asymmetric cryptography is not necessary with the current feature set, and the login authentication could be done using a PAKE. In a future iteration, we would like to design and specify the protocol more formally.
Login
When logging in, the password is NOT sent to the server directly. Instead, a hash is derived using Argon2id (with a different context string, to ensure separation from the symmetric key). This hash is sent to the server.
Brute-force protection
To protect accounts from being brute-forced, FMD Server locks an account after a number of failed attempts (currently 5). Then new logins are denied for 10 minutes and a push notification is sent to FMD Android to inform the user. Existing access tokens remain valid, so FMD Android and any existing web client session will continue to work, even though new logins are locked.
In addition, FMD Server logs the IP address of failed login attempts (requires FMD Server v0.11.0 or later). Server operators can use this to configure fail2ban, to block cross-account brute-force coming from a single IP.