it-swarm.xyz

Нужно ли экранировать get_template_directory_uri ()?

Следует ли экранировать get_template_directory_uri() с помощью esc_url()?

Я спрашиваю, потому что, взяв пример из темы по умолчанию Двадцать пятнадцать, одна и та же функция используется в двух разных местах, но только в одном она экранирована.

wp_enqueue_style( 'twentyfifteen-ie', get_template_directory_uri() . '/css/ie.css', array( 'twentyfifteen-style' ), '20141010' );

-

<script src="<?php echo esc_url( get_template_directory_uri() ); ?>/js/html5.js"></script>

Я бы сказал, что эту get_template_directory_uri() не нужно генерировать, поскольку URL не может быть обработан извне.

6
grappler

В этой функции мы находим крючок:

return apply_filters( 
    'template_directory_uri', 
    $template_dir_uri, 
    $template, 
    $theme_root_uri
);

Так что, да, URI может быть изменен плагинами, и вы должны экранировать его возвращаемое значение.

Тот же принцип применяется ко всем функциям URI WordPress, таким как get_home_url(), get_site_url() и так далее. Имейте в виду, что есть не только хорошие разработчики плагинов. Некоторые делают ошибки, может быть, просто очень мелкие, которые случаются только при некоторых обстоятельствах.

В случае wp_enqueue_style(), WordPress делает экранирует URL по умолчанию. Но это оболочка для экземпляра global WP_Styles, и это, в свою очередь, можно легко заменить - даже на менее безопасную версию. Это не очень вероятно, но вы должны знать об этой возможности.

К сожалению, WP само по себе не следует директиве лучше, чем потом сожалеть. Это даже не избежать переводов. Мой совет не смотреть на ключевые темы для лучших практик. Всегда смотрите на источник данных и посмотрите, могут ли они быть скомпрометированы.

4
fuxia

Постараюсь превратить комментарий swissspidy в ответ. Короткая версия - это зависит.

Экранирование не должно применяться случайным образом, поскольку двойное экранирование может привести к появлению URL-адреса (или любого другого содержимого), который не соответствует предполагаемому URL-адресу. Экранирование должно применяться только перед выводом. Поэтому контекст важнее конкретной функции, которая вычисляет URL.

В вашем примере первый фрагмент просто ставит в очередь URL и не выводит его. Ответственность за экранирование далее делегируется в стек WordPress коду, который на самом деле выводит его, и именно поэтому он не экранирован.

Второй фрагмент выполняет вывод, и именно поэтому URL экранируется.

Итак, как вы узнаете, когда вам следует не бежать? Надеемся, что где-то в будущем документация по Wordpress API будет включать эту информацию, но пока либо следуйте по полному пути кода до фактического вывода, либо протестируйте свою тему под "забавными" URL

2
Mark Kaplun

Вот наша функция под вопросом.

File: wp-includes/theme.php
320: /**
321:  * Retrieve theme directory URI.
322:  *
323:  * @since 1.5.0
324:  *
325:  * @return string Template directory URI.
326:  */
327: function get_template_directory_uri() {
328:    $template = str_replace( '%2F', '/', rawurlencode( get_template() ) );
329:    $theme_root_uri = get_theme_root_uri( $template );
330:    $template_dir_uri = "$theme_root_uri/$template";
331: 
332:    /**
333:     * Filters the current theme directory URI.
334:     *
335:     * @since 1.5.0
336:     *
337:     * @param string $template_dir_uri The URI of the current theme directory.
338:     * @param string $template         Directory name of the current theme.
339:     * @param string $theme_root_uri   The themes root URI.
340:     */
341:    return apply_filters( 'template_directory_uri', $template_dir_uri, $template, $theme_root_uri );
342: }
343: 

Вы пишете что-то вроде этого в своем плагине:

add_filter('template_directory_uri',function(){ return 'http://badserver.com/'; });

И у вас будет что-то вроде этого на сайте:

 enter image description here 

Яркое будущее, потому что я вижу, что класс WP_Theme не реализует фильтр в методе WP_Theme::get_template_directory_uri(). Мы знаем, что WordPress постепенно становится все лучше, лучше и более инкапсулированным.

File: wp-includes/class-wp-theme.php
898:    /**
899:     * Returns the URL to the directory of a theme's "template" files.
900:     *
901:     * In the case of a child theme, this is the URL to the directory of the
902:     * parent theme's files.
903:     *
904:     * @since 3.4.0
905:     * @access public
906:     *
907:     * @return string URL to the template directory.
908:     */
909:    public function get_template_directory_uri() {
910:        if ( $this->parent() )
911:            $theme_root_uri = $this->parent()->get_theme_root_uri();
912:        else
913:            $theme_root_uri = $this->get_theme_root_uri();
914: 
915:        return $theme_root_uri . '/' . str_replace( '%2F', '/', rawurlencode( $this->template ) );
916:    }

Больше заметок

Вы видите, что кто-то определяет в теме что-то вроде этого:

define( 'TEMPL_URI', get_template_directory_uri() );

Они говорят, что это потому, что они хотели бы сделать 'TEMPL_URI' нефильтруемым. Они ошибаются. Если плагин установил плохой фильтр, это произойдет до темы, поэтому 'TEMPL_URI' будет грязным.

Тем не менее, это нормально для определения констант, я просто хотел сказать, что константа не защитит вас.


Еще одна вещь, которую я нашел в Twenty Seventeen. Там я увидел функцию get_theme_file_uri (@since 4.7)

File: wp-includes/link-template.php
4026: /**
4027:  * Retrieves the URL of a file in the theme.
4028:  *
4029:  * Searches in the stylesheet directory before the template directory so themes
4030:  * which inherit from a parent theme can just override one file.
4031:  *
4032:  * @since 4.7.0
4033:  *
4034:  * @param string $file Optional. File to search for in the stylesheet directory.
4035:  * @return string The URL of the file.
4036:  */
4037: function get_theme_file_uri( $file = '' ) {
4038:   $file = ltrim( $file, '/' );
4039: 
4040:   if ( empty( $file ) ) {
4041:       $url = get_stylesheet_directory_uri();
4042:   } elseif ( file_exists( get_stylesheet_directory() . '/' . $file ) ) {
4043:       $url = get_stylesheet_directory_uri() . '/' . $file;
4044:   } else {
4045:       $url = get_template_directory_uri() . '/' . $file;
4046:   }
4047: 
4048:   /**
4049:    * Filters the URL to a file in the theme.
4050:    *
4051:    * @since 4.7.0
4052:    *
4053:    * @param string $url  The file URL.
4054:    * @param string $file The requested file to search for.
4055:    */
4056:   return apply_filters( 'theme_file_uri', $url, $file );
4057: }

Опять же, этот фильтр theme_file_uri может создать проблему безопасности, такую ​​как @toscho для get_template_directory_uri.

Заключение

Когда речь идет о безопасности, мы должны быть очень осторожны. Проблема здесь глубже, чем просто экранирование одного URL. Он рассматривает всю модель безопасности плагинов WordPress .

Плагины не нуждаются в функции get_template_directory_uri() и фильтре, чтобы делать плохие вещи. Они могут работать с теми же привилегиями, что и ядро ​​WordPress - они могут делать все что угодно.

Вредоносный JavaScript, который могут внедрить плохие плагины, может читать ваши пароли при вводе.

0
prosti