libreoffice/CVE-2019-9850_1_2.patch

207 lines
8.5 KiB
Diff
Raw Normal View History

Description: - expand LibreLogo check to global events
- decode url escape codes and check each path segment
- keep name percent-encoded
- expand pyuno path separators
- construct final url from parsed output
Authors: - Caolán McNamara <caolanm@redhat.com>
- Stephan Bergmann <sbergman@redhat.com>
diff --git a/include/sfx2/objsh.hxx b/include/sfx2/objsh.hxx
index b51498905..35b3091e4 100644
--- a/include/sfx2/objsh.hxx
+++ b/include/sfx2/objsh.hxx
@@ -397,6 +397,8 @@ public:
*/
bool AdjustMacroMode();
+ static bool UnTrustedScript(const OUString& rScriptURL);
+
SvKeyValueIterator* GetHeaderAttributes();
void ClearHeaderAttributesForSourceViewHack();
void SetHeaderAttributesForSourceViewHack();
diff --git a/scripting/source/protocolhandler/scripthandler.cxx b/scripting/source/protocolhandler/scripthandler.cxx
index 150ffa052..751099d92 100644
--- a/scripting/source/protocolhandler/scripthandler.cxx
+++ b/scripting/source/protocolhandler/scripthandler.cxx
@@ -47,6 +47,7 @@
#include <com/sun/star/uno/XComponentContext.hpp>
#include <com/sun/star/uri/XUriReference.hpp>
+#include <com/sun/star/uri/XVndSunStarScriptUrlReference.hpp>
#include <com/sun/star/uri/UriReferenceFactory.hpp>
#include <memory>
@@ -133,8 +134,12 @@ void SAL_CALL ScriptProtocolHandler::dispatchWithNotification(
{
try
{
- bool bIsDocumentScript = ( aURL.Complete.indexOf( "document" ) !=-1 );
- // TODO: isn't this somewhat strange? This should be a test for a location=document parameter, shouldn't it?
+ css::uno::Reference<css::uri::XUriReferenceFactory> urifac(
+ css::uri::UriReferenceFactory::create(m_xContext));
+ css::uno::Reference<css::uri::XVndSunStarScriptUrlReference> uri(
+ urifac->parse(aURL.Complete), css::uno::UNO_QUERY_THROW);
+ auto const loc = uri->getParameter("location");
+ bool bIsDocumentScript = loc == "document";
if ( bIsDocumentScript )
{
diff --git a/scripting/source/pyprov/pythonscript.py b/scripting/source/pyprov/pythonscript.py
index f5aa21733..316c5012c 100644
--- a/scripting/source/pyprov/pythonscript.py
+++ b/scripting/source/pyprov/pythonscript.py
@@ -219,10 +219,18 @@ class MyUriHelper:
# path to the .py file + "$functionname, arguments, etc
xStorageUri = self.m_uriRefFac.parse(scriptURI)
- sStorageUri = xStorageUri.getName().replace( "|", "/" );
+ # getName will apply url-decoding to the name, so encode back
+ sStorageUri = xStorageUri.getName().replace("%", "%25")
+ sStorageUri = sStorageUri.replace( "|", "/" )
# path to the .py file, relative to the base
- sFileUri = sStorageUri[0:sStorageUri.find("$")]
+ funcNameStart = sStorageUri.find("$")
+ if funcNameStart != -1:
+ sFileUri = sStorageUri[0:funcNameStart]
+ sFuncName = sStorageUri[funcNameStart+1:]
+ else:
+ sFileUri = sStorageUri
+
xFileUri = self.m_uriRefFac.parse(sFileUri)
if not xFileUri:
message = "pythonscript: invalid relative uri '" + sFileUri+ "'"
@@ -239,7 +247,9 @@ class MyUriHelper:
log.debug( message )
raise RuntimeException( message )
- ret = sBaseUri + sStorageUri
+ ret = sAbsScriptUri
+ if funcNameStart != -1:
+ ret = ret + "$" + sFuncName
log.debug( "converting scriptURI="+scriptURI + " to storageURI=" + ret )
return ret
except UnoException as e:
diff --git a/sfx2/source/doc/objmisc.cxx b/sfx2/source/doc/objmisc.cxx
index 02d79c356..a508aea86 100644
--- a/sfx2/source/doc/objmisc.cxx
+++ b/sfx2/source/doc/objmisc.cxx
@@ -41,6 +41,8 @@
#include <com/sun/star/script/provider/XScriptProvider.hpp>
#include <com/sun/star/script/provider/XScriptProviderSupplier.hpp>
#include <com/sun/star/ucb/SimpleFileAccess.hpp>
+#include <com/sun/star/uri/UriReferenceFactory.hpp>
+#include <com/sun/star/uri/XVndSunStarScriptUrlReference.hpp>
#include <com/sun/star/util/XModifiable.hpp>
#include <toolkit/helper/vclunohelper.hxx>
@@ -1347,14 +1349,36 @@ namespace
}
}
-namespace {
-
// don't allow LibreLogo to be used with our mouseover/etc dom-alike events
-bool UnTrustedScript(const OUString& rScriptURL)
+bool SfxObjectShell::UnTrustedScript(const OUString& rScriptURL)
{
- return rScriptURL.startsWithIgnoreAsciiCase("vnd.sun.star.script:LibreLogo");
-}
+ if (!rScriptURL.startsWith("vnd.sun.star.script:"))
+ return false;
+
+ // ensure URL Escape Codes are decoded
+ css::uno::Reference<css::uri::XUriReference> uri(
+ css::uri::UriReferenceFactory::create(comphelper::getProcessComponentContext())->parse(rScriptURL));
+ css::uno::Reference<css::uri::XVndSunStarScriptUrl> sfUri(uri, css::uno::UNO_QUERY);
+
+ if (!sfUri.is())
+ return false;
+
+ // pyuno encodes path separator as |
+ OUString sScript = sfUri->getName().replace('|', '/');
+ // check if any path portion matches LibreLogo and ban it if it does
+ sal_Int32 nIndex = 0;
+ do
+ {
+ OUString aToken = sScript.getToken(0, '/', nIndex);
+ if (aToken.startsWithIgnoreAsciiCase("LibreLogo"))
+ {
+ return true;
+ }
+ }
+ while (nIndex >= 0);
+
+ return false;
}
ErrCode SfxObjectShell::CallXScript( const Reference< XInterface >& _rxScriptContext, const OUString& _rScriptURL,
@@ -1363,19 +1387,22 @@ ErrCode SfxObjectShell::CallXScript( const Reference< XInterface >& _rxScriptCon
SAL_INFO("sfx", "in CallXScript" );
ErrCode nErr = ERRCODE_NONE;
- bool bIsDocumentScript = ( _rScriptURL.indexOf( "location=document" ) >= 0 );
- // TODO: we should parse the URL, and check whether there is a parameter with this name.
- // Otherwise, we might find too much.
- if ( bIsDocumentScript && !lcl_isScriptAccessAllowed_nothrow( _rxScriptContext ) )
- return ERRCODE_IO_ACCESSDENIED;
-
- if ( UnTrustedScript(_rScriptURL) )
- return ERRCODE_IO_ACCESSDENIED;
-
bool bCaughtException = false;
Any aException;
try
{
+ css::uno::Reference<css::uri::XUriReferenceFactory> urifac(
+ css::uri::UriReferenceFactory::create(comphelper::getProcessComponentContext()));
+ css::uno::Reference<css::uri::XVndSunStarScriptUrlReference> uri(
+ urifac->parse(_rScriptURL), css::uno::UNO_QUERY_THROW);
+ auto const loc = uri->getParameter("location");
+ bool bIsDocumentScript = loc == "document";
+ if ( bIsDocumentScript && !lcl_isScriptAccessAllowed_nothrow( _rxScriptContext ) )
+ return ERRCODE_IO_ACCESSDENIED;
+
+ if ( UnTrustedScript(_rScriptURL) )
+ return ERRCODE_IO_ACCESSDENIED;
+
// obtain/create a script provider
Reference< provider::XScriptProvider > xScriptProvider;
Reference< provider::XScriptProviderSupplier > xSPS( _rxScriptContext, UNO_QUERY );
diff --git a/sfx2/source/notify/eventsupplier.cxx b/sfx2/source/notify/eventsupplier.cxx
index 69076ad01..d18724d74 100644
--- a/sfx2/source/notify/eventsupplier.cxx
+++ b/sfx2/source/notify/eventsupplier.cxx
@@ -209,18 +209,24 @@ void SfxEvents_Impl::Execute( uno::Any const & aEventData, const document::Docum
else if (aType == "Service" ||
aType == "Script")
{
- if ( !aScript.isEmpty() )
+ bool bAllowed = false;
+ util::URL aURL;
+ if (!aScript.isEmpty())
{
- SfxViewFrame* pView = pDoc ?
- SfxViewFrame::GetFirst( pDoc ) :
- SfxViewFrame::Current();
-
uno::Reference < util::XURLTransformer > xTrans( util::URLTransformer::create( ::comphelper::getProcessComponentContext() ) );
- util::URL aURL;
aURL.Complete = aScript;
xTrans->parseStrict( aURL );
+ bAllowed = !SfxObjectShell::UnTrustedScript(aURL.Complete);
+ }
+
+ if (bAllowed)
+ {
+ SfxViewFrame* pView = pDoc ?
+ SfxViewFrame::GetFirst( pDoc ) :
+ SfxViewFrame::Current();
+
uno::Reference
< frame::XDispatchProvider > xProv;