CODE-利用IFrame Proxy進行Cross Domain Scripting
11 | 36,733 |
昨天收了一則考題:
如上圖,serverA上有個ParentPage.htm用IFrame內嵌了來自另一台Server(serverB)的網頁ChildPage.htm,ChildPage的網頁高度(Height)會因內容多寡而改變,大部分時候都會產生垂直軸捲。需求是 -- 希望ParentPage能依ChildPage的高度自動放大IFrame高度,避免產生捲軸。
這本來是個簡單的小需求,在ChildPage用$("body").height()取得網頁高度,將它當成參數傳給ParentPage以Javascript修改Iframe的Height就可大功告成。但本案的關鍵在於ChildPage與ParentPage分屬不同網站,依據瀏覽器的Same-Origin Policy,ChildPage不允許直接與ParentPage溝通,形成了"世上最遙遠的距離不是生與死,而是只隔了一個Pixel,卻不能傳參數過去"的難題。
解決Cross Domain Scripting限制的做法蠻多的,例如: 指定相同document.domain、JSONP... 等等。而這次決定嘗試用IFrame Proxy解決:
我們在ChildPage.htm再內嵌一個來自於serverA的IFrameProxy.htm,便形成有趣的互動關連: ChildPage存取parent會發生存取被拒、IFrameProxy存取parent(即ChildPage)也會發生存取被拒,但存取parent.parent(ParentPage)則因屬於同一document.domain可被放行。因此,便能在指向IFrameProxy.htm的URL多加上Query String帶入要傳給ParentPage的參數,IFrameProxy.htm由location.href取出參數後,就能透過parent.parent將參數送交給ParentPage。
程式範例如下:
ParentPage.htm
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<script type="text/javascript">
function setIframeSize(size) {
var p = size.split('x');
if (p.length != 2) return;
var w = parseInt(p[0]), h = parseInt(p[1]);
var frm = document.getElementById("frmX");
frm.style.width = w + "px";
frm.style.height = h + "px";
setTimeout(function () {
alert("Resize IFrame to " + w + "x" + h + "!");
}, 100);
}
</script>
</head>
<body style="background-color: Green; color: White;">
serverA/ParentPage.htm<br />
<iframe id="frmX" src="http://serverB/ChildPage.htm"
width="400" height="100"></iframe>
</body>
</html>
ChildPage.htm
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<script src="http://ajax.microsoft.com/ajax/jquery/jquery-1.4.2.min.js?WT.mc_id=DOP-MVP-37580"
type="text/javascript"></script>
<script type="text/javascript">
$(function () {
//將網頁高度帶入Query String參數
$("#frmProxy").attr("src",
"http://serverA/IframeProxy.htm?400x"
+ ($("body").height() + 20));
});
</script>
<style type="text/css">
body
{
background-color: Gray; color: White;
height: 300px;
}
</style>
</head>
<body>
serverB/ChildPage.htm <br />
<iframe id="frmProxy" style="display: none;"></iframe>
</body>
</html>
IFrameProxy.htm
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<script type="text/javascript">
var i = location.href.indexOf("?");
var qs = i > 0 ? location.href.substring(i + 1, location.href.length) : "";
var func = parent.parent.setIframeSize;
if (func) func(qs);
</script>
</head>
<body style="background-color: Green; color: White;">
serverA/IFrameProxy.htm
</body>
</html>
【重要提醒】在打破Cross Site Scripting限制的同時,也等於開啟了網頁接受來自其他網域網頁(包含惡意網頁)傳入參數的大門,在利用這些參數執行程式邏輯前,務必要檢核參數是否合於規定,避免惡意人士在其中夾帶程式碼,形成XSS資安漏洞。尤其是將收到的參數直接透過document.write()、window.eval()、指派給location.href... 等等方式輸出或執行,都是等同於裸奔的高風險行為,可能讓你顏面盡失,撰寫類似程式時千萬要謹慎為之。
Comments
# by dor0705
謝謝分享,學到不少好東西~~
# by Cheung
A very clear example, thank you !
# by Laing
前几天就为跨域的权限问题困扰半天,这是一个不错的思路。
# by Alexyont
謝謝大大的分享, 另外想請問Same origin policy, ServerA/ParentPage.htm要去call ServerB/ChildPage.htm上的javascript function是否也是違反Same origin policy? 若是的話, 是否也能在ParentPage.htm放置IframeProxy的方式來解決? 謝謝指教.
# by Jeffrey
to Alexyont, ServerA的網頁去存取ServerB網頁上的DOM元表或JavaScript物件/函數的確也違反SOP,構成Cross-Site Scripting。你提的解法我認為可行,跟文中的案子剛好反過來做(IFrameProxy由ServerB提供給ParentPage內嵌)就OK了。
# by shrdi
serverA.ParentPage.htm 和 serverB.ChildPage.htm 網頁內容都是自己寫成的才能這樣做... 如果serverB不是自己的呢? 應該就拿不到ChildPage.htm的資訊了吧?
# by Jeffrey
to shrdi, 如果無法要求ServerB配合,這招就行不通了。(行得通反而恐怖,等同於打破了XSS的安全機制)
# by gaku
所以假如我想嵌入的iframe是外部網頁, 如pchome ,yahoo.... 這篇的做法就不行了嗎?
# by Jeffrey
to gaku, 是的,被嵌入端不配合就行不通,這是瀏覽器基於安全必須維持的底線。
# by Guyher
I propose another way to achieve it and hope it helpful. It is easy to implement - No need to modify the web page at other server to be used in your . - Only need to add some javascript to your web page The key points of the proposed method are: -Obtain the HTML code of the web page to be used in your via Yahoo’s YQL - Create an with attribute src of empty Modify the obtained HTML code by adding ‘base’ tag and adding any javascript you want, e.g. for adjusting ’s - Set the ’s content to be the modified HTML code. Typically, this will have the same content/appearance as the web page at the other server. And more importantly, this is not a - one, so your script can access anything within the . For the details, on-line demo, and sample code, please refer to here: http://www.share888.info/published/PublishedDoc.asp?id=2
# by Jeffrey
to Guyher, 原理上類似透過Server端取回外部網站內容後再佯裝為自家內容,也算一種解法,謝謝分享。