Chromium Code Reviews| Index: Source/web/WebEmbeddedWorkerImpl.cpp |
| diff --git a/Source/web/WebEmbeddedWorkerImpl.cpp b/Source/web/WebEmbeddedWorkerImpl.cpp |
| index 7a5166085e9834875fbd5faa1c42ac7c0689b76d..5529a4251f83597dc512bb86337bb7ff4d19dc01 100644 |
| --- a/Source/web/WebEmbeddedWorkerImpl.cpp |
| +++ b/Source/web/WebEmbeddedWorkerImpl.cpp |
| @@ -35,6 +35,7 @@ |
| #include "core/dom/Document.h" |
| #include "core/fetch/SubstituteData.h" |
| #include "core/frame/csp/ContentSecurityPolicy.h" |
| +#include "core/inspector/ConsoleMessage.h" |
| #include "core/inspector/InspectorInstrumentation.h" |
| #include "core/inspector/WorkerDebuggerAgent.h" |
| #include "core/inspector/WorkerInspectorController.h" |
| @@ -69,6 +70,15 @@ |
| namespace blink { |
| +namespace { |
| + |
| + bool IsAmpersandOrEqualsSign(UChar character) |
| + { |
| + return character == '=' || character == '&'; |
| + } |
| + |
| +} // namespace |
| + |
| WebEmbeddedWorker* WebEmbeddedWorker::create(WebServiceWorkerContextClient* client, WebWorkerContentSettingsClientProxy* contentSettingsClient) |
| { |
| return new WebEmbeddedWorkerImpl(adoptPtr(client), adoptPtr(contentSettingsClient)); |
| @@ -309,6 +319,37 @@ void WebEmbeddedWorkerImpl::onScriptLoaderFinished() |
| startWorkerThread(); |
| } |
| +String WebEmbeddedWorkerImpl::checkForReflectedXSS() |
| +{ |
| + ASSERT(m_mainScriptLoader); |
| + |
| + String queryString = m_mainScriptLoader->url().query(); |
| + String script = m_mainScriptLoader->script(); |
| + String segment, decoded; |
| + size_t offset = 0, next; |
| + |
| + do { |
| + next = queryString.find(IsAmpersandOrEqualsSign, offset); |
| + if (next == kNotFound) { |
| + segment = queryString.substring(offset); |
| + } else { |
| + offset = next + 1; |
| + segment = queryString.substring(offset, next - offset); |
| + } |
| + if (segment.sizeInBytes() > 20) { |
|
Tom Sepez
2015/08/31 16:41:19
why 20?
|
| + decoded = decodeURLEscapeSequences(segment); |
| + if (script.contains(segment)) { |
|
Tom Sepez
2015/08/31 16:41:19
what about multiple decodings? e.g. %2525332 etc.
|
| + return segment; |
| + } |
| + if (script.contains(decoded)) { |
| + return decoded; |
| + } |
| + } |
| + } while (next != kNotFound); |
| + |
| + return ""; |
| +} |
| + |
| void WebEmbeddedWorkerImpl::startWorkerThread() |
| { |
| ASSERT(!m_askedToTerminate); |
| @@ -330,11 +371,20 @@ void WebEmbeddedWorkerImpl::startWorkerThread() |
| // We need to set the CSP to both the shadow page's document and the ServiceWorkerGlobalScope. |
| document->initContentSecurityPolicy(m_mainScriptLoader->releaseContentSecurityPolicy()); |
| + // Verify that the query string contains nothing bad. |
| + String script = m_mainScriptLoader->script(); |
| + String potentialXSS = checkForReflectedXSS(); |
| + if (potentialXSS != "") { |
| + document->addConsoleMessage(ConsoleMessage::create(SecurityMessageSource, ErrorMessageLevel, "Service Worker script invocation blocked; contained \"" + potentialXSS + "\", which was a query string parameter.")); |
| + m_workerContextClient->workerContextFailedToStart(); |
| + return; |
| + } |
| + |
| KURL scriptURL = m_mainScriptLoader->url(); |
| OwnPtr<WorkerThreadStartupData> startupData = WorkerThreadStartupData::create( |
| scriptURL, |
| m_workerStartData.userAgent, |
| - m_mainScriptLoader->script(), |
| + script, |
| m_mainScriptLoader->releaseCachedMetadata(), |
| startMode, |
| document->contentSecurityPolicy()->headers(), |