灯火互联
管理员
管理员
  • 注册日期2011-07-27
  • 发帖数41778
  • QQ
  • 火币41290枚
  • 粉丝1086
  • 关注100
  • 终身成就奖
  • 最爱沙发
  • 忠实会员
  • 灌水天才奖
  • 贴图大师奖
  • 原创先锋奖
  • 特殊贡献奖
  • 宣传大使奖
  • 优秀斑竹奖
  • 社区明星
阅读:2567回复:0

PT协议漏洞分析及利用

楼主#
更多 发布于:2013-01-13 00:39
0x00背景介绍
PT是PrivateTracker(私用种子服务器)的简称,可以统计用户的上传和下载量,计算用
户的分享率。你可以简单将它理解为BT的升级版,在拥有BT所有功能的同时,需要达到一
定的分享率才能不被删除帐号。PT其实也是Bt下载的一种,但有两个明显的改进:一是私
密的小范围下载,二是进行流量统计,根据上载量决定你的权限。其通过禁用DHT有要求地
选择并控制用户数量,这样,在有限的范围内,下载的用户基本上都可以达到自己的宽带上
限,PT下载还通过论坛等方式的约束机制将BT下载的理念现实化,真正让用户做到下载的
过程中努力上传。(摘自百度百科)
以笔者所注册的PT站点为例。由于PT协议会统计下载量和上传量,因此会有一个叫做分享
率(上传量比下载量)的数值。账号的级别与分享率、下载量、上传量三者都有关。分享率
过低会导致封号等后果。可是PT协议真的可靠吗?请看笔者一一分析而来。如果对原理不
感兴趣,请直接跳到0x03。
0x01服务端源码分析
目前大部分的PT站都是用的nexusphp,笔者以nexusphp.v1.5.beta5.20120707版本
为例进行分析。
服务端接收的比较重要的数据有:passkey,info_hash,port,uploaded,downloaded,
left,event。接下来一项一项进行说明:
Passkey:用来标识用户的唯一值
info_hash:用来标识当前资源的唯一值
port:客户端连接服务端的端口
uploaded:已经上传的数量(单位byte)
downloaded:已经下载的数量(单位byte)
left:下载未完成的数量(单位byte)
event:当前状态(重要状态有stopped、completed、started)
服务端继承了数据更新、作弊检测等信息,对应文件为./announce.php。
我们首先看数据更新这部分。对应文件231行到316行。在通过一系列验证之后,会有类似
的两行代码:
$USERUPDATESET[]="uploaded=uploaded+$upthis";
$USERUPDATESET[]="downloaded=downloaded+$truedownthis";
在文件389行有:
sql_query("UPDATEusersSET".join(",",$USERUPDATESET)."WHEREid=".$userid);
即更新users表后,上传量变为了原上传量与本次上传量之和,下载量变为了原下载量与本
次下载量之和。
接下来我们看作弊检测部分的代码。
第一个验证的地方是USER_AGENT。见announce.php第6行:
$agent=$_SERVER["HTTP_USER_AGENT"];
block_browser();
block_browser函数见./include/functions_announce.php。
functionblock_browser()
{
$agent=$_SERVER["HTTP_USER_AGENT"];
if(preg_match("/^Mozilla/",$agent)||preg_match("/^Opera/",$agent)||
preg_match("/^Links/",$agent)||preg_match("/^Lynx/",$agent))
err("Browseraccessblocked!");
//checkheaders
if(function_exists('getallheaders')){//getallheaders()isonlysupported
whenPHPisinstalledasanApachemodule
$headers=getallheaders();
//else
//$headers=emu_getallheaders();
if($_SERVER["HTTPS"]!="on")
{
if(isset($headers["Cookie"])||isset($headers["Accept-Language"])||
isset($headers["Accept-Charset"]))
err("Anti-Cheater:Youcannotusethisagent");
}
}
}
其中禁止了几种常见浏览器的USER_AGENT,并对HTTP请求头中的Cookie、Accept-Language、
Accept-Charset这几项进行检查。如果HTTP请求头有Cookie、Accept-Language、
Accept-Charset这几项,则会出错。
第二个验证的地方是端口port。见announce.php第35行:
//checkportandconnectable
if(portblacklisted($port))
err("Port$portisblacklisted.");
跟踪函数portblacklisted,在./include/functions_announce.php中,即限制了端口的
范围。但是,$port变量是通过GET方式得到的,我们可以进行伪造。
然后是各种身份信息、种子信息的获取及验证,略过。在服务端会动态维护一个peer的数
据表,来记录当前的连接信息(session)。
接下来是第三个验证的地方,对announce时间间隔的验证。见announce.php第163行:
//minannouncetime
if(isset($self);;$self['prevts']>(TIMENOW-$announce_wait))
err('Thereisaminimumannouncetimeof'.$announce_wait.'seconds');
其中$announce_wait在第100行有定义,$announce_wait
能小于30秒。$self为peer表中的内容。
第四个验证的地方在announce.php第219、220行:
=30。即两次announce间隔不
$upthis=$trueupthis=max(0,$uploaded-$self["uploaded"]);
$downthis=$truedownthis=max(0,$downloaded-$self["downloaded"]);
其中$self["uploaded"]和$self["downloaded"]是peer表中的内容,$uploaded

