若 Firefox 開發延伸套件時,應該會知道 Firefox 對於外掛並沒有安全防護機制的,只要你能裝進系統,大約就可以使用所有的元件或存取系統資源。延伸套件被視為可信賴的軟體,開發者應負起各延伸套件的安全性。

對此,Firefox 在 Java Script 開發環境的安全設計主要分為賦權未賦權的兩種安全模式。賦權的環境中,軟體可以存取所有的 XPCOM,沒有任何限制,於是它可以讀取或修改使用者的歷史紀錄、Cookie 等,甚至存取所有系統檔案。而 non-privileged 則僅提供限制嚴格的 HTML DOM API 權限,Script 的存取也依照其網址網域名稱給予嚴格限制,避免 XSS 或本地檔案讀取等安全問題發生。

無論是外部的網頁,或者是 XUL 軟體,都是使用 XML/HTML/Java Script/CSS 來撰寫,因此概念上都是由 Window 載入 XML 文件,並透過 Java Script 來存取 DOM API。

開發延伸套件時,凡是在 XUL Overlays 或 XPCOM Components 中的程式碼,都是給予完全的存取權限。而從外部網頁載入的內容,應該給於其未賦權的權限。這種安全模式的設計,乃是防止網頁上的程式可以任意存取系統資源,是一道安全保護牆。

由於 Mozilla 社群並未對安全模式定義名詞,這裡暫區分稱呼如下兩種安全模式

  • Web content document (non-privileged)
  • Chrome document (privileged)

各個程式的安全模式可依照該載入網址作區別,例如 chrome:// 有完全權限、http://example.com 則可存取 example.com、file:/// 則可存取本地檔案。

你也可在利用 PrivilegeManager  詢問使用者後存取 XPCOM 或者讓 XMLHttpRequest 跨網域存取。除了預設依照網址判斷外,開發者可以設計不同的內容使用安全模式,開發者可以決定直接載入網路資料後在 Chrome Document 中執行,或者利用 type=”content” 之方式使其載為 web content document.

但是剪下貼上是一個開發者都會犯的錯誤,最常見的錯誤之一就是直接把外面抓回來的資料,用 innerHTML 直接塞進 chrome document 中。有時候資料中會含有一些 java script,雖然 <script /> 中的語法不會被執行,但是 <img onerror=”alert(‘xss’)”> 這種程式碼還是會被觸發,外部資料中夾帶程式碼的狀況還是相當多,因此凡是處理外部連結都要小心。

Security Assessment Roberto Suggi Liverani 與 Nick Freeman 在上個月初於印度舉辦的 SecurityByte & OWASP AppSec Conference 中,與今年年中的 DefCon 17,發表了幾個 Mozilla 上的零時差漏洞。根據他們的文章與簡報,最常見的就是如 RSS Feeds 中的 <description> 的程式碼會被觸發執行、或者像是 FireFTP 1.1.4 以下的版本,會執行伺服器上的歡迎頁面。或者是熱門的 ScribeFire 3.4.3 以下版本,會以 chrome document 執行 <img onLoad=”alert(‘xss’)”>。

避免這些錯誤的方法之一是盡量使用 DOM manipulation methods 來塞入內容。在 Security best practices in extensions 一文中,講解了數個開發安全延伸套件的方法與注意事項,像是無論如何得執行他人的 Script,那就用 evalInSandbox 來執行。

另外你若得在兩種安全模式間互傳資料,正確的作法應該是盡量利用 DOM Event.

剛讀到這篇 Component Directory Lockdown 新聞時,乍看標題誤以為 Firefox 3.6 中所有的 XPCOM components 都將被閹掉、無法使用了。認真讀了火狐人肉盾牌 (Human Shield) Johnathan Nightingale公告、以及 Vladimir Vukićević詳盡說明,知道關掉的是官方自動載入 Firefox 安裝目錄下的 components 目錄。

其實是為了一些惡搞軟體所下的限制,特別是在 Windows 平台上。許多 Windows 使用者都會安裝一些防毒軟體、輔助工具等等,許多 Windows 上的工具軟體常便宜行事,會偷偷在 Firefox/components 目錄下塞入自己的 XPCOM 元件,藉此置入功能到 Firefox 中。在 Firefox 的設計中,這些 XPCOM 元件都會依照其宣告被自動載入、執行。

