Package: release.debian.org Severity: normal Tags: buster User: release.debian....@packages.debian.org Usertags: pu
[ Reason ] <nodsa> security fix for CVE-2021-26929. This is a forward port of Sylvain Beucler's team of the LTS team. [ Impact ] XSS vulnerability in html2text converter of Horde. [ Tests ] Unfortunately, unit tests have been unreliable in Debian buster's version of Horde. I have tested the package as best as possible on a live Horde instance installed via Debian packages (based on Debian buster). [ Risks ] Breakage of Horde websites if they have been set up with Debian packages as provided in Debian buster. [ Checklist ] [x] *all* changes are documented in the d/changelog [x] I reviewed all changes and I approve them [x] attach debdiff against the package in (old)stable [x] the issue is verified as fixed in unstable [ Changes ] + * CVE-2021-26929: An XSS issue was discovered in Horde Groupware Webmail + Edition (where the Horde_Text_Filter library is used). The attacker + can send a plain text e-mail message, with JavaScript encoded as a + link or email that is mishandled by preProcess in Text2html.php, + because bespoke use of \x00\x00\x00 and \x01\x01\x01 interferes with + XSS defenses. (Closes: #982769). Additionally, I have dropped the Debian QA Group from the Uploaders: field and put myself there (as I had taken over Horde maintenance during the Debian 11 cycle. [ Other info ] None.
diff -Nru php-horde-text-filter-2.3.5/debian/changelog php-horde-text-filter-2.3.5/debian/changelog --- php-horde-text-filter-2.3.5/debian/changelog 2020-01-28 10:41:46.000000000 +0100 +++ php-horde-text-filter-2.3.5/debian/changelog 2021-05-24 00:02:12.000000000 +0200 @@ -1,3 +1,19 @@ +php-horde-text-filter (2.3.5-3+deb10u2) buster; urgency=medium + + [ Mike Gabriel ] + * debian/control: + + Drop Debian QA Group from Uploaders: field, add myself instead. + + [ Sylvain Beucler ] + * CVE-2021-26929: An XSS issue was discovered in Horde Groupware Webmail + Edition (where the Horde_Text_Filter library is used). The attacker + can send a plain text e-mail message, with JavaScript encoded as a + link or email that is mishandled by preProcess in Text2html.php, + because bespoke use of \x00\x00\x00 and \x01\x01\x01 interferes with + XSS defenses. (Closes: #982769). + + -- Mike Gabriel <sunwea...@debian.org> Mon, 24 May 2021 00:02:12 +0200 + php-horde-text-filter (2.3.5-3+deb10u1) buster; urgency=medium * QA upload. diff -Nru php-horde-text-filter-2.3.5/debian/control php-horde-text-filter-2.3.5/debian/control --- php-horde-text-filter-2.3.5/debian/control 2020-01-28 10:41:46.000000000 +0100 +++ php-horde-text-filter-2.3.5/debian/control 2021-05-24 00:00:51.000000000 +0200 @@ -2,8 +2,8 @@ Section: php Priority: optional Maintainer: Horde Maintainers <team+debian-horde-t...@tracker.debian.org> -Uploaders: Debian QA Group <packa...@qa.debian.org> -Build-Depends: debhelper (>= 11), pkg-php-tools (>= 1.1), pear-horde-channel +Uploaders: Mike Gabriel <sunwea...@debian.org> +Build-Depends: debhelper (>= 11), pkg-php-tools (>= 1.1), pear-horde-channel, php-horde-secret Standards-Version: 4.1.4 Homepage: http://www.horde.org/ Vcs-Git: https://salsa.debian.org/horde-team/php-horde-text-filter.git diff -Nru php-horde-text-filter-2.3.5/debian/patches/CVE-2021-26929.patch php-horde-text-filter-2.3.5/debian/patches/CVE-2021-26929.patch --- php-horde-text-filter-2.3.5/debian/patches/CVE-2021-26929.patch 1970-01-01 01:00:00.000000000 +0100 +++ php-horde-text-filter-2.3.5/debian/patches/CVE-2021-26929.patch 2021-05-23 23:59:28.000000000 +0200 @@ -0,0 +1,202 @@ +Origin: https://github.com/horde/Text_Filter/commit/a2f67da064d7a91440b7a2448e56a6387ab94c67 +Reviewed-by: Sylvain Beucler <b...@debian.org> +Last-Update: 2021-02-18 + +From a2f67da064d7a91440b7a2448e56a6387ab94c67 Mon Sep 17 00:00:00 2001 +From: Michael J Rubinsky <mrubi...@horde.org> +Date: Sat, 13 Feb 2021 11:44:42 -0500 +Subject: [PATCH] [mjr] SECURITY: Fix XSS via Text2Html filter + +Reported by: Alex Birnberg<birnberga...@gmail.com, CVE-2021-26929 +--- + .horde.yml | 1 + + composer.json | 1 + + lib/Horde/Text/Filter/Emails.php | 23 +++++++++++++++------ + lib/Horde/Text/Filter/Linkurls.php | 26 ++++++++++++++++++++---- + lib/Horde/Text/Filter/Text2html.php | 13 +++++++----- + test/Horde/Text/Filter/Text2htmlTest.php | 6 ++++-- + 6 files changed, 53 insertions(+), 17 deletions(-) + +Index: php-horde-text-filter-2.3.5/Horde_Text_Filter-2.3.5/lib/Horde/Text/Filter/Emails.php +=================================================================== +--- php-horde-text-filter-2.3.5.orig/Horde_Text_Filter-2.3.5/lib/Horde/Text/Filter/Emails.php ++++ php-horde-text-filter-2.3.5/Horde_Text_Filter-2.3.5/lib/Horde/Text/Filter/Emails.php +@@ -34,7 +34,8 @@ class Horde_Text_Filter_Emails extends H + */ + protected $_params = array( + 'class' => '', +- 'encode' => false ++ 'encode' => false, ++ 'secret' => null + ); + + /** +@@ -85,9 +86,12 @@ EOR; + public function regexCallback($matches) + { + $data = $this->_regexCallback($matches); +- ++ $secret = new Horde_Secret(); ++ if (empty($this->_params['secretKey'])) { ++ $this->_params['secretKey'] = $secret->setKey(); ++ } + if ($this->_params['encode']) { +- $data = "\01\01\01" . base64_encode($data) . "\01\01\01"; ++ $data = "\01\01\01" . base64_encode($secret->write($this->_params['secretKey'], $data)) . "\01\01\01"; + } + + return $matches[1] . $matches[2] . (isset($matches[9]) ? $matches[9] : '') . +@@ -119,15 +123,22 @@ EOR; + * "Decodes" the text formerly encoded by using the "encode" parameter. + * + * @param string $text An encoded text. ++ * @param string $key An optional key to use with Horde_Secret encryption. ++ * If omitted a key will be fetched from a Horde_Secret ++ * instance. + * + * @return string The decoded text. + */ +- public static function decode($text) ++ public static function decode($text, $key = null) + { ++ $secret = new Horde_Secret(); ++ if (empty($key)) { ++ $key = $secret->getKey(); ++ } + return preg_replace_callback( + '/\01\01\01([\w=+\/]*)\01\01\01/', +- function($hex) { +- return base64_decode($hex[1]); ++ function($hex) use ($secret, $key) { ++ return $secret->read($key, base64_decode($hex[1])); + }, + $text); + } +Index: php-horde-text-filter-2.3.5/Horde_Text_Filter-2.3.5/lib/Horde/Text/Filter/Linkurls.php +=================================================================== +--- php-horde-text-filter-2.3.5.orig/Horde_Text_Filter-2.3.5/lib/Horde/Text/Filter/Linkurls.php ++++ php-horde-text-filter-2.3.5/Horde_Text_Filter-2.3.5/lib/Horde/Text/Filter/Linkurls.php +@@ -29,6 +29,10 @@ + * DEFAULT: false + * - target: (string) The link target. + * DEFAULT: '_blank' ++ * - secretKey: (string) A key to use for Horde_Secret encryption of encoded ++ * html tags (see the 'encode' paramter). ++ * DEFAULT: A default key will be created by an instance of ++ * Horde_Secret. + * + * Copyright 2003-2016 Horde LLC (http://www.horde.org/) + * +@@ -60,6 +64,7 @@ class Horde_Text_Filter_Linkurls extends + 'encode' => false, + 'nofollow' => false, + 'target' => '_blank', ++ 'secretKey' => null + ); + + /** +@@ -172,8 +177,13 @@ END_OF_REGEX; + '<meta http-equiv="x-dns-prefetch-control" value="on" />'; + } + ++ $secret = new Horde_Secret(); ++ if (empty($this->_params['secretKey'])) { ++ $this->_params['secretKey'] = $secret->setKey(); ++ } ++ + if ($this->_params['encode']) { +- $replacement = chr(0) . chr(0) . chr(0) . base64_encode($replacement) . chr(0) . chr(0) . chr(0); ++ $replacement = chr(0) . chr(0) . chr(0) . base64_encode($secret->write($this->_params['secretKey'], $replacement)) . chr(0) . chr(0) . chr(0); + } + + return $replacement; +@@ -183,15 +193,23 @@ END_OF_REGEX; + * "Decodes" the text formerly encoded by using the "encode" parameter. + * + * @param string $text An encoded text. ++ * @param string $key An optional key to use with Horde_Secret encryption. ++ * If omitted a key will be fetched from a Horde_Secret ++ * instance. + * + * @return string The decoded text. + */ +- public static function decode($text) ++ public static function decode($text, $key = null) + { ++ $secret = new Horde_Secret(); ++ if (empty($key)) { ++ $key = $secret->getKey(); ++ } ++ + return preg_replace_callback( + '/\00\00\00([\w=+\/]*)\00\00\00/', +- function($hex) { +- return base64_decode($hex[1]); ++ function($hex) use ($secret, $key) { ++ return $secret->read($key, base64_decode($hex[1])); + }, + $text); + } +Index: php-horde-text-filter-2.3.5/Horde_Text_Filter-2.3.5/lib/Horde/Text/Filter/Text2html.php +=================================================================== +--- php-horde-text-filter-2.3.5.orig/Horde_Text_Filter-2.3.5/lib/Horde/Text/Filter/Text2html.php ++++ php-horde-text-filter-2.3.5/Horde_Text_Filter-2.3.5/lib/Horde/Text/Filter/Text2html.php +@@ -37,7 +37,8 @@ class Horde_Text_Filter_Text2html extend + 'linkurls' => false, + 'text2html' => false, + 'parselevel' => 0, +- 'space2html' => false ++ 'space2html' => false, ++ 'secretKey' => null + ); + + /** +@@ -144,7 +145,8 @@ class Horde_Text_Filter_Text2html extend + $filters = $this->_params['linkurls']; + } else { + $filters['linkurls'] = array( +- 'encode' => true ++ 'encode' => true, ++ 'secretKey' => $this->_params['secretKey'] + ); + } + +@@ -155,7 +157,8 @@ class Horde_Text_Filter_Text2html extend + $filters += $this->_params['emails']; + } else { + $filters['emails'] = array( +- 'encode' => true ++ 'encode' => true, ++ 'secretKey' => $this->_params['secretKey'] + ); + } + } +@@ -201,9 +204,9 @@ class Horde_Text_Filter_Text2html extend + + /* Do in-lining of http://xxx.xxx to link, x...@xxx.xxx to email. */ + if ($this->_params['parselevel'] < self::NOHTML) { +- $text = Horde_Text_Filter_Linkurls::decode($text); ++ $text = Horde_Text_Filter_Linkurls::decode($text, $this->_params['secretKey']); + if ($this->_params['parselevel'] < self::MICRO_LINKURL) { +- $text = Horde_Text_Filter_Emails::decode($text); ++ $text = Horde_Text_Filter_Emails::decode($text, $this->_params['secretKey']); + } + + if ($this->_params['space2html']) { +Index: php-horde-text-filter-2.3.5/Horde_Text_Filter-2.3.5/test/Horde/Text/Filter/Text2htmlTest.php +=================================================================== +--- php-horde-text-filter-2.3.5.orig/Horde_Text_Filter-2.3.5/test/Horde/Text/Filter/Text2htmlTest.php ++++ php-horde-text-filter-2.3.5/Horde_Text_Filter-2.3.5/test/Horde/Text/Filter/Text2htmlTest.php +@@ -19,8 +19,10 @@ class Horde_Text_Filter_Text2htmlTest ex + $this->assertEquals( + $expected, + Horde_Text_Filter::filter($input, 'text2html', array( +- 'parselevel' => $level +- )) ++ 'parselevel' => $level, ++ 'secretKey' => "mGmEXue4Az0YurdMK6p3alB" ++ ) ++ ) + ); + } + diff -Nru php-horde-text-filter-2.3.5/debian/patches/series php-horde-text-filter-2.3.5/debian/patches/series --- php-horde-text-filter-2.3.5/debian/patches/series 2020-01-28 10:41:46.000000000 +0100 +++ php-horde-text-filter-2.3.5/debian/patches/series 2021-05-24 00:01:05.000000000 +0200 @@ -1 +1,2 @@ 0001_protect_the_-_this_is_not_a_range.patch +CVE-2021-26929.patch