Как безопасно выводить ссылки, предоставленные пользователем, на вашей веб-странице?

php #html #output #urlencode #htmlspecialchars

#php #HTML #Вывод #urlencode #htmlspecialchars

Вопрос:

Я хочу разрешить посетителям моего сайта (любым Tom, Dick amp; Harry) отправлять свои ссылки на мою веб-страницу для вывода на моей странице. Мне нужно проанализировать отправленные пользователем URL-адреса, прежде чем повторять их отправленные URL-адреса на моей странице. Необходимо проанализировать URL-адреса, поскольку я не буду знать, какие URL-адреса они будут отправлять, а также структуры их URL-адресов.

Теоретически пользователь может посетить мою страницу и ввести некоторый код JavaScript, используя, например:

 ?search=<script>alert('hacked')</script>
 

Вы понимаете мою точку зрения.

Я должен написать php-скрипт, который, когда пользователи отправляют свои URL-адреса, затем мой php-скрипт анализирует их URL-адреса и кодирует их, добавляя urlencode, rawurlencode, intval в соответствующие места, прежде чем выводить их через htmlspecialchars. Другой написал следующий скрипт. Проблема в том, что он выводит примерно так:

http://example.com/cat/subcat?var_1=значение 1amp;var2= 2amp;this_other=вещьamp;number_is= 13

Он должен выводиться следующим образом:

http://example.com/cat/subcat?var_1=value 1amp;var2=2amp;this_other=вещьamp;number_is=13

Это их код…. Сторонний код:

 <?php
function encodedUrl($url){
    $query_strings_array = [];
    $query_string_parts  = [];
    // parse URL amp; get query
    $scheme        = parse_url($url, PHP_URL_SCHEME);
    $host          = parse_url($url, PHP_URL_HOST);
    $path          = parse_url($url, PHP_URL_PATH);
    $query_strings = parse_url($url, PHP_URL_QUERY);

    // parse query into array
    parse_str($query_strings, $query_strings_array);

    // separate keys amp; values
   $query_strings_keys   = array_keys($query_strings_array);
   $query_strings_values = array_values($query_strings_array);

   // loop query
  for($i = 0; $i < count($query_strings_array); $i  ){
       $k   = urlencode($query_strings_keys[$i]);
       $v   = $query_strings_values[$i];
       $val = is_numeric($v) ? intval($v) : urlencode($v);
    
       $query_string_parts[] = "{$k}={$val}";
   }

   // re-assemble URL
   $encodedHostPath = rawurlencode("{$scheme}://{$host}{$path}");

   return $encodedHostPath . '?' . implode('amp;', $query_string_parts);
}

$url1 = 'http://example.com/cat/subcat?var 1=value 1amp;var2=2amp;this other=thingamp;number is=13';
$url2 = 'http://example.com/autos/cars/list.php?state=californiaamp;max_price=50000';

// run urls thru function amp; echo
// run urls thru function amp; echo
echo $encoded_url1 = encodedUrl($url1); echo '<br>'; 
echo $encoded_url2 = encodedUrl($url2); echo '<br>'; 
?>
 

Итак, я изменил это их:

 $encodedHostPath = rawurlencode("{$scheme}://{$host}{$path}");
 

к этому моему (моя поправка):

 $encodedHostPath = rawurlencode("{$scheme}").'://'.rawurlencode("{$host}").$path;
 

И, похоже, это работает. Поскольку он выводит:

http://example.com/cat/subcat?var_1=value 1amp;var2=2amp;this_other=вещьamp;number_is=13

ВОПРОС 1: Но я не уверен, помещаю ли я raw_urlencode() в правильные места или нет, поэтому лучше вам проверить. Кроме того, не должен ли $path находиться внутри raw_urlencode вот так?

 raw_urlencode($path)
 

Однако обратите внимание, что:

 raw_urlencode($path)
 

Неправильно выводится.

ВОПРОС 2: Я ДОПОЛНИТЕЛЬНО обновил их код до новой ВЕРСИИ, и он не выводится правильно. Почему это так? Где я ошибаюсь? Все, что я сделал, это добавил несколько строк. Это мое обновление (НОВАЯ ВЕРСИЯ), которое выводит неверно. Такие результаты:

http://example.com/cat/subcat?var_1=значение 1amp;var2= 2amp;this_other=вещьamp;number_is= 13

Я добавил несколько собственных строк в нижней части их кода.

МОЕ ОБНОВЛЕНИЕ (НОВАЯ ВЕРСИЯ):

 <?php
