題:
不能反向工程的順序標識字符串(“發票編號”問題)
Escher
2015-12-13 22:07:45 UTC
view on stackexchange narkive permalink

假設我經營一個網站,您可以在其中創建貓的圖片。我為每張貓圖片賦予唯一的標識符,以便可以在社交媒體上與 http://catpictures.com/base62Identifier 共享。

我可以為貓圖片賦予順序標識符(例如1,2,3等),但可以輕鬆發現用戶每天創建多少新貓圖片(通過每天返回HTTP 200的最大標識符)。這使我了解了一種常見的策略,即每月從競爭對手那裡訂購產品並註明發票編號。網站訪問量數字與業務收入密切相關,因此我顯然希望將此信息保密。

我正在考慮嘗試的工作:

這聽起來像是哈希算法的工作, 對?問題是通過觀察哈希值,很容易分辨出是哪個算法創建的(md5,crc32等)。擁有彩虹桌的人會簡化這個想法。我可以對標識符[hash(“ salt” +1),hash(“ salt” +2),...]進行加鹽處理,但隨後必須擔心與加鹽處理相關的安全性。還有碰撞檢查。

我的另一個想法是生成一個隨機的字符串,並將其用作數據庫中貓圖片的主鍵(或者我可以對貓圖片數據的前n位進行散列)。這樣,我只需要檢查衝突即可。

是否有一種標準的最佳實踐方法,可以避免通過唯一的標識符URL暴露流量?

編輯:專門尋找一種可以將安全性和適用性很好地結合在一起的解決方案,作為數據庫主鍵或可索引列。

有什麼原因不能為每個資源使用隨機數?不需要任何哈希。
使用[乘法逆](http://ericlippert.com/2013/11/14/a-practical-use-of-multiplicative-inverses/)是否足夠“安全”?
十三 答案:
Rory McCune
2015-12-13 22:52:39 UTC
view on stackexchange narkive permalink

解決此類問題的標準方法是為每張圖片創建 UUID(通用唯一標識符)。通常,這是一個隨機的128位標識符,您可以將其分配給每張圖片,而不必擔心通過對命名空間的蠻力攻擊來枚舉圖片。

例如。 NET,您可以將 GUID結構用於這種目的。 自Windows 2000 source)以來, Guid.NewGuid 生成隨機(版本4)UUID。 (古代版本生成了版本1 UUID,其中顯示了生成日期,但並沒有採取任何措施來保護您免受“發票編號”問題的影響。)