$downloaded是服务端GET方式得到的数据。这两行大致意思为在当前活动的session中,
$uploaded和$downloaded这两个变量的值必须是不断增加的。
接下来是比较重要的一个验证步骤,check_cheater函数。此函数在./
include/functions_announce.php中定义。
check_cheater函数中注释写的比较清楚,本质为不同情况下对上传速度的判断。在默认的
安全级别下,首先,如果上传速度大于100MByte/S,很明显这一定是在作弊,系统会自动
disable你的账号的;然后,如果你以MByte/S的速度上传了1GB,那你可能在作弊。如果
管理员设置了更高的安全级别,则会进行当前下载peer数的检查,若正在下载的peer数较
小但是你却以一个较高的速度在上传的话,那你就有可能在作弊。对于可能作弊的情况,如
果在24小时之内cheater表没有你的记录的话会新增一条记录,若已经有记录的话记录中
的hit数会增加1。
该函数只检查了上传有关的参数,并没有检查下载时的情况。因此我们可以伪造下载量或者
不产生下载量。
作弊检测部分的代码到此基本结束了。最后来看与当前状态(event)有关的值。
Stopped相当于你退出客户端时的状态,停止下载,停止做种,系统将你的信息从peer表
中删除。
Completed表示当前种子已经下载完成,在种子状态中可以看到。若未发送Completed
则表示还在下载或者中途删掉,表示为“未完成”状态。

0x02客户端抓包验证
笔者用uTorrent3.1.3进行测试。
首先在uTorrent中设置代理,使其通过brup,方便我们进行抓包。其中我们只需要对
主机名查询使用代理,抓取连接服务器时的数据包。

图片:20130112115128574.jpg


下载种子,载入,在高级选项中会看到tracker列表。其中tracker所对应的文件即为

0x01中服务端的脚本。

图片:20130112115128699.jpg


点击确定开始下载,用brup抓包。
第一个包是以GET方式发往scrape.php,该文件作用为判断种子是否存在。
GET
/scrape.php?passkey=xxx;info_hash=%d5%bb%80%2a%c3v%ac%3d%5e%01%90%7fu%9c%a4%bc%
afK7%81;info_hash=%12%3f%cc1%a5%8c5M%d7%9e%1b%40Q%cb%2a%14%bf%a7%f09HTTP/1.1
Host:xxx
User-Agent:uTorrent/3130(27385)
Accept-Encoding:gzip
Connection:Close
接着在资源存在的情况下发送第二个包,此数据包发往announce.php,即服务端主脚本。
以后的数据包都发往announce.php。在网站上看到该种子状态为未完成。
GET
/announce.php?passkey=xxx;info_hash=%d5%bb%80%2a%c3v%ac%3d%5e%01%90%7fu%9c%a4%b
c%afK7%81;peer_id=-UT3130-%f9j%b7J%24%e6%b9%85%9a%d1zv;port=41677;uploaded=0;do
wnloaded=0;left=137201853
;corrupt=0;key=03731F6C;event=started;numwant=200;compact=1;no_peer_id=1;ipv6=x
xxxHTTP/1.1
Host:xxxx
User-Agent:uTorrent/3130(27385)
Accept-Encoding:gzip
Connection:Close
由此包我们可以看出,状态event=started,uploaded=0,downloaded=0,left=137201853。
我们继续来看:
GET
/announce.php?passkey=xxx;info_hash=%d5%bb%80%2a%c3v%ac%3d%5e%01%90%7fu%9c%a4%b
c%afK7%81;peer_id=-UT3130-%f9j%b7J%24%e6%b9%85%9a%d1zv;port=41677;uploaded=0;do
wnloaded=52953088;left=83036349;corrupt=0;key=03731F6C;numwant=200;compact=1;no
_peer_id=1;ipv6=xxxHTTP/1.1
Host:xxx
User-Agent:uTorrent/3130(27385)
Accept-Encoding:gzip
Connection:Close
这次有了上传和下载的信息。uploaded=0,downloaded=52953088,left=83036349。
等到下载完成后,我看可以看到event=completed。在网站上看到该种子状态为已完成。
GET
/announce.php?passkey=xxx;info_hash=%d5%bb%80%2a%c3v%ac%3d%5e%01%90%7fu%9c%a4%b
c%afK7%81;peer_id=-UT3130-%f9j%b7J%24%e6%b9%85%9a%d1zv;port=41677;uploaded=0;do
wnloaded=137201853;left=0;corrupt=0;key=03731F6C;event=completed;numwant=200;co
mpact=1;no_peer_id=1;ipv6=xxxHTTP/1.1
Host:xxx
User-Agent:uTorrent/3130(27385)
Accept-Encoding:gzip
Connection:Close
当退出uTorrent客户端时,发送数据包如下:
GET
/announce.php?passkey=xxx;info_hash=%d5%bb%80%2a%c3v%ac%3d%5e%01%90%7fu%9c%a4%b
c%afK7%81;peer_id=-UT3130-%f9j%b7J%24%e6%b9%85%9a%d1zv;port=41677;uploaded=7438
336;downloaded=137201853;left=0;corrupt=0;key=03731F6C;event=stopped;numwant=0;
compact=1;no_peer_id=1HTTP/1.1
Host:xxx
User-Agent:uTorrent/3130(27385)
Accept-Encoding:gzip
Connection:Close
我看可以看到此时event=
stopped。
我们重新来看这些数据包,它们的特点是User-Agent为
uTorrent/3130(27385),没有
Cookie、Accept-Language、Accept-Charset等信息。这正通过了服务端第一个验证。Port
数值在服务端允许的范围内,这是第二个验证。经过比较抓包时间,发现下载完成前发包频
率大约为1个/分钟,下载完成之后发包频率为30分钟,即tracker的更新时间。这即保证
了下载时能随时得到足够的peer,又能使完成的peer不占用太多的服务器资源。第三个验证也顺利通过。第四个验证和最后一个验证由于无法直观的看出,在此不予说明。