問題在於不少軟體的作法都是射後不理,軟體公司常常依照特定版本的 Firefox 開發其 XPCOM 元件,安裝時強制安裝該元件檔案到 Firefox 的 components 目錄,然後就不管了。隨著時間演進,使用者可能會升級 Firefox,結果這些非官方的 XPCOM 元件未被升級,造成相容性問題而使整個瀏覽器當掉。

XPCOM 是設計來接取一些基本的系統資源、或與其他函式庫介接,若是 API 版本不合,不小心會造成當機、安全漏洞或系統損毀。特別是 XPCOM 不同於 Extension,在瀏覽器一執行時就會載入,也不作版本驗證。對於使用者而言,也無法像擴充套件一樣,透過設定介面關掉或移除有問題的外掛。於是使用者很容易就怪罪這個瀏覽器不穩定。

於是,在 Firefox 3.6 中,將只載入寫在 components.list 的官方元件。一般開發者若想使用 XPCOM 元件,應該使用包裝成 extension 的形式,讓系統自動安裝,詳細的技術細節請參考 Mozilla 開發網站

拜讀 David RichardsGnome Boston Summit 2008User Experience Hackfest 所發表的簡報,這份簡報分享了在 Florida 的 Largo 市政府 佈署了五百多台 Debian, Gnome 為基礎的 Thin Clients, 作為政府員工的工作環境。這個系統大約有七百位使用者,平均上線約 300 人。

簡報中概要描述了一些架構與技術細節,像是 Thin Clients 的基礎建設是以 NoMachine 為基礎等,詳情請參考其簡報。論述中提到政府部門的需求,以及從數百名使用者中所習得的關於可用性的經驗。私認為相當值得參考,許多開發者認為簡易方便的功能,對於一般使用者 (average user) 而言可能毫無頭緒。

這裡僅節錄我認為特別有趣的事項,這些是對這群使用者而言可行的軟體設計。

  • 設計一 MIME Helper Bars (Intermediate MIME bar),因為使用者常不知該將檔案置於何處,或是該如何開啟、列印、儲存到桌面或文件夾或編輯。於是 Helper bar 的功能是幫使用者決定預設存在哪裡,或直接列印或寄出郵件,而不需要先開啟 OpenOffice, Evolution 再開啟檔案。
  • 立方體多重視窗。使用者往往不知道該怎麼利用預設的 workspaces 設計,反而透過立體視覺作桌面切換,可以看到自己的軟體視窗浮在不同的桌面上,相較直覺。
  • 單層軟體選單。樹狀選單基本上是行不通的,使用者找不到得點選超過兩次的項目。
  • 透明視窗,讓使用者看到全部的視窗。
  • 詢問對話框 (dialog)。許多軟體設計,會用對話框詢問使用者問題,像是「你是否要寄出此郵件?」等,但這種對話框是浮動的。也就是若你同時開了許多軟體,對話框很容易就被其他視窗蓋住,按掉對話框前原本郵件編輯器就無法使用,這點十分令人困惑。比較好的設計是點選編輯器時,應優先叫出蓋在上面的對話框,或改以其他對話框設計,如嵌入原編輯器中。
  • 以電子郵件寄出功能。這是最常用得功能,可是卻藏在選單或只是一個小按鈕。
  • 自動轉檔後用電子郵件寄出。雖用 OO.o 但是有時寄出文件仍需 PDF or Microsoft Office Word 格式。使用者毫無轉檔頭緒,另存新檔、開啟 Evolution、丟進檔案或用 File Chooser 選、送出,程序太多了。
  • 檔案管理員軟體太複雜了,以檔案系統為導向的設計常困擾使用者。所有的檔案選擇介面應該一致,不要限制「選擇檔案」、「開啟檔案」等,例如你用 OpenOffice 想開啟一 odt, 但使用者選擇一 mp3 檔案,那就開啟 MP3 Player. 應該要有最常用目錄與檔案功能,而且發現常用目錄,應該自動提醒使用者是否要建立捷徑。也應該有最近開啟檔案。
  • 使用者分不清 Keyring 是甚麼。

一些其他的回應與想法已被收錄於 Feedback And Ideas Discussed During City of Largo PresentationQuick Features 一頁。

