題:
安全地將客戶端高分發送到服務器
StationaryTraveller
2017-01-15 15:45:41 UTC
view on stackexchange narkive permalink

我正在創建一個包含簡單JavaScript遊戲的Web應用程序。玩家玩完遊戲後,會將高分發送到服務器並保存。

在特定時間段後,得分最高的玩家將獲得獎賞。

安全發送高分並防止客戶端發送“假”高分的方法?

當前,我們正在使用:

  • Https。
  • 在每個遊戲之前提供服務器隨機令牌,並在遊戲結束後隨分數發送。 li>
沒有萬無一失的方法來解決此問題。唯一的方法是跟踪服務器上每個遊戲的個人得分。
TLS在這裡無關緊要,並且如果試圖*是惡意的,則您無法確保在客戶端進行任何操作。您應該閱讀[關於您實際問題的答案](http://security.stackexchange.com/a/147047/91111)。
這裡有一個類似的問題,最上面的答案有很多好的建議。https://stackoverflow.com/questions/73947/what-is-the-best-way-to-stop-people-hacking-the-php-based-highscore-table-of-a-f
順便說一句,您*問*這個問題為時已晚。如果需要,這種安全性應該從一開始就內置,而不是在以後移植。
太太,如果破解遊戲的動機(以及假的高分)比破解遊戲的難度小,那麼您的遊戲就可能做得很好,因為對偽造分數沒有足夠的興趣。
六 答案:
grc
2017-01-15 16:54:50 UTC
view on stackexchange narkive permalink

服務器無法完全信任從客戶端接收到的任何數據,因此很難驗證高分。

以下是一些選擇:

  1. 混淆客戶端代碼和到服務器的流量。這是最簡單的選項-仍然可能作弊,但可能不值得任何人花費時間。

  2. 將游戲的全部或部分重播發送到服務器進行驗證。玩家的舉動可以在服務器上運行以確定合法分數。這將適用於某些遊戲,而不適用於其他遊戲。

  3. 將游戲邏輯和驗證移至服務器。客戶端只需將每個動作中繼到服務器,並在其中進行驗證並更新遊戲狀態。

  4. ol>

    這取決於遊戲的工作方式,人們的遊戲可能性會作弊,以及您是否在乎他們。

#3是執行此操作的唯一正確方法
@theonlygusti也許我誤解了這一點,但是您不必移動遊戲邏輯-您只需要在服務器上複製它即可。如果您發送的只是玩家的所有輸入,則服務器可以重播它們並驗證分數。然後,您只需要關心'TASbot'播放器即可:)。舉一個出色的遊戲示例-DROD。因為這是一個邏輯遊戲,所以它也可以抵抗工具輔助的遊戲。唯一無法解決的問題是狙擊,即有人觀看其他玩家的演示並尋找優化點。
-1
@theonlygusti我的意思是說“移動遊戲邏輯”,我覺得需要明確指出,您只需要復制它即可。我可能應該在評論中標記您的名字,因為我真的想整體上回答這個問題,而不是您的評論:)
@theonlygusti:對於許多類型的遊戲,2和3一樣好。
@theonlygusti校正,#3是唯一做到這一點的“萬無一失”的方法(但實際上並非如此,因為它不是萬無一失的!)。這只是所提供選項中最簡單,最困難的部分。
用於確定性遊戲的@theonlygusti,(想想:俄羅斯方塊),只要您不介意向AI授予高分記錄,#2就會奏效。
@Mark#2還具有客戶可以基於未來知識進行優化的缺點。例如。在俄羅斯方塊中,如果您知道將要獲得的所有部件,則可以找到比只獲得一件然後將其放置在某個地方然後再獲得下一個部件更好的策略。
#1在JavaScript遊戲中毫無用處,因為重新生成可讀代碼比使用任何其他語言都容易得多。
Philipp
2017-01-15 16:54:58 UTC
view on stackexchange narkive permalink

如果您的攻擊者是網絡層上的中間人攻擊者,那麼https就足夠了。但是不幸的是,您的攻擊者是客戶端,所以這毫無意義。

防作弊遊戲的第一規則:永遠不要信任客戶端!客戶掌握在敵人的手中。

JavaScript遊戲在用戶的網絡瀏覽器中運行。眾所周知,作為Web開發人員,如今每個Web瀏覽器都帶有內置調試器,該調試器可以在應用程序運行時查看和更改所有變量。用戶可以在提交分數之前簡單地使用調試器來更改其分數。您無法採取任何措施來防止這種情況。借助基於瀏覽器的遊戲,您甚至無法在其上使用第三者反作弊工具(該工具具有可疑價值,並且無論如何在倫理上都值得懷疑)。

