diff --git a/VERSIONS_HOTLINE/114890 b/VERSIONS_HOTLINE/114890 new file mode 100644 index 0000000000000000000000000000000000000000..68aca6244183d82eb3334fb2610a6ef43dd382a6 --- /dev/null +++ b/VERSIONS_HOTLINE/114890 @@ -0,0 +1 @@ + - ticket #114890 : Magasin de thème : correction de failles de sécurité type injection javascript \ No newline at end of file diff --git a/library/templates/Intonation/Library/View/Wrapper/Record.php b/library/templates/Intonation/Library/View/Wrapper/Record.php index 3381989dc9a260056318cb992af22ab217af8222..6193af628ff5bef96d3f63588d65db60dbd66d15 100644 --- a/library/templates/Intonation/Library/View/Wrapper/Record.php +++ b/library/templates/Intonation/Library/View/Wrapper/Record.php @@ -79,7 +79,7 @@ class Intonation_Library_View_Wrapper_Record extends Intonation_Library_View_Wra ->setUrl($this->_view->url(['module' => 'admin', 'controller' => 'records', 'action' => 'thumbnail', - 'id' => $this->_model->getId()])) + 'id' => $this->_model->getId()], null, true)) ->setImage($this->getIco('edit', 'utils')) ->setTitle($this->_('Modifier la vignette de %s', $this->_model->getTitrePrincipal(' '))) ->setClass('menu_admin_front_anchor record_change_thumbnail') @@ -566,7 +566,7 @@ class Intonation_Library_View_Wrapper_Record extends Intonation_Library_View_Wra return (new Intonation_Library_Link) ->setUrl($this->_view->url(['controller' => 'panier', 'action' => 'add-record-ajax', - 'id_notice' => $this->_model->getId()])) + 'id_notice' => $this->_model->getId()], null, true)) ->setImage($this->getIco('add', 'utils')) ->setText($this->_('Ajouter …')) ->setTitle($this->_('Ajouter %s dans une sélection', $this->_model->getTitrePrincipal(' '))) @@ -586,7 +586,7 @@ class Intonation_Library_View_Wrapper_Record extends Intonation_Library_View_Wra ->setUrl($this->_view->url(['module' => 'admin', 'controller' => 'album', 'action' => 'link_album_to', - 'id_notice' => $this->_model->getId()])) + 'id_notice' => $this->_model->getId()], null, true)) ->setImage($this->getIco('media', 'library')) ->setText($this->_('Créer …')) ->setTitle($this->_('Créer un album numérique %s', $this->_model->getTitrePrincipal(' '))) @@ -626,7 +626,7 @@ class Intonation_Library_View_Wrapper_Record extends Intonation_Library_View_Wra $actions [] = (new Intonation_Library_Link) ->setUrl($this->_view->url(['module' => 'admin', 'controller' => 'records', - 'action' => 'reset-thumbnail'])) + 'action' => 'reset-thumbnail'], null, true)) ->setImage($this->getIco('refresh', 'utils')) ->setText($this->_('Générer …')) ->setTitle($this->_('Supprimer et re-générer la vignette de %s', diff --git a/library/templates/Intonation/Library/View/Wrapper/User/RichContent/Loans.php b/library/templates/Intonation/Library/View/Wrapper/User/RichContent/Loans.php index 83a436af4f8793cd975031e476d8cbf76ef19ac8..f09aa2b3d657fcd05c84e90b215912a48484c9e5 100644 --- a/library/templates/Intonation/Library/View/Wrapper/User/RichContent/Loans.php +++ b/library/templates/Intonation/Library/View/Wrapper/User/RichContent/Loans.php @@ -47,7 +47,8 @@ class Intonation_Library_View_Wrapper_User_RichContent_Loans extends Intonation_ return $this->_content = $this->_view->renderAjax('abonne', 'ajax-loans', - ['id' => $this->_model->getId()], + ['id_profil' => Class_Profil::getCurrentProfil()->getId(), + 'id' => $this->_model->getId()], $js); } diff --git a/library/templates/Intonation/View/Admin/TagConfigAction.php b/library/templates/Intonation/View/Admin/TagConfigAction.php index 20ededee376f703e29a6925299b4288219a54410..eea944a2ab26b4accadf9a66db14824d0f591a55 100644 --- a/library/templates/Intonation/View/Admin/TagConfigAction.php +++ b/library/templates/Intonation/View/Admin/TagConfigAction.php @@ -72,7 +72,7 @@ class Intonation_View_Admin_TagConfigAction extends ZendAfi_View_Helper_BaseHelp $this->_('Modifier la configuration de %s %s ', $this->view->_current_module['controller'], $this->view->_current_module['action']), - $this->view->url($url_params), null, true); + $this->view->url($url_params, null, true)); } diff --git a/library/templates/Intonation/View/Jumbotron.php b/library/templates/Intonation/View/Jumbotron.php index b4aef538a70ea22bab9e47e4b7afce2b4ae1748a..5838042adf493c8d0e5c0ecaecb19f2f0cb437b9 100644 --- a/library/templates/Intonation/View/Jumbotron.php +++ b/library/templates/Intonation/View/Jumbotron.php @@ -143,8 +143,8 @@ class Intonation_View_Jumbotron extends ZendAfi_View_Helper_BaseHelper { return $this->_tag('li', - $this->view->tagAnchor(array_merge($item->getNavUrl(), - ['id' => $id]), + $this->view->tagAnchor($this->view->url(array_merge($item->getNavUrl(), + ['id' => $id])), implode($html), $params), ['class' => sprintf('nav-item wrapper_%s wrapper_%s', diff --git a/library/templates/Intonation/View/RenderAjax.php b/library/templates/Intonation/View/RenderAjax.php index 8dc2469e082e553787ed39566f6d8c14ef4d818d..bf379831a04a9ad8068f511b800aca7d0a9b141b 100644 --- a/library/templates/Intonation/View/RenderAjax.php +++ b/library/templates/Intonation/View/RenderAjax.php @@ -42,7 +42,7 @@ class Intonation_View_RenderAjax extends ZendAfi_View_Helper_BaseHelper { ->beAjax() ->addJQueryReady(sprintf('$("#%s").load("%s", function() {%s});', $id, - $this->view->url($url), + $this->view->url($url, null, true), $js_callback)); return $this->_div(['id' => $id, diff --git a/library/templates/Intonation/View/Search/HtmlCriteria.php b/library/templates/Intonation/View/Search/HtmlCriteria.php index 9035ae24de7440ff65bc7a8d6563fd62cf2abbf1..2fc6b51727758654b5c8afdca489fdc7ea80465b 100644 --- a/library/templates/Intonation/View/Search/HtmlCriteria.php +++ b/library/templates/Intonation/View/Search/HtmlCriteria.php @@ -92,12 +92,13 @@ class Intonation_View_Search_HtmlCriteria extends ZendAfi_View_Helper_TagCritere if (isset($url['page'])) unset($url['page']); + $criteria_label = $this->view->escape($label); return $this->view ->tagAction((new Intonation_Library_Link) ->setUrl($this->view->url($url, null, true)) ->setImage($this->view->templateIco('clean', 'utils')) - ->setText($label) - ->setTitle($this->_('Retirer le critère: %s', $label)) + ->setText($criteria_label) + ->setTitle($this->_('Retirer le critère: %s', $criteria_label)) ->setClass('active_criteria') ->beNotResponsiveText()); } @@ -141,4 +142,4 @@ class Intonation_View_Search_HtmlCriteria extends ZendAfi_View_Helper_TagCritere $attribs = ['class' => 'd-inline text-left align-items-center']; return parent::htmlAppend($text, $attribs); } -} \ No newline at end of file +} diff --git a/library/templates/Intonation/View/Search/Result.php b/library/templates/Intonation/View/Search/Result.php index 641b8a9ac8df33089d22f5610755213033c036ab..34348f440b4a54aa1f7168a4f209655c250f4789 100644 --- a/library/templates/Intonation/View/Search/Result.php +++ b/library/templates/Intonation/View/Search/Result.php @@ -52,7 +52,7 @@ class Intonation_View_Search_Result extends ZendAfi_View_Helper_BaseHelper { $facets = $this->_renderFacets($this->_facetsContent()); $html_criteria = $this->_searchCriteriaButtons(); - $text_criteria = $this->view->search_TextCriteria($criteria); + $text_criteria = $this->view->escape($this->view->search_TextCriteria($criteria)); $title_from_url = $this->view->titre ? $this->view->titre : '*'; @@ -116,7 +116,7 @@ class Intonation_View_Search_Result extends ZendAfi_View_Helper_BaseHelper { protected function _getTitle($title_from_url, $text_criteria) { if ($this->_criteria->hasExpressionRecherche()) return $this->_('Résultat pour %s %s', - strtolower($this->_criteria->getExpressionRecherche()), + strtolower($this->view->escape($this->_criteria->getExpressionRecherche())), strtolower($text_criteria)); return $this->_('Résultat %s', diff --git a/tests/scenarios/Security/SearchInTemplatesTest.php b/tests/scenarios/Security/SearchInTemplatesTest.php new file mode 100644 index 0000000000000000000000000000000000000000..d767605264db70219ab4fbe3693d394e06e1cb9a --- /dev/null +++ b/tests/scenarios/Security/SearchInTemplatesTest.php @@ -0,0 +1,66 @@ +<?php +/** + * Copyright (c) 2012-2021, Agence Française Informatique (AFI). All rights reserved. + * + * BOKEH is free software; you can redistribute it and/or modify + * it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE as published by + * the Free Software Foundation. + * + * There are special exceptions to the terms and conditions of the AGPL as it + * is applied to this software (see README file). + * + * BOKEH is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU AFFERO GENERAL PUBLIC LICENSE for more details. + * + * You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE + * along with BOKEH; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +require_once(__DIR__ . '/SearchTest.php'); + + +class Security_SearchInTemplateTest extends Security_SearchTest { + public function setUp() { + parent::setUp(); + $this->_buildTemplateProfil(['id' => 12]); + $this->_default_params['id_profil'] = 12; + } +} + + + + +class Security_SearchInTemplatesViewNoticeJsXssTest extends Security_SearchViewNoticeTestCase { + public function setUp() { + parent::setUp(); + $this->_buildTemplateProfil(['id' => 12]); + $this->dispatch('/recherche/viewnotice/id/1/id_profil/12/%27%3bqxss(document.cookie)%3b%27'); + } + + + /** @test */ + public function jsParamInUrlShouldNotBeInjectedInInfoBlocs() { + $this->assertNotXPathContentContains('//script', 'qxss(document.cookie)'); + } + + + /** @test */ + public function pageTextNodesShouldNotContainsAnyQXSS() { + $this->assertNotXPath('//*[contains(text(), "qxss")]'); + } + + + /** @test */ + public function noOnLoadAttributesShouldContainsAnyQXSS() { + $this->assertNotXPath('//*[contains(@onload, "qxss")]'); + } + + + /** @test */ + public function noOnClickAttributesShouldContainsAnyQXSS() { + $this->assertNotXPath('//*[contains(@onclick, "qxss")]'); + } +} diff --git a/tests/scenarios/Security/SearchTest.php b/tests/scenarios/Security/SearchTest.php index 6c8b27b7b23c9bf4bc33ff2125294a5c51ec057e..690ab3594689cf5e4fdb3d4252f5a09b1ac7a631 100644 --- a/tests/scenarios/Security/SearchTest.php +++ b/tests/scenarios/Security/SearchTest.php @@ -186,7 +186,7 @@ class Security_SearchViewNoticeJsXssTest extends Security_SearchViewNoticeTestCa /** @test */ public function pageShouldNotContainsAnyQXSS() { - $this->assertNotContains('qxss('); + $this->assertNotContains('qxss(', $this->_response->getBody()); } diff --git a/tests/scenarios/Templates/TemplatesWidgetTest.php b/tests/scenarios/Templates/TemplatesWidgetTest.php index 2cfcb639c63aa578fbdf1dda7834990257bb2afe..d341934df2f5cbfde74333997751114104380825 100644 --- a/tests/scenarios/Templates/TemplatesWidgetTest.php +++ b/tests/scenarios/Templates/TemplatesWidgetTest.php @@ -1254,7 +1254,7 @@ class TemplatesDispatchAdminWidgetEditActionTest extends TemplatesIntonationTest /** @test */ public function dispatchModuleShouldContainsExpectation() { $this->dispatch('/opac/abonne/fiche/id_profil/72'); - $this->assertXPath('//a[contains(@href, "/admin/widget/edit-action/id_profil/72/id/abonne_fiche")]'); + $this->assertXPath('//a[contains(@href, "/admin/widget/edit-action/id/abonne_fiche/id_profil/72")]'); } @@ -1831,4 +1831,4 @@ class TemplatesWidgetWithTopHighlightLayoutAndCycleTest extends AbstractTemplate public function carouselDataIntervalShouldBeTwoSecond() { $this->assertXPath('//div[contains(@class, "boite library")]//div[contains(@class, "carousel slide top_highlight_carousel")][@data-interval="2000"]'); } -} \ No newline at end of file +}