From patchwork Mon Sep 7 14:43:44 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gert Doering X-Patchwork-Id: 5323 Return-Path: Delivered-To: patchwork@openvpn.net Received: by 2002:a05:7000:57cc:b0:899:8fd4:d065 with SMTP id v12csp607472mau; Mon, 7 Sep 2026 07:44:05 -0700 (PDT) X-Forwarded-Encrypted: i=2; AKwUvByhsGO+um5fSvnYhj1FlbVizKzXBvvSPZ5M+od1j9bT7KHspQ0rOGtbBncWSv7I7/6F5VXfPjnqK0Y=@openvpn.net X-Received: by 2002:a05:6870:c231:b0:45e:d660:b87 with SMTP id 586e51a60fabf-47552d7600emr16025696fac.9.1788792245743; Mon, 07 Sep 2026 07:44:05 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1788792245; cv=none; d=google.com; s=arc-20260327; b=TooEiVECmIO/KXX3ddaXqRj2t9zAVKvJQZeuzaQ3ft9//sTGVAOZ8LuO5hCvW4IpGR JoU2eiY/f0deE4n738gWBoyEfmq7f1XnFPy3MFua6mOPiYpPp490OGkqc5nntxh5CWzj ekwoYu2oVSvL+Nk1xMATIzWaHIZVSLxqWbvzki671BHGjI6O8zYrepbX3/IJU2yo/ToP T3sMxPp+Wg1GGw7/BsDxkOnPQHPou4IEVyugrU7PxsB9yc++lUhCqI23CmJeTqWZJ/R4 zsaYhVDYTL+wFD68tMt9cMy61mW6GUnIQY/wGe1yiB8kyN2JJpbzojamOaC5oURuzB83 h24Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20260327; h=errors-to:content-transfer-encoding:list-subscribe:list-help :list-post:list-archive:list-unsubscribe:list-id:precedence:subject :mime-version:references:in-reply-to:message-id:date:to:from :dkim-signature:dkim-signature:dkim-signature; bh=/kr8hZIeh/PY6EVNZKH6TlIJfM7OSgqpYl0ey46sce4=; fh=4NbAC/LsuMLI0S0hprUlLSLCiHwg6SCAifhH718Jh0Q=; b=ju/50zUJfLoDQ9S+iXvIJ2fSg1vfeg3bWLzbRKg+LkDKBupTeyslmhoPD8HYLtpYUv KirS6DsPjqRrEFo+CqHpy/exKWKZo9GwzAVjohmx0zeUtwDtygfYAMa6w6UX+MfnIV88 nL0mVP9nxH/B2afkEw2tqQexEF5T1OqXynCCYI5WUk3fyLZm3HE6br3es+hmvVQrG4tf VU2I1jp+p6JbaqePUooo8G99GSg3Cl1BhFOYCPT6WKPsTRjWYcluKsyaxrc8FsjA0ap5 zGV+q/lGbynDmfJ1vJ8JdanqoTVui/jqvF+hFYb3rMzci/Ua1M6Rjfuy2l7GKu9V9peA HlXw==; dara=google.com ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@lists.sourceforge.net header.s=beta header.b=bx2hA3Hb; dkim=neutral (body hash did not verify) header.i=@sourceforge.net header.s=x header.b=UZe3e9w1; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b=lCXiOcyn; spf=pass (google.com: domain of openvpn-devel-bounces@lists.sourceforge.net designates 216.105.38.7 as permitted sender) smtp.mailfrom=openvpn-devel-bounces@lists.sourceforge.net; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=muc.de Received: from lists.sourceforge.net (lists.sourceforge.net. [216.105.38.7]) by mx.google.com with ESMTPS id 586e51a60fabf-475560b5262si14262027fac.294.2026.09.07.07.44.05 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Mon, 07 Sep 2026 07:44:05 -0700 (PDT) Received-SPF: pass (google.com: domain of openvpn-devel-bounces@lists.sourceforge.net designates 216.105.38.7 as permitted sender) client-ip=216.105.38.7; Authentication-Results: mx.google.com; dkim=pass header.i=@lists.sourceforge.net header.s=beta header.b=bx2hA3Hb; dkim=neutral (body hash did not verify) header.i=@sourceforge.net header.s=x header.b=UZe3e9w1; dkim=neutral (body hash did not verify) header.i=@sf.net header.s=x header.b=lCXiOcyn; spf=pass (google.com: domain of openvpn-devel-bounces@lists.sourceforge.net designates 216.105.38.7 as permitted sender) smtp.mailfrom=openvpn-devel-bounces@lists.sourceforge.net; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=muc.de DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.sourceforge.net; s=beta; h=Content-Transfer-Encoding:Content-Type: List-Subscribe:List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id: Subject:MIME-Version:References:In-Reply-To:Message-ID:Date:To:From:Sender: Reply-To:Cc:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=/kr8hZIeh/PY6EVNZKH6TlIJfM7OSgqpYl0ey46sce4=; b=bx2hA3HbkgYkc1EWLKss/nrE8E p3f3ig3YAajigVafwiRUDIzYMw2ULOLfRpHhZERgWSMh4GxMkVGlZtfZQR1s7aQkGVdTNFhdBz0oI 7fspTh4TJ1h0N1+YtHRWmks1aVI92asFt0AO/yzZMgAE2enBmIzEmCgBFQltF1sD74CI=; Received: from [127.0.0.1] (helo=sfs-ml-4.v29.lw.sourceforge.com) by sfs-ml-4.v29.lw.sourceforge.com with esmtp (Exim 4.95) (envelope-from ) id 1x3aZm-0006FO-Al; Mon, 07 Sep 2026 14:44:02 +0000 Received: from [172.30.29.66] (helo=mx.sourceforge.net) by sfs-ml-4.v29.lw.sourceforge.com with esmtps (TLS1.2) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.95) (envelope-from ) id 1x3aZk-0006F7-Lu for openvpn-devel@lists.sourceforge.net; Mon, 07 Sep 2026 14:44:00 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sourceforge.net; s=x; h=Content-Transfer-Encoding:MIME-Version:References: In-Reply-To:Message-ID:Date:Subject:To:From:Sender:Reply-To:Cc:Content-Type: Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender: Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=FAe6DmkKbMr2Rhxefd5A4SDnpcibH/WwM5w1XtHLDVk=; b=UZe3e9w1NQh0wmujV8KB7IoQuT tULCth4TTbXievvCJBUwEk5NFGh0ertrttTXUstfPC5KiM4U1jRKJuUznbf/HUC255SgVd6nioP8G Risb7otuQ0QhoUdaDVBnokFnZR0BVztaZCuX+Giv4VAPMl57RaHlZoub9+O474Vs4s/c=; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sf.net; s=x ; h=Content-Transfer-Encoding:MIME-Version:References:In-Reply-To:Message-ID: Date:Subject:To:From:Sender:Reply-To:Cc:Content-Type:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=FAe6DmkKbMr2Rhxefd5A4SDnpcibH/WwM5w1XtHLDVk=; b=lCXiOcyn2usSMMdLhxdQRvdfuv 9NPBXoEUo5fL7tM7wfte3BVWsq2lQrV62F64kd/RxllNekGn3qoaUuG3qMnJBkJBXm1T3yCtVJ78X eHQY92EN/TvLyf3RmJwSCGZ7SXw/Z4jupGILDRyvhO6YL+yyuh36xFno+gbAYo7SA1zQ=; Received: from [193.149.48.129] (helo=blue.greenie.muc.de) by sfi-mx-1.v28.lw.sourceforge.com with esmtps (TLS1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.95) id 1x3aZi-0007jV-Gs for openvpn-devel@lists.sourceforge.net; Mon, 07 Sep 2026 14:44:00 +0000 Received: from blue.greenie.muc.de (localhost [127.0.0.1]) by blue.greenie.muc.de (8.18.1/8.18.1) with ESMTP id 687Ehp5g022100 for ; Mon, 7 Sep 2026 16:43:51 +0200 Received: (from gert@localhost) by blue.greenie.muc.de (8.18.2/8.18.1/Submit) id 687EhpvZ022099 for openvpn-devel@lists.sourceforge.net; Mon, 7 Sep 2026 16:43:51 +0200 From: Gert Doering To: openvpn-devel@lists.sourceforge.net Date: Mon, 7 Sep 2026 16:43:44 +0200 Message-ID: <20260907144351.22085-1-gert@greenie.muc.de> X-Mailer: git-send-email 2.53.0 In-Reply-To: References: MIME-Version: 1.0 X-Spam-Score: 1.3 (+) X-Spam-Report: Spam detection software, running on the system "sfi-spamd-2.hosts.colo.sdot.me", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: From: Lev Stipakov Commit cf08504 quotes arguments that contain cmd.exe metacharacters, so a certificate subject passed to --tls-verify cannot start a second command when CreateProcess() runs a .bat or .cmd hook. Content analysis details: (1.3 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- 1.3 RDNS_NONE Delivered to internal network by a host with no rDNS X-Headers-End: 1x3aZi-0007jV-Gs Subject: [Openvpn-devel] [PATCH v1] win32: stop cmd.exe from expanding variables in quoted arguments X-BeenThere: openvpn-devel@lists.sourceforge.net X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: openvpn-devel-bounces@lists.sourceforge.net X-getmail-retrieved-from-mailbox: Inbox X-GMAIL-THRID: 1875684617589279214 X-GMAIL-MSGID: 1875684617589279214 From: Lev Stipakov Commit cf08504 quotes arguments that contain cmd.exe metacharacters, so a certificate subject passed to --tls-verify cannot start a second command when CreateProcess() runs a .bat or .cmd hook. Quoting is not enough for %VAR% and !VAR!: cmd.exe expands those even inside double quotes, and OpenVPN exports peer-controlled certificate fields into the child environment. A subject that puts a quote and an operator in one field (O=BREAK"&whoami&") and references it from another (CN=%X509_0_O%) expands back into a quote and command operator after wide_cmd_line() has already replaced the direct quotes, running a command before the hook can reject the peer. Replace % and ! in wide_cmd_line() along with the double quotes and CRLF, so no argument can expand. This reuses two character classes that had no users, CC_AT and CC_EQUAL, renamed to CC_PERCENT and CC_EXCLAMATION. Add regression tests for a bare percent or bang, a closed expansion token, and the reported subject. This completes the CVE-2026-84256 fix for Windows batch hooks. GitHub: OpenVPN/openvpn-private-issues#176 Reported-By: Darren Carreras CVE: 2026-84256 Change-Id: I70dfdc70778458b78f80b8d0b0b786f18fe4fc76 Signed-off-by: Lev Stipakov Acked-by: Razvan Cojocaru Gerrit URL: https://gerrit.openvpn.net/c/openvpn/+/1895 --- This change was reviewed on Gerrit and approved by at least one developer. I request to merge it to master. Gerrit URL: https://gerrit.openvpn.net/c/openvpn/+/1895 This mail reflects revision 1 of this Change. Acked-by according to Gerrit (reflected above): Razvan Cojocaru diff --git a/src/openvpn/buffer.c b/src/openvpn/buffer.c index 5ce2e39..5d00415 100644 --- a/src/openvpn/buffer.c +++ b/src/openvpn/buffer.c @@ -943,11 +943,11 @@ { return true; } - if ((flags & CC_AT) && c == '@') + if ((flags & CC_PERCENT) && c == '%') { return true; } - if ((flags & CC_EQUAL) && c == '=') + if ((flags & CC_EXCLAMATION) && c == '!') { return true; } diff --git a/src/openvpn/buffer.h b/src/openvpn/buffer.h index 4471697..0a02e94 100644 --- a/src/openvpn/buffer.h +++ b/src/openvpn/buffer.h @@ -1660,8 +1660,8 @@ #define CC_SINGLE_QUOTE (1 << 21) /**< single quote */ #define CC_DOUBLE_QUOTE (1 << 22) /**< double quote */ #define CC_REVERSE_QUOTE (1 << 23) /**< reverse quote */ -#define CC_AT (1 << 24) /**< at sign */ -#define CC_EQUAL (1 << 25) /**< equal sign */ +#define CC_PERCENT (1 << 24) /**< percent sign */ +#define CC_EXCLAMATION (1 << 25) /**< exclamation mark */ #define CC_LESS_THAN (1 << 26) /**< less than sign */ #define CC_GREATER_THAN (1 << 27) /**< greater than sign */ #define CC_PIPE (1 << 28) /**< pipe */ diff --git a/src/openvpn/win32-util.c b/src/openvpn/win32-util.c index 4e3819c..e2c8810 100644 --- a/src/openvpn/win32-util.c +++ b/src/openvpn/win32-util.c @@ -94,7 +94,10 @@ { const char *arg = a->argv[i]; strcpy(work, arg); - string_mod(work, CC_PRINT, CC_DOUBLE_QUOTE | CC_CRLF, '_'); + /* cmd.exe expands %VAR% and !VAR! even inside quotes, so a value like + * %X509_0_O% could turn back into a quote and start a new command. + * Replace those along with the double quotes and CRLF. */ + string_mod(work, CC_PRINT, CC_DOUBLE_QUOTE | CC_CRLF | CC_PERCENT | CC_EXCLAMATION, '_'); if (i) { buf_printf(&buf, " "); diff --git a/tests/unit_tests/openvpn/test_argv.c b/tests/unit_tests/openvpn/test_argv.c index 5b6e26e..1fc73d8 100644 --- a/tests/unit_tests/openvpn/test_argv.c +++ b/tests/unit_tests/openvpn/test_argv.c @@ -271,15 +271,13 @@ { "CN=a,b;c=d", L"script.bat 0 CN=a,b;c=d" }, /* a space has always forced quoting */ { "O=Ctrl, CN=y", L"script.bat 0 \"O=Ctrl, CN=y\"" }, - /* cmd.exe operators */ + /* cmd.exe operators that quoting neutralizes */ { "CN=x&ver", L"script.bat 0 \"CN=x&ver\"" }, { "CN=x|ver", L"script.bat 0 \"CN=x|ver\"" }, { "CN=x>f", L"script.bat 0 \"CN=x>f\"" }, { "CN=x