2007年01月23日

無所覺的表單動作, 在使用者未察覺的情形下自動送出表單

這是本人一時興起的試驗作品,寫完之後發現... 這是「惡意」的表單動作。因為我可以在使用者毫無所覺的情形下,記錄使用者瀏覽網站的每一個動作。

原始動機起於我想要在每一個連結上加上「點擊即自動加入書籤」的功能。作法是為網頁上每一個連結都加上點擊事件 (click event) 。當使用者點擊連結時,事件處理函數會自動產生一個表單 (form) ,將連結的網址及標題 (連結標籤中的文字) 填入,再自動將表單送往 黑米共享書籤 (Hemidemi) ,即完成加入書籤的動作。整個過程中,表單是不可見及不可察覺的。瀏覽器仍然會載入連結,而使用者不會察覺到表單送出動作。


範例網頁 normal.html

這是一個非常平凡的網頁,裡面有三個連結。我說過要用點擊事件觸發自動表單動作,但這裡看不到任何傳統的 onclick=xxx 敘述。實則玄機都在第 15 行載入的 watch.js 中。

watch.js

在 watch.js 中,為 window.onload 事件指派了一個事件處理函數。該函數抓出了網頁中的所有連結,然後為這些連結指派了 onclick 事件處理函數 gotYou() 。這是第一步:為每個連結添加點擊事件處理函數。

看到 gotYou() 的內容,由於表單呈送動作 (submit) 一定會觸發瀏覽器載入新頁面的動作,為了讓使用者無所覺,必須建立一個 iframe 並將其指派為表單的動作目標視窗 (target) 。gotYou() 接著自動建立一個表單及表單欄位,並填入欄位內容。最後送出表單 (form.submit();) 。iframe 和表單都設定不顯示,因此使用者不會察覺我已經產生一個表單並將其送出。

看到此處,有興趣的讀者可以將範例網頁和 watch.js 存起來,將 watch.js 第 32 行的 action 指派之內容改成黑米書籤的書籤建立服務 (即第 31 行的網址) 。啟動瀏覽器,先登入黑米書籤再開啟範例網頁,接著點擊任一連結。瀏覽器照常載入連結的網頁,看似一切正常。這時請再回到黑米書籤,將會發現剛才的網頁已經被加入共享書籤了。

在 IE 中 (我測的是 IE6) ,此處無法指派表單動作目標為 iframe ,送出表單時 IE 會自動開啟新視窗載入表單的回傳結果。所以用 IE6 時,會看到瀏覽器新增了一個視窗,而新視窗中會顯示黑米書籤中加入了一個新書籤。

i_know_where_you_go.php

如果我只做到上面為止,或許看起來是個「體貼的自動化功能」。但接下來我要寫一個簡單的 PHP 程式 (i_know_where_you_go.php) 放在網路上,並將 watch.js 中的表單動作網址指派為這個 PHP 程式。同樣的動作,現在變成了一個使用者動作的記錄器。使用者在這頁面上點了什麼連結,全都記錄在 i_know_where_you_go.log 之中。

剛剛 IE 的使用者還會看到新視窗,這裡我加上了 window.close() 敘述直接把新視窗關掉。現在 IE 的使用者點擊連結後,只會發現「好像」閃了一下,接著注意力就放在載入的連結網頁上。渾然不知剛剛的點擊動作已經被我記錄下來了。

具有資安意識的讀者,應該已經想到如果自己的網頁被人植入一行–僅僅一行– JavaScript 的載入標籤,就足以把所有瀏覽自己網頁的參觀者都出賣了。


Posted by shirock at 樂多Roodo! │22:56 │回應(8)引用(1)JavaScript
樂多分類:網路/3C 共同主題:JavaScript範例 工具:編輯本文
Ads by Roodo! 

引用URL

http://cgi.blog.roodo.com/trackback/2665954
引用列表:
JavaScript Hijacking: 如何透過瀏覽器取得基於 Ajax 及 JSON 規範傳遞之跨網域的隱密資料。
JavaScript Hijacking and How to【石頭閒語】 at 2007年04月4日 19:48
回應文章
gotYou function這樣寫好像比較好寫一點?
可參考此篇 http://qtutu.com/blog/?p=11
function gotYou(a){
var dummyImage = new Image();
dummyImage.src = "http://www.hemidemi.com/user_bookmark/create?user_bookmark[url]=" + a.href + '&user_bookmark[title]=' + a.childNodes[0].nodeValue;
}
Posted by birdegg at 2007年01月29日 03:59
這兩種寫法有所差異。

image.src 的寫法,送出的是一個 HTTP GET request 。
我的寫法則是送出 HTTP POST request ,See 第29行。

黑米書籤沒有區分表單資料來源,是以用 GET request 也可以達成同樣目的。若表單目標區分表單資料來源,例如是一個 PHP 程式,而且只認 $_POST 的內容,則經由 GET request 送來的表單資料不會被處理。

還有一件事,經由 image.src 送出的內容,沒有各瀏覽器一致通用的方法可以分析回應內容 (like XmlHttpRequest.reponseText)。透過 form 的提交動作,則會獲得一個新頁面內容,可以再做其他事。例如上例會關閉新開啟的視窗。
Posted by 遊手好閒的石頭成 at 2007年01月29日 10:00

0.0 如果他是用新版IE 開分頁 那window. close執行後 他會詢問要不要關閉
Posted by 0.0 at 2009年01月23日 10:09

ie6之所以無法設定target到動態產生的iframe
原因是因為動態產生的iframe她沒把iframe物件參照記錄進window.frames陣列中
所以只要手動替IE寫進去就可以同樣使用target去指定post目標頁框
Posted by colin at 2009年11月30日 15:23

不好意思 更正一下
應該不能說沒寫進frames中
而是IE沒用frame name當陣列索引
Posted by colin at 2009年11月30日 15:30
你們說的事,應該都是現在的 IE7, IE8 修正過後的結果了。

畢竟這是一篇兩年前貼的舊文。也正如我所說的,這可以變成一個惡意的網頁動作。所以這一、兩年來,瀏覽器也漸漸修正了這些不適當的動作。
Posted by 遊手好閒的石頭成 at 2009年11月30日 21:34

恩恩..
老實說在我工作環境沒有像前輩這樣的程式設計師
都是一些老派IE6 ONLY的設計師
改天有機會在向您請教一番
我先把您網站上的文爬一爬
Posted by colin at 2009年12月1日 12:44
也許我是更老派的設計師。
因為我從 Netscape 2, IE 3 就在上面寫 JavaScript跟 DnyamicHTML 了。
更古怪的瀏覽器行為我都碰過啊 XD
Posted by 遊手好閒的石頭成 at 2009年12月1日 20:49