0x03PT协议漏洞及利用
经过以上的分析,我们可以总结出PT协议的漏洞。
1.上传下载的信息靠客户端发送GET请求包来完成,我们可以进行伪造;
2.PT对用户的识别只有passkey这一个信息,passkey的生成算法为MD5(用户名+时间
+passhash)。Passkey存在于下载后的种子里,虽然不能伪造,但是可以进行提取;
3.作弊检测只有上传的部分,未对下载部分进行检测,有实现可以不计下载量下载的可能;
4.一个种子可以包含多个tracker,而服务器并没有或者说无法对此状态进行检测,客户
端tracker进行更新的时候会向列表中所有的tracker发送同样的上传下载量信息。这样便
能导致刷流量的可能;
5.所有的信息都由tracker进行处理,而处理过程中多次查询数据库,有CC攻击的可能,
一旦成功,整个服务器便无法工作。
对于第一个漏洞的利用方法是人工发送数据包,只要满足之前所说的验证的规则就可以,即
注意发包格式、请求内容、发包间隔、数据速率控制、安全级别高时还要关注当前下载者的
数量等等。当前下载者的数量可由特定页面进行查询,正则匹配信息即可。由于本人才学疏
浅,利用工具并没写出。
对于第二个漏洞,我们可以向一个不知情的用户要一个下载好的种子,用uTorrent载入,
点高级查看tracker信息,记录下其passkey。当以后自己需要下载种子而又不想耗费自己
的下载量的时候,可以将自己种子的tracker替换成受害者的。这样tracker更新时传送的
信息为受害者的信息,计入受害者的下载量。当下载完毕后,重启uTorrent,把之前的下
载信息清除,然后将tracker改为自己的tracker,这样上传量计入自己的账号。
对于第三个漏洞,我们可以在刚开始下载时tracker更新获得peer之后将tracker删除掉,
这样即有peer传送文件给自己,又不会向服务器发送流量信息。等下载完成后,重启
uTorrent,将tracker加入,继续上传,上传量计入自己的账号。(慎用,安全级别高时可
能会导致其他人封号!)
对于第四个漏洞,前提是有好基友多个或者妹子一枚。一个种子自己用各种途径下载完毕后,
重启uTorrent,在tracker列表中加入自己和对方的tracker,一个人做种,多个人获得上
传量。
对于第五个漏洞,不多解释,CC攻击是违法行为。

0x04后记
这个漏洞已经发现蛮长时间了,一直没有详细说明,毕竟整个作弊的思想与分享精神相抵触。
期间笔者也进行过几次尝试,其中一次炫耀过分,导致被封账号禁ip。之后便一直低调求
发展,用代理来突破ip限制默默下载上传资源。如果没有特殊的情况,希望大家还是能够
正常的遵守PT规则,在分享中得到自己的快乐。
以上方法仅为研究所用,如出现问题,后果自负,与笔者无关。

喜欢0 评分0
游客

返回顶部