PDA

Bekijk Volledige Versie : [KAPDA::#16] - SMF SQL Injection



alireza hassani
09/12/05, 21:45
KAPDA New advisory

Vendor: http://www.simplemachines.org/
Vulnerable Version:SMF 1.1 rc1, Other versions also
may be affected.
Bug: SQL Injection
Exploitation: Remote with browser

Description:
--------------------
Simple Machines Forum is a most widely used PHP-based
message board system that uses a MySQL database.

Vulnerability:
--------------------
Lets Look at the Source Code of 'Memberlist.php' :
..
..
------------/CUT/------------
if (!is_numeric($_REQUEST['start']))
{
$request = db_query("
SELECT COUNT(ID_MEMBER)
FROM {$db_prefix}members
WHERE LOWER(SUBSTRING(realName, 1, 1)) < '" .
substr(strtolower($_REQUEST['start']), 0, 1) . "'
AND is_activated = 1", __FILE__, __LINE__);
list ($_REQUEST['start']) =
mysql_fetch_row($request);
mysql_free_result($request);
}
------------/CUT/------------
..
..

As shown up, The script does not properly validate
user-supplied input in 'start' that may allow a remote
user to launch Sql injection attacks. A Registered
user can create specially crafted parameter values
that will execute SQL commands on the underlying
database.


Demonstration URL :
-----------------------------
http://example.com/smf/index.php?action=mlist;sa=all;start='[SQL]

Solution:
--------------------
There is no vendor supplied patch for this issue at
this time.
Our recommendation for a temporary fix:
In /Sources/Memberlist.php find these lines:

//-------Start----
if (!is_numeric($_REQUEST['start']))
{
//-------End------

And add these lines after those:

//-------Start----
$Pattern="[A-Za-z]";
if (!eregi($Pattern, $_REQUEST['start'])) die('Hacking
attempt...');
//-------End------

Original Advisory:
--------------------
http://irannetjob.com/content/view/173/28/

Credit :
--------------------
Discovered & released by trueend5 (trueend5 kapda ir)
Security Science Researchers Institute Of Iran
[http://www.KAPDA.ir]

__________________________________________________
Do You Yahoo!?
Tired of spam? Yahoo! Mail has the best spam protection around
http://mail.yahoo.com

grudge@securityfocus.com, simplemachines@securityf
10/12/05, 18:45
I'm a developer from over at simplemachines and I do not see how this can pose an exploit? Let's examine the code piece by piece:

The code is entered at this point:
if (!is_numeric($_REQUEST['start']))

So, will be executed if $_REQUEST['start'] is a string. It's then used in the query. However, it's used in the query in this piece of code:

substr(strtolower($_REQUEST['start']), 0, 1)

So, the string is set to lower case, and then only the FIRST letter is used within the query. How can anyone exploit the database with a one character insertion? Of course this is within single quotes as well, so it cannot even be a command.

I simply cannot see how you could possibly exploit SQL from this?

false.hopes@gmail.com
11/12/05, 17:00
That is the silliest thing I have ever seen.
First off, the string is run through is_numeric before being used,
anything with a ' will not pass is_numeric. Secondly, the string is run
through substr and takes only one character out of the string.

Don't you attempt to run these exploits before making up some BS report?

retrogod@aliceposta.it
12/12/05, 23:00
I'm a developer from over at simplemachines and I do not see how this can pose an exploit? Let's examine the code piece by piece:

The code is entered at this point:
if (!is_numeric($_REQUEST['start']))

So, will be executed if $_REQUEST['start'] is a string. It's then used in the query. However, it's used in the query in this piece of code:

substr(strtolower($_REQUEST['start']), 0, 1)

So, the string is set to lower case, and then only the FIRST letter is used within the query. How can anyone exploit the database with a one character insertion? Of course this is within single quotes as well, so it cannot even be a command.

I simply cannot see how you could possibly exploit SQL from this?


mphhh, correct...
the only problem I see is path disclosure, 'cause you can inject only a one char string:

http://[target]/smfrc1/index.php?action=mlist;sort=realName;start=\;desc

query becomes:

SELECT COUNT(ID_MEMBER) FROM smf_members WHERE LOWER(SUBSTRING(realName, 1, 1)) < '\' AND is_activated = 1

and at screen, you have:

Errore di sintassi nella query SQL vicino a ''\'
AND is_activated = 1' linea 3
File: [full_application_path]Memberlist.php
Line: 162

but I think you cannot inject commands...

polnby@yahoo.com
12/12/05, 23:15
Take a better look at your \'Memberlist.php\' source code.

// Select the members from the database.
$request = db_query(\"
SELECT mem.ID_MEMBER
FROM {$db_prefix}members AS mem
LEFT JOIN {$db_prefix}log_online AS lo ON (lo.ID_MEMBER = mem.ID_MEMBER)
LEFT JOIN {$db_prefix}membergroups AS mg ON (mg.ID_GROUP = IF(mem.ID_GROUP = 0, mem.ID_POST_GROUP, mem.ID_GROUP))
WHERE mem.is_activated = 1
ORDER BY \" . $sort_methods[$_REQUEST[\'sort\']][$context[\'sort_direction\']] . \"
LIMIT $_REQUEST[start], $modSettings[defaultMaxMembers]\", __FILE__, __LINE__);
printMemberListRows($request);
mysql_free_result($request);
----------------------

// Find the members from the database.
// !!!SLOW This query is slow.
$request = db_query(\"
SELECT mem.ID_MEMBER
FROM {$db_prefix}members AS mem
LEFT JOIN {$db_prefix}log_online AS lo ON (lo.ID_MEMBER = mem.ID_MEMBER)
LEFT JOIN {$db_prefix}membergroups AS mg ON (mg.ID_GROUP = IF(mem.ID_GROUP = 0, mem.ID_POST_GROUP, mem.ID_GROUP))
WHERE \" . implode(\" $query OR \", $fields) . \" $query$condition
AND is_activated = 1
LIMIT $_REQUEST[start], $modSettings[defaultMaxMembers]\", __FILE__, __LINE__);
printMemberListRows($request);
mysql_free_result($request);
----------------------

Isn`t posible for an attacker to modify the query logic?

ascii
13/12/05, 02:00
grudge@securityfocus.com wrote:
> I'm a developer from over at simplemachines and
> I do not see how this can pose an exploit?

/* tabs are evil */
if (!is_numeric($_REQUEST['start'])) {

$request = db_query("SELECT COUNT(ID_MEMBER)
FROM {$db_prefix}members
WHERE LOWER(SUBSTRING(realName, 1, 1)) < '".
substr(strtolower($_REQUEST['start']), 0, 1)
."' AND is_activated = 1", __FILE__, __LINE__);

list ($_REQUEST['start']) = mysql_fetch_row($request);
mysql_free_result($request);
}

me too, this piece of code isn't exploitable

at last you can inject a ' that will issue a
php error (path disclosure, error log filling
but not an usable sql injection)

> The code is entered at this point:
> if (!is_numeric($_REQUEST['start']))

i would prefer ctype_digit or preg_match [09]
cause is_numeric accept also hex, signed and
floats

> substr(strtolower($_REQUEST['start']), 0, 1)
> I simply cannot see how you could possibly
> exploit SQL from this?

it's impossible imho, but don't relay on magic quotes
or this type of stuff, put a beautiful
mysql_real_escape_string on each string passed to the db
and cast integers (int)intval($_GET['id'])

seems KAPDA Researchers researched this 'vuln' too fast : )

ascii - http://www.ush.it

Steven M. Christey
13/12/05, 03:45
>substr(strtolower($_REQUEST['start']), 0, 1)
>
>So, the string is set to lower case, and then only the FIRST letter is
>used within the query. How can anyone exploit the database with a one
>character insertion? Of course this is within single quotes as well,
>so it cannot even be a command.


This sounds like yet another example of a researcher diagnostic error,
which I warned about a couple months ago:

A common researcher diagnosis error: misreading error messages
http://www.derkeiler.com/Mailing-Lists/securityfocus/bugtraq/2005-10/0040.html

I would bet that the software generated an error based on this portion
of the SQL/PHP code:

WHERE LOWER(SUBSTRING(realName, 1, 1)) < '" .
substr(strtolower($_REQUEST['start']), 0, 1) . "'

The original demonstration value of "start" is:

'[SQL]

and since the first character is "'", PHP would generate something
like:

WHERE LOWER(SUBSTRING(realName, 1, 1)) < '''

which would then generate a syntax error, which could then be
mis-diagnosed as SQL injection.

I bet that many so-called "SQL injection" issues are of this form of
"limited SQL syntax manipulation." It is still an error message
information leak, which some people don't think it security relevant.
But clearly it is much less severe than SQL injection.

- Steve

grudge@securityfocus.com, simplemachines@securityf
15/12/05, 09:15
Remember, SMF only shows database syntax errors to administrators anyway, so they would not even see the query string itself. All the average user trying this gets is "A database error has occured".

Either way securityfocus have kindly removed the advisory so we're happy.



mphhh, correct...
the only problem I see is path disclosure, 'cause you can inject only a one char string:

http://[target]/smfrc1/index.php?action=mlist;sort=realName;start=\;desc

query becomes:

SELECT COUNT(ID_MEMBER) FROM smf_members WHERE LOWER(SUBSTRING(realName, 1, 1)) < '\' AND is_activated = 1

and at screen, you have:

Errore di sintassi nella query SQL vicino a ''\'
AND is_activated = 1' linea 3
File: [full_application_path]Memberlist.php
Line: 162

but I think you cannot inject commands...