-
Notifications
You must be signed in to change notification settings - Fork 59
Description
Hello, consider the following questions from a nixpkgs maintainer:
Given the whole thing did not make sense to me I took a look at what they are doing with it. In the 4.0.0 release it seems to have 2 usages:
- to "obfuscate" a device ID which is useless since the value is static (and a HMAC construction would have been a better fit for that)
nordvpn-linux/cmd/daemon/main.go
Line 290 in 919fc28
deviceID := fmt.Sprintf("%x_%d", sha256.Sum256([]byte(machineID.String()+Salt)), machineIdGenerator.GetUsedInformationMask()) - it is involved when dealing with the encryption of configuration files https://github.com/NordSecurity/nordvpn-linux/blob/4.0.0/config/manager.go and https://github.com/NordSecurity/nordvpn-linux/blob/4.0.0/internal/crypto.go
As one would expect with the static salt value, the encryption of configuration files is security theater with broken cryptography usages.
On fresh install to encrypt the configuration they first generate a passphrase, encrypt it using the salt as the key and save it. Once that is done they can encrypt the configuration using the generated passphrase.
When they need to open an existing configuration, they first look for the saved encrypted passphrase, decrypt it with the salt and then use the passphrase to decrypt the configuration.
I'm not sure what's the threat model here seems it seems unlikely that an attacker with the ability to capture the encrypted configuration file could not also capture the encrypted configuration file.
Even without considering the threat model, the way cryptography is being used is not something I would expect to find in any software and even less in one putting "privacy" in the center of the business model and relying extensively on cryptography to do its job. Yes that is not the code used to mount the tunnels but this is the sort of thing that is CVE worthy.
To explain a bit more:
The code generating the passphrase does not rely on CSRNG but it is seeded from the current time. That is a relatively small space to bruteforce especially since it is not unlikely that an attacker would have a rough idea of the creation date and/or modification time of the configuration file.
nordvpn-linux/config/manager.go
Lines 287 to 298 in 919fc28
func generateKey() []byte { min, max := 33, 126 key := make([]byte, 0, 32) source := rand.NewSource(time.Now().UnixNano()) // #nosec G404 -- config encryption will go away after OSS r := rand.New(source) for i := 0; i < 32; i++ { character := r.Intn(max-min) + min key = append(key, byte(character)) } return key }
To encrypt the content they are relying on internal minimal library using AES GCM. However they are using MD5 as a key derivation function which is not meant for this usage (and well in 2025 MD5 as no place to be used in a cryptography-related context).
https://github.com/NordSecurity/nordvpn-linux/blob/4.0.0/internal/crypto.go#L13-L18
I suppose the KDF being used is not really that important since anyway they are using either a publicly known key or key generated with a cryptographically weak number generator.
I would have expected better practices for this kind of software.
Discussion found here. Your clarification would help a bunch! Thanks!