Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(82)

Side by Side Diff: third_party/WebKit/Source/core/html/parser/XSSAuditor.cpp

Issue 2428473004: Remove the 'reflected-xss' directive from CSP. (Closed)
Patch Set: Test. Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2011 Adam Barth. All Rights Reserved. 2 * Copyright (C) 2011 Adam Barth. All Rights Reserved.
3 * Copyright (C) 2011 Daniel Bates (dbates@intudata.com). 3 * Copyright (C) 2011 Daniel Bates (dbates@intudata.com).
4 * 4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions 6 * modification, are permitted provided that the following conditions
7 * are met: 7 * are met:
8 * 1. Redistributions of source code must retain the above copyright 8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright 10 * 2. Redistributions in binary form must reproduce the above copyright
(...skipping 14 matching lines...) Expand all
25 */ 25 */
26 26
27 #include "core/html/parser/XSSAuditor.h" 27 #include "core/html/parser/XSSAuditor.h"
28 28
29 #include "core/HTMLNames.h" 29 #include "core/HTMLNames.h"
30 #include "core/SVGNames.h" 30 #include "core/SVGNames.h"
31 #include "core/XLinkNames.h" 31 #include "core/XLinkNames.h"
32 #include "core/dom/Document.h" 32 #include "core/dom/Document.h"
33 #include "core/frame/LocalFrame.h" 33 #include "core/frame/LocalFrame.h"
34 #include "core/frame/Settings.h" 34 #include "core/frame/Settings.h"
35 #include "core/frame/csp/ContentSecurityPolicy.h"
36 #include "core/html/HTMLParamElement.h" 35 #include "core/html/HTMLParamElement.h"
37 #include "core/html/LinkRelAttribute.h" 36 #include "core/html/LinkRelAttribute.h"
38 #include "core/html/parser/HTMLDocumentParser.h" 37 #include "core/html/parser/HTMLDocumentParser.h"
39 #include "core/html/parser/HTMLParserIdioms.h" 38 #include "core/html/parser/HTMLParserIdioms.h"
40 #include "core/html/parser/TextResourceDecoder.h" 39 #include "core/html/parser/TextResourceDecoder.h"
41 #include "core/html/parser/XSSAuditorDelegate.h" 40 #include "core/html/parser/XSSAuditorDelegate.h"
42 #include "core/inspector/ConsoleMessage.h" 41 #include "core/inspector/ConsoleMessage.h"
43 #include "core/loader/DocumentLoader.h" 42 #include "core/loader/DocumentLoader.h"
44 #include "core/loader/MixedContentChecker.h" 43 #include "core/loader/MixedContentChecker.h"
45 #include "platform/network/EncodedFormData.h" 44 #include "platform/network/EncodedFormData.h"
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after
263 (position = decodedSnippet.find(isNotHTMLSpace<UChar>, position + 1)) != 262 (position = decodedSnippet.find(isNotHTMLSpace<UChar>, position + 1)) !=
264 kNotFound && 263 kNotFound &&
265 (position = decodedSnippet.find( 264 (position = decodedSnippet.find(
266 isTerminatingCharacter, 265 isTerminatingCharacter,
267 isHTMLQuote(decodedSnippet[position]) ? position + 1 : position)) != 266 isHTMLQuote(decodedSnippet[position]) ? position + 1 : position)) !=
268 kNotFound) { 267 kNotFound) {
269 decodedSnippet.truncate(position); 268 decodedSnippet.truncate(position);
270 } 269 }
271 } 270 }
272 271
273 static ReflectedXSSDisposition combineXSSProtectionHeaderAndCSP(
274 ReflectedXSSDisposition xssProtection,
275 ReflectedXSSDisposition reflectedXSS) {
276 ReflectedXSSDisposition result = std::max(xssProtection, reflectedXSS);
277
278 if (result == ReflectedXSSInvalid || result == FilterReflectedXSS ||
279 result == ReflectedXSSUnset)
280 return FilterReflectedXSS;
281
282 return result;
283 }
284
285 static bool isSemicolonSeparatedAttribute( 272 static bool isSemicolonSeparatedAttribute(
286 const HTMLToken::Attribute& attribute) { 273 const HTMLToken::Attribute& attribute) {
287 return threadSafeMatch(attribute.nameAsVector(), SVGNames::valuesAttr); 274 return threadSafeMatch(attribute.nameAsVector(), SVGNames::valuesAttr);
288 } 275 }
289 276
290 static String semicolonSeparatedValueContainingJavaScriptURL( 277 static String semicolonSeparatedValueContainingJavaScriptURL(
291 const String& value) { 278 const String& value) {
292 Vector<String> valueList; 279 Vector<String> valueList;
293 value.split(';', valueList); 280 value.split(';', valueList);
294 for (size_t i = 0; i < valueList.size(); ++i) { 281 for (size_t i = 0; i < valueList.size(); ++i) {
295 String stripped = stripLeadingAndTrailingHTMLSpaces(valueList[i]); 282 String stripped = stripLeadingAndTrailingHTMLSpaces(valueList[i]);
296 if (protocolIsJavaScript(stripped)) 283 if (protocolIsJavaScript(stripped))
297 return stripped; 284 return stripped;
298 } 285 }
299 return emptyString(); 286 return emptyString();
300 } 287 }
301 288
302 XSSAuditor::XSSAuditor() 289 XSSAuditor::XSSAuditor()
303 : m_isEnabled(false), 290 : m_isEnabled(false),
304 m_xssProtection(FilterReflectedXSS), 291 m_xssProtection(FilterReflectedXSS),
305 m_didSendValidCSPHeader(false),
306 m_didSendValidXSSProtectionHeader(false), 292 m_didSendValidXSSProtectionHeader(false),
307 m_state(Uninitialized), 293 m_state(Uninitialized),
308 m_scriptTagFoundInRequest(false), 294 m_scriptTagFoundInRequest(false),
309 m_scriptTagNestingLevel(0), 295 m_scriptTagNestingLevel(0),
310 m_encoding(UTF8Encoding()) { 296 m_encoding(UTF8Encoding()) {
311 // Although tempting to call init() at this point, the various objects 297 // Although tempting to call init() at this point, the various objects
312 // we want to reference might not all have been constructed yet. 298 // we want to reference might not all have been constructed yet.
313 } 299 }
314 300
315 void XSSAuditor::initForFragment() { 301 void XSSAuditor::initForFragment() {
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
359 345
360 if (DocumentLoader* documentLoader = 346 if (DocumentLoader* documentLoader =
361 document->frame()->loader().documentLoader()) { 347 document->frame()->loader().documentLoader()) {
362 const AtomicString& headerValue = 348 const AtomicString& headerValue =
363 documentLoader->response().httpHeaderField(HTTPNames::X_XSS_Protection); 349 documentLoader->response().httpHeaderField(HTTPNames::X_XSS_Protection);
364 String errorDetails; 350 String errorDetails;
365 unsigned errorPosition = 0; 351 unsigned errorPosition = 0;
366 String reportURL; 352 String reportURL;
367 KURL xssProtectionReportURL; 353 KURL xssProtectionReportURL;
368 354
369 // Process the X-XSS-Protection header, then mix in the CSP header's value.
370 ReflectedXSSDisposition xssProtectionHeader = parseXSSProtectionHeader( 355 ReflectedXSSDisposition xssProtectionHeader = parseXSSProtectionHeader(
371 headerValue, errorDetails, errorPosition, reportURL); 356 headerValue, errorDetails, errorPosition, reportURL);
372 357
373 if (xssProtectionHeader == AllowReflectedXSS) 358 if (xssProtectionHeader == AllowReflectedXSS)
374 UseCounter::count(*document, UseCounter::XSSAuditorDisabled); 359 UseCounter::count(*document, UseCounter::XSSAuditorDisabled);
375 else if (xssProtectionHeader == FilterReflectedXSS) 360 else if (xssProtectionHeader == FilterReflectedXSS)
376 UseCounter::count(*document, UseCounter::XSSAuditorEnabledFilter); 361 UseCounter::count(*document, UseCounter::XSSAuditorEnabledFilter);
377 else if (xssProtectionHeader == BlockReflectedXSS) 362 else if (xssProtectionHeader == BlockReflectedXSS)
378 UseCounter::count(*document, UseCounter::XSSAuditorEnabledBlock); 363 UseCounter::count(*document, UseCounter::XSSAuditorEnabledBlock);
379 else if (xssProtectionHeader == ReflectedXSSInvalid) 364 else if (xssProtectionHeader == ReflectedXSSInvalid)
380 UseCounter::count(*document, UseCounter::XSSAuditorInvalid); 365 UseCounter::count(*document, UseCounter::XSSAuditorInvalid);
381 366
382 m_didSendValidXSSProtectionHeader = 367 m_didSendValidXSSProtectionHeader =
383 xssProtectionHeader != ReflectedXSSUnset && 368 xssProtectionHeader != ReflectedXSSUnset &&
384 xssProtectionHeader != ReflectedXSSInvalid; 369 xssProtectionHeader != ReflectedXSSInvalid;
385 if ((xssProtectionHeader == FilterReflectedXSS || 370 if ((xssProtectionHeader == FilterReflectedXSS ||
386 xssProtectionHeader == BlockReflectedXSS) && 371 xssProtectionHeader == BlockReflectedXSS) &&
387 !reportURL.isEmpty()) { 372 !reportURL.isEmpty()) {
388 xssProtectionReportURL = document->completeURL(reportURL); 373 xssProtectionReportURL = document->completeURL(reportURL);
389 if (MixedContentChecker::isMixedContent(document->getSecurityOrigin(), 374 if (MixedContentChecker::isMixedContent(document->getSecurityOrigin(),
390 xssProtectionReportURL)) { 375 xssProtectionReportURL)) {
391 errorDetails = "insecure reporting URL for secure page"; 376 errorDetails = "insecure reporting URL for secure page";
392 xssProtectionHeader = ReflectedXSSInvalid; 377 xssProtectionHeader = ReflectedXSSInvalid;
393 xssProtectionReportURL = KURL(); 378 xssProtectionReportURL = KURL();
394 } 379 }
395 } 380 }
396 if (xssProtectionHeader == ReflectedXSSInvalid) 381 if (xssProtectionHeader == ReflectedXSSInvalid) {
397 document->addConsoleMessage(ConsoleMessage::create( 382 document->addConsoleMessage(ConsoleMessage::create(
398 SecurityMessageSource, ErrorMessageLevel, 383 SecurityMessageSource, ErrorMessageLevel,
399 "Error parsing header X-XSS-Protection: " + headerValue + ": " + 384 "Error parsing header X-XSS-Protection: " + headerValue + ": " +
400 errorDetails + " at character position " + 385 errorDetails + " at character position " +
401 String::format("%u", errorPosition) + 386 String::format("%u", errorPosition) +
402 ". The default protections will be applied.")); 387 ". The default protections will be applied."));
388 }
403 389
404 ReflectedXSSDisposition cspHeader = 390 m_xssProtection = xssProtectionHeader;
405 document->contentSecurityPolicy()->getReflectedXSSDisposition(); 391 if (m_xssProtection == ReflectedXSSInvalid ||
406 m_didSendValidCSPHeader = 392 m_xssProtection == ReflectedXSSUnset) {
407 cspHeader != ReflectedXSSUnset && cspHeader != ReflectedXSSInvalid; 393 m_xssProtection = FilterReflectedXSS;
394 }
408 395
409 m_xssProtection =
410 combineXSSProtectionHeaderAndCSP(xssProtectionHeader, cspHeader);
411 // FIXME: Combine the two report URLs in some reasonable way.
412 if (auditorDelegate) 396 if (auditorDelegate)
413 auditorDelegate->setReportURL(xssProtectionReportURL.copy()); 397 auditorDelegate->setReportURL(xssProtectionReportURL.copy());
414 398
415 EncodedFormData* httpBody = documentLoader->request().httpBody(); 399 EncodedFormData* httpBody = documentLoader->request().httpBody();
416 if (httpBody && !httpBody->isEmpty()) 400 if (httpBody && !httpBody->isEmpty())
417 m_httpBodyAsString = httpBody->flattenToString(); 401 m_httpBodyAsString = httpBody->flattenToString();
418 } 402 }
419 403
420 setEncoding(m_encoding); 404 setEncoding(m_encoding);
421 } 405 }
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
459 else if (m_scriptTagNestingLevel) { 443 else if (m_scriptTagNestingLevel) {
460 if (request.token.type() == HTMLToken::Character) 444 if (request.token.type() == HTMLToken::Character)
461 didBlockScript = filterCharacterToken(request); 445 didBlockScript = filterCharacterToken(request);
462 else if (request.token.type() == HTMLToken::EndTag) 446 else if (request.token.type() == HTMLToken::EndTag)
463 filterEndToken(request); 447 filterEndToken(request);
464 } 448 }
465 449
466 if (didBlockScript) { 450 if (didBlockScript) {
467 bool didBlockEntirePage = (m_xssProtection == BlockReflectedXSS); 451 bool didBlockEntirePage = (m_xssProtection == BlockReflectedXSS);
468 std::unique_ptr<XSSInfo> xssInfo = XSSInfo::create( 452 std::unique_ptr<XSSInfo> xssInfo = XSSInfo::create(
469 m_documentURL, didBlockEntirePage, m_didSendValidXSSProtectionHeader, 453 m_documentURL, didBlockEntirePage, m_didSendValidXSSProtectionHeader);
470 m_didSendValidCSPHeader);
471 return xssInfo; 454 return xssInfo;
472 } 455 }
473 return nullptr; 456 return nullptr;
474 } 457 }
475 458
476 bool XSSAuditor::filterStartToken(const FilterTokenRequest& request) { 459 bool XSSAuditor::filterStartToken(const FilterTokenRequest& request) {
477 m_state = FilteringTokens; 460 m_state = FilteringTokens;
478 bool didBlockScript = eraseDangerousAttributesIfInjected(request); 461 bool didBlockScript = eraseDangerousAttributesIfInjected(request);
479 462
480 if (hasName(request.token, scriptTag)) { 463 if (hasName(request.token, scriptTag)) {
(...skipping 436 matching lines...) Expand 10 before | Expand all | Expand 10 after
917 } 900 }
918 901
919 bool XSSAuditor::isSafeToSendToAnotherThread() const { 902 bool XSSAuditor::isSafeToSendToAnotherThread() const {
920 return m_documentURL.isSafeToSendToAnotherThread() && 903 return m_documentURL.isSafeToSendToAnotherThread() &&
921 m_decodedURL.isSafeToSendToAnotherThread() && 904 m_decodedURL.isSafeToSendToAnotherThread() &&
922 m_decodedHTTPBody.isSafeToSendToAnotherThread() && 905 m_decodedHTTPBody.isSafeToSendToAnotherThread() &&
923 m_httpBodyAsString.isSafeToSendToAnotherThread(); 906 m_httpBodyAsString.isSafeToSendToAnotherThread();
924 } 907 }
925 908
926 } // namespace blink 909 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698