07/04/08 01:29:13 and also for files 07/04/08 01:29:24 there's a thing that nobody knows 07/04/08 01:29:49 when there's a check like 07/04/08 01:30:21 substr($file, "the last 4 chars") == '.php' 07/04/08 01:30:34 or similar 07/04/08 01:31:00 if it's ereg*() you can use nullbytes 07/04/08 01:31:08 if it's subst 07/04/08 01:31:12 it's binary safe 07/04/08 01:31:26 bu file opening functions are not 07/04/08 01:31:37 so you can safely append a null byte 07/04/08 01:31:52 the other bypass is to append / to the path 07/04/08 01:31:58 since php when open files 07/04/08 01:32:12 make lstat on every piece of the path 07/04/08 01:32:37 php doesn't make assumpions if a specific part of the path is a dir or a file 07/04/08 01:34:49 it depends on the file system 07/04/08 01:35:33 lstat64("/etc", {st_mode=S_IFDIR|0755, st_size=7032, ...}) = 0 07/04/08 01:35:33 lstat64("/etc/passwd", {st_mode=S_IFREG|0644, st_size=3120, ...}) = 0 07/04/08 01:35:33 open("/etc/passwd/", O_RDONLY) = -1 ENOTDIR (Not a directory) 07/04/08 01:35:33 write(1, "\nWarning: file_get_contents(/etc"..., 113 07/04/08 01:35:33 Warning: file_get_contents(/etc/passwd/): failed to open stream: Not a directory in Command line code on line 1 07/04/08 01:35:33 ) = 113 07/04/08 01:35:33 close(2) = 0 07/04/08 01:35:33 close(1) = 0 07/04/08 01:35:40 this is on reiser fs 07/04/08 01:35:47 (doesn't work) 07/04/08 01:38:12 lstat64("/etc/passwd", {st_mode=S_IFREG|0644, st_size=1243, ...}) = 0 07/04/08 01:38:12 open("/etc/passwd", O_RDONLY|O_LARGEFILE) = 3 07/04/08 01:38:12 fstat64(3, {st_mode=S_IFREG|0644, st_size=1243, ...}) = 0 07/04/08 01:38:12 _llseek(3, 0, [0], SEEK_CUR) = 0 07/04/08 01:38:12 close(3) = 0 07/04/08 01:38:12 close(2) = 0 07/04/08 01:38:29 this is on ext3 07/04/08 01:38:34 (works :D) 07/04/08 01:39:37 as you can see php lookup /etc 07/04/08 01:39:40 and see it's a dir 07/04/08 01:39:59 than /etc/passwd 07/04/08 01:40:02 and see it's a file 07/04/08 01:40:09 and handles that as a file 07/04/08 01:51:47 ah, nice 07/04/08 01:52:40 yup lstat VS open + fstat : ) 07/04/08 01:53:06 not only php does thid 07/04/08 01:53:58 though i can't really see where that would help (unless /etc/passwd/.php opens /etc/passwd) 07/04/08 01:54:57 /etc/./passwd <-- you can do this cause path are collapsed before reaching the os 07/04/08 01:55:02 not always anyway 07/04/08 01:55:14 there is some normalization code 07/04/08 01:55:27 the trailing / is useful in something like 07/04/08 01:56:00 or /etc//passwd etc 07/04/08 01:56:43 if (substr($file, strlen($file)-4, 4) == '.php') 07/04/08 01:56:50 die("die!"); 07/04/08 01:56:53 else 07/04/08 01:56:58 do_something(); 07/04/08 01:58:05 ah 07/04/08 01:58:13 so can you write to something.php/ ? 07/04/08 01:58:19 exactly 07/04/08 01:58:24 'cos that could own most file uploads... 07/04/08 01:58:35 well not, most but blacklist ones 07/04/08 01:58:38 only with the righe file system 07/04/08 01:58:53 but then again you can own blacklist systems by doing .php.xyz anyway, but that's still awesome 07/04/08 01:59:27 i used this trick in reading, but probably in writing it's the same 07/04/08 01:59:44 yeah, that's true, source disclosure is cool 07/04/08 01:59:54 hehehe 07/04/08 01:59:55 :D 07/04/08 02:00:20 keep secret as always 07/04/08 02:00:40 sure :)