~ubuntu-branches/ubuntu/lucid/webkit/lucid-updates

« back to all changes in this revision

Viewing changes to WebCore/page/XSSAuditor.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Gustavo Noronha Silva
  • Date: 2010-01-06 21:25:06 UTC
  • mfrom: (1.2.6 upstream) (4.3.7 sid)
  • Revision ID: james.westby@ubuntu.com-20100106212506-gd0czn4zrwf1j19l
* New upstream release
- adds basic Content-Encoding support, thanks to soup
  (Closes: #529271)
- fixes over-advertising content types as supported by
  the media player (Closes: #559420)
* debian/control:
- updated libsoup build requirement (>= 2.28.2)
* debian/libwebkit-1.0-2.symbols:
- updated with new symbols
* debian/copyright:
- updated information since 1.1.17
* Imported patch from https://bugs.webkit.org/show_bug.cgi?id=30623
- I am shipping this patch because I believe it is correct, it is the
  way to go, it fixes a race, and it needs testing.

Show diffs side-by-side

added added

removed removed

Lines of Context:
105
105
    if (!isEnabled())
106
106
        return true;
107
107
 
108
 
    if (findInRequest(code, false, true)) {
 
108
    FindTask task;
 
109
    task.string = code;
 
110
    task.decodeEntities = false;
 
111
    task.allowRequestIfNoIllegalURICharacters = true;
 
112
 
 
113
    if (findInRequest(task)) {
109
114
        DEFINE_STATIC_LOCAL(String, consoleMessage, ("Refused to execute a JavaScript script. Source code of script found within request.\n"));
110
115
        m_frame->domWindow()->console()->addMessage(JSMessageSource, LogMessageType, ErrorMessageLevel, consoleMessage, 1, String());
111
116
        return false;
118
123
    if (!isEnabled())
119
124
        return true;
120
125
 
121
 
    if (findInRequest(code, true, false, true)) {
 
126
    FindTask task;
 
127
    task.string = code;
 
128
    task.decodeURLEscapeSequencesTwice = true;
 
129
 
 
130
    if (findInRequest(task)) {
122
131
        DEFINE_STATIC_LOCAL(String, consoleMessage, ("Refused to execute a JavaScript script. Source code of script found within request.\n"));
123
132
        m_frame->domWindow()->console()->addMessage(JSMessageSource, LogMessageType, ErrorMessageLevel, consoleMessage, 1, String());
124
133
        return false;
131
140
    if (!isEnabled())
132
141
        return true;
133
142
 
134
 
    if (findInRequest(code, true, true)) {
 
143
    FindTask task;
 
144
    task.string = code;
 
145
    task.allowRequestIfNoIllegalURICharacters = true;
 
146
 
 
147
    if (findInRequest(task)) {
135
148
        DEFINE_STATIC_LOCAL(String, consoleMessage, ("Refused to execute a JavaScript script. Source code of script found within request.\n"));
136
149
        m_frame->domWindow()->console()->addMessage(JSMessageSource, LogMessageType, ErrorMessageLevel, consoleMessage, 1, String());
137
150
        return false;
147
160
    if (isSameOriginResource(url))
148
161
        return true;
149
162
 
150
 
    if (findInRequest(context + url)) {
 
163
    FindTask task;
 
164
    task.context = context;
 
165
    task.string = url;
 
166
 
 
167
    if (findInRequest(task)) {
151
168
        DEFINE_STATIC_LOCAL(String, consoleMessage, ("Refused to execute a JavaScript script. Source code of script found within request.\n"));
152
169
        m_frame->domWindow()->console()->addMessage(JSMessageSource, LogMessageType, ErrorMessageLevel, consoleMessage, 1, String());
153
170
        return false;
163
180
    if (isSameOriginResource(url))
164
181
        return true;
165
182
 
166
 
    if (findInRequest(url)) {
 
183
    FindTask task;
 
184
    task.string = url;
 
185
    task.allowRequestIfNoIllegalURICharacters = true;
 
186
 
 
187
    if (findInRequest(task)) {
167
188
        String consoleMessage = String::format("Refused to load an object. URL found within request: \"%s\".\n", url.utf8().data());
168
189
        m_frame->domWindow()->console()->addMessage(JSMessageSource, LogMessageType, ErrorMessageLevel, consoleMessage, 1, String());
169
190
        return false;
179
200
    if (isSameOriginResource(url))
180
201
        return true;
181
202
 
182
 
    if (findInRequest(url)) {
 
203
    FindTask task;
 
204
    task.string = url;
 
205
 
 
206
    if (findInRequest(task)) {
183
207
        DEFINE_STATIC_LOCAL(String, consoleMessage, ("Refused to load from document base URL. URL found within request.\n"));
184
208
        m_frame->domWindow()->console()->addMessage(JSMessageSource, LogMessageType, ErrorMessageLevel, consoleMessage, 1, String());
185
209
        return false;
265
289
    return (m_frame->document()->url().host() == resourceURL.host() && resourceURL.query().isEmpty());
266
290
}
267
291
 
268
 
bool XSSAuditor::findInRequest(const String& string, bool decodeEntities, bool allowRequestIfNoIllegalURICharacters, 
269
 
                               bool decodeURLEscapeSequencesTwice) const
 
292
bool XSSAuditor::findInRequest(const FindTask& task) const
270
293
{
271
294
    bool result = false;
272
295
    Frame* parentFrame = m_frame->tree()->parent();
273
296
    if (parentFrame && m_frame->document()->url() == blankURL())
274
 
        result = findInRequest(parentFrame, string, decodeEntities, allowRequestIfNoIllegalURICharacters, decodeURLEscapeSequencesTwice);
 
297
        result = findInRequest(parentFrame, task);
275
298
    if (!result)
276
 
        result = findInRequest(m_frame, string, decodeEntities, allowRequestIfNoIllegalURICharacters, decodeURLEscapeSequencesTwice);
 
299
        result = findInRequest(m_frame, task);
277
300
    return result;
278
301
}
279
302
 
280
 
bool XSSAuditor::findInRequest(Frame* frame, const String& string, bool decodeEntities, bool allowRequestIfNoIllegalURICharacters, 
281
 
                               bool decodeURLEscapeSequencesTwice) const
 
303
bool XSSAuditor::findInRequest(Frame* frame, const FindTask& task) const
282
304
{
283
305
    ASSERT(frame->document());
284
306
 
287
309
        return false;
288
310
    }
289
311
 
290
 
    if (string.isEmpty())
 
312
    if (task.string.isEmpty())
291
313
        return false;
292
314
 
293
315
    FormData* formDataObj = frame->loader()->documentLoader()->originalRequest().httpBody();
 
316
    const bool hasFormData = formDataObj && !formDataObj->isEmpty();
294
317
    String pageURL = frame->document()->url().string();
295
318
 
296
 
    if (!formDataObj && string.length() >= 2 * pageURL.length()) {
 
319
    String canonicalizedString;
 
320
    if (!hasFormData && task.string.length() > 2 * pageURL.length()) {
297
321
        // Q: Why do we bother to do this check at all?
298
322
        // A: Canonicalizing large inline scripts can be expensive.  We want to
299
 
        //    bail out before the call to canonicalize below, which could
300
 
        //    result in an unneeded allocation and memcpy.
 
323
        //    reduce the size of the string before we call canonicalize below,
 
324
        //    since it could result in an unneeded allocation and memcpy.
301
325
        //
302
326
        // Q: Why do we multiply by two here?
303
327
        // A: We attempt to detect reflected XSS even when the server
305
329
        //    attacker can do get the server to inflate his/her input by a
306
330
        //    factor of two by sending " characters, which the server
307
331
        //    transforms to \".
308
 
        return false;
309
 
    }
 
332
        canonicalizedString = task.string.substring(0, 2 * pageURL.length());
 
333
    } else
 
334
        canonicalizedString = task.string;
310
335
 
311
336
    if (frame->document()->url().protocolIs("data"))
312
337
        return false;
313
338
 
314
 
    String canonicalizedString = canonicalize(string);
 
339
    canonicalizedString = canonicalize(canonicalizedString);
315
340
    if (canonicalizedString.isEmpty())
316
341
        return false;
317
342
 
318
 
    if (string.length() < pageURL.length()) {
319
 
        // The string can actually fit inside the pageURL.
320
 
        String decodedPageURL = m_cache.canonicalizeURL(pageURL, frame->document()->decoder()->encoding(), decodeEntities, decodeURLEscapeSequencesTwice);
321
 
 
322
 
        if (allowRequestIfNoIllegalURICharacters && (!formDataObj || formDataObj->isEmpty()) 
323
 
            && decodedPageURL.find(&isIllegalURICharacter, 0) == -1)
324
 
            return false; // Injection is impossible because the request does not contain any illegal URI characters. 
325
 
 
326
 
        if (decodedPageURL.find(canonicalizedString, 0, false) != -1)
327
 
            return true;  // We've found the smoking gun.
328
 
    }
329
 
 
330
 
    if (formDataObj && !formDataObj->isEmpty()) {
331
 
        String formData = formDataObj->flattenToString();
332
 
        if (string.length() < formData.length()) {
333
 
            // Notice it is sufficient to compare the length of the string to
334
 
            // the url-encoded POST data because the length of the url-decoded
335
 
            // code is less than or equal to the length of the url-encoded
336
 
            // string.
337
 
            String decodedFormData = m_cache.canonicalizeURL(formData, frame->document()->decoder()->encoding(), decodeEntities, decodeURLEscapeSequencesTwice);
338
 
            if (decodedFormData.find(canonicalizedString, 0, false) != -1)
339
 
                return true;  // We found the string in the POST data.
340
 
        }
 
343
    if (!task.context.isEmpty())
 
344
        canonicalizedString = task.context + canonicalizedString;
 
345
 
 
346
    String decodedPageURL = m_cache.canonicalizeURL(pageURL, frame->document()->decoder()->encoding(), task.decodeEntities, task.decodeURLEscapeSequencesTwice);
 
347
 
 
348
    if (task.allowRequestIfNoIllegalURICharacters && !hasFormData && decodedPageURL.find(&isIllegalURICharacter, 0) == -1)
 
349
        return false; // Injection is impossible because the request does not contain any illegal URI characters.
 
350
 
 
351
    if (decodedPageURL.find(canonicalizedString, 0, false) != -1)
 
352
        return true; // We've found the string in the GET data.
 
353
 
 
354
    if (hasFormData) {
 
355
        String decodedFormData = m_cache.canonicalizeURL(formDataObj->flattenToString(), frame->document()->decoder()->encoding(), task.decodeEntities, task.decodeURLEscapeSequencesTwice);
 
356
        if (decodedFormData.find(canonicalizedString, 0, false) != -1)
 
357
            return true; // We found the string in the POST data.
341
358
    }
342
359
 
343
360
    return false;