Какой EncodeFor для данных - атрибуты с URL

Я пытаюсь вставить 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 ответ

Решение

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

Вообще не кодирует

<!--- 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 (% был закодирован в его шестнадцатеричном представлении &#x25;).

Заключение

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


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

Другие вопросы по тегам