Hello Martin,
In ./ext/standard/basic_functions.c ab Zeile 5787 (für PHP 5.3.6).
Es geht also um diese beiden Funktions-Baumuster...
(die sind jetzt aus der 5.3-dev, die neuere habe ich noch nicht runtergeladen)
Das heißt also, wir müssen nach SG() suchen und ggf. noch nach zend_hash_exists()
#------------------
/* {{{ proto bool is_uploaded_file(string path)
Check if file was created by rfc1867 upload */
PHP_FUNCTION(is_uploaded_file)
{
char *path;
int path_len;
if (!SG(rfc1867\_uploaded\_files)) {
RETURN\_FALSE;
}
if (zend\_parse\_parameters(ZEND\_NUM\_ARGS() TSRMLS\_CC, "s", &path, &path\_len) == FAILURE) {
return;
}
if (zend\_hash\_exists(SG(rfc1867\_uploaded\_files), path, path\_len + 1)) {
RETURN\_TRUE;
} else {
RETURN\_FALSE;
}
}
/* }}} */
#------------------------
/* {{{ proto bool move_uploaded_file(string path, string new_path)
Move a file if and only if it was created by an upload */
PHP_FUNCTION(move_uploaded_file)
{
char *path, *new_path;
int path_len, new_path_len;
zend_bool successful = 0;
#ifndef PHP_WIN32
int oldmask; int ret;
#endif
if (!SG(rfc1867\_uploaded\_files)) {
RETURN\_FALSE;
}
if (zend\_parse\_parameters(ZEND\_NUM\_ARGS() TSRMLS\_CC, "ss", &path, &path\_len, &new\_path, &new\_path\_len) == FAILURE) {
return;
}
if (!zend\_hash\_exists(SG(rfc1867\_uploaded\_files), path, path\_len + 1)) {
RETURN\_FALSE;
}
if (PG(safe\_mode) && (!php\_checkuid(new\_path, NULL, CHECKUID\_CHECK\_FILE\_AND\_DIR))) {
RETURN\_FALSE;
}
if (php\_check\_open\_basedir(new\_path TSRMLS\_CC)) {
RETURN\_FALSE;
}
VCWD\_UNLINK(new\_path);
if (VCWD\_RENAME(path, new\_path) == 0) {
successful = 1;
#ifndef PHP_WIN32
oldmask = umask(077);
umask(oldmask);
ret = VCWD\_CHMOD(new\_path, 0666 & ~oldmask);
if (ret == -1) {
php\_error\_docref(NULL TSRMLS\_CC, E\_WARNING, "%s", strerror(errno));
}
#endif
} else if (php_copy_file_ex(path, new_path, STREAM_DISABLE_OPEN_BASEDIR TSRMLS_CC) == SUCCESS) {
VCWD_UNLINK(path);
successful = 1;
}
if (successful) {
zend\_hash\_del(SG(rfc1867\_uploaded\_files), path, path\_len + 1);
} else {
php\_error\_docref(NULL TSRMLS\_CC, E\_WARNING, "Unable to move '%s' to '%s'", path, new\_path);
}
RETURN\_BOOL(successful);
}
/* }}} */
Wenn es nicht um den Inhalt der Files gehen sollte, sondern nur um den Namen, dann halte ich diese Funktionen für nutzlosen Overhead. Denn das Array $_FILES sollte sicher sein und somit sollte zumindest der Name der Temporärdatei nicht manipuliert werden können, da dieser vom System kommt und das Array nur der jeweiligen Scriptinstanz zur Verfügung steht. Hingegen könnte das File in einem gemeinsam genutzten Bereich liegen und auch das t-flag bei Linux schützt nicht gegen Manipulation des Files, sondern nur gegen Löschen/Verschieben oder Namensänderung.
Move_uploaded_file() war genau der Punkt, an dem ich im Wiki-Artikel jetzt hängengeblieben war. Ohne Kenntnis der Zusammenhänge mag ich das nicht gebetsmühlenartig wieder zur Bentutzung vorschlagen. PHP hatte schon andere Designfehler (magic_quotes, PHP_SELF, usw), die später zu weit verbreiteten Sicherheitslücken geführt haben.
Mein Resümeé daraus ist also: für die Modulversion _unbedingt_ das upload_tmp_dir auf ein eigenes HTTP-geschütztes Verzeichnis setzen, usw...
Für Sessions gilt ja Ähnliches.
Liebe Grüße aus dem auch heute sonnigen Oberharz
Tom vom Berg