这是indexloc提供的服务,不要输入任何密码
| Differences between
and this patch
- Source/WebCore/ChangeLog +52 lines
Lines 1-3 Source/WebCore/ChangeLog_sec1
1
2016-12-01  John Wilander  <wilander@apple.com>
2
3
        Require preflight for non-standard CORS-safelisted request headers Accept, Accept-Language, and Content-Language
4
        https://bugs.webkit.org/show_bug.cgi?id=165178
5
        <rdar://problem/18792250>
6
7
        Reviewed by NOBODY (OOPS!).
8
9
        Fetch currently only restricts the header Content-Type for simple requests:
10
        https://fetch.spec.whatwg.org/#cors-safelisted-request-header
11
12
        This means simple CORS requests can send unexpected characters in Accept, 
13
        Accept-Language, and Content-Language header values.
14
15
        RFC 7231 implies restrictions on these header values:
16
        - Accept https://tools.ietf.org/html/rfc7231#section-5.3.2
17
        - Accept-Language https://tools.ietf.org/html/rfc7231#section-5.3.5
18
        - Content-Language https://tools.ietf.org/html/rfc7231#section-3.1.3.2
19
20
        As per discussions in the W3C WebAppSec group we should try to restrict 
21
        these header values to help protect servers that do not expect simple CORS 
22
        requests.
23
24
        Non-standard, safelisted header values should trigger a preflight and require
25
        the headers to be whitelisted in the response's Access-Control-Allow-Headers.
26
        For Fetch in no-cors mode this change means non-standard header values are not
27
        allowed to be set.
28
29
        Test: http/tests/xmlhttprequest/cors-non-standard-safelisted-headers-should-trigger-preflight.html
30
31
        * loader/CrossOriginAccessControl.cpp:
32
        (WebCore::isOnAccessControlSimpleRequestHeaderWhitelist):
33
            Now makes a call to WebCore::isValidAcceptHeaderValue() for Accept
34
            headers and WebCore::isValidLanguageHeaderValue() for Accept-Language 
35
            and Content-Language headers.
36
        * platform/network/HTTPParsers.cpp:
37
        (WebCore::isValidAcceptHeaderValue):
38
            Basic check that the characters are all ASCII alphanumeric, ' ', '*', '.',
39
            '/', ';', or '='.
40
        (WebCore::isValidLanguageHeaderValue):
41
            Basic check that the characters are all ASCII alphanumeric, ' ', '*', '-',
42
            '.', ';', or '='.
43
        (WebCore::isSimpleHeader):
44
            Now makes a call to WebCore::isValidAcceptHeaderValue() for Accept
45
            headers and WebCore::isValidLanguageHeaderValue() for Accept-Language
46
            and Content-Language headers.
47
        (WebCore::isCrossOriginSafeRequestHeader):
48
            Now makes a call to WebCore::isValidAcceptHeaderValue() for Accept
49
            headers and WebCore::isValidLanguageHeaderValue() for Accept-Language
50
            and Content-Language headers.
51
        * platform/network/HTTPParsers.h:
52
1
2016-11-30  Sam Weinig  <sam@webkit.org>
53
2016-11-30  Sam Weinig  <sam@webkit.org>
2
54
3
        [WebIDL] Remove custom bindings for File and Blob constructors
55
        [WebIDL] Remove custom bindings for File and Blob constructors
