|   | php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login | 
| 
 PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits              [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
  [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
  [2020-02-06 14:02 UTC] cmb@php.net
  [2020-02-06 14:02 UTC] cmb@php.net
 
-Status: Verified
+Status: Closed
 | |||||||||||||||||||||||||||
|  Copyright © 2001-2025 The PHP Group All rights reserved. | Last updated: Thu Oct 30 23:00:01 2025 UTC | 
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