Loading
0

论PHP常见漏洞第一弹:安装的问题

 首先拿到一份源码,肯定是先install上,而在安装文件上又会经常出现问题。

一般的安装文件在安装完成后,基本上都不会自动删除这个安装的文件,我遇到过的会自动删除的好像也就qibocms了。

其他的基本都是通过生成一个lock文件来判断程序是否安装过了,如果存在这个lock文件了就会退出了。 这里首先先来说一下安装文件经常出现的问题。

根本无验证

这种的虽然不多,但是有时还是会遇到个。在安装完成, 并不会自动删除文件,又不会生成lock来判断是否安装过了。导致了可以直接重装过

例子: WooYun: PHPSHE B2C 重装

安装file

因为install一般都会有step 步骤啥的。。Step 1 check 啥啥 step 2 是安装啥的。 而一些cms 默认step是1,而step又是GET 来的 而他check lock的时候就是在step 1里面。 这时候如果我们直接用GET提交step 2,那么就直接进入下一步了,就没check lock了。

例如某cms中的安装文件

if (empty ($step))
{
    $step = 1;//当用户没有提交step的时候 赋值为1
}
require_once ("includes/inc_install.php");
$gototime = 2000;
 
/*------------------------
显示协议文件
------------------------*/
if ($step == 1) //当1才检测lock
{
    if (file_exists('installed.txt'))
    {
        echo '<html>
        <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
        </head>
        <body>
        你已经安装过该系统,如果想重新安装,请先删除install目录下的 installed.txt 文件,然后再安装。
        </body>
        </html>';
        exit;
    }
    include_once ("./templates/s1.html");
    exit ();
}
 
/*------------------------
测试环境要求
------------------------*/
else
    if ($step == 2) // 我们直接提交step为2 就不check lock了
    { 
        $phpv = @ phpversion();
        $sp_os = $_ENV["OS"];
        $sp_gd = @ gdversion();
        $sp_server = $_SERVER["SERVER_SOFTWARE"];
        $sp_host = (empty ($_SERVER["SERVER_ADDR"]) ? $_SERVER["SERVER_HOST"] : $_SERVER["SERVER_ADDR"]);
        $sp_name = $_SERVER["SERVER_NAME"];
        $sp_max_execution_time = ini_get('max_execution_time');
        $sp_allow_reference = (ini_get('allow_call_time_pass_reference') ? '<font color=green>[√]On</font>' : '<font color=red>[×]Off</font>');
        $sp_allow_url_fopen = (in

变量覆盖导致重装

header("Content-Type: text/html; charset={$lang}");
    
foreach(Array('_GET','_POST','_COOKIE') as $_request){
    
    foreach($$_request as $_k => $_v) ${$_k} = _runmagicquotes($_v);
    
}
    
function _runmagicquotes(&$svar){
    
    if(!get_magic_quotes_gpc()){
    
        if( is_array($svar) ){
    
            foreach($svar as $_k => $_v) $svar[$_k] = _runmagicquotes($_v);
    
        }else{
    
            $svar = addslashes($svar);
    
        }
    
    }
    
    return $svar;
    
}
    
if(file_exists($insLockfile)){
    
    exit(" 程序已运行安装,如果你确定要重新安装,请先从FTP中删除 install/install_lock.txt!");
    
}
 
foreach($$_request as $_k => $_v) ${$_k} = _runmagicquotes($_v);

这里是一个经常遇到的一个变量覆盖。

导致了我们可以覆盖掉$insLockfile从而让file_exists为false就不会退出了。导致再次重装。 这个变量覆盖不知道咋的 能在一些小cms的安装文件里看到。

之前看的xdcms 和 frcms 都存在这个变量覆盖。
例子: WooYun: frcms 重装系统

解析漏洞

这个也比较少, 就随便说句。就是像dedecms很久以前的那样在安装完成后会在install.php rename 为 Install.php.bak 但是由于apache的解析漏洞,如果无法识别最后的一个后缀的话,就会向上解析,那么就又成php了。然后又结合dedecms安装时的变量覆盖,又成重装了。

满足一些条件不会退出的。

这种例子也不算太多, 自己好像也没遇到过太多。

首先以之前发过的sitestar举例下

if(file_exists($lockfile) && ($_a=='template' || $_a=='setting' || $_a=='check')) {
    
        exit('please delete install.lock!');
    
}

这里我们来理解一下这个逻辑, 这里的file_exists($lockfile) 因为安装成功后 lockfile 肯定存在的,所以这里肯定会是true。然后再看一下,这里是一个 && true true 才会进入语句块。 那么如果$_a 不为 template 、 setting 、 check 的话,那么后面的就为false True and false => false就不会进入这个语句块,就不会exit,再配合后面的

else if($_a=="create"){
    
    $link = mysql_connect($db_host,$db_user,$db_pwd);

刚好有个其他的 如果$_a 为 create 那么就不会退出这个脚本
刚好这个create 能达到Getshell的效果
例子: WooYun: 建站之星Sitestar前台Getshell一枚

剩下的还有hdwiki之前也有一个基本差不多这样的例子

if (file_exists(HDWIKI_ROOT.'/data/install.lock') && $step != '8') {
echo "<font color='red'>{$lang['tipAlreadyInstall']}</font>";

exit();

}

如果step为8的话 那么就不会执行exit了。

case 8:
                require_once HDWIKI_ROOT.'/config.php';
                require_once HDWIKI_ROOT.'/lib/hddb.class.php';
                require_once HDWIKI_ROOT.'/lib/util.class.php';
                require_once HDWIKI_ROOT.'/lib/string.class.php';
 
                $db = new hddb(DB_HOST, DB_USER, DB_PW, DB_NAME, DB_CHARSET);
                //install 
                $setting=$db->result_first('select `value` from '.DB_TABLEPRE.'setting WHERE `variable` = \'site_appkey\'');
                if ($setting){
                    echo "<span style='font-size:20px;'>百科联盟开通成功.</span><a href='../'>进入首页</a>";
                    break;
                }
 
                //update info
                $data = $_GET['info'];
                $data = str_replace(' ', '+', $data);
                $info = base64_decode($data);
 
                if ($info){
                    $obj = unserialize($info);
                    if(is_array($obj)){
                        $url2 = 'http://localhost/count2/in.php?action=update&sitedomain='.$_SERVER['SERVER_NAME'].'&info='.$data;
                        $data = util::hfopen($url2);
                        //if gbk then toutf8
                        if ($lang['commonCharset'] == 'GBK'){
                            $obj['sitenick'] = string::hiconv($obj['sitenick'], 'gbk', 'utf-8');

刚好这里step 8又能执行一些特殊的操作。。 现在就把case 8 注释掉了。

这里代码我就不复制过了 免得占篇幅。

这里差不多是我比较常遇到的一些安装文件经常遇到的问题了,突然想也想不到其他啥的了。

转载自:http://drops.wooyun.org/papers/4544,在原文基础上有简单整理修改。

【声明】:8090安全小组门户(https://www.8090-sec.com)登载此文出于传递更多信息之目的,并不代表本站赞同其观点和对其真实性负责,仅适于网络安全技术爱好者学习研究使用,学习中请遵循国家相关法律法规。如有问题请联系我们:邮箱hack@ddos.kim,我们会在最短的时间内进行处理。