13

我們目前正在研究一個非常簡單的Web應用程序,並且我們想「混淆」(什麼是正確的術語?)或者以某種方式編碼請求參數,所以我們可以減少機會一個空閒的用戶無法發送任意數據。編碼/模糊HTTP參數

例如,URL看起來像/webapp?user=Oscar&count=3

我們希望有類似的財產以後:/webapp?data=EDZhjgzzkjhGZKJHGZIUYZT,並有與實際要求信息的服務器解碼該值。

在開始實施類似這樣的事情之前(可能做錯了)我想知道是否有什麼可以做到這一點?

我們在服務器上有Java,客戶端上有JavaScript。

+0

如果從形式發佈,該參數將不會是URL – DwB 2010-10-25 18:53:56

+1

這就是爲什麼DWB說,「郵報」 – 2010-10-25 19:23:12

+0

據我所知混淆是當數據被隱藏,因爲複雜(如ROT13或XOR的一部分操作),加密就是您必須知道訪問數據的祕密。 – 2010-10-25 20:07:43

回答

27

不,不要這樣做。如果您可以在您的客戶端代碼中構建一些模糊處理將數據傳輸回服務器的方法,那麼故意的黑客也是如此。無論您的官方客戶端做什麼,您都無法信任發送到您的服務器的數據。 堅持轉義客戶端數據並根據服務器端的白名單進行驗證。使用SSL,如果可以,請將您的請求參數放在POST中而不是GET中。

擴展編輯

你的困惑來自於從請求數據篡改,與需要實現標準的安全措施阻止用戶的目標造成的。 Web應用程序的標準安全措施涉及使用身份驗證,權限和會話管理,審計跟蹤,數據驗證和安全通信渠道的組合。

使用SSL不會阻止客戶端篡改數據,但它確實可以防止中間人看到或篡改數據。它還指示行爲良好的瀏覽器不要在URL歷史記錄中緩存敏感數據。

