Этот код содержит уязвимость обхода файловой системы.Вы не выполняете проверку аргументов, ведущих к файлу.Файлы на диске открываются вслепую и передаются клиенту.
Что если вы работаете в системе Unix?Что произойдет, если кто-то отправит ?y=&f=../../../etc/passwd
?
Это даже не затрагивает тот факт, что вы не проводите никакой очистки для желаемого имени пользователя файла.Пользователь может представить полностью поддельные данные и получить полностью поддельное имя файла.
Этот код не выполняет проверку ошибок, и даже явно отключает ошибки при выдаче файла пользователю, используя readfile
.Это корень вашей проблемы.Никто не знает, что происходит.
Итак, мы можем это исправить.
Перво-наперво, вы захотите провести некоторую проверку y
и f
.Вы упомянули, что y
- это год, поэтому
$year = (int)$_GET['y'];
должно сработать.Вводя целое число в целое число, вы удаляете там любые возможности.
f
будет немного сложнее.Вы не дали нам представление о том, как называются файлы.Вы захотите добавить проверку соответствия шаблону, чтобы обеспечить поиск только допустимых имен файлов.Например, если все PDF-файлы называются «report_something_0000.pdf», тогда вы захотите проверить, скажем,
$file = null;
if(preg_match('/^report_something_\d{4}\.pdf$/', $_GET['f'])) {
$file = $_GET['f'];
}
Теперь, когда у нас есть правильное имя файла и правильный годовой каталог,Следующим шагом является . Убедитесь, что файл существует .
$path = 'E:/Omrop/' . $year . '/' . $file;
if(!$file || !file_exists($path) || !is_readable($path)) {
header('HTTP/1.0 404 File Not Found', true, 404);
header('Content-type: text/html');
echo "<h1>404 File Not Found</h1>";
exit;
}
Если $file
не было установлено из-за сбоя сопоставления с шаблоном или если не найден путь к файлу, сценарий отправит сообщение об ошибке.
Я собираюсь предположить , что ваши проблемы с открытием старых PDF-файлов вызваны тем, что файлы не существуют или имеют плохие разрешения.Вы предоставляете Adobe Reader правильные заголовки, а затем никаких данных.
Вы также захотите выполнить такую же проверку работоспособности для заданного пользователем желаемого имени файла.Опять же, я не знаю ваших требований здесь, но убедитесь, что ничто фальшивое не может проникнуть внутрь.
Далее, избавьтесь от @ перед readfile
.Это подавляет любые реальные ошибки, и вы захотите их увидеть.Поскольку вы, вероятно, не хотите видеть их в выводе, убедитесь, что вместо них настроен журнал ошибок .
Наконец ... как этот код вообще работает? Вы излучаете заголовки в середине HTML! Мало того, вы при этом даете явную длину содержимого.Вы должны получить чертовски много ошибок от этого.Вы уверены, что случайно не скопировали / вставили какой-то код здесь?Может быть, вы забыли раздел в верхней части, где вы звоните ob_start()
?Несмотря на это, канаву все до открывающего тега <?php
.