Предыстория


Друг писал свой личный блог и попросил посмотреть. Помимо кучи дыр я обнаружил в исходном html следующую конструкцию:

<img src="<? echo '/img/'.$image[1].'jpg';?>">

$image-выборка аватарок из базы данных. Пользователи могли загружать свои фотки на аватар. Фотографии сохранялись в папку img с своим же именем.

И тут мне пришла в голову идея.

Использование XSS


Я подумал, ведь если каким то образом внести

image" onerror="javascript:alert()"

в базу данных, кусок кода станет

<src="image" onerror="javascript:alert()" ">

Так как такой картинки не существует в папке img, сработает onerror, одним словом xss.

К этому моменту я уже понял, что картинки сохранялись со своими именами. Я попытался создать некий файл, имя которого привело было все описанное выше в действие. И тут начались первые проблемы — Windows был против использования " в названии файла. Но мне пришла в голову идея использовать символы ANSII. Нарыв их таблицу —

image
, я создал символ " так — 34; (между # и 3 не нужен пробел. Просто хабр преобразует его в "). Так он сохранился в Windows. Но так как теги бывают как и

<img src=''>

так и

<img src="">

(разница в кавычках, если вы еще не увидели (: ), то я создал для себя 2 картинки с двойной и одинарной кавычкой. Одним словом конечное имя файла стало
javascript& #58;alert()& #34;onerror='javascript& #58;alert()' .jpg
& #58;-это : кто еще не понял.

Как это работает:


Вернемся к изначальному коду:

<img src="<? echo '/img/'.$image[1].'jpg';?>">

а теперь представим что в $image[1] лежит javascript& #58;alert()& #34;onerror='javascript& #58;alert()', & #34; как и на любом сайте преобразуется в ", : — в :(Хабр не исключение), и с учетом преобразований код становится

<img src="/img/javascript:alert()" onerror='javascrip:alert().jpg' ">

и разумеется срабатывает onerror.

.jpg становится свойством функции alert(), но так как алерт ничего не возвращает, то в консоли будет простое предупреждение, что ошибка чтения свойства нулевого объекта.

Как обезопаситься?


  • Как верно сделаны большинство сайтов, не сохранять названия фоток оригинальными. Например 'avatar_'.md5(time())
  • Либо можно использовать стандартные приемы защиты от xss: htmlspecialchars(), add_slash();
  • Не давать загружать картинки(:

Комментарии (4)


  1. moodpulse
    12.01.2022 01:14
    +4

    Названия файлов — такой же пользовательский ввод, как и всё остальное. И, соответственно, они подлежат правильной и аккуратной обработке. На эту тему очень много всего написано уже.

    А на raw php шаблонизацию, честно говоря, в 2022 очень больно смотреть. Выбор почти любого другого способа полечил бы множество проблем.


  1. AjnaGame
    12.01.2022 01:21
    +1

    Ну всё, надевайте блек хет теперь


  1. horror_x
    12.01.2022 01:52

    я создал символ " так — 34; (между # и 3 не нужен пробел
    Для этого есть сущность &amp; — &#34;.


  1. SamSol
    12.01.2022 02:21

    Поддерживаю! Вникай, разбирайся как все работает! Молодец!