Какой EncodeFor для данных - атрибуты с URL - PullRequest
0 голосов
/ 11 октября 2018

Я пытаюсь вставить URL в атрибут data-.В частности

<tr data-href="/page.cfm?Id=#EncodeForHTMLAttribute(ID)#">
   ...

ИЛИ, возможно, это должно быть

<tr data-href="/page.cfm?Id=#EncodeForURL(ID)#">
   ...

Обратите внимание, что идентификатор может содержать специальные символы

Редактировать:

Намного позже я собираюсь

$("tr").click(function() { window.location = $(this).data("href"); });

1 Ответ

0 голосов
/ 13 октября 2018

Давайте проанализируем несколько сценариев:

Не кодировать вообще

<!--- our "tricky" ID --->
<cfset ID = '"><script>alert("my evil script");</script><div foo="'>
<!--- we are closing the data-href attribute, injecting our JS and start a new tag to complete the remaining tag --->

<cfoutput>

    <div data-href="page.cfm?Id=#ID#"></div>
    <!--- [data-href] is printed as: page.cfm?Id="><script>alert("my evil script");</script><div foo=" --->

</cfoutput>

Результат

Появляется диалоговое окно с предупреждением «Мой злой скрипт».

Заключение

Никогда не оставляйте пользовательский ввод без кодировки! (Вы это уже знали).


Кодирование строки запроса для вывода в виде HTML

Примечание: Вы всегда должны кодировать полное значение атрибута HTML, а не только его части.

<!--- our "tricky" ID --->
<cfset ID = "&a=b?c">
<!--- we are having some reserved characters here that will confuse the browser's query string parser --->

<cfoutput>

    <div data-href="#encodeForHtmlAttribute("page.cfm?Id=#ID#")#"></div>
    <!--- [data-href] is printed as: page.cfm&#x3f;Id&#x3d;&amp;a&#x3d;b&#x3f;c --->

    <script>

        var attr = document.getElementsByTagName('div')[0].getAttribute('data-href');

        console.log(attr); <!--- page.cfm?Id=&a=b?c --->

        <cfif structIsEmpty(URL)> <!--- test related: to prevent infinite redirection --->
            location.href = attr;
        </cfif>

    </script>

</cfoutput>

<cfdump var="#URL#">

Результат

При запросе page.cfm мы будем перенаправлены на page.cfm?Id=&a=b?c, обычное значение атрибута data-href.Однако дамп области URL предоставит нам пары ключ-значение:

Id: [empty string]
 a: b?c

Что и следовало ожидать, потому что синтаксический анализатор строки запроса браузера не мог различить буквальное значение и техническое назначениеперсонажи. Я недавно ответил на это здесь.

Заключение

Кодирование вывода недостаточно при наличии нескольких контекстов (здесь: HTML & URL / QueryString).


Кодирование строки запроса в виде URL

<!--- our "tricky" ID --->
 <cfset ID = 'a&b="><script>alert("my evil script");</script><div foo="'>
 <!--- we are mixing in both contexts now --->

 <cfoutput>

     <div data-href="page.cfm?Id=#encodeForUrl(ID)#"></div>
     <!--- [data-href] is printed as: page.cfm?Id=a%26b%3D%22%3E%3Cscript%3Ealert%28%22my+evil+script%22%29%3B%3C%2Fscript%3E%3Cdiv+foo%3D%22 --->

     <script>

         var attr = document.getElementsByTagName('div')[0].getAttribute('data-href');

         console.log(attr); <!--- page.cfm?Id=a%26b%3D%22%3E%3Cscript%3Ealert%28%22my+evil+script%22%29%3B%3C%2Fscript%3E%3Cdiv+foo%3D%22 --->

         <cfif structIsEmpty(URL)> <!--- test related: to prevent infinite redirection --->
             location.href = attr;
         </cfif>

     </script>

 </cfoutput>

 <cfdump var="#URL#">