唯一的對策是實施所有值得操縱的遊戲機制在服務器上。客戶端除了將用戶的命令轉發到服務器並根據服務器的消息可視化遊戲玩法外,什麼都不做。實際的遊戲玩法應該在作弊者無法到達的服務器上進行。

是的,這意味著您將不得不從頭開始重新設計遊戲的軟件架構。這也意味著您將必須添加一些預測和內插代碼,以使網絡滯後現像不那麼明顯。這也意味著您將需要更好的服務器硬件和更好的服務器Internet連接。但是,當您想要一款不作弊的在線遊戲時,這是唯一的選擇。

通常是“信任,但要驗證”響應-請參閱grc答案中的選項#2。
@MSalters不是“信任”,而是驗證**是矛盾的嗎?您不信任客戶,這就是您驗證其響應的原因。如果您信任客戶,為什麼需要進行驗證?
@Tom“信任但驗證”是來自俄羅斯諺語的常見短語(請參閱[Wikipedia](https://en.wikipedia.org/wiki/Trust,_but_verify))。是的,這是矛盾的,但您也可以將其理解為與“除非被證實有罪,否則是無辜的”。或者,如果維基百科假設用戶在編輯時出於善意行事(這只是一個維基,因為它沒有被鎖定),但仍然要求他們引用參考文獻。
Lie Ryan
2017-01-15 22:29:01 UTC
view on stackexchange narkive permalink

要獲得可靠的遊戲高分,您需要的是“ 工作證明”,或者更恰當的稱呼為遊戲證明。

工作證明/遊戲是在完成遊戲之前很難計算的任何數據,但是在完成遊戲之後很容易計算並且很容易被服務器驗證。例如,對於數獨遊戲,工作證明就是解決難題的方法。

不幸的是,在許多遊戲中都沒有通用的方法來集成合適的遊戲證明系統。並非總是可以在不調整或重新調整遊戲玩法的情況下集成遊戲證明,或者將排行榜的範圍限制為僅可以包含足夠安全的遊戲證明的元素。

遊戲證明遊戲開始於服務器為遊戲的RNG發行種子。然後,客戶將必須找到與球員已經簽發的種子相匹配的比賽證明。在許多遊戲中,可以通過將游戲的解決方案以高分提交的方式提交到服務器來形成遊戲證明,在其他遊戲中,可能需要根據遊戲和證明的不同程度來記錄整個遊戲會話的詳細程度。您正在使用的遊戲。

遊戲證明需要具有抗重玩性(一個玩家不應使用另一位玩家的已完成遊戲來簡化自己的遊戲證據的計算)。這將游戲證明限制在遊戲中,其中存在一些隨機性,即玩家不能只是重複使用另一位玩家的遊戲證明,而且也不能具有過多的不確定性行為,以致無法驗證該遊戲。

證明的玩法也很有限。例如,在數獨遊戲中,不可能證明玩家解決難題所需的時間。遊戲證明也不能總是區分玩家自己玩的遊戲和編寫了為他們玩遊戲的腳本的玩家。

防止解決方案“抄襲”的一種方法是在遊戲開始之前指定玩家的姓名,並根據該姓名對隨機數種子進行哈希處理。並讓遊戲報告未散佈的種子以及名稱和解決方案。
由於我們在這裡擁有服務器端,因此很容易跟踪時間。它是謎題生成與結果提交之間的數量。
CR Drost
2017-01-16 00:15:32 UTC
view on stackexchange narkive permalink

我只想提到有解決此問題的一種方法,但是您可能無法使用它;該解決方案稱為“同態加密”,它允許客戶端執行已知的計算而無需確切知道他們正在使用什麼值,並且服務器可以檢查所計算值的結構以證明客戶端不只是發送回一個隨機字符串,但實際上是根據提供的幾個值構建而成的。

問題是,它是 slow 還是 incomplete ,其中“ incomplete”的意思是“未包含所有邏輯原語”。通常,它是一個部分系統,允許進行一些加密和解密操作E(),D()以及一些複雜的操作⊕,使得

D(E(A)⊕E(B)) = A + B,

等。

因此,讓我們看一下如何解決某些遊戲的問題。考慮一個“熄燈”類型的遊戲,在該遊戲中,您按下六角形網格的 N 十六進制,然後每個都切換其狀態和周圍狀態。這是那些“印刷機”上的可交換代數,因此在給定的解決方案中,總共不超過N個印刷機,加上每個十六進制僅取決於初始狀態加上其自身的印刷機加上其周圍的6個十六進制。 / p>

由於我們的同態加密方案僅允許+,而不能進行XOR,因此我們為每個hex分配了一個3位計數器,用於對其進行翻轉的次數。 (客戶端軟件會自動將十六進制的每兩次按縮小到一次按。)因此,實際的翻轉動作是位矢量,

  001 001 000 000 000 001 001 001 000 001 001 000 000 ... 000 00000000 00000001  

換句話說,它們在翻轉的這3位字段中每個都有1,在某些16位計數器中還有1。

我們使用同態加密方案對所有這些加密,然後將它們分別發送給客戶端,然後客戶端將根據我們發送回的這些加密值計算出的加密值發送給我們。然後,我們將其解密,並將解密後的值與位串

  001 001 001 001 ... 001 11111111 00000000  

進行比較,並與初始遊戲進行比較狀態與這8個計數器位的0相鄰。

如果他們向我們發送一個隨機值,則我們接受它的機會是2 -(N + 8) sup>,因此他們通過測試的唯一有用方法是使用我們為它們提供的值以某種允許的組合使用。它們可以訪問一些由於整數溢出而不允許直接執行的操作,但是我們總是可以使字段的寬度大於3位,以使這些計數器的使用成本更高。但是我們從來沒有傳遞過他們各自的按鈕,更不用說重放歷史了:我們接受了一個向量,上面寫著“這是我如何翻轉網格”,這是每個人都在警告您的“超級不安全的事情”,但是我們這樣做的方式是,如果他們沒有訪問密鑰就無法完成我們擔心的事情。

相反,您在加密投票中會看到這種事情,您需要確保投票機的安全性。不會自發給愛麗絲1000票。

我看不到為什麼加密在這裡有用。我們確保客戶真正解決難題的唯一方法是包括他所做的“工作證明”。如果工作證明未加密,會有什麼區別?
@AgnishomChattopadhyay您能想到某些解決方案S的工作量證明比S本身更長的情況嗎?借助同態加密,您基本上不必這樣做。
OscarAkaElvis
2017-01-15 16:04:08 UTC
view on stackexchange narkive permalink

客戶端的所有內容都可以被欺騙。因此答案是否定的。謝謝@盧克公園

我沒聽懂你的第二段。假設我將“隨機”令牌保留在服務器端。客戶發送分數時如何驗證? 在第三段中,安全地發送初始隨機令牌意味著什麼?
在服務器端發送它意味著,例如,如果您使用的是php,則必須在後端(而不是通過js)使用php發送它。我想客戶端無法嗅探任何內容,如果您說的夠用https的話。為了驗證它,您必須在帳戶服務器上接收和存儲初始令牌(在會話中或任何地方的數據庫中),然後在接收到客戶端的令牌(可能是欺騙的)之後,必須將其與發送的初始令牌進行比較(這是安全的),以便沒有欺騙的可能。
您可以這樣說,欺騙任何客戶端。因此,剩下的答案都是不必要的。
@Luke公園,他問“有沒有一種方法可以安全地發送高分,並防止客戶發送“假”高分?”所以我試圖解釋整個過程
沒有整個過程。你不能阻止它。合法客戶所做的任何事情都可能被非法客戶欺騙。
你錯了。關鍵是服務器可以為後端創建的遊戲創建初始令牌,並將其發送到比分服務器。該令牌是安全的。然後,在遊戲之後,可以欺騙客戶端令牌,好的,但是安全機制是客戶端發送的令牌必須與創建遊戲時首先發送的安全令牌匹配。
但是客戶端仍然是將分數發送到服務器的客戶端,對嗎?有了令牌?
讓我們[繼續聊天中的討論](http://chat.stackexchange.com/rooms/51820/discussion-between-oscarakaelvis-and-luke-park)。
經過一會兒更深的思考,我想你是對的盧克公園,對不起。我編輯了答案。
Ben Harrison
2017-01-18 22:09:42 UTC
view on stackexchange narkive permalink

我的建議更多是混淆技術,對於許多用戶來說可能是一個令人沮喪的障礙。但是,無論是高級用戶還是堅定的用戶,仍然可以分析您的源代碼以重現結果。

使用 Hashids之類的工具來創建分數的哈希值,並將其發送到您的服務器請求中以及明文得分。用戶ID的字符串值可以是用於編碼得分的哈希值的鹽,如果共享,則使哈希值無用。在服務器端,您可以解碼該哈希並將結果與發送的純文本分數進行比較,以確保它們符合預期。

我想指出的是,哈希只是可以使用的一種工具。此特定庫的一個限制是它不支持負數(假設您的遊戲可能需要它)。
它僅比發送純文本好一點,因為用戶知道他的ID並可以像服務器一樣對其進行解碼。


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