php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #66322 COMPersistHelper::SaveToFile can save to wrong location
Submitted: 2013-12-19 07:30 UTC Modified: 2020-02-06 13:51 UTC
From: cyg0x7 at gmail dot com Assigned: cmb (profile)
Status: Closed Package: COM related
PHP Version: 5.4.23 OS: windows
Private report: No CVE-ID: None
 [2013-12-19 07:30 UTC] cyg0x7 at gmail dot com
Description:
------------
The problem exist in function COMPersistHelper::SaveToFile which check fullpath, but call php_com_string_to_olestring with filename from args and fullpath's length. Because fullpath's length may less than filename's length, with '/../' skill, it's safe-mode bypass.

=====ext/com_persist.c================================
CPH_METHOD(SaveToFile)
{
	HRESULT res;
	char *filename, *fullpath = NULL;
	int filename_len;
	zend_bool remember = TRUE;
	OLECHAR *olefilename = NULL;
	CPH_FETCH();
	
	CPH_NO_OBJ();

	res = get_persist_file(helper);
	if (helper->ipf) {
		if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p!|b",
					&filename, &filename_len, &remember)) {
			php_com_throw_exception(E_INVALIDARG, "Invalid arguments" TSRMLS_CC);
			return;
		}

		if (filename) {
			fullpath = expand_filepath(filename, NULL TSRMLS_CC);
			if (!fullpath) {
				RETURN_FALSE;
			}
	
			if (php_check_open_basedir(fullpath TSRMLS_CC)) {
				efree(fullpath);
				RETURN_FALSE;
			}

			olefilename = php_com_string_to_olestring(filename, strlen(fullpath), helper->codepage TSRMLS_CC);
			efree(fullpath);
		}
		res = IPersistFile_Save(helper->ipf, olefilename, remember);
		if (SUCCEEDED(res)) {
			if (!olefilename) {
				res = IPersistFile_GetCurFile(helper->ipf, &olefilename);
				if (S_OK == res) {
					IPersistFile_SaveCompleted(helper->ipf, olefilename);
					CoTaskMemFree(olefilename);
					olefilename = NULL;
				}
			} else if (remember) {
				IPersistFile_SaveCompleted(helper->ipf, olefilename);
			}
		}
			
		if (olefilename) {
			efree(olefilename);
		}

		if (FAILED(res)) {
			php_com_throw_exception(res, NULL TSRMLS_CC);
		}

	} else {
		php_com_throw_exception(res, NULL TSRMLS_CC);
	}
} 

Test script:
---------------
the file path like this(have not been verified): 
c:/windows/../../../boot.ini/../../../../../../webphp/AAAAAA.php


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2013-12-19 08:10 UTC] cyg0x7 at gmail dot com
-Package: Systems problem +Package: COM related
 [2013-12-19 08:10 UTC] cyg0x7 at gmail dot com
sr,it was COM related.
 [2020-02-06 13:51 UTC] cmb@php.net
-Summary: COMPersistHelper::SaveToFile safe-mode bypass +Summary: COMPersistHelper::SaveToFile can save to wrong location -Status: Open +Status: Verified -Type: Security +Type: Bug -Assigned To: +Assigned To: cmb
 [2020-02-06 13:51 UTC] cmb@php.net
Well, safe_mode is removed as of PHP 5.4.0, so a bypass is not
possible, and I don't see another way how this typo could be
exploited, so I'm re-categorizing as bug.
 [2020-02-06 14:02 UTC] cmb@php.net
Automatic comment on behalf of cmbecker69@gmx.de
Revision: http://git.php.net/?p=php-src.git;a=commit;h=5e2ea00b1539d6003548f7698ece1f737c14fb51
Log: Fix #66322: COMPersistHelper::SaveToFile can save to wrong location
 [2020-02-06 14:02 UTC] cmb@php.net
-Status: Verified +Status: Closed
 
PHP Copyright © 2001-2020 The PHP Group
All rights reserved.
Last updated: Fri Jul 10 13:01:25 2020 UTC