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
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: cyg0x7 at gmail dot com
New email:
PHP Version: OS:

 

 [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

Pull Requests

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-2024 The PHP Group
All rights reserved.
Last updated: Sun Oct 27 16:01:27 2024 UTC