看來你有一些簡單的Web應用程序沒有身份驗證,並傳遞請求參數在GET中控制它,因此一些非技術上精明的人可能會發現可以簡單地更改user=WorkerBeeuser=Boss,因此他們可以訪問他們不應該看到的數據,或者做他們不應該做的事情。 您的願望(或您的客戶的願望)混淆這些參數是天真的,因爲它只會打消技術最不熟練的人。這是一個不完整的測量,您還沒有找到現有解決方案的原因是它不是一個好方法。您最好花時間實施一個體面的身份驗證系統,並提供審計跟蹤以確保衡量(如果確實如此,請將Gary's answer標記爲正確)。

所以,把它包起來:

  1. 安全通過模糊處理是不是 安全性可言。
  2. 即使用戶數據被遮擋,也不能信任 用戶數據。 Validate your data
  3. 使用安全通信通道(SSL) 可幫助阻止其他相關威脅。
  4. 你 應放棄你的做法,並做 正確的事情。正確的做法,在 你的情況,很可能意味着添加一個 認證機制與 權限系統,以防止用戶 訪問的東西,他們不 特權不夠看 - 包括 東西他們可能會被 嘗試訪問篡改GET參數。 Gary R's answer,以及戴夫和威爾的評論點擊這個在頭上 。
+1

所以,你的建議是*「不要這樣做,因爲它不完美」*?我真的不知道如何驗證客戶端數據。例如,如果URL是'/ getinfo?user = oscar'我想如何驗證白名單中的值:「Oscar」。不會使用SSL + POST就像不使用SSL一樣容易? – OscarRyz 2010-10-25 19:48:42

+1

@OcarRyz,對於您的示例,您可能希望將該用戶簽署到您的應用程序中,並使用存儲在cookie中的會話ID來驗證其身份以用於將來的請求。然後,當他們嘗試查看奧斯卡的信息時,您可以驗證奧斯卡是否存在,並且該用戶是奧斯卡本人,或者是有權查看奧斯卡信息的人。 – 2010-10-25 20:06:12

+0

我喜歡這個答案。是的,U應該總是在服務器端驗證正確的輸入,不管是什麼!另外,如果你保留一點點有意義的查詢字符串,它可以讓混搭開發者在你的網站上做一些有趣的事情,如果他想做的話! – 2010-10-25 20:37:24

0

您可以使用base64或類似的東西編碼數據。我會用JSON將參數自身編碼爲序列化它們。

10

如果您的目標是「減少空閒用戶發送任意數據的機會」,我會嘗試另一種更簡單的方法。製作一個私人加密密鑰並將其存儲在應用服務器端。無論何時您的應用程序生成一個url,都可以使用您的私有加密密鑰創建url的哈希值,並將該哈希值放入查詢字符串中。每當用戶請求帶有url中參數的頁面時,重新計算散列並查看它是否匹配。這會讓你確定你的應用程序計算出了url。它會讓你的查詢字符串參數可讀。在僞代碼中,

SALT = "so9dnfi3i21nwpsodjf"; 

function computeUrl(url) { 
    return url + "&hash=" + md5(url + SALT); 
} 

function checkUrl(url) { 
    hash = /&hash=(.+)/.match(url); 
    oldUrl = url.strip(/&hash=.+/); 
    return md5(oldUrl + SALT) == hash; 
} 
+1

非常好,乾淨! – oimoim 2010-10-25 19:10:21

+0

你是什麼意思「每當你的應用程序生成一個url」?你的意思是「當客戶產生請求時」? – 2010-10-25 19:10:45

+0

@Mike,我假設url字符串將來自應用程序的服務器端。例如,應用程序可能會執行類似'">Get 3 of these.' – 2010-10-25 19:18:26

3

如果以防止「靜態」的網址被操縱的目標,那麼你可以簡單地加密參數,或簽字。對於URL參數的MD5以及一些鹽,它可能「足夠安全」。例如,鹽可以是存儲在會話中的隨機字符串。

那麼你可以:

http://example.com/service?x=123&y=Bob&sig=ABCD1324 

該技術公開的數據(即,它們可以「看見」 XYZ = 123),但它們不能改變的數據。

有一個「加密」的優點(我使用這個術語鬆散)。這是您加密URL的整個參數部分的地方。

在這裏,你可以這樣做:

http://example.com/service?data=ABC1235ABC 

有關使用加密的好處是雙重的。

一個它保護數據(例如,它們的用戶永遠不會看到xyz = 123)。

另一個特點壽就在於它的可擴展:

http://example.com/service?data=ABC1235ABC&newparm=123&otherparm=abc 

在這裏,你可以解碼原始的有效載荷,並做了(安全)的新數據合併。

因此,請求可以將ADD數據添加到請求中,而不會更改EXISTING數據。

您可以通過簽名技術做同樣的事情,您只需要將整個請求合併到一個「blob」中,並且該blob被隱式簽名。這是「有效」加密,只是一個弱加密。

顯然你不想在客戶端做任何這樣的事情。毫無意義。如果你可以這樣做,「他們」可以做到這一點,你不能說出區別,所以你可能根本就不這樣做 - 除非你想通過正常的HTTP端口「加密」數據(vs TLS,但人們會明智地想知道「爲什麼打擾」)。

對於Java而言,所有這些工作都在Filter中進行,這就是我所做的。後端與此隔離。

如果您願意,您可以使用出站過濾器將後端完全隔離,該出站過濾器可以在出站時處理URL加密/簽名。

這也是我所做的。

不利的一面是,它非常重要,它使得它正確和高效。你需要一個輕量級的HTML解析器來提取URL(我寫了一個流解析器來實時動態地執行它,所以它不會將整個頁面複製到RAM中)。

好的一面是所有的內容方面「正常」,因爲他們不知道任何事情。

處理Javascript時還有一些特殊處理(因爲您的過濾器不會輕易「知道」哪裏有要加密的URL)。我解決了這個問題,要求將url標記爲特定的「var signedURL ='....'」,這樣我就可以在輸出中輕鬆找到它們。不要像你想象的那樣爲設計師減輕負擔。

過濾器的另一個亮點是您可以禁用它。如果你有一些「奇怪的行爲」發生,只需關閉它。如果行爲仍然存在,您會發現與加密相關的錯誤。它還讓開發人員以純文本工作,併爲集成測試留下加密。

很痛苦,但總體來說很不錯。

+0

大多數人不會通過將數據存儲在服務器端會話中來執行此操作嗎?這看起來像MS視圖狀態對我來說。 – UpTheCreek 2013-04-27 11:02:00

5

如果您試圖限制對數據的訪問,請使用某種登錄機制,並使用Cookie提供單點登錄身份驗證密鑰。如果客戶使用密鑰發送cookie,則他們可以根據與其賬戶相關的權限(管理員,公共用戶等)來操作數據。只要看看Spring Security,CAS等,以便在Java中使用這個實現。 cookie中提供的令牌通常使用發行服務器的私鑰進行加密,並且通常具有防篡改功能。

或者,如果您希望您的公共用戶(未經身份驗證)能夠將一些數據發佈到您的網站,則所有投注都將關閉。您必須在服務器端進行驗證。這意味着限制對某些URI的訪問,並確保清理所有輸入。

這裏的黃金法則是禁止一切,除了你知道的安全的東西。