Sec Bug->Bug #66322 [Opn->Ver]: COMPersistHelper::SaveToFile can save to wrong location
| From: | cmb@php.net | Date: | Thu, 06 Feb 2020 13:51:14 +0000 |
| Subject: | Sec Bug->Bug #66322 [Opn->Ver]: COMPersistHelper::SaveToFile can save to wrong location | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-225388@lists.php.net to get a copy of this message | ||
Edit report at https://bugs.php.net/bug.php?id=66322&edit=1
ID: 66322
Updated by: cmb@php.net
Reported by: cyg0x7 at gmail dot com
-Summary: COMPersistHelper::SaveToFile safe-mode bypass
+Summary: COMPersistHelper::SaveToFile can save to wrong
location
-Status: Open
+Status: Verified
-Type: Security
+Type: Bug
Package: COM related
Operating System: windows
PHP Version: 5.4.23
-Assigned To:
+Assigned To: cmb
Block user comment: N
Private report: Y
New Comment:
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.
Previous Comments:
------------------------------------------------------------------------
[2013-12-19 08:10:33] cyg0x7 at gmail dot com
sr,it was COM related.
------------------------------------------------------------------------
[2013-12-19 07:30:08] 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
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=66322&edit=1