网页游戏外挂分析及防范

最近在开发社区版网页游戏,其实在整个开发过程中碰到了不少问题。而这些问题也被很细心的用户们发现,并使用外挂程序钻了空子。例如我在前面曾写过的一篇博客《web开发安全守则之永远不要相信用户的输入》中介绍过,因为判断用户购买道具时,整个程序遗漏对负数的处理。今天借着另外一个外挂问题,讲讲网页游戏中的外挂。

网页游戏里面的外挂和网络游戏的外挂是截然不同的,需要技术也要简单很多。一般常用方法是使用模拟http的数据提交,当然这个过程需要知道前台(一般flash)的请求接口以及该请求接口的功能;使用程序自动地按序调用这些接口。

例如:在农场游戏中偷取好友的菜, 而这个操作需要访问http://www.aaa.com/steal.php,它需要传递参数a=B;c=D; 那么下面这段php脚本就能达到这么一个效果(注意一般程序都需要登录,这里你需要处理传递那边的session——id,具体可以使用下面提到的两个工具获得)

$rr_url = 'http://www.aaa.com/steal.php';
function curlCookie($url, $cookie, $post)
{
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_HEADER, false);
    $cookie && curl_setopt($ch, CURLOPT_COOKIE, $cookie);
    curl_setopt($ch, CURLOPT_POST, true);
    $post  && curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    $res = curl_exec($ch);
    curl_close($ch);
    return $res;
}
$cookie = '';//这个是记录你登陆的session_id
$post = http_build_query(array('a'=>'B', 'c'=>'D'));
curlCookie($rr_url, $cookie, $post);

如果你把整个游戏的流程分析清楚了(要有耐心),那么写成一系列的这样的请求脚本,你就可以让程序自动跑了。至于怎么样去观察每个请求的详细信息,这个有两个工具,使用firefox的话,一般就用firebug;在ie下面使用httpwatch。

 

上面是进行网页网挂开发的基础知识,要知道更多的东西,就需要了解http的协议了,不过有上面知识你就入门了;于是不使用手动玩游戏,让外挂程序帮你实现。而要获取更大的好处,就需要寻找程序的漏洞,这可是是个需要耐心的活。举个例子,该游戏是一款足球游戏, 你每天可以与别人打比赛,但是每天比赛场次有限制,一天最多能打30场。而你想免费多打几场的话,就需要找漏洞:

 

1.最简单的方式:从打比赛的接口下手,首先尝试使用多并发的程序不停地访问这个接口,我们遇到的问题就是在php的fastcgi进行处理的时候,由于是一个人多个请求:

A:判断剩余场次

B:中间执行代码

C:更新比赛场次

两个请求出现了这么一种情况, i请求在执行B, 这个时候ii请求执行了A,这样他就可以多打比赛了,对于这样的操作我们可以设置标志变量;另外B的过程会很短,给利用的机会并不多。

php也有多线程的操作,下面是前面程序的多线程版本

 

function multiCurlCookie($url, $cookie, $post)
{
	$main = curl_multi_init();
	for($i=0; $i<THREADS; $i++)
	{
		$ch[$i] = curl_init($url);
		curl_setopt($ch[$i], CURLOPT_URL, $url);
		curl_setopt($ch[$i], CURLOPT_HEADER, false);
		$cookie && curl_setopt($ch[$i], CURLOPT_COOKIE, $cookie);
		curl_setopt($ch[$i], CURLOPT_POST, true);
		$post  && curl_setopt($ch[$i], CURLOPT_POSTFIELDS, $post);
		curl_setopt($ch[$i], CURLOPT_RETURNTRANSFER, true);
		curl_multi_add_handle($main, $ch[$i]);
	}
	$running = 0;
	do{
		curl_multi_exec($main, $running);
	}while($running > 0);

	for($i=0; $i<THREADS; $i++)
	{
		$s .= var_export(curl_multi_getContent($ch[$i]), true) . "\n";
	}
	file_put_contents('curl', $s);
	curl_multi_close($main);
}

 

 

2。找更新比赛场次的地方。例如我们这款游戏, 就是在某一个地方更新比赛的场次的逻辑处理出了问题,而聪明的外挂者发现了这个问题,于是利用这个漏洞不断打比赛,打完以后又不定地将比赛场次更新大最大值。

 

下面说说如何防御这样的外挂:

1. 对程序进行详细地测试

2.对程序修改的时候,要考虑周全,绝大多数破坏行为是由于程序没有考虑周全,同时我们也不得不佩服这些外挂者的细心

3.对一些敏感的信息要做日志,方便以后观察

 

发现系统出了外挂,我们从那些地方找到入侵者的蛛丝马迹:

1.php的错误日志--检查用户是否有非法的输入,造成php错误

2.nginx/apache的访问日志记录,检查用户访问程序的顺序和具体的接口,看其中是否有可能存在的漏洞

3.自己的日志记录,一般的程序会对关键部分记录日志,以此观察某些操作是否正常---这一项在程序设计的时候就需要考虑

4.数据库里面的数据,观察用户更新了那些与他相关的数据

5.数据库语句的日志记录---例如mysql里面的bin.log文件

 

今天出现的这个问题 就是发现数据库操作日志文件中大量更新比赛场次的操作,调整思路,找出原来在更新比赛场次时的一个问题。也就是程序上的逻辑考虑不周全。

 

简单地说了这么多,其实核心就是程序设计的时候要考虑周全,留意用户的不正常行为。我们没有测试到的地方,外挂开发者们帮我找到了,于是尽快发现问题,解决问题。我这里的并没有提到其他方面的安全问题,例如服务器和数据库的操作权限造成的管理权限泄漏,php脚本的攻击。这些都是在程序一开始就必须做的基本安全防范。

posted @ 2010-11-21 15:23  库从志  阅读(1660)  评论(0编辑  收藏  举报