謝邀。。。。 壓根沒人邀請我,好像這個詞成為知乎的通用開篇詞語。
十月一的假期間,看到這個問題,當時沒怎麽在意。幾天後,在微博上,又看到這個問題,冥冥中,有種想回答的沖動。上周六時,研發部門內部周會時,聽到其他計畫組的一個整型溢位問題,導致刷錢的bug。這更加堅定我要回答這個問題的決心,拯救地球的任務,就交給我了。以下是在下經歷過的webgame安全問題的經驗,定有不妥指出,還請各位斧正。如果覺得幫助了你,亦可分享給其他做webgame研發的朋友,做交流探討。
原問題是『網頁遊戲都有哪些安全問題?』,我覺得不妥,我給改成了『網頁遊戲都有哪些安全問題?如何做得更安全?』,同時,問題也從『大家來研究探討一下,網頁遊戲攻防技術。必定,這個話題很敏感。目前,網頁遊戲已經很多了,會不會被黑產盯上?網頁遊戲會不會被黑,資料庫會不會被拖庫』改成了『大家來研究探討一下,網頁遊戲攻防技術。必定,這個話題很敏感。目前,網頁遊戲已經很多了,會不會被黑產盯上?網頁遊戲會不會被入侵?入侵方式有哪些?如何做好網頁遊戲的入侵防禦?挽救措施有哪些?如何才能最小化減少廠商損失?』,更改的理由是『本文原提問者開篇提到「大家來研究探討一下,網頁遊戲攻防技術。」,那麽應該不光提到如何入侵,更應該提到如何防禦,應該細心描述漏洞形成原理,規避方式,以提高研發者技能水平;應該詳細講解安全事件發生後,如何最小化減少廠商損失,減少使用者損失,保護遊戲平衡。』,幸運的是,這個修改,被知乎透過了。對此,表示感謝。
前面安全專家
@余弦站在安全工作者的角度,回答了這個問題。下面我將以webgame研發者角度,切合遊戲業務模組邏輯,從業務需求,資料庫設計,程式編寫,操作方式上來講解漏洞形成原理,規避方案,也歡迎大家討論。
登入認證
近幾年,網頁遊戲幾乎都是以聯運方式營運,意味著遊戲伺服器本身不保存使用者密碼,使用者登入在平台,透過平台跟遊戲伺服器的介面對接登入。介面做加密認證。故webgame的帳號密碼安全問題,這裏不提了。但登入認證的hash字串安全,也還是要註意的。比如登入hash字串的生效時間,hash字串的加密參數來源,比如包括使用者名稱、登入IP,瀏覽器user-agent等數據,以防止改hash被泄漏了,也是很難透過伺服器的驗證。
遊戲充值
webgame的遊戲充值流程,跟普通網頁充值流程一致,沒有特殊的地方,其不同點就是跟其他眾多平台做聯合營運時,勢必要每個公司做介面對接,且介面規範各式各樣,且遊戲廠商沒有話語權,必須按照他們的介面規範來,這實在棘手。騰訊的充值介面的驗證方式,安全性做的較為突出,大約程式碼:
$signKey
=
array
(
'openid'
,
'appid'
,
'ts'
,
'payitem'
,
'token'
,
'billno'
,
'version'
,
'zoneid'
,
'providetype'
,
'amt'
,
'payamt_coins'
,
'pubacct_payamt_coins'
);
$sign
=
array
();
//從GET參數中,對比找出上面參數的值
foreach
(
$signKey
as
$key
)
{
if
(
isset
(
$data
[
$key
]))
{
$sign
[
$key
]
=
$data
[
$key
];
//只有 GET裏有的參數,才參與sig的計算
}
}
######開始生成簽名############
//1: URL編碼 URI
$url
=
rawurlencode
(
$url
);
//2:按照key進行字典升序排列
ksort
(
$sign
);
//3: &拼接,並URL編碼
$arrQuery
=
array
();
foreach
(
$sign
as
$key
=>
$val
)
{
$arrQuery
[]
=
$key
.
'='
.
str_replace
(
'-'
,
'-'
,
$val
);
}
$query_string
=
join
(
'&'
,
$arrQuery
);
//4 以POST方式拼接 1、3 以及URL
$src
=
'GET&'
.
$url
.
'&'
.
rawurlencode
(
$query_string
);
// ## 構造金鑰
$key
=
$this
->
config
->
get
(
'qq_appkey'
)
.
'&'
;
//### 生成簽名
$sig
=
base64_encode
(
hash_hmac
(
"sha1"
,
$src
,
strtr
(
$key
,
'-_'
,
'+/'
),
true
));
if
(
$sig
!=
$data
[
'sig'
]
)
{
$return
[
'ret'
]
=
4
;
$return
[
'msg'
]
=
'請求參數錯誤:(sig)'
;
$this
->
output
->
set
(
json_encode
(
$return
));
return
;
}
在此基礎上,還可以做的嚴謹點:
-
增加隨機參數名、參數值。隨機參數名、參數值由聯運方隨機生成,按照參數名的字串所屬ASCII碼順序排序,參數名、參數值均參與sign的計算,增加暴力破解金鑰(app key)難度。
-
增加回呼驗證訂單號,金額資訊。遊戲充值伺服器接收到充值請求時,反向到該平台回呼介面,確認此筆訂單有效性,以防止加密金鑰泄漏的問題。
遠端檔引入
在網頁遊戲的研發中,多數都是使用框架來做,即使用REQUEST來的參數,作為請求檔名的一部份,來使用,那麽很容易形成遠端檔引入的漏洞。在我們之前的遊戲中,曾出現過一例這樣的漏洞問題。
// Load the local application controller
// Note: The Router class automatically validates the controller path. If this include fails it
// means that the default controller in the Routes.php file is not resolving to something valid.
if
(
!
file_exists
(
APPROOT
.
'controllers/'
.
load
(
'Router'
)
->
getDirectory
()
.
load
(
'Router'
)
->
get class
()
.
EXT
))
{
load
(
'Errors'
)
->
show404
(
'Unable to load your default controller. Please make sure the controller specified in your Routes.php file is valid.'
);
}
include
(
APPROOT
.
'controllers/'
.
load
(
'Router'
)
->
getDirectory
()
.
load
(
'Router'
)
->
get class
()
.
EXT
);
load
(
'Benchmark'
)
->
mark
(
'load_basic_ class_time_end'
);