v4 UUID是否不是通過加密功能強的PRNG生成的,從而使其具有適當的隨機性?
@AndréBorie:使用UUID作為主鍵時觀察到的主要性能缺陷是隨機UUID不適合用作聚簇索引,這是PK的默認SQL Server設置。因此,必須確保適當配置表,並將主鍵設置為NON CLUSTERED。
@Escher [規範](https://www.itu.int/rec/T-REC-X.667-200409-S/en)“強烈建議”採用密碼安全的RNG,但並不禁止使用非RNG確保一個。
關於UUID與CSPRNG的說明:最好的兩個詞是使用CSPRNG生成數字,然後通過位掩碼將其設置為UUID v4。
關於這些問題的擴展討論應該轉到DBA.SE,但是從DBA的PoV UUID可能會出現問題。它們以自然的形式不適合使用集群密鑰,從而導致過多的碎片。 SQL Server中的“後續UUID”折衷可以解決此問題,但會重新創建關鍵的猜測問題。某些人認為,它們的大小也可能是一個更大的問題:以及數據中每行12個額外的字節(與32位整數鍵相比),相關索引的每行有12個額外的字節(而對於32位整數,則為每行12個) * all *索引(如果您的集群鍵在UUID中)。
@David Spillett,答案是“不要在UUID上群集”。關鍵索引不必是聚簇索引。
@GreenstoneWalker:是的,但是有時也沒有另一個真正有用的集群鍵,在任何情況下,很多人默認就不考慮其PK進行集群。我要說的是“事先考慮一下,您和/或您的DBA稍後會感謝您”(我認為您同意)。
Ángel
2015-12-14 02:07:05 UTC
view on stackexchange narkive permalink

我只會使用圖片哈希。有人弄清楚您使用的哈希是什麼問題?如果我認為“ URL的這一部分看起來像sha1”,請下載文件,並且它具有那個 sha1,我是對的。但這並不能使我打破您的“貓的安全性”。即使嘗試破壞散列來找出圖片是可以治療的,但嘗試這樣做而不是簡單地下載圖片也沒有意義。

除非兩個用戶上傳同一張貓的圖片(都是從其他地方上傳),然後哪個用戶“擁有”它(例如可以刪除)?這是假設禁止重複本身不是好處。
@abligh,很好,在這種情況下,我只保留一個上傳它但未刪除它的用戶列表。但是,當然這取決於用例。在某些情況下,您需要隱藏來自不同用戶的兩個文檔實際上是相同的事實,在這種情況下,您可以將用戶ID放入哈希內容中。
如果不是貓的照片而是大的ZIP文件(例如),此方法還可以防止重複的文件被上傳。
@abligh您不必使用主鍵作為在典型URL路由中查找圖片的方法。例如,您可能擁有“ mysite.com/users/user_id/pictures/image_hash”或“ mysite.com/pictures/image_has/users/user_id”。我想我想說的是,只要您執行`image <-> user`關聯,圖像散列就可以用來在數據庫中查找圖像(就像其他任何列一樣),而不是整數主鍵,然後只有與圖像ID關聯的用戶才能刪除它。但是,如果您沒有強制登錄上載,那就是另一個問題。
@Prinsig和具有相同散列的不同文件
Philipp
2015-12-13 23:09:08 UTC
view on stackexchange narkive permalink

僅生成圖像數據的加密安全哈希並將其用作標識符。

這有兩個副作用:

  • 人們可以判斷圖像是否要求提供帶有該哈希的圖像已存在於您的服務中。
  • 人們無法上傳重複的圖像。

這兩種效果本質上都不錯。他們甚至可能派上用場。但是,如果您想避免它們,則可以使用來自安全隨機數生成器的偽隨機數對每個圖像散列加鹽。

衝突不必擔心。借助SHA256之類的哈希函數,天生的隨機碰撞的可能性是如此之小,當您找到一個時,就會很感動

我認為另一個副作用是需要長貓圖片網址:P
*人們無法上傳**完全相同的重複圖片*。打開一個.jpg,“另存為”,並對兩個文件進行哈希處理。 *可能*,您的軟件發現沒有變化並寫入原始數據,但是以任何圖像格式調整一個像素,哈希將有所不同。因此,鑑於“相同”圖片可能不是同一文件(例如,在手機上自動調整大小),您甚至無法可靠地防止人們意外地上傳“相同”圖片。 [圖像哈希](http://stackoverflow.com/q/998662/2583476)可以解決此問題,但這不是安全的哈希。當然沒關係。
具有實際圖像託管服務(例如Imgur)的@Chris,一個常見的用例是獲取從其他地方獲得的圖像文件並按原樣上傳,而根本不進行編輯,不更改單個像素,甚至不打開它在圖像編輯器中,然後點擊“另存為”。人們上傳點對點的相同圖片可能很普遍。
-1
關鍵是聲明“人們無法上傳精確的圖像副本”是錯誤的。
user253751
2015-12-14 03:33:05 UTC
view on stackexchange narkive permalink

標準方法是簡單地使用加密安全的偽隨機數生成器(CSPRNG)隨機生成您的URL。

不需要任何哈希等操作-只需使用普通的舊隨機數即可。它們也不必是GUID(除非出於某種原因,除非您的數據庫比簡單數字更好地處理GUID)。大概您的站點已經記住了每個URL可以訪問的圖像,因此只需對其進行修改以處理隨機URL而不是順序URL。

一個128位隨機數應該足夠長。

在處理新圖像時,請記住檢查重複的URL。

使用UUID(或GUID)意味著您不必檢查重複項-“ U”代表唯一,是UUID或GUID保證的一部分。但是,UUID不一定能保證不可預測性。用來生成足夠數量的比特的密碼安全偽隨機數生成器(CSPRNG)可以同時提供這兩者。
@JohnDeters大多數UUID是5型UUID,它們只是隨機數,並帶有“這是隨機數”指示符。
我同意。 RFC第6部分,安全性考慮因素始於:“不要假設UUID很難猜測;例如,它們不應用作安全性功能(僅擁有所有權即可授予訪問權限的標識符)。”但是,如果使用CSPRNG生成足夠大的數字,將很難猜測。照片的哈希值不適用於CSPRNG。
@immibis,如果願意,您可以自由編輯其他答案-但這並不是Stack Exchange的確切政策。請參閱http://security.stackexchange.com/help/editing和http://security.stackexchange.com/help/privileges/edit。如果您認為我的編輯沒有改善您的回答或使答案更糟,則可以撤消這些編輯。 (就我個人而言,我認為自己的編輯是一種改進,在添加了我在編輯中添加的其他警告之後,這將成為對該問題的最佳答案……但請隨時發表自己的看法。)
Aldian
2015-12-15 15:52:01 UTC
view on stackexchange narkive permalink

根據我在問題,評論和其他答案中所讀的內容,一切都在為每張圖片尋找唯一的標識符,這是無法猜測的,也無法提供有關圖片數量的信息,並且易於在圖片中處理。

然後,為什麼不只使用插入時間戳(自1970年以來的毫秒數)呢?如果兩個人有可能在同一毫秒內插入一張貓的圖片,則可以將其與對應於該毫秒內插入次數的序列號連接起來。

這樣一來,只有有人積極地搜索您的最後一張照片會發現有人最後一次添加照片,前提是您讓這樣的混蛋做出看起來像日常的dos攻擊。

同時,您無需擔心衝突或數據庫支持。

4chan做類似的事情,並且充滿了圖像
Philipp
2015-12-13 23:22:04 UTC
view on stackexchange narkive permalink

替代解決方案:

將元數據添加到圖像標識符。示例:

philipp_20151213_00002.jpg -用戶Philipp在2015年12月13日發布的第二張圖片。

我洩漏了該元數據,但它只是用戶可以使用的數據

這不會告訴觀察者您的服務上總共發布了多少圖像,僅與特定用戶在特定日期的活動有關。如果您也想隱藏它,則可以使用偽隨機數而不是連續數。當一個用戶一天內上傳大量圖像時,碰撞仍然可能發生,但是它們很少見,您只需生成一個新的隨機數,直到沒有被拍攝的隨機數,就可以處理它們。

Jonathan Gray
2015-12-13 22:55:32 UTC
view on stackexchange narkive permalink

這是一種方法。在服務器範圍內保留8字節的CSPRNG。然後為每個新圖像生成另一個8字節的CSPRNG。將此CSPRNG與整個服務器範圍的CSPRNG哈希在一起(md5很好)。然後,將哈希的最後8個字節與圖像ID(在數據庫中從0開始自動遞增)進行異或。客戶端將收到圖像的唯一8字節CSPRNG的Base64編碼以及8字節XOR結果。這將是公共映像ID。

當服務器接收到公共映像ID時,它將對公共ID的前8個字節以及服務器範圍內的8字節CSPRNG進行哈希處理。然後,它將獲取哈希的最後8個字節,並將其與公共ID的最後8個字節進行XOR運算。結果將是可以從數據庫中索引的專用內部ID。

更新(說明):

首先,預先定義一個隨機全局變量CSPRNG將用於所有ID計算(8字節或64位,具有18,446,744,073,709,551,616可能的組合)。

  serverCSPRNG = CSPRNG(8) 

對於從privateID(8個字節)創建一個新的公共ID(16個字節),請執行以下操作:

  newCSPRNG = CSPRNG(8)hashEnding = last8Bytes(md5(newCSPRNG + serverCSPRNG))publicID = newCSPRNG + XOR(hashEnding,privateID) 

用於從publicID派生privateID:

  hashEnding = last8Bytes(md5(first5Bytes(publicID)+ serverCSPRNG) )privateID = XOR(hashEnding,last8Bytes(publicID)) 

為了獲得更高的安全性,可以對publicID的最後8個字節進行XOR二級全局(僅靜態服務器)CSPRNG為了完全保護它免受暴力攻擊(因為它實施了安全模型一次性租金)。

這比僅使用隨機數更為複雜。它提供一些特定的優勢嗎?另外,如果您真的想提出這個建議,則可能要使用數學來描述您的方案。可能會更容易理解。最後,8個字節足夠嗎?如果有$ 2 ^ {32} $個圖像,那麼通過生日悖論,攻擊者可以通過執行$ 2 ^ {32} $個探測器來大致估計出您擁有多少圖像,因此我懷疑您最好使用128位左右。
@D.W。正如您建議的那樣,我將嘗試使用一種更類似於數學的方法來清除它。實際上會有8個字節的2 ^ 64(18,446,744,073,709,551,616,616)種可能的組合(這是64位保護)。但是,使用常規蠻力方法不能簡單地打破這種方法。它更多是一種一次性的方法。這是因為蠻力是在服務器CSPRNG上完成的,這將要求先了解公共ID以及相關的內部ID。甚至可以通過輔助服務器端CSPRNG(用於真正的128位保護)克服這一問題。
@D.W。至於特定優點,其他方法要求使用可能使用需要數據庫中具有附加索引列的實現的值。此方法*在行插入之後*導出公共ID,這可能也是有益的。此外,此方法在使用一個主數據庫的群集設置中將更好地擴展。由於可以將非唯一值插入需要唯一值的列中(如果正確實現),因此也無需補償錯誤。
感謝您的更新:新的說明使事情變得更加清晰。但是,我認為8字節不夠。暴力攻擊者只需要猜測“ serverCSPRNG”值,該值只有64位,因此暴力攻擊僅需要2 ^ 64 md5計算。這低於今天的建議,並且可能會以合理的費用實現。我確實看到了優勢;很好但是,我會建議一個稍微不同的方案:例如,我建議使用“ publicID = E(K,privateID)”,其中“ K”是一個128位服務器密鑰,而“ E”是一種強加密方法(AES?) 。
@D.W。我選擇此方法而不是強加密,因為它效率更高。但是,就像我試圖解釋的那樣(也許我不清楚),當進行暴力破解時,無法確定您擁有的值是否正確。有確定性的猜測方式,但是使用第二個8字節服務器範圍的隨機值也消除了這種可能性。第二隨機值的相加將完成對完全不確定的“完美”加密的要求。它比一次性膠墊稍微麻煩一些,但是概念實際上是相同的。
*“強行使用時,無法確定您所設置的值是否正確” *-我認為這是不正確的。我懷疑私有ID經常會具有某種結構,從而可以驗證“ serverCSPRNG”的正確猜測(例如,如果私有ID是連續的):猜測“ serverCSPRNG”,進行試用解密,並查看生成的privateID是否具有正確的結構/格式。
@D.W。私有ID是連續的,是的,但是該值最終會與通過隨機值得出的哈希值進行XOR運算。由於它是通過數學方式得出的,因此任何可能的公共ID都會產生有效的私有ID。確實沒有辦法驗證加密貨幣的任何部分以對此進行蠻力攻擊,尤其是在使用輔助CSPRNG的情況下(這將防止對已知私有ID的攻擊)。實際上,知道一台服務器CSPRNG僅在強行強制另一台服務器時會有所幫助(假定還知道私有ID)。
我想指出的是,我知道如果知道多個順序的公共ID,就有可能獲得足夠的信息以對原始服務器CSPRNG進行暴力破解。但是,在這種情況下,哈希衝突實際上對我們有利,因此可以使誤報成為可能。不好看輔助服務器級CSPRNG的額外使用增加了保護功能,該功能仍將防止由於第一個服務器的折衷(強力)而導致的內部ID洩漏。沒有這些,他們真正可以追踪的就是序列。
RobIII
2015-12-16 21:02:41 UTC
view on stackexchange narkive permalink

此處所述:哈希,UUID等具有“缺點”,即在數據庫中插入這些哈希/ uuid是PK且PK聚簇的記錄可能非常昂貴(定義昂貴...),因為它們通常不是順序的(除非使用了 NEWSEQUENTIALID 之類的特定功能,但是:請注意該頁面上的“重要”塊:“ 如果擔心隱私,請不要使用此功能。可以猜測下一個生成的GUID的值... “)。

除了這裡的建議,我還會考慮類似Twitter的(已停產雪花之類的東西。我寫了一個類似的.Net庫( IdGen);它的自述文件提供了一些有關其工作原理的信息。優點是生成的ID仍(大部分)是順序的,不會佔用太多空間(64位vs.128位UUID /哈希),並且可以在(不協調的)分佈式環境中使用,在該環境中您有多個主機/進程在生成ID時不會引起衝突。而且儘管它們是順序的,但是它們並不會在一段時間內提供太多有關貓圖片數量(或更籠統地說,“已使用ID”的數量)的信息。

Peter Taylor
2015-12-16 23:00:16 UTC
view on stackexchange narkive permalink

這聽起來像是哈希算法的工作,對嗎?

否,因為您觀察到必須擔心衝突。對我來說,這聽起來像是排列的工作,即分組密碼。這確實需要管理密鑰,這是不利的一面,但它允許您使用數據庫的自動增量功能,而不必擔心衝突。

棘手的部分是決定如何處理IV ,這裡您可以選擇。每次創建網址時,您都可以生成一個新的網址,因此,例如每張貓圖片2 ^ 128個不同的URL。您可以使IV按用戶或按會話進行,並作為用戶配置文件/會話狀態的一部分存儲在服務器端。您甚至可以將其設置為按用戶使用,但可以包含在URL中,因此您可以跟踪誰成功使圖片具有病毒性。

Alfred Armstrong
2015-12-14 23:29:07 UTC
view on stackexchange narkive permalink

一種方法是使用 hashids

Hashids是一個小型的開放源代碼庫,可從數字生成短的,唯一的,非順序的ID。

它將347之類的數字轉換為“ yr8”之類的字符串,或將[27,986]之類的數字數組轉換為“ 3kTMd”。

您還可以將這些ID解碼回去。這對於將多個參數捆綁為一個或簡單地將它們用作短UID很有用。

您的數據庫性能不受損害,因為您可以繼續在內部使用數字順序ID。同時,外部鍵是不透明的。

請注意,哈希值不是加密安全的:http://carnage.github.io/2015/08/cryptanalysis-of-hashids/可以由足夠積極的對手將ID轉換為數字
我認為對於此用例,哈希值是合理的。儘管哈希值是可逆的,但它們起步很短,可以保證它們是唯一的,並且可以防止令人反感的英語單詞(如fuck)顯示為哈希。通過使用大秘密可以減輕可逆性。它不會像UUID那樣“加密安全”,但是它確實具有許多面向客戶的發票編號所需要的屬性。
並非所有情況都需要加密安全性。需要時,我會選擇任意GUID。
Burhan Khalid
2015-12-16 12:54:06 UTC
view on stackexchange narkive permalink

我對這個問題有低技術含量的解決方案。只需使用URL縮短服務,或編寫自己的URL縮短服務。

它提供以下內容:

  1. 您的公共URL不會在社交媒體網站上公開。
  2. 保證您的URL是隨機的和任意的。
  3. 您可以自由更改資源命名的基礎實現,並且外部鏈接將繼續起作用。
  4. 更容易共享 http://catpic.to/i34dhY http://catpictures.com/some-guid-string
  5. 唯一ID很容易索引/搜索。
  6. ol>

    如果您不想依賴第三方服務,則可以通過使用該語言實現雙向功能輕鬆滾動自己的服務您的選擇。

Ian Ringrose
2015-12-16 21:49:10 UTC
view on stackexchange narkive permalink

問題:

  • 我們希望有一個連續的數字;否則,由於必須以隨機的順序更新索引的中間位置,因此向數據庫中添加記錄會變得昂貴。
  • 我們不希望數字與已上傳的貓數相關。
  • li>
  • 我們需要唯一的號碼,但只能在您的網站內。

因此:

  • nextCat 是設置為第一個網站啟動時設置為0,則可能需要為64位。
  • nextCat 已遞增 每次添加貓,並且 newCat 設置為 true
  • nextCat 會遞增 代碼>由隨機計時器觸發,該計時器以比您預期添加貓更快的速率觸發。但是,如果 newCat true ,則不會為此計時器觸發增量,並且將 newCat 設置為 false
  • 每隻貓也都具有GUID,但永遠不需要根據其GUID來找到它。
  • 貓的網址是something.com/cats/catNumber-catGuid
  • 如果當請求了cat的catGuid錯誤時,則對與cat不相關的catNumber給出相同的響應。

(計時器為隨機執行一次,因此很難區分在定時器觸發之間是否添加了兩隻貓。)

那麼貓的索引例如是0、1、4、7、8、10、12、15等?如果您知道用於生成隨機間隔的分佈,則可以取期望值,然後將Cat索引之間的差異相隔24小時,以對在此期間生成的Cat進行很好的估計。
謝謝@Escher,,我已經更新了答案,因此很難找到貓的索引。
fredogone
2015-12-14 02:04:15 UTC
view on stackexchange narkive permalink

一般最佳實踐:切勿在任何Web鏈接中公開PKEY。

在數據庫中-為了提高速度,您的PKEY必須是BIGINT。同樣在數據庫中,請考慮將此字段...( public_filename ..如果不存在)添加到表中。 public_filename 字段必須是引導字符串。使用guid函數將文件上傳到服務器後,使用唯一的文件名重命名該文件,並使用該文件名填充 public_filename

public_filename 應該為

也用於Web鏈接,而不是PKEY。

我還建議保留一個 user_filename 字段,以支持來自上載器的所有取證搜索-如果允許的話。 user_filename 是用戶上傳的原始文件名。

切勿在任何Web鏈接中公開PKEY-始終使用某種形式的 public_filename 。使用數據庫查詢將 public_filename 取消引用到PKEY,然後從那裡可以找出要從服務器提供服務的文件。

另一種最佳做法-永遠不要覆蓋用戶文件自動上傳。用序列號(-001,-002)重命名 user_filename 字段。

很可能您會從同一用戶那裡獲得許多名為“ mycat”的文件。

公開主鍵沒有錯。通常使用hash(data)作為鍵。
Navin-作為主鍵的哈希字符串確實很慢。你為什麼要那個?法醫-您沒有快速的序列。
fredogone-將哈希存儲在64位int中,而不是字符串中。當圖像添加到系統中時,您將僅對圖像進行哈希處理。當用戶想要檢索它時,他們需要記住哈希值。
Navin-您剛剛取消了取證程序,除非您保留另一個字段來獲取時間戳。
好吧,如果您曾經更新/編輯行,那麼自動遞增的ID也不會給您順序。
沒有任何法證證據正在尋找-是嗎?但是,如果您正在尋找在一定範圍的行之間創建的行-它會..自動遞增ID會為您提供。


該問答將自動從英語翻譯而來。原始內容可在stackexchange上找到,我們感謝它分發的cc by-sa 3.0許可。
Loading...