XSS уязвимость в названии файла

в 1:46, , рубрики: Песочница, метки: , ,

Предыстория

Друг писал свой личный блог и попросил посмотреть. Помимо кучи дыр я обнаружил в исходном 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();
  • Не давать загружать картинки(:

* - обязательные к заполнению поля