PT协议漏洞分析及利用
3587 点击·0 回帖
![]() | ![]() | |
![]() | 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规则,在分享中得到自己的快乐。 以上方法仅为研究所用,如出现问题,后果自负,与笔者无关。 | |
![]() | ![]() |