Commit fbec81e4 authored by weinig@apple.com's avatar weinig@apple.com

WebCore:

        Reviewed by Darin Adler.

        Fix for <rdar://problem/5726604> 
        dom-checker: deleting properties of the window object cross-domain should not be allowed

        Fix flaw found while testing with dom-checker testing tool (http://code.google.com/p/dom-checker/).

        Test: http/tests/security/cross-frame-access-delete.html

        * bindings/js/JSDOMWindowCustom.cpp:
        (WebCore::JSDOMWindow::deleteProperty): Override deleteProperty to not delete cross-domain.
        * bindings/js/JSHistoryCustom.cpp:
        (WebCore::JSHistory::deleteProperty): ditto.
        * bindings/js/JSLocation.cpp:
        (WebCore::JSLocation::deleteProperty): ditto.
        * bindings/js/JSLocation.h:

        * bindings/scripts/CodeGeneratorJS.pm: Add deleteProperty declaration when CustomDeleteProperty is used.
        * page/DOMWindow.idl: Add CustomDeleteProperty extended attribute.
        * page/History.idl: ditto.

LayoutTests:

        Reviewed by Darin Adler.

        Test for <rdar://problem/5726604>
        dom-checker: deleting properties of the window object cross-domain should not be allowed

        * http/tests/security/cross-frame-access-delete-expected.txt: Added.
        * http/tests/security/cross-frame-access-delete.html: Added.
        * http/tests/security/resources/cross-frame-iframe-for-delete-test.html: Added.



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@30032 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent f2ab90ff
2008-02-05 Samuel Weinig <sam@webkit.org>
Reviewed by Darin Adler.
Test for <rdar://problem/5726604>
dom-checker: deleting properties of the window object cross-domain should not be allowed
* http/tests/security/cross-frame-access-delete-expected.txt: Added.
* http/tests/security/cross-frame-access-delete.html: Added.
* http/tests/security/resources/cross-frame-iframe-for-delete-test.html: Added.
2008-02-05 Nikolas Zimmermann <zimmermann@kde.org>
Reviewed by Oliver.
......
CONSOLE MESSAGE: line 1: Unsafe JavaScript attempt to access frame with URL http://localhost:8000/security/resources/cross-frame-iframe-for-delete-test.html from frame with URL http://127.0.0.1:8000/security/cross-frame-access-delete.html. Domains, protocols and ports must match.
CONSOLE MESSAGE: line 1: Unsafe JavaScript attempt to access frame with URL http://localhost:8000/security/resources/cross-frame-iframe-for-delete-test.html from frame with URL http://127.0.0.1:8000/security/cross-frame-access-delete.html. Domains, protocols and ports must match.
CONSOLE MESSAGE: line 1: Unsafe JavaScript attempt to access frame with URL http://localhost:8000/security/resources/cross-frame-iframe-for-delete-test.html from frame with URL http://127.0.0.1:8000/security/cross-frame-access-delete.html. Domains, protocols and ports must match.
CONSOLE MESSAGE: line 1: Unsafe JavaScript attempt to access frame with URL http://localhost:8000/security/resources/cross-frame-iframe-for-delete-test.html from frame with URL http://127.0.0.1:8000/security/cross-frame-access-delete.html. Domains, protocols and ports must match.
CONSOLE MESSAGE: line 1: Unsafe JavaScript attempt to access frame with URL http://localhost:8000/security/resources/cross-frame-iframe-for-delete-test.html from frame with URL http://127.0.0.1:8000/security/cross-frame-access-delete.html. Domains, protocols and ports must match.
CONSOLE MESSAGE: line 1: Unsafe JavaScript attempt to access frame with URL http://localhost:8000/security/resources/cross-frame-iframe-for-delete-test.html from frame with URL http://127.0.0.1:8000/security/cross-frame-access-delete.html. Domains, protocols and ports must match.
PASS: eval('delete targetWindow.existingProperty') should be 'false' and is.
PASS: eval('delete targetWindow[1]') should be 'false' and is.
PASS: eval('delete targetWindow.history.existingProperty') should be 'false' and is.
PASS: eval('delete targetWindow.history[1]') should be 'false' and is.
PASS: eval('delete targetWindow.location.existingProperty') should be 'false' and is.
PASS: eval('delete targetWindow.location[1]') should be 'false' and is.
--------
Frame: '<!--framePath //<!--frame0-->-->'
--------
----- tests for deleting the properties of window, window.history, and window.location cross-domain -----
PASS: window.existingProperty should be 'test value' and is.
PASS: window[1] should be 'test value' and is.
PASS: window.history.existingProperty should be 'test value' and is.
PASS: window.history[1] should be 'test value' and is.
PASS: window.location.existingProperty should be 'test value' and is.
PASS: window.location[1] should be 'test value' and is.
<html>
<head>
<script src="resources/cross-frame-access.js"></script>
<script>
if (window.layoutTestController) {
layoutTestController.dumpAsText();
layoutTestController.dumpChildFramesAsText();
layoutTestController.waitUntilDone();
}
receiver = function(e)
{
if (e.data == "setValuesComplete")
deleteTest();
}
document.addEventListener('message', receiver, false);
deleteTest = function()
{
targetWindow = frames[0];
shouldBe("eval('delete targetWindow.existingProperty')", "false");
shouldBe("eval('delete targetWindow[1]')", "false");
shouldBe("eval('delete targetWindow.history.existingProperty')", "false");
shouldBe("eval('delete targetWindow.history[1]')", "false");
shouldBe("eval('delete targetWindow.location.existingProperty')", "false");
shouldBe("eval('delete targetWindow.location[1]')", "false");
targetWindow.postMessage("deletingValuesComplete");
}
</script>
</head>
<body>
<iframe src="http://localhost:8000/security/resources/cross-frame-iframe-for-delete-test.html"></iframe>
<pre id="console"></pre>
</body>
</html>
<html>
<head>
<script src="cross-frame-access.js"></script>
<script>
receiver = function(e)
{
if (e.data == "deletingValuesComplete")
setCheck();
}
document.addEventListener('message', receiver, false);
window.onload = function()
{
window.existingProperty = "test value";
window[1] = "test value";
window.history.existingProperty = "test value";
window.history[1] = "test value";
window.location.existingProperty = "test value";
window.location[1] = "test value";
window.parent.postMessage("setValuesComplete");
}
setCheck = function()
{
log("\n----- tests for deleting the properties of window, window.history, and window.location cross-domain -----\n");
shouldBe("window.existingProperty", "'test value'");
shouldBe("window[1]", "'test value'");
shouldBe("window.history.existingProperty", "'test value'");
shouldBe("window.history[1]", "'test value'");
shouldBe("window.location.existingProperty", "'test value'");
shouldBe("window.location[1]", "'test value'");
if (window.layoutTestController)
layoutTestController.notifyDone();
}
</script>
</head>
<body>
<pre id="console"></pre>
</body>
</html>
2008-02-05 Samuel Weinig <sam@webkit.org>
Reviewed by Darin Adler.
Fix for <rdar://problem/5726604>
dom-checker: deleting properties of the window object cross-domain should not be allowed
Fix flaw found while testing with dom-checker testing tool (http://code.google.com/p/dom-checker/).
Test: http/tests/security/cross-frame-access-delete.html
* bindings/js/JSDOMWindowCustom.cpp:
(WebCore::JSDOMWindow::deleteProperty): Override deleteProperty to not delete cross-domain.
* bindings/js/JSHistoryCustom.cpp:
(WebCore::JSHistory::deleteProperty): ditto.
* bindings/js/JSLocation.cpp:
(WebCore::JSLocation::deleteProperty): ditto.
* bindings/js/JSLocation.h:
* bindings/scripts/CodeGeneratorJS.pm: Add deleteProperty declaration when CustomDeleteProperty is used.
* page/DOMWindow.idl: Add CustomDeleteProperty extended attribute.
* page/History.idl: ditto.
2008-02-05 Alp Toker <alp@atoker.com>
Rubber-stamped by Mark Rowe.
......@@ -117,6 +117,14 @@ bool JSDOMWindow::customPut(ExecState* exec, const Identifier& propertyName, JSV
return false;
}
bool JSDOMWindow::deleteProperty(ExecState* exec, const Identifier& propertyName)
{
// Only allow deleting properties by frames in the same origin.
if (!allowsAccessFrom(exec))
return false;
return Base::deleteProperty(exec, propertyName);
}
void JSDOMWindow::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames)
{
// Only allow the window to enumerated by frames in the same origin.
......
......@@ -76,6 +76,14 @@ bool JSHistory::customPut(ExecState* exec, const Identifier& propertyName, JSVal
return false;
}
bool JSHistory::deleteProperty(ExecState* exec, const Identifier& propertyName)
{
// Only allow deleting by frames in the same origin.
if (!allowsAccessFromFrame(exec, impl()->frame()))
return false;
return Base::deleteProperty(exec, propertyName);
}
void JSHistory::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames)
{
// Only allow the history object to enumerated by frames in the same origin.
......
......@@ -198,6 +198,14 @@ void JSLocation::put(ExecState* exec, const Identifier& propertyName, JSValue* v
}
}
bool JSLocation::deleteProperty(ExecState* exec, const Identifier& propertyName)
{
// Only allow deleting by frames in the same origin.
if (!allowsAccessFromFrame(exec, frame()))
return false;
return Base::deleteProperty(exec, propertyName);
}
void JSLocation::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames)
{
// Only allow the location object to enumerated by frames in the same origin.
......
......@@ -40,7 +40,7 @@ namespace WebCore {
virtual bool getOwnPropertySlot(KJS::ExecState*, const KJS::Identifier&, KJS::PropertySlot&);
KJS::JSValue* getValueProperty(KJS::ExecState*, int token) const;
virtual void put(KJS::ExecState*, const KJS::Identifier&, KJS::JSValue*, int attr = KJS::None);
virtual bool deleteProperty(KJS::ExecState*, const KJS::Identifier&);
virtual void getPropertyNames(KJS::ExecState*, KJS::PropertyNameArray&);
enum {
......
......@@ -365,6 +365,9 @@ sub GenerateHeader
push(@headerContent, " virtual bool implementsCall() const;\n\n");
}
# Custom deleteProperty function
push(@headerContent, " virtual bool deleteProperty(KJS::ExecState*, const KJS::Identifier&);\n") if $dataNode->extendedAttributes->{"CustomDeleteProperty"};
# Custom getPropertyNames function
push(@headerContent, " virtual void getPropertyNames(KJS::ExecState*, KJS::PropertyNameArray&);\n") if $dataNode->extendedAttributes->{"CustomGetPropertyNames"};
......
......@@ -25,7 +25,16 @@
module window {
interface [LegacyParent=KJS::Window, DoNotCache, CheckDomainSecurity, GenerateNativeConverter, CustomGetOwnPropertySlot, CustomPutFunction, CustomGetPropertyNames] DOMWindow {
interface [
LegacyParent=KJS::Window,
DoNotCache,
CheckDomainSecurity,
GenerateNativeConverter,
CustomGetOwnPropertySlot,
CustomPutFunction,
CustomDeleteProperty,
CustomGetPropertyNames
] DOMWindow {
// DOM Level 0
readonly attribute Screen screen;
readonly attribute [DoNotCheckDomainSecurity] History history;
......
......@@ -25,7 +25,12 @@
module window {
interface [CustomGetOwnPropertySlot, CustomPutFunction, CustomGetPropertyNames] History {
interface [
CustomGetOwnPropertySlot,
CustomPutFunction,
CustomDeleteProperty,
CustomGetPropertyNames
] History {
readonly attribute unsigned long length;
void back();
......
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