function encodedUrledited($url){
    $query_strings_array = [];
    $query_string_parts  = [];
    // parse URL amp; get query
    $scheme        = parse_url($url, PHP_URL_SCHEME);
    $host          = parse_url($url, PHP_URL_HOST);
    $path          = parse_url($url, PHP_URL_PATH);
    $query_strings = parse_url($url, PHP_URL_QUERY);

    // parse query into array
    parse_str($query_strings, $query_strings_array);

    // separate keys amp; values
   $query_strings_keys   = array_keys($query_strings_array);
   $query_strings_values = array_values($query_strings_array);

   // loop query
  for($i = 0; $i < count($query_strings_array); $i  ){
       $k   = urlencode($query_strings_keys[$i]);
       $v   = $query_strings_values[$i];
       $val = is_numeric($v) ? intval($v) : urlencode($v);
    
       $query_string_parts[] = "{$k}={$val}";
   }

   // re-assemble URL
   $encodedHostPath = rawurlencode("{$scheme}").'://'.rawurlencode("{$host}").$path;
   
   return $encodedHostPath . '?' .implode('amp;', $query_string_parts);
}

if(!ISSET($_POST['url1']) amp;amp; empty($_POST['url1']) amp;amp; !ISSET($_POST['url2']) amp;amp; empty($_POST['url2']))
{
    //Default Values for Substituting empty User Inputs.
    $url1 = 'http://example.com/cat/subcat?var 1=value 1amp;var2=2amp;this other=thingamp;number is=138';
    $url2 = 'http://example.com/autos/cars/list.php?state=californiaamp;max_price=500008';
}
else
{
    //User has made following inputs...
    $url1 = $_POST['url1'];
    $url2 = $_POST['url2'];
    
    //Encode User's Url inputs. (Add rawurlencode(), urlencode() and intval() in user's submitted url where appropriate).
    $encoded_url1 = encodedUrledited($url1);
    $encoded_url2 = encodedUrledited($url2);
}

echo $link1 = '<a href=' .htmlspecialchars($encoded_url1) .'>' .htmlspecialchars($encoded_url1) .'</a>';
echo '<br/>';
echo $link2 = '<a href=' .htmlspecialchars($encoded_url2) .'>' .htmlspecialchars($encoded_url2) . '</a>';
echo '<br>';

?>
 

Эта тема действительно касается 2-го кода. Мое обновление.

Спасибо!

Комментарии:

1. Неясно, о чем вы говорите, результаты вашего последнего кода не отображаются в кодировке URL так, как вы сказали — 3v4l.org/9j9h5

2. @CBroe, я ответил на свой собственный вопрос в качестве исправления. Можете ли вы определить разницу между кодом в моем op и моим ответом (исправлением)? Спасибо! Вы можете закрыть эту тему.

Ответ №1:

Я исправил свой код. Отвечая на мой собственный вопрос.

Исправлен код:

 function encodedUrledited($url){
    $query_strings_array = [];
    $query_string_parts  = [];
    // parse URL amp; get query
    $scheme        = parse_url($url, PHP_URL_SCHEME);
    $host          = parse_url($url, PHP_URL_HOST);
    $path          = parse_url($url, PHP_URL_PATH);
    $query_strings = parse_url($url, PHP_URL_QUERY);

    // parse query into array
    parse_str($query_strings, $query_strings_array);

    // separate keys amp; values
   $query_strings_keys   = array_keys($query_strings_array);
   $query_strings_values = array_values($query_strings_array);

   // loop query
  for($i = 0; $i < count($query_strings_array); $i  ){
       $k   = $query_strings_keys[$i];
       $key = is_numeric($k) ? intval($k) : urlencode($k);
       
       $v   = $query_strings_values[$i];
       $val = is_numeric($v) ? intval($v) : urlencode($v);
    
       $query_string_parts[] = "{$key}={$val}";
   }

   // re-assemble URL
   $encodedHostPath = rawurlencode($scheme).'://'.rawurlencode($host).$path;   
   $encodedHostPath .= '?' .implode('amp;', $query_string_parts);
   
   return $encodedHostPath;
}

if(!ISSET($_POST['url1']) amp;amp; empty($_POST['url1']) amp;amp; !ISSET($_POST['url2']) amp;amp; empty($_POST['url2']))
{
    //Default Values for Substituting empty User Inputs.
    $url1 = 'http://example.com/cat/subcat?var 1=value 1amp;var2=2amp;this other=thingamp;number is=138';
    $url2 = 'http://example.com/autos/cars/list.php?state=californiaamp;max_price=500008';
}
else
{
    //User has made following inputs...
    $url1 = $_POST['url1'];
    $url2 = $_POST['url2'];
    
    //Encode User's Url inputs. (Add rawurlencode(), urlencode() and intval() in user's submitted url where appropriate).
}

$encoded_url1 = encodedUrledited($url1);
$encoded_url2 = encodedUrledited($url2);

$link1 = '<a href=' .htmlspecialchars($encoded_url1) .'>' .htmlspecialchars($encoded_url1) .'</a>';
$link2 = '<a href=' .htmlspecialchars($encoded_url2) .'>' .htmlspecialchars($encoded_url2) . '</a>';

echo $link1; echo '<br/>';
echo $link2; echo '<br/>';

?>
 

Эти 2 следующие строки должны были быть вне ELSE. Их не было. Отсюда и вся проблема. Переместил их за пределы ELSE, и теперь скрипт работает нормально.

 $encoded_url1 = encodedUrledited($url1);
$encoded_url2 = encodedUrledited($url2);