Control: tags -1 moreinfo confirmed
On 2021-05-08 07:29:01 +0200, Bas Couwenberg wrote:
> Package: release.debian.org
> Severity: normal
> User: release.debian.org@packages.debian.org
> Usertags: unblock
>
> Please unblock package mapserver to fix CVE-2021-32062 as reported in #988208.
>
> [ Reason ]
> Fix security issue.
>
> [ Impact ]
> Unfixed security issue.
>
> [ Tests ]
> Upstream CI.
>
> [ Risks ]
> Low, leaf package.
>
> [ 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 testing
>
> [ Other info ]
> 0001-Use-CPLSetConfigOption-CPLGetConfigOption-for-some-C.patch is required as a dependency of 0001-Address-flaw-in-CGI-mapfile-loading-that-makes-it-po.patch.
>
> unblock mapserver/7.6.2-2
> diff -Nru mapserver-7.6.2/debian/changelog mapserver-7.6.2/debian/changelog
> --- mapserver-7.6.2/debian/changelog 2020-12-09 06:01:02.000000000 +0100
> +++ mapserver-7.6.2/debian/changelog 2021-05-08 07:12:18.000000000 +0200
> @@ -1,3 +1,12 @@
> +mapserver (7.6.2-2) unstable; urgency=high
> +
> + * Drop unused lintian overrides.
> + * Add upstream patches to fix CVE-2021-32062.
> + (closes: #988208)
> + * Update symbols file.
> +
> + -- Bas Couwenberg <sebastic@debian.org> Sat, 08 May 2021 07:12:18 +0200
> +
> mapserver (7.6.2-1) unstable; urgency=medium
>
> * Update symbols for other architectures.
> diff -Nru mapserver-7.6.2/debian/libmapserver2.lintian-overrides mapserver-7.6.2/debian/libmapserver2.lintian-overrides
> --- mapserver-7.6.2/debian/libmapserver2.lintian-overrides 2020-08-06 05:34:57.000000000 +0200
> +++ mapserver-7.6.2/debian/libmapserver2.lintian-overrides 1970-01-01 01:00:00.000000000 +0100
> @@ -1,3 +0,0 @@
> -# Cannot easily be fixed
> -file-references-package-build-path *
> -
> diff -Nru mapserver-7.6.2/debian/libmapserver2.symbols mapserver-7.6.2/debian/libmapserver2.symbols
> --- mapserver-7.6.2/debian/libmapserver2.symbols 2020-12-09 06:00:39.000000000 +0100
> +++ mapserver-7.6.2/debian/libmapserver2.symbols 2021-05-08 07:11:08.000000000 +0200
> @@ -945,6 +945,7 @@
> msCSVJoinPrepare@Base 6.2.1
> msCairoCleanup@Base 6.2.1
> msCalculateScale@Base 6.2.1
> + msCaseEvalRegex@Base 7.6.2
> msCaseReplaceSubstring@Base 6.2.1
> msCheckLabelMinDistance@Base 7.0.0
> msCheckParentPointer@Base 6.2.1
> @@ -1418,6 +1419,7 @@
> msIsGlyphASpace@Base 7.2.0
> msIsLayerQueryable@Base 6.2.1
> msIsOuterRing@Base 6.2.1
> + msIsValidRegex@Base 7.6.2
This version is not high enough. The symbols need to be marked as
requiring 7.6.2-2~
Please remove the moreinfo tag once that fixed version is available in
unstable.
Cheers
> msIsXMLTagValid@Base 6.2.1
> msItemInGroups@Base 6.2.1
> msJoinClose@Base 6.2.1
> diff -Nru mapserver-7.6.2/debian/mapserver-bin.lintian-overrides mapserver-7.6.2/debian/mapserver-bin.lintian-overrides
> --- mapserver-7.6.2/debian/mapserver-bin.lintian-overrides 2020-08-06 05:34:57.000000000 +0200
> +++ mapserver-7.6.2/debian/mapserver-bin.lintian-overrides 1970-01-01 01:00:00.000000000 +0100
> @@ -1,3 +0,0 @@
> -# Cannot easily be fixed
> -file-references-package-build-path *
> -
> diff -Nru mapserver-7.6.2/debian/patches/0001-Address-flaw-in-CGI-mapfile-loading-that-makes-it-po.patch mapserver-7.6.2/debian/patches/0001-Address-flaw-in-CGI-mapfile-loading-that-makes-it-po.patch
> --- mapserver-7.6.2/debian/patches/0001-Address-flaw-in-CGI-mapfile-loading-that-makes-it-po.patch 1970-01-01 01:00:00.000000000 +0100
> +++ mapserver-7.6.2/debian/patches/0001-Address-flaw-in-CGI-mapfile-loading-that-makes-it-po.patch 2021-05-08 07:10:49.000000000 +0200
> @@ -0,0 +1,161 @@
> +Description: Address flaw in CGI mapfile loading that makes it possible to bypass security controls.
> +Author: Even Rouault <even.rouault@spatialys.com>
> +Origin: https://github.com/MapServer/MapServer/commit/927ac97cb9ece305306b5ab2b5600d3afe8c1732
> +Bug: https://github.com/MapServer/MapServer/issues/6313
> +Bug-Debian: https://bugs.debian.org/988208
> +
> +--- a/mapfile.c
> ++++ b/mapfile.c
> +@@ -97,6 +97,16 @@ int msValidateParameter(const char *valu
> + return(MS_FAILURE);
> + }
> +
> ++int msIsValidRegex(const char* e) {
> ++ ms_regex_t re;
> ++ if(ms_regcomp(&re, e, MS_REG_EXTENDED|MS_REG_NOSUB) != 0) {
> ++ msSetError(MS_REGEXERR, "Failed to compile expression (%s).", "msEvalRegex()", e);
> ++ return(MS_FALSE);
> ++ }
> ++ ms_regfree(&re);
> ++ return MS_TRUE;
> ++}
> ++
> + int msEvalRegex(const char *e, const char *s)
> + {
> + ms_regex_t re;
> +@@ -107,6 +117,26 @@ int msEvalRegex(const char *e, const cha
> + msSetError(MS_REGEXERR, "Failed to compile expression (%s).", "msEvalRegex()", e);
> + return(MS_FALSE);
> + }
> ++
> ++ if(ms_regexec(&re, s, 0, NULL, 0) != 0) { /* no match */
> ++ ms_regfree(&re);
> ++ return(MS_FALSE);
> ++ }
> ++ ms_regfree(&re);
> ++
> ++ return(MS_TRUE);
> ++}
> ++
> ++int msCaseEvalRegex(const char *e, const char *s)
> ++{
> ++ ms_regex_t re;
> ++
> ++ if(!e || !s) return(MS_FALSE);
> ++
> ++ if(ms_regcomp(&re, e, MS_REG_EXTENDED|MS_REG_ICASE|MS_REG_NOSUB) != 0) {
> ++ msSetError(MS_REGEXERR, "Failed to compile expression (%s).", "msEvalRegex()", e);
> ++ return(MS_FALSE);
> ++ }
> +
> + if(ms_regexec(&re, s, 0, NULL, 0) != 0) { /* no match */
> + ms_regfree(&re);
> +--- a/mapserv.c
> ++++ b/mapserv.c
> +@@ -166,7 +166,8 @@ int main(int argc, char *argv[])
> +
> + /* push high-value ENV vars into the CPL global config - primarily for IIS/FastCGI */
> + const char* const apszEnvVars[] = {
> +- "CURL_CA_BUNDLE", "MS_MAPFILE", "MS_MAP_NO_PATH", "MS_MAP_PATTERN",
> ++ "CURL_CA_BUNDLE", "MS_MAPFILE", "MS_MAP_NO_PATH", "MS_MAP_PATTERN", "MS_MAP_ENV_PATTERN",
> ++ "MS_MAP_BAD_PATTERN", "MS_MAP_ENV_BAD_PATTERN",
> + NULL /* guard */ };
> + for( int i = 0; apszEnvVars[i] != NULL; ++i ) {
> + const char* value = getenv(apszEnvVars[i]);
> +--- a/mapserver.h
> ++++ b/mapserver.h
> +@@ -2159,7 +2159,9 @@ void msPopulateTextSymbolForLabelAndStri
> + MS_DLL_EXPORT char *msWriteReferenceMapToString(referenceMapObj *ref);
> + MS_DLL_EXPORT char *msWriteLegendToString(legendObj *legend);
> + MS_DLL_EXPORT char *msWriteClusterToString(clusterObj *cluster);
> ++ MS_DLL_EXPORT int msIsValidRegex(const char* e);
> + MS_DLL_EXPORT int msEvalRegex(const char *e, const char *s);
> ++ MS_DLL_EXPORT int msCaseEvalRegex(const char *e, const char *s);
> + #ifdef USE_MSFREE
> + MS_DLL_EXPORT void msFree(void *p);
> + #else
> +--- a/mapservutil.c
> ++++ b/mapservutil.c
> +@@ -199,41 +199,67 @@ mapObj *msCGILoadMap(mapservObj *mapserv
> + int i, j;
> + mapObj *map = NULL;
> +
> ++ const char *ms_map_bad_pattern_default = "[/\\]{2}|[/\\]?\\.+[/\\]|,";
> ++ const char *ms_map_env_bad_pattern_default = "^(AUTH_.*|CERT_.*|CONTENT_(LENGTH|TYPE)|DOCUMENT_(ROOT|URI)|GATEWAY_INTERFACE|HTTP.*|QUERY_STRING|PATH_(INFO|TRANSLATED)|REMOTE_.*|REQUEST_(METHOD|URI)|SCRIPT_(FILENAME|NAME)|SERVER_.*)";
> ++
> ++ int ms_mapfile_tainted = MS_TRUE;
> + const char *ms_mapfile = CPLGetConfigOption("MS_MAPFILE", NULL);
> ++
> + const char *ms_map_no_path = CPLGetConfigOption("MS_MAP_NO_PATH", NULL);
> + const char *ms_map_pattern = CPLGetConfigOption("MS_MAP_PATTERN", NULL);
> ++ const char *ms_map_env_pattern = CPLGetConfigOption("MS_MAP_ENV_PATTERN", NULL);
> ++
> ++ const char *ms_map_bad_pattern = CPLGetConfigOption("MS_MAP_BAD_PATTERN", NULL);
> ++ if(ms_map_bad_pattern == NULL) ms_map_bad_pattern = ms_map_bad_pattern_default;
> ++
> ++ const char *ms_map_env_bad_pattern = CPLGetConfigOption("MS_MAP_ENV_BAD_PATTERN", NULL);
> ++ if(ms_map_env_bad_pattern == NULL) ms_map_env_bad_pattern = ms_map_env_bad_pattern_default;
> +
> + for(i=0; i<mapserv->request->NumParams; i++) /* find the mapfile parameter first */
> + if(strcasecmp(mapserv->request->ParamNames[i], "map") == 0) break;
> +
> + if(i == mapserv->request->NumParams) {
> +- if(ms_mapfile != NULL) {
> +- map = msLoadMap(ms_mapfile,NULL);
> +- } else {
> ++ if(ms_mapfile == NULL) {
> + msSetError(MS_WEBERR, "CGI variable \"map\" is not set.", "msCGILoadMap()"); /* no default, outta here */
> + return NULL;
> + }
> ++ ms_mapfile_tainted = MS_FALSE;
> + } else {
> +- if(getenv(mapserv->request->ParamValues[i])) /* an environment variable references the actual file to use */
> +- map = msLoadMap(getenv(mapserv->request->ParamValues[i]), NULL);
> +- else {
> +- /* by here we know the request isn't for something in an environment variable */
> +- if(ms_map_no_path != NULL) {
> +- msSetError(MS_WEBERR, "Mapfile not found in environment variables and this server is not configured for full paths.", "msCGILoadMap()");
> ++ if(getenv(mapserv->request->ParamValues[i])) { /* an environment variable references the actual file to use */
> ++ /* validate env variable name */
> ++ if(msIsValidRegex(ms_map_env_bad_pattern) == MS_FALSE || msCaseEvalRegex(ms_map_env_bad_pattern, mapserv->request->ParamValues[i]) == MS_TRUE) {
> ++ msSetError(MS_WEBERR, "CGI variable \"map\" fails to validate.", "msCGILoadMap()");
> + return NULL;
> + }
> +-
> +- if(ms_map_pattern != NULL && msEvalRegex(ms_map_pattern, mapserv->request->ParamValues[i]) != MS_TRUE) {
> +- msSetError(MS_WEBERR, "Parameter 'map' value fails to validate.", "msCGILoadMap()");
> ++ if(ms_map_env_pattern != NULL && msEvalRegex(ms_map_env_pattern, mapserv->request->ParamValues[i]) != MS_TRUE) {
> ++ msSetError(MS_WEBERR, "CGI variable \"map\" fails to validate.", "msCGILoadMap()");
> ++ return NULL;
> ++ }
> ++ ms_mapfile = getenv(mapserv->request->ParamValues[i]);
> ++ } else {
> ++ /* by now we know the request isn't for something in an environment variable */
> ++ if(ms_map_no_path != NULL) {
> ++ msSetError(MS_WEBERR, "CGI variable \"map\" not found in environment and this server is not configured for full paths.", "msCGILoadMap()");
> + return NULL;
> + }
> ++ ms_mapfile = mapserv->request->ParamValues[i];
> ++ }
> ++ }
> +
> +- /* ok to try to load now */
> +- map = msLoadMap(mapserv->request->ParamValues[i], NULL);
> ++ /* validate ms_mapfile if tainted */
> ++ if(ms_mapfile_tainted == MS_TRUE) {
> ++ if(msIsValidRegex(ms_map_bad_pattern) == MS_FALSE || msEvalRegex(ms_map_bad_pattern, ms_mapfile) == MS_TRUE) {
> ++ msSetError(MS_WEBERR, "CGI variable \"map\" fails to validate.", "msCGILoadMap()");
> ++ return NULL;
> ++ }
> ++ if(ms_map_pattern != NULL && msEvalRegex(ms_map_pattern, ms_mapfile) != MS_TRUE) {
> ++ msSetError(MS_WEBERR, "CGI variable \"map\" fails to validate.", "msCGILoadMap()");
> ++ return NULL;
> + }
> + }
> +-
> +
> ++ /* ok to try to load now */
> ++ map = msLoadMap(ms_mapfile, NULL);
> + if(!map) return NULL;
> +
> + if(!msLookupHashTable(&(map->web.validation), "immutable")) {
> diff -Nru mapserver-7.6.2/debian/patches/0001-Use-CPLSetConfigOption-CPLGetConfigOption-for-some-C.patch mapserver-7.6.2/debian/patches/0001-Use-CPLSetConfigOption-CPLGetConfigOption-for-some-C.patch
> --- mapserver-7.6.2/debian/patches/0001-Use-CPLSetConfigOption-CPLGetConfigOption-for-some-C.patch 1970-01-01 01:00:00.000000000 +0100
> +++ mapserver-7.6.2/debian/patches/0001-Use-CPLSetConfigOption-CPLGetConfigOption-for-some-C.patch 2021-05-08 07:10:49.000000000 +0200
> @@ -0,0 +1,107 @@
> +Description: Use CPLSetConfigOption/CPLGetConfigOption for some CGI/FastCGI-related env vars.
> + Push a few high-value env vars into CPL config and then reference that instead of the env (mostly for IIS/FastCGI).
> +Author: Steve Lime <steve.lime@state.mn.us>
> +Origin: https://github.com/MapServer/MapServer/commit/b128dace3ec3e61bf063f7285d1279e9f9fd9e28
> +Bug: https://github.com/MapServer/MapServer/pull/6304
> +
> +--- a/maphttp.c
> ++++ b/maphttp.c
> +@@ -39,7 +39,7 @@
> + #include "mapthread.h"
> + #include "mapows.h"
> +
> +-
> ++#include "cpl_conv.h"
> +
> + #include <time.h>
> + #ifndef _WIN32
> +@@ -471,7 +471,7 @@ int msHTTPExecuteRequests(httpRequestObj
> + * If set then the value is the full path to the ca-bundle.crt file
> + * e.g. CURL_CA_BUNDLE=/usr/local/share/curl/curl-ca-bundle.crt
> + */
> +- pszCurlCABundle = getenv("CURL_CA_BUNDLE");
> ++ pszCurlCABundle = CPLGetConfigOption("CURL_CA_BUNDLE", NULL);
> +
> + if (debug) {
> + msDebug("HTTP: Starting to prepare HTTP requests.\n");
> +--- a/mapserv.c
> ++++ b/mapserv.c
> +@@ -43,6 +43,8 @@
> + #include "mapio.h"
> + #include "maptime.h"
> +
> ++#include "cpl_conv.h"
> ++
> + #ifndef WIN32
> + #include <signal.h>
> + #endif
> +@@ -162,6 +164,15 @@ int main(int argc, char *argv[])
> + if(msGetGlobalDebugLevel() >= MS_DEBUGLEVEL_TUNING)
> + msGettimeofday(&execstarttime, NULL);
> +
> ++ /* push high-value ENV vars into the CPL global config - primarily for IIS/FastCGI */
> ++ const char* const apszEnvVars[] = {
> ++ "CURL_CA_BUNDLE", "MS_MAPFILE", "MS_MAP_NO_PATH", "MS_MAP_PATTERN",
> ++ NULL /* guard */ };
> ++ for( int i = 0; apszEnvVars[i] != NULL; ++i ) {
> ++ const char* value = getenv(apszEnvVars[i]);
> ++ if(value) CPLSetConfigOption(apszEnvVars[i], value);
> ++ }
> ++
> + /* -------------------------------------------------------------------- */
> + /* Process arguments. In normal use as a cgi-bin there are no */
> + /* commandline switches, but we provide a few for test/debug */
> +--- a/mapserv.h
> ++++ b/mapserv.h
> +@@ -41,6 +41,7 @@
> + #include "maptile.h"
> +
> + #include "cgiutil.h"
> ++
> + /*
> + ** Defines
> + */
> +--- a/mapservutil.c
> ++++ b/mapservutil.c
> +@@ -33,6 +33,8 @@
> + #include "maptime.h"
> + #include "mapows.h"
> +
> ++#include "cpl_conv.h"
> ++
> + /*
> + ** Enumerated types, keep the query modes in sequence and at the end of the enumeration (mode enumeration is in maptemplate.h).
> + */
> +@@ -197,12 +199,15 @@ mapObj *msCGILoadMap(mapservObj *mapserv
> + int i, j;
> + mapObj *map = NULL;
> +
> ++ const char *ms_mapfile = CPLGetConfigOption("MS_MAPFILE", NULL);
> ++ const char *ms_map_no_path = CPLGetConfigOption("MS_MAP_NO_PATH", NULL);
> ++ const char *ms_map_pattern = CPLGetConfigOption("MS_MAP_PATTERN", NULL);
> ++
> + for(i=0; i<mapserv->request->NumParams; i++) /* find the mapfile parameter first */
> + if(strcasecmp(mapserv->request->ParamNames[i], "map") == 0) break;
> +
> + if(i == mapserv->request->NumParams) {
> +- char *ms_mapfile = getenv("MS_MAPFILE");
> +- if(ms_mapfile) {
> ++ if(ms_mapfile != NULL) {
> + map = msLoadMap(ms_mapfile,NULL);
> + } else {
> + msSetError(MS_WEBERR, "CGI variable \"map\" is not set.", "msCGILoadMap()"); /* no default, outta here */
> +@@ -213,12 +218,12 @@ mapObj *msCGILoadMap(mapservObj *mapserv
> + map = msLoadMap(getenv(mapserv->request->ParamValues[i]), NULL);
> + else {
> + /* by here we know the request isn't for something in an environment variable */
> +- if(getenv("MS_MAP_NO_PATH")) {
> ++ if(ms_map_no_path != NULL) {
> + msSetError(MS_WEBERR, "Mapfile not found in environment variables and this server is not configured for full paths.", "msCGILoadMap()");
> + return NULL;
> + }
> +
> +- if(getenv("MS_MAP_PATTERN") && msEvalRegex(getenv("MS_MAP_PATTERN"), mapserv->request->ParamValues[i]) != MS_TRUE) {
> ++ if(ms_map_pattern != NULL && msEvalRegex(ms_map_pattern, mapserv->request->ParamValues[i]) != MS_TRUE) {
> + msSetError(MS_WEBERR, "Parameter 'map' value fails to validate.", "msCGILoadMap()");
> + return NULL;
> + }
> diff -Nru mapserver-7.6.2/debian/patches/series mapserver-7.6.2/debian/patches/series
> --- mapserver-7.6.2/debian/patches/series 2020-12-08 05:49:56.000000000 +0100
> +++ mapserver-7.6.2/debian/patches/series 2021-05-08 07:10:49.000000000 +0200
> @@ -1,3 +1,5 @@
> perl-mapscript-install.patch
> java-hardening.patch
> interpreter-path.path
> +0001-Use-CPLSetConfigOption-CPLGetConfigOption-for-some-C.patch
> +0001-Address-flaw-in-CGI-mapfile-loading-that-makes-it-po.patch
--
Sebastian Ramacher
Attachment:
signature.asc
Description: PGP signature