昨日晚去 Tossug 聽 Chrome OS 團隊的Google 工程師談偉航介紹 Chromium OSericsk 前輩對此聚會寫了演講摘要紀錄。演講的內容大約不外乎推廣 Chrome OS 設計理念,也就是「快速」、「簡單」、「安全」。

關於這個演講,我自己所見的疑問之一,是使用者資料安全的問題。雖說 Google 倡議其設計會將個人資料加密後存於本機,既使實體電腦遺失也不用擔心資料被竊走 (所謂豔照門 ?),但其資料是會存至雲端系統,功能是讓你在不同的機器上同步個人資料與設定。不過目前網路上還沒有文件或技術規格說明其如何儲存個人資料,而個人資料的可儲存空間收費方式也是一個待議的問題。

作為一個使用者,我實在不希望任何的設定或文件以明碼的方式存於 Google,這家公司已經掌握太多個人資料了。一些使用者願意使用像是 Google Desktop 之類可以帶來一些便利的工具,但實質上是自願拿個人隱私與獨大公司交換便利性。這個代價實在太大了一點。

查了一下目前版本的 cryptohome 設計是預設以一動態金鑰對加目錄作 aes-cbc-essiv:sha256 加密。因整合一 pam_google 模組,各帳號登入時會自動掛載,並獨立加密。至於資料傳到雲端的部份,目前尚不知其如何作。

Native Client

另外一議題,似乎還沒有多少人重視,但我仍期待的是 Native Client。在當代的作業系統上,即便你有超過一半以上的時間可能都只是發發信件、瀏覽網站、上上社交網站,但是還是有許多使用者期待良好的影音效果或遊戲。雖說現在有各家利用 JIT 技術激烈激烈的 ECMA Script (Java Script) Engine,再配合 HTML5 已經可以作相當多應用。不過這種系統介面無法滿足想用盡每一個處理器指令集的多媒體解碼器或遊戲製造商,而且這些軟體開發者手上都已經有不少 code base,他們會希望可以移植,而不是從頭開發。

所以最好還是在系統上挖一個洞,讓開發者可以在瀏覽器上用盡所有硬體資源。業界的一個實做方式是 Microsoft 的 ActiveX,基本概念上就是讓你可以存取作業系統上的各種軟體元件。但是其安全機制一是透過數位簽章 (digital signing) 確保安裝檔未被竄改,一則是詢問使用者是否允許安裝。而這種模式輕易的讓許多麻瓜的電腦上種滿了木馬。

其中一個選擇是使用 NPAPI 的 Plugin. 雖說現在 Chrome Browser 已經開放了 NPAPI 的外掛支援。但是其實 NPAPI 相當不安全,且不甚方便的。不安全指 NPAPI 的權限極大,現有的架構讓 Plugin 可以讓人存取系統資料。而避免安全問題的方式,就是不自動安裝,除了熱門外掛外,其餘的皆讓使用者自己去尋找官方安裝檔。這有效的降低中毒機會,因為麻瓜往往不知道從哪下載木馬。實際的使用經驗仍不便利。

另外一種模式是建立一個沙箱 (Sandbox),讓所有的程式都在安全的 VM 上跑。這種實做之一是 Adobe 的 Alchemy 計畫,Alchemy 的作法是利用 LLVM 與調整過得 gcc  將 C/C++ 原始碼編譯成給 Action Script Virtual Machine 2 用的 bytecode。於是你可以將原本的 C/C++ 軟體移植到 VM 上,並在瀏覽器中執行。好處是安全,壞處是這樣降低了一些效能,同時也無法用到特定硬體上的多媒體處理指令集。

而 Google 所倡議的作法是 Native Client. 基本作法是希望可以既提供便利性,也可以涵蓋安全與效能之需求。在 IEEE Symposium on Security and Privacy (Oakland’09) 所發表的這篇論文 Native Client: A Sandbox for Portable, Untrusted x86 Native Code 中詳盡的描述了在 x86 的一些策略與作法。

基本上,Native Client 的架構分為

  • 內部沙箱:binary validation
  • 外部沙箱:OS system-call interception
  • service runtime binary module loader
  • service runtime trampoline interfaces
  • IMC (Inter Mdule Communication) (aka SRPC, Simple RPC)
  • NPAPI

