CVE-2020-27519: Improper Privilege Management (CWE-269)
value: Pritunl Client v1.2.2550.20 contains a local privilege escalation vulnerability in the pritunl-service component. The attack vector is: malicious openvpn config. A local attacker could leverage the log and log-append along with log injection to create or append to privileged script files and execute code as root/SYSTEM.
CWE description: The product does not properly assign, modify, track, or check privileges for an actor, creating an unintended sphere of control for that actor.
CVSS v3 base score: 7.8
Published: 2021-04-30T14:15Z
Repository: https://github.com/pritunl/pritunl-client-electron
Language: Go
Files changed: service/profile/profile.go
Commit date: 2020-09-02 18:51:02 -0400
Commit message: Filter openvpn configuration data

Diff: diff --git a/service/profile/profile.go b/service/profile/profile.go
index 67b6d375..2ba9ecb3 100644
--- a/service/profile/profile.go
+++ b/service/profile/profile.go
@@ -212,12 +212,47 @@ func (p *Profile) write() (pth string, err error) {
 		return
 	}
 
 	pth = filepath.Join(rootDir, p.Id)
 
+	data := ""
+	for _, line := range strings.Split(p.Data, "\n") {
+		trimLine := strings.TrimSpace(line)
+		trimLine = strings.Trim(trimLine, "#")
+		trimLine = strings.Trim(trimLine, "-")
+		trimLine = strings.Trim(trimLine, "_")
+		trimLine = strings.Trim(trimLine, ":")
+		trimLine = strings.Trim(trimLine, ";")
+		trimLine = strings.Trim(trimLine, "*")
+		trimLine = strings.Trim(trimLine, "%")
+		trimLine = strings.Trim(trimLine, "$")
+		trimLine = strings.Trim(trimLine, "+")
+		trimLine = strings.Trim(trimLine, "=")
+		trimLine = strings.Trim(trimLine, "~")
+		trimLine = strings.Trim(trimLine, "(")
+		trimLine = strings.Trim(trimLine, ")")
+		trimLine = strings.Trim(trimLine, "[")
+		trimLine = strings.Trim(trimLine, "]")
+		trimLine = strings.Trim(trimLine, "{")
+		trimLine = strings.Trim(trimLine, "}")
+
+		if strings.Contains(trimLine, "script-security") ||
+			strings.HasPrefix(trimLine, "log ") ||
+			strings.HasPrefix(trimLine, "up ") ||
+			strings.HasPrefix(trimLine, "down ") ||
+			strings.HasPrefix(trimLine, "route-pre-down ") ||
+			strings.HasPrefix(trimLine, "tls-verify ") ||
+			strings.HasPrefix(trimLine, "ipchange ") ||
+			strings.HasPrefix(trimLine, "route-up ") {
+
+			continue
+		}
+		data += line + "\n"
+	}
+
 	_ = os.Remove(pth)
-	err = ioutil.WriteFile(pth, []byte(p.Data), os.FileMode(0600))
+	err = ioutil.WriteFile(pth, []byte(data), os.FileMode(0600))
 	if err != nil {
 		err = &WriteError{
 			errors.Wrap(err, "profile: Failed to write profile"),
 		}
 		return

Vulnerable code: 	err = ioutil.WriteFile(pth, []byte(p.Data), os.FileMode(0600))
Fixed code: 	data := ""
	for _, line := range strings.Split(p.Data, "\n") {
		trimLine := strings.TrimSpace(line)
		trimLine = strings.Trim(trimLine, "#")
		trimLine = strings.Trim(trimLine, "-")
		trimLine = strings.Trim(trimLine, "_")
		trimLine = strings.Trim(trimLine, ":")
		trimLine = strings.Trim(trimLine, ";")
		trimLine = strings.Trim(trimLine, "*")
		trimLine = strings.Trim(trimLine, "%")
		trimLine = strings.Trim(trimLine, "$")
		trimLine = strings.Trim(trimLine, "+")
		trimLine = strings.Trim(trimLine, "=")
		trimLine = strings.Trim(trimLine, "~")
		trimLine = strings.Trim(trimLine, "(")
		trimLine = strings.Trim(trimLine, ")")
		trimLine = strings.Trim(trimLine, "[")
		trimLine = strings.Trim(trimLine, "]")
		trimLine = strings.Trim(trimLine, "{")
		trimLine = strings.Trim(trimLine, "}")

		if strings.Contains(trimLine, "script-security") ||
			strings.HasPrefix(trimLine, "log ") ||
			strings.HasPrefix(trimLine, "up ") ||
			strings.HasPrefix(trimLine, "down ") ||
			strings.HasPrefix(trimLine, "route-pre-down ") ||
			strings.HasPrefix(trimLine, "tls-verify ") ||
			strings.HasPrefix(trimLine, "ipchange ") ||
			strings.HasPrefix(trimLine, "route-up ") {

			continue
		}
		data += line + "\n"
	}

	err = ioutil.WriteFile(pth, []byte(data), os.FileMode(0600))