Ладно, думаю, я понял это.
По сути, это неверный ввод, файл, с которым у вас проблемы, на основе ошибки
Предупреждение: fopen (проект 1 / https://test.com/user_adam): не удалось открыть поток: нет такого файла или каталога
Я действительно надеюсь, что у вас нет файлов с именем project 1/https://test.com/user_adam
. Но, исходя из того, что вы говорите:
Допустим, я хочу, чтобы пользователи типа идентифицировали как ссылку, поэтому, когда я пытаюсь, например, https://test.com/user_adam
, я получаю ошибку (это хорошо работает, если имя пользователя не имеет "/"):
А это:
http://localhost/linkey/live.php?uname=https://test.com/user_adam&rname=project%201&enSubmit=Enter
Что показывает мне, что uname
= uname=https://test.com/user_adam
и rname
= rname=project 1
. Или по-английски rnameпапка, а uname - это имя пользователя. Это все денди, пока вы не введете туда URL.
Я бы сделал что-то вроде этого:
$uname=$_GET['uname'];
$arr_name = expode('/', $uname); //this offers a small amount of protection too (see below)
$uname = end($arr_name);
Что в данном случаеоставит $uname
со всем после последнего /
или user_adam
. Тогда ваш путь станет project 1/user_adam
.
Обратный путь в каталогах
Однако,Вы широко открыты для атак через каталоги (копаться в коде еще хуже, чем я подозревал).Именно здесь злоумышленник может передать подобные вещи (%2F
- это /
в кодировке URL)
http://localhost/linkey/live.php?rname=..%2F..%2Fsomefolder&uname=foo&enSubmit=bar
Что это значит, scandir()
будет искать эту папку ../../somefolder
.Теперь скажите, что папка содержит все ваши PHP-файлы, затем откроет их и, вероятно, удалит их с помощью unlink
:
if (isset($_GET['enSubmit']) && isset($_GET['uname']) && isset($_GET['rname'])){
echo'<meta http-equiv="refresh" content="10">';
$room=$_GET['rname']; //../../somefolder
$uname=$_GET['uname']; //foo
if (!is_dir($room)) mkdir($room);
$files = scandir($room); //../../somefolder
foreach ($files as $user){
//$user = somefile.php
if ($user=='.' || $user=='..') continue; //fails (or false here)
$handle=fopen("$room/$user",'r'); // ../../somefolder/somefile.php
$time = fread($handle, filesize("$room/$user")); //time will be a non number string, likly
fclose($handle);
if ((time()-$time)>20) unlink("$room/$user"); //time() - string(or 0) is almost always > 20 ... or TRUE here.
}
....
}
Вы можете проверить условие отмены связи здесь, предположив, что первая строка файла phpначинается с <?php
.В любом случае мы можем предположить, что это будет нечисловая строка.Затем, когда он преобразуется в целое число (преобразованное путем вычитания), его числовое значение фактически равно 0. Тогда time() - 0
равно time()
, что намного больше, чем 20
.
var_dump( (time()-'<?php')>20); //true
Песочница
И поскольку это условие не может остановить его, запускается следующий бит:
unlink("$room/$user"); //unlink('../../somefolder/somefile.php')
По сути, передавая этот «материал», если я знаю местоположение файла PHP, который запускает пользовательPHP (на сервере) имеет доступ, я могу удалить его.Или я могу в принципе удалить любые «известные» файлы из любой папки на вашем сервере, к которой PHP может получить доступ.Как бы я их знал, ну все, что мне нужно сделать, это посмотреть URL в большинстве случаев.Я должен был проверить это, чтобы убедиться, но я не вижу ничего, что указывало бы, что это не будет работать.Не дай Бог кто-нибудь поместит туда ../../public_html
и сотрет ваш сайт с лица земли (надеюсь, у вас есть резервные копии вашего сервера) ...
Вы можете подумать, что это всего лишь стартовый проект.Но что, если вы или ваш пользователь случайно поместите в папку, содержащую файлы PHP или другие файлы, которые вы не хотите удалять?Это может произойти.
Это действительно важно, поэтому я подумал, что должен упомянуть об этом.
Приветствия.