谢邀。。。。 压根没人邀请我,好像这个词成为知乎的通用开篇词语。
十月一的假期间,看到这个问题,当时没怎么在意。几天后,在微博上,又看到这个问题,冥冥中,有种想回答的冲动。上周六时,研发部门内部周会时,听到其他项目组的一个整型溢出问题,导致刷钱的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'
);