目的是為了達到 Software Fault Isolation,安全上的設計用了 x86 memory segmentation 來限制軟體可存取之記憶體與資料範圍,另外也控制 system-call 的限制,僅開放特定 API。另外若該軟體呼叫了不支援的指令集,則系統會以 HLT 指令避開,避免程式執行錯誤。

使用時,瀏覽器外掛會直接下載已編譯的 nexe 檔案,並用其特製 loader 載入執行,使用時不像傳統外掛模式,還需逐同意或手動安裝,方便許多。而與網頁的互動也可以用 Java Script 透過 SRPC 或 NPAPI 控制。

若想進一步瞭解,請閱讀 Native Client: A Sandbox for Portable, Untrusted x86 Native Code 一文 (請參考簡體中文摘要),以及 Brad Chen技術演講,技術演講頗多場,可參考 Google I/O video (簡報) 這場,或較新的 Velocity video 這場或在 University of Washington 演講

沒時間看的話,可以看上述的短片的簡介,影片中稍微展示了利用 Native Client 解決影片解碼軟體的問題。目前的軟體架構已經擺入如 SDL, termcap 等,因此你可以玩玩最常被拿來展示的 SDL Doom 或是嵌入 Web 的 VIM!

Native Client 的架構與效能,相較於其他的 sandbox 環境應該是簡單且快一點,至少跟 Microsoft Xax 比起來容易許多。剩下的問題就是能否贏得開發者與使用者的青睞,Native Client 必須要證明其是絕對安全,為了確保安全性,今年,Google 甚至還辦了一個競賽,邀請大家來協助破解。另外一個重要的課題是,移植軟體的相容性與除錯性也會是非常重要,這點還沒有經驗或文件,尚無法判斷。

目前使用 NPAPI 時,現有 API 有些問題,容易造成與 HTML 混用時的一些排版或顯示錯誤。關於這方面 Google 也已經提議了一組新的解決方法在 Mozilla 的 PlatformIndependentNPAPI

其他

另外一些關於 Chrome OS 平台的筆記

Tossug 會後有段時間說明 G 社目前為 Chrome OS 開了些職缺,供人投遞履歷,有人感興趣嗎?

若想利用 HTML 5 開發一些多媒體程式的網站,你大概會需要一個本地檔案處理的 API 來儲存影片、圖檔等。同時你大概也會希望創作一種類似桌面系統的使用經驗,讓使用者可以直接從原生作業系統拖拉檔案到你的 Web Apps 中。而檔案塞進網頁程式後,又可以製作成縮圖,讓使用者透過網頁介面進行管理。

這些功能在 Google Gears 0.5.21.0 皆已經實做,包含了支援 Bolb, Blob BuilderDrag & Drop supportImage thumbnailing

除了 Google Gears 的實做以外,其實從 Gecko 1.9.2 後在 Firefox 3.6 與 Fennec 1.0 也支援了這些直接利用 Java Script 進行檔案處理的功能。於是你可以利用 Java Script 刻一個的檔案瀏覽器工具,拿 FileList 來接受使用者拖拉進瀏覽器或自選的檔案列表,用 FileReader 作一些簡單的處理,像是把圖片丟進 Canvas 讓使用者改一改後,再傳到網路上伺服器存放等。依據安全性考量,你自然不能直接拿 File Reader 來讀系統檔案,File Reader 的參數都必須是使用者自行選擇帶入的 File 型別才可以。如此便可避免拿 Java Script 作壞事的機會。

Mozilla 的 Arun Ranganathan 已提交 File API 一案至 W3C 供獨立審核。其他關於 HTML5 的 API 請見我的 blog,或參考 Mozilla 的 HTML5 support in Mozilla

關於 Web Typography。過去,你若想讓網頁上出現多樣性的字型與排版,往往得將文字作成圖片或 Flash 來顯示。如此一來常常使網頁失去文字複製、搜尋引擎最佳化 (SEO) 的功能,一個網頁製作再精美,但卻沒有人可找來閱讀的話,也是徒勞無用的。

於是你想使用瀏覽器預設的功能,但又不想屈就於有限的作業系統內建字型,這該怎麼辦?你或許會利用像是 sIFR, FLIR, Typeface.jsCufón 等替代方案。

