CVE-2017-6903: Insufficient Information (NVD-CWE-noinfo)
value: In ioquake3 before 2017-03-14, the auto-downloading feature has insufficient content restrictions. This also affects Quake III Arena, OpenArena, OpenJK, iortcw, and other id Tech 3 (aka Quake 3 engine) forks. A malicious auto-downloaded file can trigger loading of crafted auto-downloaded files as native code DLLs. A malicious auto-downloaded file can contain configuration defaults that override the user's. Executable bytecode in a malicious auto-downloaded file can set configuration variables to values that will result in unwanted native code DLLs being loaded, resulting in sandbox escape.
CWE description: There is insufficient information about the issue to classify it; details are unkown or unspecified.
CVSS v3 base score: 7.8
Published: 2017-03-14T22:59Z
Repository: https://github.com/iortcw/iortcw
Language: C
Files changed: MP/code/client/cl_main.c, MP/code/qcommon/files.c, MP/code/sys/sys_main.c, SP/code/client/cl_main.c, SP/code/qcommon/files.c, SP/code/sys/sys_main.c
Commit date: 2017-03-13 19:37:39 -0400
Commit message: All: Don't load .pk3s as .dlls, and don't load user config files from .pk3s

Diff: diff --git a/MP/code/client/cl_main.c b/MP/code/client/cl_main.c
index f23e717..92675c5 100644
--- a/MP/code/client/cl_main.c
+++ b/MP/code/client/cl_main.c
@@ -3672,11 +3672,11 @@ void CL_InitRef( void ) {
 #endif
 
 	Com_Printf( "----- Initializing Renderer ----\n" );
 
 #ifdef USE_RENDERER_DLOPEN
-	cl_renderer = Cvar_Get("cl_renderer", "opengl1", CVAR_ARCHIVE | CVAR_LATCH);
+	cl_renderer = Cvar_Get("cl_renderer", "opengl1", CVAR_ARCHIVE | CVAR_LATCH | CVAR_PROTECTED);
 
 	Com_sprintf(dllName, sizeof(dllName), "renderer_mp_%s_" ARCH_STRING DLL_EXT, cl_renderer->string);
 
 	if(!(rendererLib = Sys_LoadDll(dllName, qfalse)) && strcmp(cl_renderer->string, cl_renderer->resetString))
 	{
@@ -4012,11 +4012,11 @@ void CL_Init( void ) {
 
 	cl_showMouseRate = Cvar_Get( "cl_showmouserate", "0", 0 );
 
 	cl_allowDownload = Cvar_Get( "cl_allowDownload", "1", CVAR_ARCHIVE );
 #ifdef USE_CURL_DLOPEN
-	cl_cURLLib = Cvar_Get("cl_cURLLib", DEFAULT_CURL_LIB, CVAR_ARCHIVE);
+	cl_cURLLib = Cvar_Get("cl_cURLLib", DEFAULT_CURL_LIB, CVAR_ARCHIVE | CVAR_PROTECTED);
 #endif
 
 	// init autoswitch so the ui will have it correctly even
 	// if the cgame hasn't been started
 	// -NERVE - SMF - disabled autoswitch by default
diff --git a/MP/code/qcommon/files.c b/MP/code/qcommon/files.c
index 3980f1c..c262e6b 100644
--- a/MP/code/qcommon/files.c
+++ b/MP/code/qcommon/files.c
@@ -1422,16 +1422,22 @@ separate file or a ZIP file.
 */
 long FS_FOpenFileRead(const char *filename, fileHandle_t *file, qboolean uniqueFILE)
 {
 	searchpath_t *search;
 	long len;
+	qboolean isLocalConfig;
 
 	if(!fs_searchpaths)
 		Com_Error(ERR_FATAL, "Filesystem call made without initialization");
 
+	isLocalConfig = !strcmp(filename, "autoexec.cfg") || !strcmp(filename, Q3CONFIG_CFG);
 	for(search = fs_searchpaths; search; search = search->next)
 	{
+		// autoexec.cfg and wolfconfig_mp.cfg can only be loaded outside of pk3 files.
+		if (isLocalConfig && search->pack)
+			continue;
+
 	        len = FS_FOpenFileReadDir(filename, search, file, uniqueFILE, qfalse);
 	        
 	        if(file == NULL)
 	        {
 	                if(len > 0)
diff --git a/MP/code/sys/sys_main.c b/MP/code/sys/sys_main.c
index b4181da..f3dc2e9 100644
--- a/MP/code/sys/sys_main.c
+++ b/MP/code/sys/sys_main.c
@@ -497,10 +497,17 @@ from executable path, then fs_basepath.
 */
 
 void *Sys_LoadDll(const char *name, qboolean useSystemLib)
 {
 	void *dllhandle;
+
+	// Don't load any DLLs that end with the pk3 extension
+	if (COM_CompareExtension(name, ".pk3"))
+	{
+		Com_Printf("Rejecting DLL named \"%s\"", name);
+		return NULL;
+	}
 	
 	if(useSystemLib)
 		Com_Printf("Trying to load \"%s\"...\n", name);
 	
 	if(!useSystemLib || !(dllhandle = Sys_LoadLibrary(name)))
diff --git a/SP/code/client/cl_main.c b/SP/code/client/cl_main.c
index 6a9a2c4..18c16aa 100644
--- a/SP/code/client/cl_main.c
+++ b/SP/code/client/cl_main.c
@@ -3346,11 +3346,11 @@ void CL_InitRef( void ) {
 #endif
 
 	Com_Printf( "----- Initializing Renderer ----\n" );
 
 #ifdef USE_RENDERER_DLOPEN
-	cl_renderer = Cvar_Get("cl_renderer", "opengl1", CVAR_ARCHIVE | CVAR_LATCH);
+	cl_renderer = Cvar_Get("cl_renderer", "opengl1", CVAR_ARCHIVE | CVAR_LATCH | CVAR_PROTECTED);
 
 	Com_sprintf(dllName, sizeof(dllName), "renderer_sp_%s_" ARCH_STRING DLL_EXT, cl_renderer->string);
 
 	if(!(rendererLib = Sys_LoadDll(dllName, qfalse)) && strcmp(cl_renderer->string, cl_renderer->resetString))
 	{
@@ -3688,11 +3688,11 @@ void CL_Init( void ) {
 
 	cl_showMouseRate = Cvar_Get( "cl_showmouserate", "0", 0 );
 
 	cl_allowDownload = Cvar_Get( "cl_allowDownload", "0", CVAR_ARCHIVE );
 #ifdef USE_CURL_DLOPEN
-	cl_cURLLib = Cvar_Get("cl_cURLLib", DEFAULT_CURL_LIB, CVAR_ARCHIVE);
+	cl_cURLLib = Cvar_Get("cl_cURLLib", DEFAULT_CURL_LIB, CVAR_ARCHIVE | CVAR_PROTECTED);
 #endif
 
 	// init autoswitch so the ui will have it correctly even
 	// if the cgame hasn't been started
 	Cvar_Get( "cg_autoswitch", "2", CVAR_ARCHIVE );
diff --git a/SP/code/qcommon/files.c b/SP/code/qcommon/files.c
index c63ee2e..15910bd 100644
--- a/SP/code/qcommon/files.c
+++ b/SP/code/qcommon/files.c
@@ -1589,16 +1589,22 @@ separate file or a ZIP file.
 */
 long FS_FOpenFileRead(const char *filename, fileHandle_t *file, qboolean uniqueFILE)
 {
 	searchpath_t *search;
 	long len;
+	qboolean isLocalConfig;
 
 	if(!fs_searchpaths)
 		Com_Error(ERR_FATAL, "Filesystem call made without initialization");
 
+	isLocalConfig = !strcmp(filename, "autoexec.cfg") || !strcmp(filename, Q3CONFIG_CFG);
 	for(search = fs_searchpaths; search; search = search->next)
 	{
+		// autoexec.cfg and wolfconfig.cfg can only be loaded outside of pk3 files.
+		if (isLocalConfig && search->pack)
+			continue;
+
 		len = FS_FOpenFileReadDir(filename, search, file, uniqueFILE, qfalse);
 
 		if(file == NULL)
 		{
 			if(len > 0)
diff --git a/SP/code/sys/sys_main.c b/SP/code/sys/sys_main.c
index d24f402..e591d98 100644
--- a/SP/code/sys/sys_main.c
+++ b/SP/code/sys/sys_main.c
@@ -497,10 +497,17 @@ from executable path, then fs_basepath.
 */
 
 void *Sys_LoadDll(const char *name, qboolean useSystemLib)
 {
 	void *dllhandle;
+
+	// Don't load any DLLs that end with the pk3 extension
+	if (COM_CompareExtension(name, ".pk3"))
+	{
+		Com_Printf("Rejecting DLL named \"%s\"", name);
+		return NULL;
+	}
 	
 	if(useSystemLib)
 		Com_Printf("Trying to load \"%s\"...\n", name);
 	
 	if(!useSystemLib || !(dllhandle = Sys_LoadLibrary(name)))

Vulnerable code: 	cl_renderer = Cvar_Get("cl_renderer", "opengl1", CVAR_ARCHIVE | CVAR_LATCH);
	cl_cURLLib = Cvar_Get("cl_cURLLib", DEFAULT_CURL_LIB, CVAR_ARCHIVE);
	cl_renderer = Cvar_Get("cl_renderer", "opengl1", CVAR_ARCHIVE | CVAR_LATCH);
	cl_cURLLib = Cvar_Get("cl_cURLLib", DEFAULT_CURL_LIB, CVAR_ARCHIVE);
Fixed code: 	cl_renderer = Cvar_Get("cl_renderer", "opengl1", CVAR_ARCHIVE | CVAR_LATCH | CVAR_PROTECTED);
	cl_cURLLib = Cvar_Get("cl_cURLLib", DEFAULT_CURL_LIB, CVAR_ARCHIVE | CVAR_PROTECTED);
	qboolean isLocalConfig;
	isLocalConfig = !strcmp(filename, "autoexec.cfg") || !strcmp(filename, Q3CONFIG_CFG);
		// autoexec.cfg and wolfconfig_mp.cfg can only be loaded outside of pk3 files.
		if (isLocalConfig && search->pack)
			continue;


	// Don't load any DLLs that end with the pk3 extension
	if (COM_CompareExtension(name, ".pk3"))
	{
		Com_Printf("Rejecting DLL named \"%s\"", name);
		return NULL;
	}
	cl_renderer = Cvar_Get("cl_renderer", "opengl1", CVAR_ARCHIVE | CVAR_LATCH | CVAR_PROTECTED);
	cl_cURLLib = Cvar_Get("cl_cURLLib", DEFAULT_CURL_LIB, CVAR_ARCHIVE | CVAR_PROTECTED);
	qboolean isLocalConfig;
	isLocalConfig = !strcmp(filename, "autoexec.cfg") || !strcmp(filename, Q3CONFIG_CFG);
		// autoexec.cfg and wolfconfig.cfg can only be loaded outside of pk3 files.
		if (isLocalConfig && search->pack)
			continue;


	// Don't load any DLLs that end with the pk3 extension
	if (COM_CompareExtension(name, ".pk3"))
	{
		Com_Printf("Rejecting DLL named \"%s\"", name);
		return NULL;
	}