| OLD | NEW |
| 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 426 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 437 else if (hasName(request.token, metaTag)) | 437 else if (hasName(request.token, metaTag)) |
| 438 didBlockScript |= filterMetaToken(request); | 438 didBlockScript |= filterMetaToken(request); |
| 439 else if (hasName(request.token, baseTag)) | 439 else if (hasName(request.token, baseTag)) |
| 440 didBlockScript |= filterBaseToken(request); | 440 didBlockScript |= filterBaseToken(request); |
| 441 else if (hasName(request.token, formTag)) | 441 else if (hasName(request.token, formTag)) |
| 442 didBlockScript |= filterFormToken(request); | 442 didBlockScript |= filterFormToken(request); |
| 443 else if (hasName(request.token, inputTag)) | 443 else if (hasName(request.token, inputTag)) |
| 444 didBlockScript |= filterInputToken(request); | 444 didBlockScript |= filterInputToken(request); |
| 445 else if (hasName(request.token, buttonTag)) | 445 else if (hasName(request.token, buttonTag)) |
| 446 didBlockScript |= filterButtonToken(request); | 446 didBlockScript |= filterButtonToken(request); |
| 447 else if (hasName(request.token, linkTag)) |
| 448 didBlockScript |= filterLinkToken(request); |
| 447 | 449 |
| 448 return didBlockScript; | 450 return didBlockScript; |
| 449 } | 451 } |
| 450 | 452 |
| 451 void XSSAuditor::filterEndToken(const FilterTokenRequest& request) | 453 void XSSAuditor::filterEndToken(const FilterTokenRequest& request) |
| 452 { | 454 { |
| 453 ASSERT(m_scriptTagNestingLevel); | 455 ASSERT(m_scriptTagNestingLevel); |
| 454 m_state = FilteringTokens; | 456 m_state = FilteringTokens; |
| 455 if (hasName(request.token, scriptTag)) { | 457 if (hasName(request.token, scriptTag)) { |
| 456 m_scriptTagNestingLevel--; | 458 m_scriptTagNestingLevel--; |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 593 } | 595 } |
| 594 | 596 |
| 595 bool XSSAuditor::filterButtonToken(const FilterTokenRequest& request) | 597 bool XSSAuditor::filterButtonToken(const FilterTokenRequest& request) |
| 596 { | 598 { |
| 597 ASSERT(request.token.type() == HTMLToken::StartTag); | 599 ASSERT(request.token.type() == HTMLToken::StartTag); |
| 598 ASSERT(hasName(request.token, buttonTag)); | 600 ASSERT(hasName(request.token, buttonTag)); |
| 599 | 601 |
| 600 return eraseAttributeIfInjected(request, formactionAttr, kURLWithUniqueOrigi
n, SrcLikeAttributeTruncation); | 602 return eraseAttributeIfInjected(request, formactionAttr, kURLWithUniqueOrigi
n, SrcLikeAttributeTruncation); |
| 601 } | 603 } |
| 602 | 604 |
| 605 bool XSSAuditor::filterLinkToken(const FilterTokenRequest& request) |
| 606 { |
| 607 ASSERT(request.token.type() == HTMLToken::StartTag); |
| 608 ASSERT(hasName(request.token, linkTag)); |
| 609 |
| 610 size_t indexOfAttribute = 0; |
| 611 if (!findAttributeWithName(request.token, relAttr, indexOfAttribute)) |
| 612 return false; |
| 613 |
| 614 const HTMLToken::Attribute& attribute = request.token.attributes().at(indexO
fAttribute); |
| 615 if (!equalIgnoringCase(String(attribute.value), "import")) |
| 616 return false; |
| 617 |
| 618 return eraseAttributeIfInjected(request, hrefAttr, kURLWithUniqueOrigin, Src
LikeAttributeTruncation, AllowSameOriginHref); |
| 619 } |
| 620 |
| 603 bool XSSAuditor::eraseDangerousAttributesIfInjected(const FilterTokenRequest& re
quest) | 621 bool XSSAuditor::eraseDangerousAttributesIfInjected(const FilterTokenRequest& re
quest) |
| 604 { | 622 { |
| 605 DEFINE_STATIC_LOCAL(String, safeJavaScriptURL, ("javascript:void(0)")); | 623 DEFINE_STATIC_LOCAL(String, safeJavaScriptURL, ("javascript:void(0)")); |
| 606 | 624 |
| 607 bool didBlockScript = false; | 625 bool didBlockScript = false; |
| 608 for (size_t i = 0; i < request.token.attributes().size(); ++i) { | 626 for (size_t i = 0; i < request.token.attributes().size(); ++i) { |
| 609 bool eraseAttribute = false; | 627 bool eraseAttribute = false; |
| 610 bool valueContainsJavaScriptURL = false; | 628 bool valueContainsJavaScriptURL = false; |
| 611 const HTMLToken::Attribute& attribute = request.token.attributes().at(i)
; | 629 const HTMLToken::Attribute& attribute = request.token.attributes().at(i)
; |
| 612 // FIXME: Don't create a new String for every attribute.value in the doc
ument. | 630 // FIXME: Don't create a new String for every attribute.value in the doc
ument. |
| (...skipping 13 matching lines...) Expand all Loading... |
| 626 if (!eraseAttribute) | 644 if (!eraseAttribute) |
| 627 continue; | 645 continue; |
| 628 request.token.eraseValueOfAttribute(i); | 646 request.token.eraseValueOfAttribute(i); |
| 629 if (valueContainsJavaScriptURL) | 647 if (valueContainsJavaScriptURL) |
| 630 request.token.appendToAttributeValue(i, safeJavaScriptURL); | 648 request.token.appendToAttributeValue(i, safeJavaScriptURL); |
| 631 didBlockScript = true; | 649 didBlockScript = true; |
| 632 } | 650 } |
| 633 return didBlockScript; | 651 return didBlockScript; |
| 634 } | 652 } |
| 635 | 653 |
| 636 bool XSSAuditor::eraseAttributeIfInjected(const FilterTokenRequest& request, con
st QualifiedName& attributeName, const String& replacementValue, TruncationKind
treatment) | 654 bool XSSAuditor::eraseAttributeIfInjected(const FilterTokenRequest& request, con
st QualifiedName& attributeName, const String& replacementValue, TruncationKind
treatment, HrefRestriction restriction) |
| 637 { | 655 { |
| 638 size_t indexOfAttribute = 0; | 656 size_t indexOfAttribute = 0; |
| 639 if (!findAttributeWithName(request.token, attributeName, indexOfAttribute)) | 657 if (!findAttributeWithName(request.token, attributeName, indexOfAttribute)) |
| 640 return false; | 658 return false; |
| 641 | 659 |
| 642 const HTMLToken::Attribute& attribute = request.token.attributes().at(indexO
fAttribute); | 660 const HTMLToken::Attribute& attribute = request.token.attributes().at(indexO
fAttribute); |
| 643 if (!isContainedInRequest(canonicalize(snippetFromAttribute(request, attribu
te), treatment))) | 661 if (!isContainedInRequest(canonicalize(snippetFromAttribute(request, attribu
te), treatment))) |
| 644 return false; | 662 return false; |
| 645 | 663 |
| 646 if (threadSafeMatch(attributeName, srcAttr)) { | 664 if (threadSafeMatch(attributeName, srcAttr) || (restriction == AllowSameOrig
inHref && threadSafeMatch(attributeName, hrefAttr))) { |
| 647 if (isLikelySafeResource(String(attribute.value))) | 665 if (isLikelySafeResource(String(attribute.value))) |
| 648 return false; | 666 return false; |
| 649 } else if (threadSafeMatch(attributeName, http_equivAttr)) { | 667 } else if (threadSafeMatch(attributeName, http_equivAttr)) { |
| 650 if (!isDangerousHTTPEquiv(String(attribute.value))) | 668 if (!isDangerousHTTPEquiv(String(attribute.value))) |
| 651 return false; | 669 return false; |
| 652 } | 670 } |
| 653 | 671 |
| 654 request.token.eraseValueOfAttribute(indexOfAttribute); | 672 request.token.eraseValueOfAttribute(indexOfAttribute); |
| 655 if (!replacementValue.isEmpty()) | 673 if (!replacementValue.isEmpty()) |
| 656 request.token.appendToAttributeValue(indexOfAttribute, replacementValue)
; | 674 request.token.appendToAttributeValue(indexOfAttribute, replacementValue)
; |
| (...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 805 | 823 |
| 806 bool XSSAuditor::isSafeToSendToAnotherThread() const | 824 bool XSSAuditor::isSafeToSendToAnotherThread() const |
| 807 { | 825 { |
| 808 return m_documentURL.isSafeToSendToAnotherThread() | 826 return m_documentURL.isSafeToSendToAnotherThread() |
| 809 && m_decodedURL.isSafeToSendToAnotherThread() | 827 && m_decodedURL.isSafeToSendToAnotherThread() |
| 810 && m_decodedHTTPBody.isSafeToSendToAnotherThread() | 828 && m_decodedHTTPBody.isSafeToSendToAnotherThread() |
| 811 && m_httpBodyAsString.isSafeToSendToAnotherThread(); | 829 && m_httpBodyAsString.isSafeToSendToAnotherThread(); |
| 812 } | 830 } |
| 813 | 831 |
| 814 } // namespace blink | 832 } // namespace blink |
| OLD | NEW |