sIFR (Scalable Inman Flash Replacement) 來講,sIFR 是利用 Java Script 與 Flash 動態的替換瀏覽器上的文字,字型則來自網頁設計者預先從系統中設定欲使用的字型於 Flash 中。

而 Cufón 概念亦差不多,不過作法是先將字型外型轉成 Java Script/JSON 格式,實際使用時再利用 HTML5 Canvas 繪出字型。Cufón 的作法所生成的 Java Script 雖比所用的 Truetype 字型小,但其實檔案大小也頗大,BCSEEATI 試驗了一分割字型方式,可有效降低傳輸量,但需把字型計算工作轉移到伺服器端。

Cufón 的一項缺點是,用了 Canvas 來繪圖,結果造成使用者無法點選文字。關於這個問題,TypeSelectTypeface.js 用 span tag 解決的選字的問題。這些作法都頗討厭,因為你要求瀏覽器為了美觀顯示,多做了圖形運算或重複塞了一圖一字就為了美觀跟可選字。

若是可以讓瀏覽器直接依字型繪字不是很好嗎?在 Firefox 3.5 (Gecko 1.9.1) 後,Firefox 開始支援了 CSS 的@font-face 語法。於是,你有機會可以用 font-family 來指定一些擺在網路上 TrueType 或 OpenType 字型,直接讓流覽器繪出美麗的文字 (中文版: 顛覆網路 35 天 (4b): 以 @font-face 使用你喜歡的字體 by BobChao)。 文泉驛的雲字體計劃便是應用 CSS 更換字型的例子之一。

但是對於字型廠商來說,並不樂見讓你隨意在網路上使用 TrueType 或 OpenType 字型。主要的原因就是版權濫用,同樣的一套字型很可能會被大量複製。另外,對於瀏覽器開發者而言,納入 DRM 控制網頁用字型顯然是與網路傳統背道而馳。對使用者而言,這兩種格式都太大,會浪費相當頻寬下載所需字型。

就頻寬的問題而言,其中一種解決方式如 Microsoft 所倡議的 Embedded OpenType (EOT),解決方案是以工具掃瞄網頁,並從字型檔中抽出網頁所需的字型。這樣的確可以降低頻寬使用,但是總覺的每次都要產生特定的字型檔實在有點太麻煩。

比較好的作法或許使利用壓縮的機制來降低傳輸量。Mozilla 的 Jonathan Kew 於是提議了一種新的規格 ZOT,基本上就是 OpenType 的壓縮,但壓縮的是 SFNT 字型檔中的獨立表格。這種格式的好處是有效壓縮字型檔大小,在 Web Open Font Format for Firefox 3.6 一文中提到,此格式可將 3.1MB 的 TTF 字型檔壓縮成 1MB 左右。另外一個好處是由於 table 獨立壓縮,因此像是記憶體容量較小的行動裝置,可以下載字型後依照 cmap 表格找到相對應的字型,依照需求再逐一解縮壓,可解省些系統支援。

另外一個需求會是版權的問題,Jonathan Kew 倡議 ZOT 時,同時有人為了字型供應商的需求做了 .webfont 格式。基本上的用意是希望能夠在字型中夾帶一些 metadata,使供應商可以追蹤網站所使用字型是否符合版權,但是不加以 DRM 保護。這個提議已經得到一些字型供應商的支持

這些規格加起來就是 WOFF File Format 在新釋出的 Firefox 3.6 中,預定支援 Web Open Font Format (WOFF) 之格式。ars technica 有一篇詳盡的報導 Web Open Font Format backed by Mozilla, type foundries,介紹了 WOFF 中的一些規格演繹與技術說明。在 after Firefox 3.6 – new font control features for designers 一文中有相當精彩的字型應用展示,如利用網頁字型重現傳統印刷字等。

目前此規格已經在 W3 的 Web Fonts Working Group Charter 中,目前只有 Firefox 支援 WOFF,接下來要便看其他的瀏覽器是否願意支持此規格了。可於 www-font 郵遞論壇追蹤最新的進展。

2009-12-02 後記: John Boardley 的 Web fonts. Where are we? 亦相當有參考價值。簡體中文翻譯請見關於 Web 字體:現狀與未來