Результат

При запросе page.cfm мы будем перенаправлены на page.cfm?Id=a%26b%3D%22%3E%3Cscript%3Ealert%28%22my+evil+script%22%29%3B%3C%2Fscript%3E%3Cdiv+foo%3D%22, обычное значение data-hrefприписывать.Дамп области URL предоставит нам пару ключ-значение:

Id: a&b="><script>alert("my evil script");</script><div foo="

На этот раз парсер строки запроса браузера может различать буквальное значение и техническое назначение символов.Но как насчет HTML-контекста здесь?Ну, процентное кодирование, выполняемое encodeForUrl(), не конфликтует с зарезервированными символами HTML, потому что % не имеет технической цели в HTML и ничего не нарушает.

Заключение

Теоретически мы сделали здесь.Нет необходимости в HTML-кодировании значения в кодировке URL, поскольку нет перекрытия двух кодировок.


Кодирование строки запроса в виде URL - И - для вывода в виде HTML

<!--- our "tricky" ID --->
 <cfset ID = 'a&b="><script>alert("my evil script");</script><div foo="'>
<!--- we are mixing in both contexts again --->

<cfoutput>

    <div data-href="#encodeForHtmlAttribute("page.cfm?Id=#encodeForUrl(ID)#")#"></div>
    <!--- [data-href] is printed as: page.cfm&#x3f;Id&#x3d;a&#x25;26b&#x25;3D&#x25;22&#x25;3E&#x25;3Cscript&#x25;3Ealert&#x25;28&#x25;22my&#x2b;evil&#x2b;script&#x25;22&#x25;29&#x25;3B&#x25;3C&#x25;2Fscript&#x25;3E&#x25;3Cdiv&#x2b;foo&#x25;3D&#x25;22 --->

    <script>

        var attr = document.getElementsByTagName('div')[0].getAttribute('data-href');

        console.log(attr); <!--- page.cfm?Id=a%26b%3D%22%3E%3Cscript%3Ealert%28%22my+evil+script%22%29%3B%3C%2Fscript%3E%3Cdiv+foo%3D%22 --->

        <cfif structIsEmpty(URL)> <!--- test related: to prevent infinite redirection --->
            location.href = attr;
        </cfif>

    </script>

</cfoutput>

<cfdump var="#URL#">

Результат

При запросе page.cfm мы будем перенаправлены на page.cfm?Id=a%26b%3D%22%3E%3Cscript%3Ealert%28%22my+evil+script%22%29%3B%3C%2Fscript%3E%3Cdiv+foo%3D%22, обычное значение атрибута data-href.Дамп области URL предоставит нам пару ключ-значение:

Id: a&b="><script>alert("my evil script");</script><div foo="

Кажется, ничего не изменилось, верно?Не совсем.Вот как наша data-href теперь выглядит в итоговом HTML-выводе: page.cfm&#x3f;Id&#x3d;a&#x25;26b&#x25;3D&#x25;22&#x25;3E&#x25;3Cscript&#x25;3Ealert&#x25;28&#x25;22my&#x2b;evil&#x2b;script&#x25;22&#x25;29&#x25;3B&#x25;3C&#x25;2Fscript&#x25;3E&#x25;3Cdiv&#x2b;foo&#x25;3D&#x25;22
Как видите, кодирование процентов теперь дополнительно кодируется для HTML (% было закодировано в его шестнадцатеричное представление * 1077).*).

Заключение

Значение теперь безопасно для обоих контекстов.


Существует больше кодировок, которые могут смешиваться (например, encodeForJavaScript()),Но ты получил идею.Это всегда о том, какие символы в значении требуют, чтобы кодировка была неверно истолкована для их технического назначения.Это может закончиться так, как если бы у вас было от 3 до 4 вложенных кодировок.Но опять же: обычно эти кодировки не конфликтуют друг с другом, поэтому необязательно кодировать их для всех контекстов.

...