Безопасно ли помещать пользовательские данные в кодировке base64 в src img? - PullRequest
2 голосов
/ 06 февраля 2012

Безопасно ли принимать POST данные, которые должны быть данными в кодировке base64, и использовать их в качестве атрибута src img?

<img src="data:image/png;base64,[data here]" />

Очевидно, что без фильтрации можно легко вырваться из атрибута src и тега img и вставить вредоносные <script /> или другие теги, поэтому моя идея состоит в том, чтобы

base64_decode($rawPostData)

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

base64_encode($decodedData)

чтобы поместить его в атрибут src.

Есть ли какие-либо уязвимости (такие как XSS, возможно переполнение буфера?) С таким подходом?

Фон

Мне это нужно для страницы, которая преобразует сторонние svg в canvas в base64 кодированные данные, используя JavaScript (точнее, используя «canvg»). Мне нужно передать изображение в сценарии на стороне сервера для выполнения некоторых других задач с использованием изображения, а также для отображения изображения пользователю / клиенту.

Ответы [ 3 ]

3 голосов
/ 06 февраля 2012

Я бы принял изображение как изображение, затем base64_encode это. Это избавляет вас от ненужных промежуточных шагов проверки того, что оно было отправлено, как ожидалось, а также делает невозможным вызов XSS.

Если вам необходимо проверить base64, как на изображении, достаточно просто проверить, что он содержит только символы base64, поскольку вы встраиваете его только в тег img (а символы разрыва тега недопустимы в base64.

Используйте встроенные функции:

if (base64_decode($mystring, true)) {
    // is valid
} else {
    // not valid
}
1 голос
/ 06 февраля 2012

Не безопасно, если вы не проверяете содержимое данных.

Пример:

$data= '"/><script>alert("hi");</script>';

print '<img src="data:image/png;base64,'.$data.'" />';

Очень просто проверить, что $data содержит только действительные символы base64 . Ничто из этого не сломает ваш тег.

Edit:

Следующее просто приведет к повреждению изображения:

$data= '"/><script>alert("hi");</script>';

$data64 = base64_encode($data);

print '<img src="data:image/png;base64,'.$data64.'" />';
0 голосов
/ 18 ноября 2016

Основная проблема безопасности заключается в том, что вы не можете применить чистый XSS к данным этого типа. Часть строки «data: image / png; base64,» удаляется , если применяется чистый XSS, портящий изображение .

Имея это в виду, я создал решение, которое ответило мне хорошо:

  1. Мы знаем, что начало изображения base64 следует схеме, аналогичной «data: image / png; base64,», поэтому следующий код может зафиксировать это начало

    $data = substr($imageBase64, 0, strpos($imageBase64, ",") + 1);
  2. Хорошо, но мы полагаемся только на первую найденную запятую, которая не обеспечивает никакой безопасности. Итак, давайте используем preg_replace (), чтобы убедиться, что записанная нами строка действительно соответствует нашим ожиданиям.

    $data = preg_replace('#^data:image/[^;]+;base64,#', '', $data);
  3. Если все пойдет по плану, результат, сохраненный в $data, будет пустой строкой. В противном случае наше изображение здесь больше не действует. Теперь нам нужно проверить, что находится после первой запятой, поэтому мы просто будем использовать base64_decode.

    $img = preg_replace('#^data:image/[^;]+;base64,#', '', $imageBase64);
    if(base64_decode($img, true)) {
      // is valid
    } else {
      // not valid
    }
  4. Мы используем тот же preg_replace, чтобы заменить начало строки, а затем мы проверяем остальное, чтобы убедиться, что оно соответствует действительным данным base64. Если значение положительное, вы уже можете без проблем сохранить исходную строку в базе данных, потому что ее строка действительно чистая, а если значение отрицательное, мы снова имеем недопустимое изображение.

...