Changeset 20074 in webkit


Ignore:
Timestamp:
Mar 8, 2007 6:25:25 PM (17 years ago)
Author:
darin
Message:

Reviewed by Adele.

  • <rdar://problem/4470381> multipart/form-data boundary security vulnerability

By making the form data boundary a string with some random data in it, we reduce
the possibility that anyone could take advantage of it by creating a file that
intentionally has the boundary string in it.

  • html/HTMLFormElement.h: Removed boundary(), setBoundary(), and m_boundary. Marked a lot more stuff private.
  • html/HTMLFormElement.cpp: (WebCore::HTMLFormElement::HTMLFormElement): Removed code to initialize m_boundary. (WebCore::randomNumber): Added. Function that returns a random number, including seeding the random number generator the first time it's called. For now, usees the more random function random() on Mac OS X and the more-standard rand() on other platforms. (WebCore::HTMLFormElement::formData): Take a parameter with the form boundary string, and use that instead of m_boundary. (WebCore::getUniqueBoundaryString): Added. Makes a boundary string using random numbers and base 64 encoding. (WebCore::HTMLFormElement::submit): Call getUniqueBoundaryString and pass the boundary string into formData for multipart form posts.
Location:
trunk/WebCore
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/WebCore/ChangeLog

    r20072 r20074  
     12007-03-08  Darin Adler  <darin@apple.com>
     2
     3        Reviewed by Adele.
     4
     5        - <rdar://problem/4470381> multipart/form-data boundary security vulnerability
     6
     7        By making the form data boundary a string with some random data in it, we reduce
     8        the possibility that anyone could take advantage of it by creating a file that
     9        intentionally has the boundary string in it.
     10
     11        * html/HTMLFormElement.h: Removed boundary(), setBoundary(), and m_boundary.
     12        Marked a lot more stuff private.
     13        * html/HTMLFormElement.cpp:
     14        (WebCore::HTMLFormElement::HTMLFormElement): Removed code to initialize
     15        m_boundary.
     16        (WebCore::randomNumber): Added. Function that returns a random number, including
     17        seeding the random number generator the first time it's called. For now, usees the more
     18        random function random() on Mac OS X and the more-standard rand() on other platforms.
     19        (WebCore::HTMLFormElement::formData): Take a parameter with the form boundary string,
     20        and use that instead of m_boundary.
     21        (WebCore::getUniqueBoundaryString): Added. Makes a boundary string using random numbers
     22        and base 64 encoding.
     23        (WebCore::HTMLFormElement::submit): Call getUniqueBoundaryString and pass the boundary
     24        string into formData for multipart form posts.
     25
    1262007-03-08  Maciej Stachowiak  <mjs@apple.com>
    227
  • trunk/WebCore/html/HTMLFormElement.cpp

    r19872 r20074  
    11/*
    2  * This file is part of the DOM implementation for KDE.
    3  *
    42 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
    53 *           (C) 1999 Antti Koivisto (koivisto@kde.org)
    64 *           (C) 2001 Dirk Mueller (mueller@kde.org)
    7  * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc.
     5 * Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
    86 *           (C) 2006 Alexey Proskuryakov (ap@nypop.com)
    97 *
     
    2826#include "HTMLFormElement.h"
    2927
     28#include "Base64.h"
    3029#include "CString.h"
    3130#include "csshelper.h"
     
    6059    m_inreset = false;
    6160    m_enctype = "application/x-www-form-urlencoded";
    62     m_boundary = "----------0xKhTmLbOuNdArY";
    6361    m_malformed = false;
    6462    m_preserveAcrossRemove = false;
     
    197195}
    198196
    199 PassRefPtr<FormData> HTMLFormElement::formData() const
    200 {
    201     DeprecatedCString enc_string = ""; // used for non-multipart data
     197static int randomNumber()
     198{
     199    static bool randomSeeded = false;
     200
     201#if PLATFORM(DARWIN)
     202    if (!randomSeeded) {
     203        srandomdev();
     204        randomSeeded = true;
     205    }
     206    return random();
     207#else
     208    if (!randomSeeded) {
     209        srand(static_cast<unsigned>(time(0)));
     210        randomSeeded = true;
     211    }
     212    return rand();
     213#endif
     214}
     215
     216PassRefPtr<FormData> HTMLFormElement::formData(const char* boundary) const
     217{
     218    DeprecatedCString enc_string = "";
    202219
    203220    String str = m_acceptcharset;
     
    246263                {
    247264                    DeprecatedCString hstr("--");
    248                     hstr += m_boundary.deprecatedString().latin1();
     265                    hstr += boundary;
    249266                    hstr += "\r\n";
    250267                    hstr += "Content-Disposition: form-data; name=\"";
     
    295312
    296313
    297     if (m_multipart)
    298         enc_string = ("--" + m_boundary.deprecatedString() + "--\r\n").ascii();
     314    if (m_multipart) {
     315        enc_string = "--";
     316        enc_string += boundary;
     317        enc_string += "--\r\n";
     318    }
    299319
    300320    result->appendData(enc_string.data(), enc_string.length());
     
    316336}
    317337
    318 void HTMLFormElement::setBoundary( const String& bound )
    319 {
    320     m_boundary = bound;
    321 }
    322 
    323338bool HTMLFormElement::prepareSubmit(Event* event)
    324339{
     
    344359{
    345360    submit(0, false);
     361}
     362
     363// Returns a 0-terminated C string in the vector.
     364static void getUniqueBoundaryString(Vector<char>& boundary)
     365{
     366    // Start with an informative prefix.
     367    const char boundaryPrefix[] = "----WebKit-form-boundary-";
     368    boundary.append(boundaryPrefix, strlen(boundaryPrefix));
     369
     370    // Append 16 characters of base 64 randomness.
     371    Vector<char> randomBytes;
     372    for (int i = 0; i < 3; ++i) {
     373        int randomness = randomNumber();
     374        randomBytes.append(static_cast<char>(randomness >> 24));
     375        randomBytes.append(static_cast<char>(randomness >> 16));
     376        randomBytes.append(static_cast<char>(randomness >> 8));
     377        randomBytes.append(static_cast<char>(randomness));
     378    }
     379    Vector<char> randomBase64;
     380    base64Encode(randomBytes, randomBase64);
     381    boundary.append(randomBase64);
     382
     383    // Add a 0 at the end so we can use this as a C-style string.
     384    boundary.append(0);
    346385}
    347386
     
    386425
    387426    if (!m_post)
     427
     428    if (m_post) {
     429        if (!m_multipart)
     430            frame->loader()->submitForm("POST", m_url, formData(0), m_target, enctype(), String(), event);
     431        else {
     432            Vector<char> boundary;
     433            getUniqueBoundaryString(boundary);
     434            frame->loader()->submitForm("POST", m_url, formData(boundary.data()), m_target, enctype(), boundary.data(), event);
     435        }
     436    } else {
    388437        m_multipart = false;
    389    
    390     if (m_post)
    391         frame->loader()->submitForm("POST", m_url, formData(), m_target, enctype(), boundary(), event);
    392     else
    393         frame->loader()->submitForm("GET", m_url, formData(), m_target, String(), String(), event);
     438        frame->loader()->submitForm("GET", m_url, formData(0), m_target, String(), String(), event);
     439    }
    394440
    395441    if (needButtonActivation && firstSuccessfulSubmitButton)
  • trunk/WebCore/html/HTMLFormElement.h

    r19872 r20074  
    11/*
    2  * This file is part of the DOM implementation for KDE.
    3  *
    42 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
    53 *           (C) 1999 Antti Koivisto (koivisto@kde.org)
    64 *           (C) 2000 Dirk Mueller (mueller@kde.org)
    7  * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc.
     5 * Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
    86 *
    97 * This library is free software; you can redistribute it and/or
     
    6260    void setEncoding(const String& enctype) { setEnctype(enctype); }
    6361
    64     String boundary() const { return m_boundary; }
    65     void setBoundary(const String&);
    66 
    6762    bool autoComplete() const { return m_autocomplete; }
    6863
     
    105100    void setTarget(const String&);
    106101
     102    // FIXME: Change this to be private after getting rid of all the clients.
     103    Vector<HTMLGenericFormElement*> formElements;
     104
     105private:
     106    void parseEnctype(const String&);
     107    PassRefPtr<FormData> formData(const char* boundary) const;
     108    unsigned formElementIndex(HTMLGenericFormElement*);
     109
    107110    friend class HTMLFormCollection;
    108111
    109112    HTMLCollection::CollectionInfo* collectionInfo;
    110113
    111     Vector<HTMLGenericFormElement*> formElements;
    112114    Vector<HTMLImageElement*> imgElements;
    113115    String m_url;
     
    125127    bool m_preserveAcrossRemove : 1;
    126128
    127 private:
    128     void parseEnctype(const String&);
    129     PassRefPtr<FormData> formData() const;
    130 
    131     unsigned formElementIndex(HTMLGenericFormElement*);
    132 
    133129    String oldNameAttr;
    134130};
Note: See TracChangeset for help on using the changeset viewer.