From feebc6d466ba78c5a34b4f6bbdfcce6a0785e709 Mon Sep 17 00:00:00 2001 From: Sebastien SAUVAGE Date: Sun, 3 Mar 2013 22:15:38 +0100 Subject: [PATCH] Corrected vulnerabilities (see report below) Title : Shaarli Vulnerabilities Author : @erwan_lr | @_WPScan_ Vendor : http://sebsauvage.net/wiki/doku.php?id=php:shaarli Download : https://github.com/sebsauvage/Shaarli/archive/master.zip | http://sebsauvage.net/files/shaarli_0.0.40beta.zip Affected versions : master-705F835, 0.0.40-beta (versions below may also be vulnerable) Vulnerabilities : Persistent XSS & Unvalidated Redirects and Forwards Persistent XSS : - During the instalation or configuration modification, the title field is vulnerable. e.g Quotes can not be used because of var_export(), but String.fromCharCode works - The url field of a link is vulnerable : When there is no redirector : javascript:alert(1) Then, the code is triggered when a user click the url of a link Or with a classic XSS : "> Unvalidated Redirects and Forwards : A request with the param linksperpage or privateonly can be used to redirect a user to an arbitrary referer e.g GET /Audit/Shaarli/master-705f835/?linksperpage=10 HTTP/1.1 Host: 127.0.0.1 Referer: https://duckduckgo.com History : March 2, 2013 - Vendor contacted --- index.php | 17 ++++++++++++++--- tpl/linklist.html | 2 +- tpl/page.header.html | 2 +- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/index.php b/index.php index bac5b7d2..224690ef 100644 --- a/index.php +++ b/index.php @@ -1265,7 +1265,11 @@ function renderPage() if (isset($_GET['linksperpage'])) { if (is_numeric($_GET['linksperpage'])) { $_SESSION['LINKS_PER_PAGE']=abs(intval($_GET['linksperpage'])); } - header('Location: '.(empty($_SERVER['HTTP_REFERER'])?'?':$_SERVER['HTTP_REFERER'])); + // Make sure the referer is from Shaarli itself. + $referer = '?'; + if (!empty($_SERVER['HTTP_REFERER']) && strcmp(parse_url($_SERVER['HTTP_REFERER'],PHP_URL_HOST),$_SERVER['SERVER_NAME'])==0) + $referer = $_SERVER['HTTP_REFERER']; + header('Location: '.$referer); exit; } @@ -1280,7 +1284,11 @@ function renderPage() { unset($_SESSION['privateonly']); // See all links } - header('Location: '.(empty($_SERVER['HTTP_REFERER'])?'?':$_SERVER['HTTP_REFERER'])); + // Make sure the referer is from Shaarli itself. + $referer = '?'; + if (!empty($_SERVER['HTTP_REFERER']) && strcmp(parse_url($_SERVER['HTTP_REFERER'],PHP_URL_HOST),$_SERVER['SERVER_NAME'])==0) + $referer = $_SERVER['HTTP_REFERER']; + header('Location: '.$referer); exit; } @@ -1437,7 +1445,10 @@ function renderPage() if (!tokenOk($_POST['token'])) die('Wrong token.'); // Go away ! $tags = trim(preg_replace('/\s\s+/',' ', $_POST['lf_tags'])); // Remove multiple spaces. $linkdate=$_POST['lf_linkdate']; - $link = array('title'=>trim($_POST['lf_title']),'url'=>trim($_POST['lf_url']),'description'=>trim($_POST['lf_description']),'private'=>(isset($_POST['lf_private']) ? 1 : 0), + $url = trim($_POST['lf_url']); + if (!startsWith($url,'http:') && !startsWith($url,'ftp:') && !startsWith($url,'magnet:') && !startsWith($url,'?')) + $url = 'http://'.$url; + $link = array('title'=>trim($_POST['lf_title']),'url'=>$url,'description'=>trim($_POST['lf_description']),'private'=>(isset($_POST['lf_private']) ? 1 : 0), 'linkdate'=>$linkdate,'tags'=>str_replace(',',' ',$tags)); if ($link['title']=='') $link['title']=$link['url']; // If title is empty, use the URL as title. $LINKSDB[$linkdate] = $link; diff --git a/tpl/linklist.html b/tpl/linklist.html index 3a703512..37ffeb64 100644 --- a/tpl/linklist.html +++ b/tpl/linklist.html @@ -40,7 +40,7 @@ {/if} - {$value.title|htmlspecialchars} + {$value.title|htmlspecialchars}
{if="$value.description"}
{$value.description}
{/if} {if="!$GLOBALS['config']['HIDE_TIMESTAMPS'] || isLoggedIn()"} diff --git a/tpl/page.header.html b/tpl/page.header.html index 60fc1767..125b365b 100644 --- a/tpl/page.header.html +++ b/tpl/page.header.html @@ -2,7 +2,7 @@
Shaare your links...
{if="!empty($linkcount)"}{$linkcount} links{/if}
- {$shaarlititle} + {$shaarlititle|htmlspecialchars} {if="!empty($_GET['source']) && $_GET['source']=='bookmarklet'"} {ignore} When called as a popup from bookmarklet, do not display menu. {/ignore} -- 2.41.0