- Source/WebCore/loader/CrossOriginAccessControl.cpp -1 / +2 lines
Lines 49-57 bool isOnAccessControlSimpleRequestHeade Source/WebCore/loader/CrossOriginAccessControl.cpp_sec1
49
{
49
{
50
    switch (name) {
50
    switch (name) {
51
    case HTTPHeaderName::Accept:
51
    case HTTPHeaderName::Accept:
52
        return isValidAcceptHeaderValue(value);
52
    case HTTPHeaderName::AcceptLanguage:
53
    case HTTPHeaderName::AcceptLanguage:
53
    case HTTPHeaderName::ContentLanguage:
54
    case HTTPHeaderName::ContentLanguage:
54
        return true;
55
        return isValidLanguageHeaderValue(value);
55
    case HTTPHeaderName::ContentType: {
56
    case HTTPHeaderName::ContentType: {
56
        // Preflight is required for MIME types that can not be sent via form submission.
57
        // Preflight is required for MIME types that can not be sent via form submission.
57
        String mimeType = extractMIMETypeFromMediaType(value);
58
        String mimeType = extractMIMETypeFromMediaType(value);
- Source/WebCore/platform/network/HTTPParsers.cpp -3 / +36 lines
Lines 34-39 Source/WebCore/platform/network/HTTPParsers.cpp_sec1
34
#include "HTTPParsers.h"
34
#include "HTTPParsers.h"
35
35
36
#include "HTTPHeaderNames.h"
36
#include "HTTPHeaderNames.h"
37
#include "Language.h"
37
#include <wtf/DateMath.h>
38
#include <wtf/DateMath.h>
38
#include <wtf/NeverDestroyed.h>
39
#include <wtf/NeverDestroyed.h>
39
#include <wtf/text/CString.h>
40
#include <wtf/text/CString.h>
Lines 126-131 bool isValidHTTPHeaderValue(const String Source/WebCore/platform/network/HTTPParsers.cpp_sec2
126
    return true;
127
    return true;
127
}
128
}
128
129
130
// See RFC 7231, Section 5.3.2
131
bool isValidAcceptHeaderValue(const String& value)
132
{
133
    for (unsigned i = 0; i < value.length(); ++i) {
134
        UChar c = value[i];
135
        if (isASCIIAlphanumeric(c) || c == ' ' || c == '*' || c == '.' || c == '/' || c == ';' || c == '=')
136
            continue;
137
        return false;
138
    }
139
    
140
    return true;
141
}
142
143
// See RFC 7231, Section 5.3.5 and 3.1.3.2
144
bool isValidLanguageHeaderValue(const String& value)
145
{
146
    for (unsigned i = 0; i < value.length(); ++i) {
147
        UChar c = value[i];
148
        if (isASCIIAlphanumeric(c) || c == ' ' || c == '*' || c == '-' || c == '.' || c == ';' || c == '=')
149
            continue;
150
        return false;
151
    }
152
    
153
    // FIXME: Validate further by splitting into language tags and optional quality
154
    // values (q=) and then check each language tag.
155
    // Language tags https://tools.ietf.org/html/rfc7231#section-3.1.3.1
156
    // Language tag syntax https://tools.ietf.org/html/bcp47#section-2.1
157
    return true;
158
}
159
129
// See RFC 7230, Section 3.2.6.
160
// See RFC 7230, Section 3.2.6.
130
bool isValidHTTPToken(const String& value)
161
bool isValidHTTPToken(const String& value)
131
{
162
{
Lines 732-738 void parseAccessControlExposeHeadersAllo Source/WebCore/platform/network/HTTPParsers.cpp_sec3
732
    }
763
    }
733
}
764
}
734
765
735
// Implememtnation of https://fetch.spec.whatwg.org/#cors-safelisted-response-header-name
766
// Implementation of https://fetch.spec.whatwg.org/#cors-safelisted-response-header-name
736
bool isForbiddenHeaderName(const String& name)
767
bool isForbiddenHeaderName(const String& name)
737
{
768
{
738
    HTTPHeaderName headerName;
769
    HTTPHeaderName headerName;
Lines 778-786 bool isSimpleHeader(const String& name, Source/WebCore/platform/network/HTTPParsers.cpp_sec4
778
        return false;
809
        return false;
779
    switch (headerName) {
810
    switch (headerName) {
780
    case HTTPHeaderName::Accept:
811
    case HTTPHeaderName::Accept:
812
        return isValidAcceptHeaderValue(value);
781
    case HTTPHeaderName::AcceptLanguage:
813
    case HTTPHeaderName::AcceptLanguage:
782
    case HTTPHeaderName::ContentLanguage:
814
    case HTTPHeaderName::ContentLanguage:
783
        return true;
815
        return isValidLanguageHeaderValue(value);
784
    case HTTPHeaderName::ContentType: {
816
    case HTTPHeaderName::ContentType: {
785
        String mimeType = extractMIMETypeFromMediaType(value);
817
        String mimeType = extractMIMETypeFromMediaType(value);
786
        return equalLettersIgnoringASCIICase(mimeType, "application/x-www-form-urlencoded") || equalLettersIgnoringASCIICase(mimeType, "multipart/form-data") || equalLettersIgnoringASCIICase(mimeType, "text/plain");
818
        return equalLettersIgnoringASCIICase(mimeType, "application/x-www-form-urlencoded") || equalLettersIgnoringASCIICase(mimeType, "multipart/form-data") || equalLettersIgnoringASCIICase(mimeType, "text/plain");
Lines 824-832 bool isCrossOriginSafeRequestHeader(HTTP Source/WebCore/platform/network/HTTPParsers.cpp_sec5
824
{
856
{
825
    switch (name) {
857
    switch (name) {
826
    case HTTPHeaderName::Accept:
858
    case HTTPHeaderName::Accept:
859
        return isValidAcceptHeaderValue(value);
827
    case HTTPHeaderName::AcceptLanguage:
860
    case HTTPHeaderName::AcceptLanguage:
828
    case HTTPHeaderName::ContentLanguage:
861
    case HTTPHeaderName::ContentLanguage:
829
        return true;
862
        return isValidLanguageHeaderValue(value);
830
    case HTTPHeaderName::ContentType: {
863
    case HTTPHeaderName::ContentType: {
831
        String mimeType = extractMIMETypeFromMediaType(value);
864
        String mimeType = extractMIMETypeFromMediaType(value);
832
        return equalLettersIgnoringASCIICase(mimeType, "application/x-www-form-urlencoded") || equalLettersIgnoringASCIICase(mimeType, "multipart/form-data") || equalLettersIgnoringASCIICase(mimeType, "text/plain");
865
        return equalLettersIgnoringASCIICase(mimeType, "application/x-www-form-urlencoded") || equalLettersIgnoringASCIICase(mimeType, "multipart/form-data") || equalLettersIgnoringASCIICase(mimeType, "text/plain");
- Source/WebCore/platform/network/HTTPParsers.h +2 lines
Lines 69-74 enum XFrameOptionsDisposition { Source/WebCore/platform/network/HTTPParsers.h_sec1
69
69
70
bool isValidReasonPhrase(const String&);
70
bool isValidReasonPhrase(const String&);
71
bool isValidHTTPHeaderValue(const String&);
71
bool isValidHTTPHeaderValue(const String&);
72
bool isValidAcceptHeaderValue(const String&);
73
bool isValidLanguageHeaderValue(const String&);
72
bool isValidHTTPToken(const String&);
74
bool isValidHTTPToken(const String&);
73
bool parseHTTPRefresh(const String& refresh, double& delay, String& url);
75
bool parseHTTPRefresh(const String& refresh, double& delay, String& url);
74
std::optional<std::chrono::system_clock::time_point> parseHTTPDate(const String&);
76
std::optional<std::chrono::system_clock::time_point> parseHTTPDate(const String&);
- LayoutTests/ChangeLog +39 lines
Lines 1-3 LayoutTests/ChangeLog_sec1
1
2016-12-01  John Wilander  <wilander@apple.com>
2
3
        Require preflight for non-standard CORS-safelisted request headers Accept, Accept-Language, and Content-Language
4
        https://bugs.webkit.org/show_bug.cgi?id=165178
5
        <rdar://problem/18792250>
6
7
        Reviewed by NOBODY (OOPS!).
8
9
        Fetch currently only restricts the header Content-Type for simple requests:
10
        https://fetch.spec.whatwg.org/#cors-safelisted-request-header
11
12
        This means simple CORS requests can send unexpected characters in Accept, 
13
        Accept-Language, and Content-Language header values.
14
15
        RFC 7231 implies restrictions on these header values:
16
        - Accept https://tools.ietf.org/html/rfc7231#section-5.3.2
17
        - Accept-Language https://tools.ietf.org/html/rfc7231#section-5.3.5
18
        - Content-Language https://tools.ietf.org/html/rfc7231#section-3.1.3.2
19
20
        As per discussions in the W3C WebAppSec group we should try to restrict 
21
        these header values to help protect servers that do not expect simple CORS 
22
        requests.
23
24
        Non-standard, safelisted header values should trigger a preflight and require
25
        the headers to be whitelisted in the response's Access-Control-Allow-Headers.
26
        For Fetch in no-cors mode this change means non-standard header values are not
27
        allowed to be set.
28
29
        * http/tests/xmlhttprequest/cors-non-standard-safelisted-headers-should-trigger-preflight-expected.txt: Added.
30
        * http/tests/xmlhttprequest/cors-non-standard-safelisted-headers-should-trigger-preflight.html: Added.
31
            Tests that:
32
            - Normal Accept, Accept-Language, and Content-Language headers don't trigger
33
                a preflight.
34
            - Abnormal Accept, Accept-Language, and Content-Language headers do trigger 
35
                a preflight.
36
            - Abnormal Accept, Accept-Language, and Content-Language headers are 
37
                accepted if the server whitelists them.
38
        * http/tests/xmlhttprequest/resources/cors-preflight-safelisted-headers-responder.php: Added.
39
1
2016-12-01  Antoine Quint  <graouts@apple.com>
40
2016-12-01  Antoine Quint  <graouts@apple.com>
2
41
3
        [Modern Media Controls] Provide a UI object to show a list of tracks
42
        [Modern Media Controls] Provide a UI object to show a list of tracks
- LayoutTests/http/tests/xmlhttprequest/cors-non-standard-safelisted-headers-should-trigger-preflight-expected.txt +18 lines
Line 0 LayoutTests/http/tests/xmlhttprequest/cors-non-standard-safelisted-headers-should-trigger-preflight-expected.txt_sec1
1
CONSOLE MESSAGE: XMLHttpRequest cannot load http://localhost:8000/xmlhttprequest/resources/cors-preflight-safelisted-headers-responder.php. Request header field Accept is not allowed by Access-Control-Allow-Headers.
2
CONSOLE MESSAGE: XMLHttpRequest cannot load http://localhost:8000/xmlhttprequest/resources/cors-preflight-safelisted-headers-responder.php. Request header field Accept-Language is not allowed by Access-Control-Allow-Headers.
3
CONSOLE MESSAGE: XMLHttpRequest cannot load http://localhost:8000/xmlhttprequest/resources/cors-preflight-safelisted-headers-responder.php. Request header field Content-Language is not allowed by Access-Control-Allow-Headers.
4
CONSOLE MESSAGE: XMLHttpRequest cannot load http://localhost:8000/xmlhttprequest/resources/cors-preflight-safelisted-headers-responder.php. Request header field Content-Language is not allowed by Access-Control-Allow-Headers.
5
CONSOLE MESSAGE: XMLHttpRequest cannot load http://localhost:8000/xmlhttprequest/resources/cors-preflight-safelisted-headers-responder.php. Request header field Accept is not allowed by Access-Control-Allow-Headers.
6
PASS Accept header with normal value SHOULD NOT cause a preflight
7
PASS Accept-Language header with normal value SHOULD NOT cause a preflight
8
PASS Content-Language header with normal value SHOULD NOT cause a preflight
9
PASS Accept header with abnormal value SHOULD cause a preflight
10
PASS Accept-Language header with abnormal value SHOULD cause a preflight
11
PASS Content-Language header with abnormal value SHOULD cause a preflight
12
PASS Accept header with normal value, Accept-Language header with normal value, and Content-Language header with abnormal value SHOULD cause a preflight
13
PASS Accept header with normal value and then another Accept header with abnormal value SHOULD cause a preflight
14
PASS Accept header with abnormal value and explicitly allowed headers SHOULD be allowed
15
PASS Content-Language header with abnormal value and explicitly allowed headers SHOULD be allowed
16
PASS Accept header with normal value, Accept-Language header with normal value, Content-Language header with abnormal value, and explicitly allowed headers SHOULD be allowed
17
PASS Accept header with normal value, then another Accept header with abnormal value, and explicitly allowed headers SHOULD be allowed
18
- LayoutTests/http/tests/xmlhttprequest/cors-non-standard-safelisted-headers-should-trigger-preflight.html +147 lines
Line 0 LayoutTests/http/tests/xmlhttprequest/cors-non-standard-safelisted-headers-should-trigger-preflight.html_sec1
1
<!DOCTYPE html>
2
<html lang="en">
3
<head>
4
    <meta charset="UTF-8">
5
    <title>Non-Standard Safelisted Headers SHOULD Trigger a Preflight</title>
6
    <script src="../resources/js-test-pre.js"></script>
7
</head>
8
<body>
9
<!-- https://fetch.spec.whatwg.org/#cors-safelisted-request-header -->
10
<script>
11
    if (window.testRunner) {
12
        testRunner.dumpAsText();
13
        testRunner.waitUntilDone();
14
    }
15
16
    var invocation;
17
    var url = 'http://localhost:8000/xmlhttprequest/resources/cors-preflight-safelisted-headers-responder.php';
18
19
    function createReadyStateHandler (description, testNumber) {
20
        return function handler (e) {
21
            if (invocation.readyState === XMLHttpRequest.DONE) {
22
                testPassed(description);
23
                if (testNumber === (testCases.length - 1)) {
24
                    if (window.testRunner) {
25
                        testRunner.notifyDone();
26
                    }
27
                } else {
28
                    runTestCase(testNumber + 1);
29
                }
30
            }
31
        }
32
    }
33
34
    function createOnErrorHandler (description, testNumber) {
35
        return function handler (e) {
36
                e.preventDefault();
37
                testPassed(description);
38
                if (testNumber === (testCases.length - 1)) {
39
                    if (window.testRunner) {
40
                        testRunner.notifyDone();
41
                    }
42
                } else {
43
                    runTestCase(testNumber + 1);
44
                }
45
            }
46
    }
47
48
    var abnormalSimpleCorsHeaderValue = "() { :;};"
49
    var testCases = [
50
        // Positive test cases with normal headers
51
        {
52
            headersToAdd: [{ name : "Accept", value: "text/*" }],
53
            explicitlyAllowHeaders: false,
54
            shouldCausePreflight: false,
55
            description: "Accept header with normal value SHOULD NOT cause a preflight"
56
        }
57
        ,{
58
            headersToAdd: [{ name : "Accept-Language", value: "en" }],
59
            explicitlyAllowHeaders: false,
60
            shouldCausePreflight: false,
61
            description: "Accept-Language header with normal value SHOULD NOT cause a preflight"
62
        }
63
        ,{
64
            headersToAdd: [{ name : "Content-Language", value: "en" }],
65
            explicitlyAllowHeaders: false,
66
            shouldCausePreflight: false,
67
            description: "Content-Language header with normal value SHOULD NOT cause a preflight"
68
        }
69
        // Negative test cases with abnormal headers
70
        ,{
71
            headersToAdd: [{ name : "Accept", value: abnormalSimpleCorsHeaderValue }],
72
            explicitlyAllowHeaders: false,
73
            shouldCausePreflight: true,
74
            description: "Accept header with abnormal value SHOULD cause a preflight"
75
        }
76
        ,{
77
            headersToAdd: [{ name : "Accept-Language", value: abnormalSimpleCorsHeaderValue }],
78
            explicitlyAllowHeaders: false,
79
            shouldCausePreflight: true,
80
            description: "Accept-Language header with abnormal value SHOULD cause a preflight"
81
        }
82
        ,{
83
            headersToAdd: [{ name : "Content-Language", value: abnormalSimpleCorsHeaderValue }],
84
            explicitlyAllowHeaders: false,
85
            shouldCausePreflight: true,
86
            description: "Content-Language header with abnormal value SHOULD cause a preflight"
87
        }
88
        ,{
89
            headersToAdd: [{ name : "Accept", value: "text/*" }, { name : "Accept-Language", value: "en" }, { name : "Content-Language", value: abnormalSimpleCorsHeaderValue }],
90
            explicitlyAllowHeaders: false,
91
            shouldCausePreflight: true,
92
            description: "Accept header with normal value, Accept-Language header with normal value, and Content-Language header with abnormal value SHOULD cause a preflight"
93
        }
94
        ,{
95
            headersToAdd: [{ name : "Accept", value: "text/*" }, { name : "Accept", value: abnormalSimpleCorsHeaderValue }],
96
            explicitlyAllowHeaders: false,
97
            shouldCausePreflight: true,
98
            description: "Accept header with normal value and then another Accept header with abnormal value SHOULD cause a preflight"
99
        }
100
        // Positive test cases with abnormal headers
101
        ,{
102
            headersToAdd: [{ name : "Accept", value: abnormalSimpleCorsHeaderValue }],
103
            explicitlyAllowHeaders: true,
104
            shouldCausePreflight: true,
105
            description: "Accept header with abnormal value and explicitly allowed headers SHOULD be allowed"
106
        }
107
        ,{
108
            headersToAdd: [{ name : "Content-Language", value: abnormalSimpleCorsHeaderValue }],
109
            explicitlyAllowHeaders: true,
110
            shouldCausePreflight: true,
111
            description: "Content-Language header with abnormal value and explicitly allowed headers SHOULD be allowed"
112
        }
113
        ,{
114
            headersToAdd: [{ name : "Accept", value: "text/*" }, { name : "Accept-Language", value: "en" }, { name : "Content-Language", value: abnormalSimpleCorsHeaderValue }],
115
            explicitlyAllowHeaders: true,
116
            shouldCausePreflight: true,
117
            description: "Accept header with normal value, Accept-Language header with normal value, Content-Language header with abnormal value, and explicitly allowed headers SHOULD be allowed"
118
        }
119
        ,{
120
            headersToAdd: [{ name : "Accept", value: "text/*" }, { name : "Accept", value: abnormalSimpleCorsHeaderValue }],
121
            explicitlyAllowHeaders: true,
122
            shouldCausePreflight: true,
123
            description: "Accept header with normal value, then another Accept header with abnormal value, and explicitly allowed headers SHOULD be allowed"
124
        }
125
    ];
126
127
    function runTestCase(testNumber) {
128
        var testCase = testCases[testNumber];
129
        invocation = new XMLHttpRequest();
130
        if(invocation) {
131
            invocation.open('GET', url + (testCase.explicitlyAllowHeaders ? "/?explicitlyAllowHeaders=true" : ""), true);
132
            for (var i = 0; i < testCase.headersToAdd.length; i++) {
133
                invocation.setRequestHeader(testCase.headersToAdd[i].name, testCase.headersToAdd[i].value);
134
            }
135
            if (testCase.shouldCausePreflight && !testCase.explicitlyAllowHeaders) {
136
                invocation.onerror = createOnErrorHandler(testCase.description, testNumber);
137
            } else {
138
                invocation.onreadystatechange = createReadyStateHandler(testCase.description, testNumber);
139
            }
140
            invocation.send();
141
        }
142
    }
143
144
    runTestCase(0);
145
</script>
146
</body>
147
</html>
- LayoutTests/http/tests/xmlhttprequest/resources/cors-preflight-safelisted-headers-responder.php +8 lines
Line 0 LayoutTests/http/tests/xmlhttprequest/resources/cors-preflight-safelisted-headers-responder.php_sec1
1
<?php
2
header('Access-Control-Allow-Origin: http://127.0.0.1:8000');
3
4
if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS' && isset($_GET['explicitlyAllowHeaders'])) {
5
    header('Access-Control-Allow-Methods: GET, OPTIONS');
6
    header('Access-Control-Allow-Headers: Accept, Accept-Language, Content-Language');
7
}
8
?>

Return to Bug 165178