CVE-2024-39698 (published 2024-07-09T18:15Z)

electron-updater allows for automatic updates for Electron apps. The file `packages/electron-updater/src/windowsExecutableCodeSignatureVerifier.ts` implements the signature validation routine for Electron applications on Windows. Because of the surrounding shell, a first pass by `cmd.exe` expands any environment variable found in command-line above. This creates a situation where `verifySignature()` can be tricked into validating the certificate of a different file than the one that was just downloaded. If the step is successful, the malicious update will be executed even if its signature is invalid. This attack assumes a compromised update manifest (server compromise, Man-in-the-Middle attack if fetched over HTTP, Cross-Site Scripting to point the application to a malicious updater server, etc.). The patch is available starting from 6.3.0-alpha.6.

CVSS v3 base score: 7.5, HIGH (CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:H)

Weakness information:
cwe_id: CWE-295
cwe_name: Improper Certificate Validation
description: The product does not validate, or incorrectly validates, a certificate.
extended_description: When a certificate is invalid or malicious, it might allow an attacker to spoof a trusted entity by interfering in the communication path between the host and client. The product might connect to a malicious host while believing it is a trusted host, or the product might be deceived into accepting spoofed data that appears to originate from a trusted host.
         

Fix information:
repo_url: https://github.com/electron-userland/electron-builder
commit_details: repo_url: https://github.com/electron-userland/electron-builder
author: Mike Maietta
author_date: 2024-07-05 09:06:33-07:00
msg: fix: verify LiteralPath of update file during windows signature verification (#8295)
repository: repo_url: https://github.com/electron-userland/electron-builder
repo_name: electron-userland/electron-builder
description: A complete solution to package and build a ready for distribution Electron app with “auto update” support out of the box
repo_language: TypeScript
owner: electron-userland
file_changes: filename: nervous-carrots-begin.md
change_type: ModificationType.ADD
diff: @@ -0,0 +1,5 @@
+---
+"electron-updater": patch
+---
+
+fix: verify LiteralPath of update file during windows signature verification

programming_language: Markdown
filename: windowsExecutableCodeSignatureVerifier.ts
change_type: ModificationType.MODIFY
diff: @@ -2,6 +2,7 @@ import { parseDn } from "builder-util-runtime"
 import { execFile, execFileSync } from "child_process"
 import * as os from "os"
 import { Logger } from "./main"
+import * as path from "path"
 
 // $certificateInfo = (Get-AuthenticodeSignature 'xxx\yyy.exe'
 // | where {$_.Status.Equals([System.Management.Automation.SignatureStatus]::Valid) -and $_.SignerCertificate.Subject.Contains("CN=siemens.com")})
@@ -48,6 +49,18 @@ export function verifySignature(publisherNames: Array<string>, unescapedTempUpda
           }
           const data = parseOut(stdout)
           if (data.Status === 0) {
+            try {
+              const normlaizedUpdateFilePath = path.normalize(data.Path)
+              const normalizedTempUpdateFile = path.normalize(unescapedTempUpdateFile)
+              logger.info(`LiteralPath: ${normlaizedUpdateFilePath}. Update Path: ${normalizedTempUpdateFile}`)
+              if (normlaizedUpdateFilePath !== normalizedTempUpdateFile) {
+                handleError(logger, new Error(`LiteralPath of ${normlaizedUpdateFilePath} is different than ${normalizedTempUpdateFile}`), stderr, reject)
+                resolve(null)
+                return
+              }
+            } catch (error: any) {
+              logger.warn(`Unable to verify LiteralPath of update asset due to missing data.Path. Skipping this step of validation. Message: ${error.message ?? error.stack}`)
+            }
             const subject = parseDn(data.SignerCertificate.Subject)
             let match = false
             for (const name of publisherNames) {
@@ -96,7 +109,6 @@ function parseOut(out: string): any {
     // duplicates data.SignerCertificate (contains RawData)
     delete signerCertificate.SubjectName
   }
-  delete data.Path
   return data
 }
 

programming_language: TypeScript