Commit 2978880d authored by dcheng@chromium.org's avatar dcheng@chromium.org

Prevent web content from forging File entries in drag and drop.

There are two separate bugs that this and the corresponding Chrome patch
aim to address:
- On Linux, files and URLs are transferred in the same MIME type, so
  it's impossible to tell if a filename was set by a trusted source or
  forged by web content.
- DownloadURL triggers the download of potentially cross-origin content.
  On some platforms, such as Windows, the resulting download is treated
  as a file drag by Chrome, allowing web content to read cross origin
  content.

In order to prevent web content from doing this, drags initiated by a
renderer will be marked as tainted. When tainted drags are over web
content, Blink will only allow the resulting filename to be used for
navigation, with Chrome enforcing this with the sandbox policy.

Unfortunately, this does break some potentially interesting use cases
like being able to drag an attachment from Gmail to a file input, but
those will have to be separately addressed, if possible.

BUG=346135
R=abarth@chromium.org, tony@chromium.org

Review URL: https://codereview.chromium.org/193803002

git-svn-id: svn://svn.chromium.org/blink/trunk@169711 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent c7b66ffb
...@@ -91,6 +91,10 @@ public: ...@@ -91,6 +91,10 @@ public:
int modifierKeyState() const { return m_modifierKeyState; } int modifierKeyState() const { return m_modifierKeyState; }
void setModifierKeyState(int modifierKeyState) { m_modifierKeyState = modifierKeyState; } void setModifierKeyState(int modifierKeyState) { m_modifierKeyState = modifierKeyState; }
// The accessor should only ever be called by DragData.
const String& filenameForNavigation() const { return m_filenameForNavigation; }
void setFilenameForNavigation(const String& filename) { m_filenameForNavigation = filename; }
// FIXME: oilpan: This trace() has to trace Supplementable. // FIXME: oilpan: This trace() has to trace Supplementable.
void trace(Visitor*); void trace(Visitor*);
...@@ -104,6 +108,8 @@ private: ...@@ -104,6 +108,8 @@ private:
WillBeHeapVector<RefPtrWillBeMember<DataObjectItem> > m_itemList; WillBeHeapVector<RefPtrWillBeMember<DataObjectItem> > m_itemList;
String m_filenameForNavigation;
// State of Shift/Ctrl/Alt/Meta keys. // State of Shift/Ctrl/Alt/Meta keys.
int m_modifierKeyState; int m_modifierKeyState;
}; };
......
...@@ -265,7 +265,7 @@ bool DragController::performDrag(DragData* dragData) ...@@ -265,7 +265,7 @@ bool DragController::performDrag(DragData* dragData)
return false; return false;
if (m_page->settings().navigateOnDragDrop()) if (m_page->settings().navigateOnDragDrop())
m_page->mainFrame()->loader().load(FrameLoadRequest(0, ResourceRequest(dragData->asURL()))); m_page->mainFrame()->loader().load(FrameLoadRequest(0, ResourceRequest(dragData->asURL(DragData::ConvertFilenames))));
return true; return true;
} }
...@@ -946,7 +946,7 @@ DragOperation DragController::dragOperation(DragData* dragData) ...@@ -946,7 +946,7 @@ DragOperation DragController::dragOperation(DragData* dragData)
// attached sheet If this can be determined from within WebCore // attached sheet If this can be determined from within WebCore
// operationForDrag can be pulled into WebCore itself // operationForDrag can be pulled into WebCore itself
ASSERT(dragData); ASSERT(dragData);
return dragData->containsURL() && !m_didInitiateDrag ? DragOperationCopy : DragOperationNone; return dragData->containsURL(DragData::ConvertFilenames) && !m_didInitiateDrag ? DragOperationCopy : DragOperationNone;
} }
bool DragController::isCopyKeyDown(DragData* dragData) bool DragController::isCopyKeyDown(DragData* dragData)
......
...@@ -69,16 +69,21 @@ static bool containsHTML(const DataObject* dropData) ...@@ -69,16 +69,21 @@ static bool containsHTML(const DataObject* dropData)
bool DragData::containsURL(FilenameConversionPolicy filenamePolicy) const bool DragData::containsURL(FilenameConversionPolicy filenamePolicy) const
{ {
return m_platformDragData->types().contains(mimeTypeTextURIList) return m_platformDragData->types().contains(mimeTypeTextURIList)
|| (filenamePolicy == ConvertFilenames && m_platformDragData->containsFilenames()); || (filenamePolicy == ConvertFilenames
&& (m_platformDragData->containsFilenames() || !m_platformDragData->filenameForNavigation().isEmpty()));
} }
String DragData::asURL(FilenameConversionPolicy filenamePolicy, String* title) const String DragData::asURL(FilenameConversionPolicy filenamePolicy, String* title) const
{ {
String url; String url;
if (m_platformDragData->types().contains(mimeTypeTextURIList)) if (m_platformDragData->types().contains(mimeTypeTextURIList)) {
m_platformDragData->urlAndTitle(url, title); m_platformDragData->urlAndTitle(url, title);
else if (filenamePolicy == ConvertFilenames && containsFiles()) } else if (filenamePolicy == ConvertFilenames) {
if (containsFiles())
url = filePathToURL(m_platformDragData->filenames()[0]); url = filePathToURL(m_platformDragData->filenames()[0]);
else
url = filePathToURL(m_platformDragData->filenameForNavigation());
}
return url; return url;
} }
......
...@@ -51,6 +51,7 @@ enum DragApplicationFlags { ...@@ -51,6 +51,7 @@ enum DragApplicationFlags {
class DragData { class DragData {
public: public:
// ConvertFilenames is only intended to be used when treating drags as a navigation action.
enum FilenameConversionPolicy { DoNotConvertFilenames, ConvertFilenames }; enum FilenameConversionPolicy { DoNotConvertFilenames, ConvertFilenames };
// clientPosition is taken to be the position of the drag event within the target window, with (0,0) at the top left // clientPosition is taken to be the position of the drag event within the target window, with (0,0) at the top left
...@@ -61,10 +62,10 @@ public: ...@@ -61,10 +62,10 @@ public:
DragApplicationFlags flags() const { return m_applicationFlags; } DragApplicationFlags flags() const { return m_applicationFlags; }
DataObject* platformData() const { return m_platformDragData; } DataObject* platformData() const { return m_platformDragData; }
DragOperation draggingSourceOperationMask() const { return m_draggingSourceOperationMask; } DragOperation draggingSourceOperationMask() const { return m_draggingSourceOperationMask; }
bool containsURL(FilenameConversionPolicy filenamePolicy = ConvertFilenames) const; bool containsURL(FilenameConversionPolicy filenamePolicy = DoNotConvertFilenames) const;
bool containsPlainText() const; bool containsPlainText() const;
bool containsCompatibleContent() const; bool containsCompatibleContent() const;
String asURL(FilenameConversionPolicy filenamePolicy = ConvertFilenames, String* title = 0) const; String asURL(FilenameConversionPolicy filenamePolicy = DoNotConvertFilenames, String* title = 0) const;
String asPlainText() const; String asPlainText() const;
void asFilenames(Vector<String>&) const; void asFilenames(Vector<String>&) const;
PassRefPtr<DocumentFragment> asFragment(LocalFrame*, PassRefPtr<Range> context, bool allowPlainText, bool& chosePlainText) const; PassRefPtr<DocumentFragment> asFragment(LocalFrame*, PassRefPtr<Range> context, bool allowPlainText, bool& chosePlainText) const;
......
...@@ -161,4 +161,10 @@ void WebDragData::setFilesystemId(const WebString& filesystemId) ...@@ -161,4 +161,10 @@ void WebDragData::setFilesystemId(const WebString& filesystemId)
DraggedIsolatedFileSystem::provideTo(*m_private.get(), DraggedIsolatedFileSystem::supplementName(), DraggedIsolatedFileSystem::create(filesystemId)); DraggedIsolatedFileSystem::provideTo(*m_private.get(), DraggedIsolatedFileSystem::supplementName(), DraggedIsolatedFileSystem::create(filesystemId));
} }
void WebDragData::setFilenameForNavigation(const WebString& filename)
{
ensureMutable();
m_private->setFilenameForNavigation(filename);
}
} // namespace blink } // namespace blink
...@@ -102,6 +102,8 @@ public: ...@@ -102,6 +102,8 @@ public:
BLINK_EXPORT WebString filesystemId() const; BLINK_EXPORT WebString filesystemId() const;
BLINK_EXPORT void setFilesystemId(const WebString&); BLINK_EXPORT void setFilesystemId(const WebString&);
BLINK_EXPORT void setFilenameForNavigation(const WebString&);
#if BLINK_IMPLEMENTATION #if BLINK_IMPLEMENTATION
explicit WebDragData(const PassRefPtrWillBeRawPtr<WebCore::DataObject>&); explicit WebDragData(const PassRefPtrWillBeRawPtr<WebCore::DataObject>&);
WebDragData& operator=(const PassRefPtrWillBeRawPtr<WebCore::DataObject>&); WebDragData& operator=(const PassRefPtrWillBeRawPtr<WebCore::DataObject>&);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment